假设我有一个这样的模型。 M1和M2是连接模型左右两侧的两层。
The example model: Red lines indicate backprop directions

在训练过程中,我希望 M1 可以学习从 L2_left 激活到 L2_right 激活的映射。类似地,M2 可以学习从 L3_right 激活到 L3_left 激活的映射。
该模型还需要学习两个输入和输出之间的关系。
因此,我应该分别为 M1、M2 和 L3_left 设置三个损失函数。

我可能可以使用:

model.compile(optimizer='rmsprop',
          loss={'M1': 'mean_squared_error',
                'M2': 'mean_squared_error',
                'L3_left': mean_squared_error'})

但是在训练的时候,我们需要提供y_true,例如:
model.fit([input_1,input_2], y_true)

在这种情况下, y_true 是隐藏层激活,而不是来自数据集。
是否可以构建这个模型并使用它的隐藏层激活来训练它?

最佳答案

如果您只有 一个输出 ,那么您必须只有 一个损失函数

如果你想要 三个损失函数 ,你必须有 三个输出 ,当然还有 三个 Y 向量 用于训练。

如果您想在模型中间使用损失函数,则必须从这些层获取输出。

创建模型图:(如果模型已经定义,请参阅本答案的结尾)

#Here, all "SomeLayer(blabla)" could be replaced by a "SomeModel" if necessary
    #Example of using a layer or a model:
        #M1 = SomeLayer(blablabla)(L12)
        #M1 = SomeModel(L12)

from keras.models import Model
from keras.layers import *

inLef = Input((shape1))
inRig = Input((shape2))

L1Lef = SomeLayer(blabla)(inLef)
L2Lef = SomeLayer(blabla)(L1Lef)
M1 = SomeLayer(blablaa)(L2Lef) #this is an output

L1Rig = SomeLayer(balbla)(inRig)

conc2Rig = Concatenate(axis=?)([L1Rig,M1]) #Or Add, or Multiply, however you're joining the models
L2Rig = SomeLayer(nlanlab)(conc2Rig)
L3Rig = SomeLayer(najaljd)(L2Rig)

M2 = SomeLayer(babkaa)(L3Rig) #this is an output

conc3Lef = Concatenate(axis=?)([L2Lef,M2])
L3Lef = SomeLayer(blabla)(conc3Lef) #this is an output

使用三个输出创建模型:

现在您已经准备好图表并且您知道输出是什么,您可以创建模型:
model = Model([inLef,inRig], [M1,M2,L3Lef])
model.compile(loss='mse', optimizer='rmsprop')

如果您希望每个输出有不同的损失,那么您可以创建一个列表:
#example of custom loss function, if necessary
def lossM1(yTrue,yPred):
    return keras.backend.sum(keras.backend.abs(yTrue-yPred))

#compiling with three different loss functions
model.compile(loss = [lossM1, 'mse','binary_crossentropy'], optimizer =??)

但是您也必须拥有三种不同的 yTraining,用于训练:
model.fit([input_1,input_2], [yTrainM1,yTrainM2,y_true], ....)

如果您的模型已经定义并且您不像我那样创建它的图形:

然后,您必须在 yourModel.layers[i] 中找到哪些是 M1 和 M2,因此您创建一个新模型,如下所示:
M1 = yourModel.layers[indexForM1].output
M2 = yourModel.layers[indexForM2].output
newModel = Model([inLef,inRig], [M1,M2,yourModel.output])

如果您希望两个输出相等:

在这种情况下,只需减去 lambda 层中的两个输出,并使该 lambda 层成为模型的输出,期望值 = 0。

使用与之前完全相同的变量,我们将创建两个附加层来减去输出:
diffM1L1Rig = Lambda(lambda x: x[0] - x[1])([L1Rig,M1])
diffM2L2Lef = Lambda(lambda x: x[0] - x[1])([L2Lef,M2])

现在你的模型应该是:
newModel = Model([inLef,inRig],[diffM1L1Rig,diffM2L2lef,L3Lef])

训练将期望这两个差异为零:
yM1 = np.zeros((shapeOfM1Output))
yM2 = np.zeros((shapeOfM2Output))
newModel.fit([input_1,input_2], [yM1,yM2,t_true], ...)

关于keras - 如何使用隐藏层激活来构建损失函数并在 Keras 拟合期间提供 y_true?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43889021/

10-15 12:32