我想使用具有张量流的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()