【问题标题】:Custom loss function which depends on another neural network in keras自定义损失函数,它依赖于 keras 中的另一个神经网络
【发布时间】:2018-11-28 16:41:12
【问题描述】:

我对 keras 有一个“我该怎么做”的问题:

假设我有第一个神经网络,比如 NNa,它有 4 个输入 (x,y,z,t),已经训练过。 如果我有第二个神经网络,比如 NNb,它的损失函数取决于第一个神经网络。

NNb的自定义损失函数customLossNNb调用NNa的预测有一个固定的网格(x,y,z),只修改最后一个变量t。

在伪python代码中我想训练第二个NN:NNb:

grid=np.mgrid[0:10:1,0:10:1,0:10:1].reshape(3,-1).T

Y[:,0]=time
Y[:,1]=something

def customLossNNb(NNa,grid):
     def diff(y_true,y_pred): 
         for ii in range(y_true.shape[0]):
               currentInput=concatenation of grid and y_true[ii,0]
               toto[ii,:]=NNa.predict(currentInput)
               #some stuff with toto
         return #...
     return diff

然后

NNb.compile(loss=customLossNNb(NNa,K.variable(grid)),optimizer='Adam')
NNb.fit(input,Y)

实际上给我带来麻烦的线路是currentInput=concatenation of grid and y_true[ii,0]

我尝试使用K.variable(grid) 将网格作为张量发送到 customLossNNb。但是我不能在损失函数中定义一个新的张量,比如CurrentY,它的形状为(grid.shape[0],1),填充y[ii,0]当前t),然后连接gridcurrentY 构建currentInput

有什么想法吗?

谢谢

【问题讨论】:

  • 正如我在回答中指出的那样,您不能在损失函数中使用 model.predict(x),因为它不能成为图表的一部分。改用model(x),但是你需要正确地冻结权重。 tensor.shape 属性也不是图表的一部分。要成为图表的一部分,这需要返回张量对象。您可以使用 keras.backend.shape(tensor)。 For 循环也不会成为图表的一部分。一般来说,我认为你需要自己澄清一下图形对象的概念。

标签: python keras


【解决方案1】:

您可以使用 keras 的功能 API 将自定义损失函数包含到图中。本例中的模型可以用作函数,如下所示:

for l in NNa.layers: 
    l.trainable=False
x=Input(size)
y=NNb(x)
z=NNa(y)

Predict 方法不起作用,因为损失函数应该是图形的一部分,并且 predict 方法返回 np.array

【讨论】:

  • 警告:虽然是正确的,但您需要通过使用NNa:newTargets = NNa.predict(oldTargets) 预测它们来更改目标以使其正常工作。
  • 我假设从一开始就有NNa的目标,而NNb没有目标,否则直接使用它们更容易......尽管我可以想象这仍然是合理的情况
  • 您好,感谢您的回答,但似乎我对自己的问题不是很清楚,我在原帖中添加了更多详细信息
【解决方案2】:

首先,使NNa 无法训练。请注意,如果您的模型具有内部模型,您应该递归地执行此操作。

def makeUntrainable(layer):
    layer.trainable = False

    if hasattr(layer, 'layers'):
        for l in layer.layers:
            makeUntrainable(l)

makeUntrainable(NNa)

那么你有两个选择:

  • 将NNa附加到模型的末尾(注意y_truey_pred都将被更改)
    • 然后更改您的目标(使用 NNa 预测)以获得正确的结果,因为您的模型现在需要 NNa 的输出,而不是 NNb。
  • 创建一个在其中使用 NNa 的自定义损失函数,而不更改目标

选项 1 - 附加模型

inputs = NNb.inputs   
outputs = NNa(NNb.outputs) #make sure NNb is outputing 4 tensors to match NNa inputs   
fullModel = Model(inputs,outputs)

#changing the targets:
newY_train = NNa.predict(oldY_train)    

选项 2 - 创建自定义损失

警告:请在训练此配置时测试 NNa 的权重是否真的冻结

from keras.losses import binary_crossentropy

def customLoss(true,pred):
    true = NNa(true)
    pred = NNa(pred)

    #use some of the usual losses or create your own
    binary_crossentropy(true,pred)

NNb.compile(optimizer=anything, loss = customLoss)

【讨论】:

  • 您好,感谢您的回答,但似乎我对自己的问题不是很清楚,我在原帖中添加了更多详细信息
猜你喜欢
  • 2020-08-06
  • 1970-01-01
  • 2020-01-24
  • 2019-05-17
  • 2020-11-19
  • 1970-01-01
  • 2018-07-25
  • 2016-12-05
  • 2018-02-23
相关资源
最近更新 更多