Keras神经网络输出函数参数/如何构造损失函数?

Keras neural network outputting function parameters / how to construct loss function?

我正在研究基于 Keras/TensorFlow 的神经网络。我正在尝试做一些不同的事情。

通常情况下,网络的输出层会产生一个输出张量(即数字列表)。然后使用均方误差等损失函数将这些数字直接与目标训练数据列表(标签)进行比较。

但是,我希望网络的输出层是一个数字列表,用作函数参数。该函数对这些参数进行操作以生成新的数字列表。然后损失函数变成函数输出和标签之间的 MSE(而不是通常情况下输出层和标签之间的 MSE)。

我知道我需要编写一个 Keras 自定义损失函数,它根据输出层值计算目标函数的值,然后计算并 returns 目标函数输出和标签之间的 MSE。我还意识到所有这些都需要在 TensorFlow 图中完成,并且目标函数需要是可微的,以便可以计算梯度。我相信我已经足够了解这一切了。

这是我无法理解的。假设输出层有四个神经元——称它们为 a、b、c、d。它们中的每一个都是目标函数 F(a, b, c, d) 的单独参数。假设我将 F(a, b, c, d) 迭代 20 次并获得一组 20 个值。即 F(a, b, c, d, 1); F(a, b, c, d, 2);等。然后我只想取这20个值和相应标签张量中的20个值之间的MSE。那就是损失函数。

我只是不太了解 Keras/Tensorflow 后端,不知道如何获取输出张量的各个元素。如何处理此张量中的第零个、第一个、第二个等元素,以便我可以使用它们来计算函数值?我知道如何对整个张量执行操作,但我不明白如何处理单个张量元素。

我希望我已经足够清楚地解释了这个问题。

感谢您的帮助!

由于预测结果和标签必须具有相同的形状,我们应该创建一个完整的模型,包含你想要的函数(而不是将函数留给损失函数)。

稍后我们可以获取上一层的输出,这将是所需的参数。

因此,假设您已经准备好模型到输出参数的层(A Dense(4) 最有可能,它将为每个输入样本输出 4 个参数 ).

让我们在它之后添加两个 lambda 层。

  • 一个用于输出 4 个独立于样本的唯一参数,因为您稍后会想要检索它们
  • 一个是实际函数a*sin(bx + c) + d

所以:

#add them to your model the usual way you do
model.add(Lambda(getParameters,output_shape=(4,),name='paramLayer'))
model.add(Lambda(yourFunction,output_shape=(1,),name='valueLayer'))

其中:

import keras.backend as K

def getParameters(x):

    #since x comes in as a batch with shape (20,4) -- (or any other batch size different from 20)

    #let's condense X in one sample only, because we want only 4 elements, not 20*4 elements
    xCondensed = K.mean(x,axis=0,keepdims=True)
        #I'm using keepdims because we will need that x end up with the same number of samples for compatibility purposes (keras rules)

    #let's expand x again (for compatibility purposes), now repeating the 4 values 20 (or more) times
    return K.ones_like(x) * xCondensed



def yourFunction(x):


    #now x has 4 parameters (assuming you had a Dense(4) before these lambda layers)
    a = x[:,0]
    b = x[:,1]
    c = x[:,2]
    d = x[:,3]

    #creating the 20 (or more) iterations
    ones = K.ones_like(x[:,0])
    iterationsStartingAt1= K.cumsum(ones)
    iterationsStartingAt0= iterationsStartingAt1 - 1
    iterations = #choose one of the above


    return (a * K.sin((b*iterations) + c)) + d

现在您可以训练这个传递标签的模型了。

当你想要检索四个参数时,你需要另一个模型,它结束得更早:

from keras.models import Model

paramModel = Model(model.inputs,model.get_layer('paramLayer').output)
params = paramModel.predict(testOrTrainData)

结果的形状将类似于 (20,4),但会重复所有 20 行。