Keras Lambda层可以用来处理输入的数据和形状吗?

Keras Lambda层可以用来处理输入的数据和形状吗?,keras,Keras,我想用Keras和tensorflow从两个现有网络(模型)a和B中创建一个新网络。新网络的架构是这样的 输入->A->B->输出 A的输出形状为(15500),B的输入形状为(1000)。我有一个转换方法,它接受shape(15100)的输入,调用一个完全不同的网络(C)的predict,然后返回shape(1000)的输出 我假设我必须引入一个Lambda层,它将使用我的转换方法将a的输出转换为B所需的格式。但是,当我尝试这样做时,我得到了一个错误 TypeError:在转换方法中调用pre

我想用Keras和tensorflow从两个现有网络(模型)a和B中创建一个新网络。新网络的架构是这样的

输入->A->B->输出

A的输出形状为(15500),B的输入形状为(1000)。我有一个转换方法,它接受shape(15100)的输入,调用一个完全不同的网络(C)的predict,然后返回shape(1000)的输出

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

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

这是转换方法

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
注:变量名称来自原始答案部分的示例

更新,是的,原始答案中的代码仅使用
模型1
中的
密集\u 2

这不是你想要的,所以我去挖了。答案很简单

  • 荷载C及其重量
  • 更新模型的输出,以便我们可以将任意层设置为输出
  • 使用
    layer.trainable=False
    将C的层设置为不可训练
  • 最后,像调用层
    model_1(inp2)
下面是更新的原始答案中的示例,为了证明C中的权重不可训练,我们将打印
model_1.summary()

下面是这种方法的一个快速示例:请注意,您必须 确保图层形状兼容

你可以想象这是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()

不,如果C是一个可训练的网络,那么转换方法将不起作用。我们需要更多细节,C的架构是什么?@PutonSpectales我有一个带有RNN层的自动编码器。它的架构是(输入->退出->LSTM->密集->密集->重复向量->LSTM)。C具有前5层,用于从编码器层获取输出。也就是说,C=Model(输入,Model.get_layer('densite_2').output)好的,那么你有3个网络A,B,C,你的目标是训练一个网络D:input->A->B->output。但是,在训练D的同时,您还希望将C的预测(输入)作为网络转换的一部分。我说得对吗?你说得对!在转换步骤中,我想要模型C的子集(前几层)的输出,而不仅仅是第n层。也就是说,如果经过训练的网络C有层C1->C2->C3->C4->C5->C6->C7,我想在我的D中使用子模型(C1->C2->C3->C4-C5)的输出。你上面的例子,在D网络中,你只需要“密集”层,在我想,我们需要考虑网络之前的所有层次,只是纠正我以前的赞扬中的最后一句话。在上面的例子中,在D网络中,你只需要使用“稠密”层,因为我认为我们需要在“致密”层之前考虑所有的层,我认为你原来的答案会有点改变。D中的层“sums=Lambda(Lambda x:model_1.get_layer(name='densite')(x))(inp2)”可以替换为“sums=Lambda(Lambda x:intermediate_model(x))(inp2)”,其中中间层是模型(C.input,C.get_layer('densite')。output)。我假设lambda层在默认情况下是不可训练的。但是,不确定。我将把可训练标志标记为false,然后再试一次。@Fasil那么新的答案对你不起作用了?你遇到了什么问题?我还没有尝试新的答案。我尝试了你最初的建议,只是做了一些我在上一篇文章中提到的小改动。培训正在进行中。一旦我完成了训练,我一定会尝试新的答案并将结果发布在这里。非常感谢你的回答。
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')
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()