使用 Keras,如何将 CuDNNLSTM 生成的权重加载到 LSTM 模型中?
Using Keras, How can I load weights generated from CuDNNLSTM into LSTM Model?
我已经基于 LSTM 层使用 Keras 开发了一个神经网络模型。为了提高 Paperspace(GPU 云处理基础设施)的速度,我用新的 CuDNNLSTM 切换了 LSTM 层层。然而,这仅适用于支持 GPU cuDNN 的机器。 PS:CuDNNLSTM 仅在 Keras master
上可用,在最新版本中不可用。
所以我生成了权重并将它们以 hdf5
格式保存在云端,我想在我的 MacBook 上本地使用它们。由于 CuDNNLSTM 层不可用,仅针对我的本地安装,我已切换回 LSTM。
阅读这篇文章 tweet about CuDNN from @fchollet 我认为它会工作得很好,只需将权重读回 LSTM 模型即可。
但是,当我尝试导入它们时,Keras 抛出此错误:
Traceback (most recent call last):
{...}
tensorflow.python.framework.errors_impl.InvalidArgumentError: Dimension 0 in both shapes must be equal, but are 2048 and 4096 for 'Assign_2' (op: 'Assign') with input shapes: [2048], [4096].
{...}
ValueError: Dimension 0 in both shapes must be equal, but are 2048 and 4096 for 'Assign_2' (op: 'Assign') with input shapes: [2048], [4096]
用 h5cat 分析 hdf5
文件,我可以看出这两个结构是不同的。
TL;DR
我无法将 CuDNNLSTM 生成的权重加载到 LSTM 模型中。
我做错事了吗?我怎样才能让它们无缝工作?
这是我的模型:
SelectedLSTM = CuDNNLSTM if is_gpu_enabled() else LSTM
# ...
model = Sequential()
model.add(SelectedLSTM(HIDDEN_DIM, return_sequences=True, input_shape=(SEQ_LENGTH, vocab_size)))
model.add(Dropout(0.2))
model.add(SelectedLSTM(HIDDEN_DIM, return_sequences=False))
model.add(Dense(vocab_size))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
原因是CuDNNLSTM
层的bias
是LSTM
层的两倍大。这是因为 cuDNN API 的底层实现。您可以将以下等式(从 cuDNN 用户指南中复制)与常用的 LSTM 等式进行比较:
CuDNN 使用了两个偏置项,因此偏置权重的数量增加了一倍。要将其转换回 LSTM
使用的内容,需要对两个偏置项求和。
我已经提交了一个 PR 来进行转换,它已被合并。你可以从GitHub安装最新的Keras,应该可以解决加载权重的问题。
补充一下上面@Yu-Yang 的回答,最新的 Keras 会自动将 CuDMMLSTM
权重转换为 LSTM
,但 不会 为您更改您的 .json 模型架构。
要在 LSTM 上进行 运行 推理,您需要打开 JSON 文件,然后手动将 CuDNNLSTM
的所有实例更改为 LSTM
。然后 运行 model_from_json
加载模型,load_weights
加载权重。
我一开始尝试 运行ning load_weights
而没有手动更改 CuDNNLSTM
模型,但出现了一堆错误。
我已经基于 LSTM 层使用 Keras 开发了一个神经网络模型。为了提高 Paperspace(GPU 云处理基础设施)的速度,我用新的 CuDNNLSTM 切换了 LSTM 层层。然而,这仅适用于支持 GPU cuDNN 的机器。 PS:CuDNNLSTM 仅在 Keras master
上可用,在最新版本中不可用。
所以我生成了权重并将它们以 hdf5
格式保存在云端,我想在我的 MacBook 上本地使用它们。由于 CuDNNLSTM 层不可用,仅针对我的本地安装,我已切换回 LSTM。
阅读这篇文章 tweet about CuDNN from @fchollet 我认为它会工作得很好,只需将权重读回 LSTM 模型即可。
但是,当我尝试导入它们时,Keras 抛出此错误:
Traceback (most recent call last):
{...}
tensorflow.python.framework.errors_impl.InvalidArgumentError: Dimension 0 in both shapes must be equal, but are 2048 and 4096 for 'Assign_2' (op: 'Assign') with input shapes: [2048], [4096].
{...}
ValueError: Dimension 0 in both shapes must be equal, but are 2048 and 4096 for 'Assign_2' (op: 'Assign') with input shapes: [2048], [4096]
用 h5cat 分析 hdf5
文件,我可以看出这两个结构是不同的。
TL;DR
我无法将 CuDNNLSTM 生成的权重加载到 LSTM 模型中。 我做错事了吗?我怎样才能让它们无缝工作?
这是我的模型:
SelectedLSTM = CuDNNLSTM if is_gpu_enabled() else LSTM
# ...
model = Sequential()
model.add(SelectedLSTM(HIDDEN_DIM, return_sequences=True, input_shape=(SEQ_LENGTH, vocab_size)))
model.add(Dropout(0.2))
model.add(SelectedLSTM(HIDDEN_DIM, return_sequences=False))
model.add(Dense(vocab_size))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
原因是CuDNNLSTM
层的bias
是LSTM
层的两倍大。这是因为 cuDNN API 的底层实现。您可以将以下等式(从 cuDNN 用户指南中复制)与常用的 LSTM 等式进行比较:
CuDNN 使用了两个偏置项,因此偏置权重的数量增加了一倍。要将其转换回 LSTM
使用的内容,需要对两个偏置项求和。
我已经提交了一个 PR 来进行转换,它已被合并。你可以从GitHub安装最新的Keras,应该可以解决加载权重的问题。
补充一下上面@Yu-Yang 的回答,最新的 Keras 会自动将 CuDMMLSTM
权重转换为 LSTM
,但 不会 为您更改您的 .json 模型架构。
要在 LSTM 上进行 运行 推理,您需要打开 JSON 文件,然后手动将 CuDNNLSTM
的所有实例更改为 LSTM
。然后 运行 model_from_json
加载模型,load_weights
加载权重。
我一开始尝试 运行ning load_weights
而没有手动更改 CuDNNLSTM
模型,但出现了一堆错误。