keras – 可以使用Lambda层来操纵输入的数据和形状吗?

我想使用具有张量流的Keras在两个现有网络(模型)A和B中创建一个新网络.新网络的架构是这样的

输入 – > A – > B – >产量

A的输出具有(15,500)的形状,B的输入具有(1000)的形状.我有一个转换方法,它接受形状(15,100)的输入并调用完全不同的网络(C)的预测,并返回形状为(1000)的输出.

我假设我必须引入一个Lambda层,它将使用我的转换方法将A的输出转换为B所需的格式.但是,当我尝试这个时,我得到错误

“TypeError:/不支持的操作数类型/:’Dimension’和’float’_”在转换方法中调用predict.

这是转换方法

def convert(x):
    C = load_model("path/to/the/network/C.h5")
    return C.predict(x)

我不确定这是否是正确的做法,如果是,那么为什么会出现这个错误.如果不是正确的方式,那么,我的方法应该是什么.

Keras版本:2.0.1
Tensorflow版本:1.0.1

谢谢,

最佳答案 我将假设您不是在尝试将C作为新网络的一部分进行训练(我们称之为D).这就是我想象你想要的

 A
 | 
(C) # transform step. a non-trainable keras model
 |
 B
 |
out

请注意,变量名称来自原始答案部分中的示例.

更新,是原始答案中的代码仅使用来自model_1的dense_2图层.

这不是你想要的,所以我去挖掘.而且很漂亮,答案很简单.

>加载C及其重量,
>更新模型的输出,以便我们可以将任意图层设置为输出.
>使用layer.trainable = False将C层设置为不可训练.
>最后,调用变换模型就像使用图层model_1(inp2)一样

以下是原始答案更新中的示例,为了证明C中的权重不可训练我们将打印model_1.summary()

# let `model_1` be C in the diagram above.
from keras.models import Model
from keras.layers import (Lambda, Dense, Input)

inp = Input(shape=(5, ))
lam = Lambda(lambda x: x + 2, name='lamb')(inp)
den = Dense(1, name='dense')(lam) # this is the `model_1` output
model_1 = Model(inp, den)

# suppose we want an intermediate output from model_1
# (the `lam` layer for instance)
# we update the outputs and use that output in model2

model.outputs = [model.output,  model.get_layer(name='lamb').output]
print(model.outputs)

# [<tf.Tensor 'dense_11/BiasAdd:0' shape=(?, 1) dtype=float32>,
# <tf.Tensor 'lamb_9/add:0' shape=(?, 5) dtype=float32>]

# now build D, since we can treat a model like a layer( awesome!) 
# we can just let models A, B in the diagram above be layers 
# (for this exmple) - nothing changes.

# But first set the layers of `model_1` to not be trainable:

print(model_1.summary()) # Trainable params: 6.0 - before
for l in model_1.layers:
    l.trainable = False 
print(model_1.summary()) # Trainable params: 0.0  - after

# ...then D is:

inp2 = Input(shape=(5, ))     # imagine that this layer is model A
transform = model_1(inp2)[1]  # this is (C) the transform step. 
                              # Notice that we pulled out the lambda 
                              # output by using the index into the
                              # `model_1's` outputs.

# carry on as normal
den2 = Dense(1)(transform) # imagine that this is B
model_2 = Model(inp2, den2)
model_2.compile(loss='mse', optimizer='adam')
model_2.summary()

# simulate data
X = np.random.randn(10, 5)
y = np.random.randn(10, 1)

# fit D
model_2.fit(X, y)  # ... it trains!

几点说明:

>我们不打算调用编译,因为我们不需要
配置培训模型.请参阅compile()的文档字符串
或者相当于keras docs
>但是,如果我们使用keras.models.load_model加载模型.
该模型已编译,但它不应该有任何影响,因为我们是
打算使用layer.trainable = False.请参阅save()的doc字符串

原始答案

而不是使用数组返回预测,抓取输出C的最后一层.

def convert(x):
    # there is not need to load C in the lambda layer.
    # load it somewhere outside of the training op.
    # assuming you have C loaded...
    return C.get_layer('dense_2')(x)

以下是此方法的一个简单示例:请注意,您必须进行此操作
确保图层形状兼容.

你可以想象这是模式C.

from keras.models import Model
from keras.layers import (Lambda, Dense, Input)

inp = Input(shape=(5,))
lam = Lambda(lambda x: x + 2, name='lamb')(inp)
den = Dense(1, name='dense')(lam) # this is the `model_` output
model_1 = Model(inp, den)
model_1.compile(loss='mse', optimizer='adam')

我们要抓住lam层的输出
并将其用作下面D中的转换步骤:

inp2 = Input(shape=(5, ))
# grab the 'dense' layer from `model_1` 
sums = Lambda(lambda x: model_1.get_layer(name='dense')(x))(inp2)
den2 = Dense(1)(sums)
model_2 = Model(inp2, sums)
model_2.compile(loss='mse', optimizer='adam')
model_2.summary()
点赞