Python 3.x 无法使用自定义距离函数加载带有lambda函数的keras模型

Python 3.x 无法使用自定义距离函数加载带有lambda函数的keras模型,python-3.x,keras,Python 3.x,Keras,我正在尝试构建一个系统,使用暹罗LSTM模型检查句子的相似性,该模型使用曼哈顿距离作为距离函数,同时合并两个层。 我正在使用本文中的代码 问题是,在我将模型构建并保存在json文件中后,由于抛出错误,我无法加载该模型 未定义名称“指数负曼哈顿距离” 代码如下: # Model variables n_hidden = 50 gradient_clipping_norm = 1.25 batch_size = 64 n_epoch = 5 def exponent_neg_manhattan_

我正在尝试构建一个系统,使用暹罗LSTM模型检查句子的相似性,该模型使用曼哈顿距离作为距离函数,同时合并两个层。 我正在使用本文中的代码

问题是,在我将模型构建并保存在json文件中后,由于抛出错误,我无法加载该模型

未定义名称“指数负曼哈顿距离”

代码如下:

# Model variables
n_hidden = 50
gradient_clipping_norm = 1.25
batch_size = 64
n_epoch = 5

def exponent_neg_manhattan_distance(left, right):
    ''' Helper function for the similarity estimate of the LSTMs outputs'''
    return K.exp(-K.sum(K.abs(left-right), axis=1, keepdims=True))

# The visible layer
left_input = Input(shape=(max_seq_length,), dtype='int32')
right_input = Input(shape=(max_seq_length,), dtype='int32')

embedding_layer = Embedding(len(embeddings), embedding_dim, weights=[embeddings], input_length=max_seq_length, trainable=False)

# Embedded version of the inputs
encoded_left = embedding_layer(left_input)
encoded_right = embedding_layer(right_input)

# Since this is a siamese network, both sides share the same LSTM
shared_lstm = LSTM(n_hidden)

left_output = shared_lstm(encoded_left)
right_output = shared_lstm(encoded_right)

# Calculates the distance as defined by the MaLSTM model
malstm_distance = Merge(mode=lambda x: exponent_neg_manhattan_distance(x[0], x[1]), output_shape=lambda x: (x[0][0], 1))([left_output, right_output])

# Pack it all up into a model
malstm = Model([left_input, right_input], [malstm_distance])

# Adadelta optimizer, with gradient clipping by norm
optimizer = Adadelta(clipnorm=gradient_clipping_norm)

malstm.compile(loss='mean_squared_error', optimizer=optimizer, metrics=['accuracy'])

# Start training
training_start_time = time()

malstm_trained = malstm.fit([X_train['left'], X_train['right']], Y_train, batch_size=batch_size, nb_epoch=n_epoch,
                            validation_data=([X_validation['left'], X_validation['right']], Y_validation))

print("Training time finished.\n{} epochs in {}".format(n_epoch, datetime.timedelta(seconds=time()-training_start_time)))

malstm.save('malstm.h5')
model_json = malstm.to_json()

with open ('malstm.json', 'w') as file:
    file.write(model_json)

malstm.save_weights('malst_w.h5')
现在,当我尝试加载模型时,出现以下错误:

model = model_from_json(open('malstm.json').read(), custom_objects = {"exponent_neg_manhattan_distance":exponent_neg_manhattan_distance})
C:\Users\archi\Miniconda3\lib\site-packages\keras\engine\topology.py:1271: UserWarning: The `Merge` layer is deprecated and will be removed after 08/2017. Use instead layers from `keras.layers.merge`, e.g. `add`, `concatenate`, etc.
  return cls(**config)
Traceback (most recent call last):

  File "<ipython-input-12-4c72a4db6c29>", line 1, in <module>
    model = model_from_json(open('malstm.json').read(), custom_objects = {"exponent_neg_manhattan_distance":exponent_neg_manhattan_distance})

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\models.py", line 349, in model_from_json
    return layer_module.deserialize(config, custom_objects=custom_objects)

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\layers\__init__.py", line 55, in deserialize
    printable_module_name='layer')

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\utils\generic_utils.py", line 144, in deserialize_keras_object
    list(custom_objects.items())))

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\engine\topology.py", line 2524, in from_config
    process_node(layer, node_data)

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\engine\topology.py", line 2483, in process_node
    layer(input_tensors, **kwargs)

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\engine\topology.py", line 619, in __call__
    output = self.call(inputs, **kwargs)

  File "C:\Users\archi\Miniconda3\lib\site-packages\keras\legacy\layers.py", line 209, in call
    return self.mode(inputs, **arguments)

  File "<ipython-input-19-913812c640b3>", line 28, in <lambda>

NameError: name 'exponent_neg_manhattan_distance' is not defined
model=model_from_json(open('malstm.json').read(),自定义_对象={“指数负曼哈顿距离”:指数负曼哈顿距离})
C:\Users\archi\Miniconda3\lib\site packages\keras\engine\topology.py:1271:UserWarning:“合并”层已弃用,将在2017年8月后删除。改用“keras.layers.merge”中的图层,例如“add”、“concatenate”等。
返回cls(**配置)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
model=model_from_json(open('malstm.json').read(),自定义_对象={“指数负曼哈顿距离”:指数负曼哈顿距离})
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\models.py”,第349行,位于来自\u json的模型\u中
返回层\模块。反序列化(配置,自定义\对象=自定义\对象)
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\layers\\uuuu init\uuuuu.py”,第55行,反序列化
可打印\u模块\u name='layer')
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\utils\generic\u utils.py”,第144行,反序列化\u keras\u对象
列表(自定义对象.项())
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\engine\topology.py”,第2524行,在from\u config中
处理节点(层、节点数据)
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\engine\topology.py”,第2483行,进程节点中
图层(输入_张量,**kwargs)
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\engine\topology.py”,第619行,在调用中__
输出=自调用(输入,**kwargs)
文件“C:\Users\archi\Miniconda3\lib\site packages\keras\legacy\layers.py”,第209行,在调用中
返回self.mode(输入,**参数)
文件“”,第28行,在
NameError:未定义名称“指数负曼哈顿距离”

我在网上搜索过,这个问题可能是因为使用了lambda函数。我有没有办法加载这个模型,因为训练花了很多时间。任何帮助都将不胜感激

将注释转换为答案:如果您只需在代码中再次创建网络,就可以恢复网络的权重。错误是关于从JSON创建网络,但让我们从以下方面进行操作:

# ...
# Pack it all up into a model
malstm = Model([left_input, right_input], [malstm_distance])
# ... you don't need compile for only predict
# ... skip training and model saving
# malstm.save_weights('malst_w.h5')
malstm.load_weights('malst_w.h5')
malstm.predict(...)

现在,权重将加载到您在代码中创建的现有模型中。

首先使用model.save保存您的模型 然后加载自定义对象

model.save(“model\u路径”)
从keras.models导入负载_模型
#返回与前一个模型相同的已编译模型=
加载模型(“模型路径”,
自定义_对象={
“拉丹”:拉丹,
“指数负曼哈顿距离”:指数负曼哈顿距离})

您是否可以将
指数函数_neg _manhattan _distance
-简单地包装成一个参数化函数,并将其用作自定义对象(将消除lambda,以及它引入的问题)?您可以重新创建相同的模型,然后使用
model.load\u weights
只加载权重,避免从json创建。@MarcelZoll我已经为一个新模型完成了这项工作,它现在正在工作。我想做的是完全避免制作和训练一个新模型。@nuric这需要我至少训练一个时代的模型,还是我可以直接训练?我为这些问题道歉。我对神经网络真的很陌生,我只是在想一些事情。