使用keras调用load_model时报错ValueError: Unknown Layer:LayerName

出现该错误是因为要保存的model中包含了自定义的层(Custom Layer),导致加载模型的时候无法解析该Layer。详见can not load_model() if my model contains my own Layer

该issue下的解决方法不够全,综合了一下后可得完整解决方法如下:
load_model函数中添加custom_objects参数,该参数接受一个字典,键值为自定义的层:

model = load_model(model_path, custom_objects={'AttLayer': 
AttLayer})  # 假设自定义的层的名字为AttLayer

添加该语句后,可能会解决问题,也可能出现新的Error:
init() got an unexpected keyword argument ‘name’, 为解决该Error,可以参照keras-team的写法,在自定义的层中添加get_config函数,该函数定义形如:

def get_config(self):    
    config = {
        'attention_dim': self.attention_dim    
    }    
    base_config = super(AttLayer, self).get_config()    
    return dict(list(base_config.items()) + list(config.items()))

其中,config属性中的定义是自定义层中__init__函数的参数,__init__函数如下:

def __init__(self, attention_dim, **kwargs):    
    self.init = initializers.get('normal')    
    self.supports_masking = True    
    self.attention_dim = attention_dim    
    super(AttLayer, self).__init__()

注意:
1、__init__函数中需添加**kwargs参数

2、只需要将__init__函数的参数写入config属性中,__init__函数体中的内容不必加进去,get_config函数其他部分也无需改动,否则会报错

3、自定义的类AttLayer如下:

"""
Implementation of Attention Layer
"""
class AttLayer(Layer):
    def __init__(self, attention_dim, **kwargs):
        self.init = initializers.get('normal')
        self.supports_masking = True
        self.attention_dim = attention_dim
        super(AttLayer, self).__init__()

    def build(self, input_shape):
        assert len(input_shape) == 3
        self.W = K.variable(self.init((input_shape[-1], self.attention_dim)))
        self.b = K.variable(self.init((self.attention_dim, )))
        self.u = K.variable(self.init((self.attention_dim, 1)))
        self.trainable_weights = [self.W, self.b, self.u]
        super(AttLayer, self).build(input_shape)

    def compute_mask(self, inputs, mask=None):
        return mask

    def call(self, x, mask=None):
        # size of x :[batch_size, sel_len, attention_dim]
        # size of u :[batch_size, attention_dim]
        # uit = tanh(xW+b)
        uit = K.tanh(K.bias_add(K.dot(x, self.W), self.b))
        ait = K.dot(uit, self.u)
        ait = K.squeeze(ait, -1)

        ait = K.exp(ait)

        if mask is not None:
            # Cast the mask to floatX to avoid float64 upcasting in theano
            ait *= K.cast(mask, K.floatx())
        ait /= K.cast(K.sum(ait, axis=1, keepdims=True) + K.epsilon(), K.floatx())
        ait = K.expand_dims(ait)
        weighted_input = x * ait
        output = K.sum(weighted_input, axis=1)

        return output

    def compute_output_shape(self, input_shape):
        return (input_shape[0], input_shape[-1])

    def get_config(self):
        config = {
            'attention_dim': self.attention_dim
        }
        base_config = super(AttLayer, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

你可能感兴趣的:(Keras,keras)