【问题标题】:Save/load a keras model with constants保存/加载带有常量的 keras 模型
【发布时间】:2018-09-19 19:58:29
【问题描述】:

我有一个 Keras 模型,我想在其中为预测添加一个常数。经过一番谷歌搜索,我得到了以下代码,这正是我想要的:

import numpy as np
from keras.layers import Input, Add
from keras.backend import variable
from keras.models import Model, load_model

inputs = Input(shape=(1,))
add_in = Input(tensor=variable([[5]]), name='add')
output = Add()([inputs, add_in])

model = Model([inputs, add_in], output)
model.compile(loss='mse', optimizer='adam')

X = np.array([1,2,3,4,5,6,7,8,9,10])
model.predict(X)

但是,如果我保存并加载此模型,Keras 似乎会丢失常量:

p = 'k_model.hdf5'
model.save(p)
del model
model2 = load_model(p)
model2.predict(X)

返回:

检查模型时出错:您所在的 Numpy 数组列表 传递给您的模型不是模型预期的大小。预计 查看 2 个数组,但得到了以下 1 个数组的列表:

如何在保存/加载 Keras 模型时包含常量?

【问题讨论】:

  • 它总是一个常数吗?例如,模型的所有输入总是 5 吗?为什么不使用 Lambda 层呢?
  • @today 它始终是一个常数。无论输入如何,我都想要一个始终将 5 添加到预测的模型。
  • 我可以采取的另一种方法是向模型添加一个始终为 5 的输入,但这意味着我必须分配一个非常大的 numpy 数组。我上面使用的方法似乎更优雅一些,除了保存/加载问题。

标签: python serialization keras constants


【解决方案1】:

既然你提到它总是一个常数,为它定义一个单独的输入层是没有意义的;特别考虑到它不是您模型的输入。我建议你改用Lambda 层:

import numpy as np
from keras.layers import Input, Lambda
from keras.models import Model, load_model

def add_five(a):
    return a + 5

inputs = Input(shape=(1,))
output = Lambda(add_five)(inputs)

model = Model(inputs, output)
model.compile(loss='mse', optimizer='adam')

X = np.array([1,2,3,4,5,6,7,8,9,10])
model.predict(X)

输出:

array([[ 6.],
       [ 7.],
       [ 8.],
       [ 9.],
       [10.],
       [11.],
       [12.],
       [13.],
       [14.],
       [15.]], dtype=float32)

由于add_five函数已经存储在模型文件中,所以保存并重新加载模型时不会出现问题。

更新:您可以将此扩展到每个输入样本包含多个元素的情况。例如,如果输入形状是(2,),并且您想将每个样本的第一个元素加 5,第二个元素加 10,您可以轻松修改 add_five 函数并重新定义它,如下所示:

def add_constants(a):
    return a + [5, 10]  

# ... the same as above (just change the function name and input shape)

X = np.array([1,2,3,4,5,6,7,8,9,10]).reshape(5, 2)
model.predict(X)

输出:

# X
array([[ 1,  2],
       [ 3,  4],
       [ 5,  6],
       [ 7,  8],
       [ 9, 10]])

# predictions
array([[ 6., 12.],
       [ 8., 14.],
       [10., 16.],
       [12., 18.],
       [14., 20.]], dtype=float32)

【讨论】:

  • 如果我想为每个输入添加不同的值怎么办,例如5到第一个,8到第二个?
  • @Zach 注意你的模型的输入形状是(1,),所以这意味着每个训练样本由一个样本组成。因此没有第二个元素。但是,我已经为我的答案添加了更新。看看它是否回答了您的问题。
  • 这非常简单和优雅。谢谢!
猜你喜欢
  • 2020-08-07
  • 1970-01-01
  • 2019-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2022-12-17
  • 1970-01-01
相关资源
最近更新 更多