Tensorflow 在模型定义中使用循环和Lambda层时,Keras load_模型错误

Tensorflow 在模型定义中使用循环和Lambda层时,Keras load_模型错误,tensorflow,keras,Tensorflow,Keras,下面给出了一个最小的示例 from keras.models import Model from keras.layers import Dense, Input, Lambda, Concatenate from keras.models import load_model from keras.optimizers import Adam def build_model_with_loop(): x = Input(shape=(22,), name='inputs')

下面给出了一个最小的示例

from keras.models import Model
from keras.layers import Dense, Input, Lambda, Concatenate
from keras.models import load_model
from keras.optimizers import Adam


def build_model_with_loop():
    x = Input(shape=(22,), name='inputs')
    # 2 branches
    xls = [[] for i in range(2)]
    branch = [[0,10],[10,22]]
    for _i, (b, e) in enumerate(branch):
        xls[_i] = Lambda(lambda x: x[:, b:e])(x)
    c = Concatenate()(xls)
    y = Dense(1)(c)
    model = Model(inputs=x, outputs=y)
    model.compile(loss='mse', optimizer=Adam(1E-3))
    return model

def build_model_without_loop():
    x = Input(shape=(22,), name='inputs')
    # 2 branches
    xls = [[] for i in range(2)]
    xls[0] = Lambda(lambda x: x[:, 0:10])(x)
    xls[1] = Lambda(lambda x: x[:, 10:22])(x)
    c = Concatenate()(xls)
    y = Dense(1)(c)
    model = Model(inputs=x, outputs=y)
    model.compile(loss='mse', optimizer=Adam(1E-3))
    return model     


model = build_model_without_loop()
model.save('model_test.h5')
model = load_model('model_test.h5')
Traceback (most recent call last):
  File "/home/junjiechen/.pyenv/versions/3.6.5/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 1659, in _create_c_op
c_op = c_api.TF_FinishOperation(op_desc)

tensorflow.python.framework.errors_impl.InvalidArgumentError: Dimension 0 in both shapes must be equal, but are 24 and 22. Shapes are [24,1] and [22,1]. for 'Assign' (op: 'Assign') with input shapes: [24,1], [22,1].
ValueError: Dimension 0 in both shapes must be equal, but are 24 and 22. Shapes are [24,1] and [22,1]. for 'Assign' (op: 'Assign') with input shapes: [24,1], [22,1].
这个模型很简单。输入形状为
[batch\u size,22]
,模型将首先将输入分成两个分支,分别为
[batch\u size,10]
[batch\u size,12]
。这里我们使用keras中的
Lambda
层来进行分离。但是,如果我们在模型定义中使用
for
循环,则
加载\模型
无法正确加载保存的模型
模型
。错误消息如下所示

from keras.models import Model
from keras.layers import Dense, Input, Lambda, Concatenate
from keras.models import load_model
from keras.optimizers import Adam


def build_model_with_loop():
    x = Input(shape=(22,), name='inputs')
    # 2 branches
    xls = [[] for i in range(2)]
    branch = [[0,10],[10,22]]
    for _i, (b, e) in enumerate(branch):
        xls[_i] = Lambda(lambda x: x[:, b:e])(x)
    c = Concatenate()(xls)
    y = Dense(1)(c)
    model = Model(inputs=x, outputs=y)
    model.compile(loss='mse', optimizer=Adam(1E-3))
    return model

def build_model_without_loop():
    x = Input(shape=(22,), name='inputs')
    # 2 branches
    xls = [[] for i in range(2)]
    xls[0] = Lambda(lambda x: x[:, 0:10])(x)
    xls[1] = Lambda(lambda x: x[:, 10:22])(x)
    c = Concatenate()(xls)
    y = Dense(1)(c)
    model = Model(inputs=x, outputs=y)
    model.compile(loss='mse', optimizer=Adam(1E-3))
    return model     


model = build_model_without_loop()
model.save('model_test.h5')
model = load_model('model_test.h5')
Traceback (most recent call last):
  File "/home/junjiechen/.pyenv/versions/3.6.5/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 1659, in _create_c_op
c_op = c_api.TF_FinishOperation(op_desc)

tensorflow.python.framework.errors_impl.InvalidArgumentError: Dimension 0 in both shapes must be equal, but are 24 and 22. Shapes are [24,1] and [22,1]. for 'Assign' (op: 'Assign') with input shapes: [24,1], [22,1].
ValueError: Dimension 0 in both shapes must be equal, but are 24 and 22. Shapes are [24,1] and [22,1]. for 'Assign' (op: 'Assign') with input shapes: [24,1], [22,1].
然而,如果我们使用
构建模型而不使用循环
,那么一切都会顺利进行。如何解决此问题并在模型定义中正确使用循环


事实上,问题也可能来自
Lambda
层。如果两个分支具有相同的维度
[batch\u size,11]
,则不会发生错误。

解决方案是在
Lambda
层中使用
参数
选项,以便正确传递相应的参数。事实上,上面显示的问题是由于python的
lambda
函数造成的

def build_model_with_loop():
    x = Input(shape=(22,), name='inputs')
    # 2 branches
    xls = [[] for i in range(2)]
    branch = [[0,10],[10,22]]
    def get_branch(x, beg, end):
        return x[:, beg:end]
    for i, (b, e) in enumerate(branch):
        xls[i] = Lambda(get_branch, arguments={'beg':b, 'end':e})(x)
    c = Concatenate()(xls)
    y = Dense(1)(c)
    model = Model(inputs=x, outputs=y)
    model.compile(loss='mse', optimizer=Adam(1E-3))
    return model
在这里,我们定义
get_分支
函数包装器,并通过
Lambda
层中的
arguments
选项传递
beg
end