我正在研究基于Keras / TensorFlow的神经网络。我想做一些不同的事情。
通常,网络的输出层产生输出张量(即数字列表)。然后使用诸如均方误差的损失函数将这些数字直接与训练数据(标签)的目标列表进行比较。
但是,我希望网络的输出层是一个用作功能参数的数字列表。该函数对这些参数进行操作以生成新的数字列表。然后,损失函数成为函数输出和标签之间的MSE(而不是通常情况下,输出层和标签之间的MSE)。
据我所知,我需要编写一个Keras自定义丢失函数,该函数根据输出图层值计算目标函数的值,然后计算并返回目标函数输出和标签之间的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后端,知道如何获得输出张量的各个元素。如何解决此张量中的第0,第1,第2等元素,以便我可以使用它们来计算函数值?我知道如何在整个张量上执行操作,但我不明白如何处理单个张量元素。
我希望我已经足够清楚地解释了这个问题。
感谢您的帮助!
答案 0 :(得分:3)
由于预测结果和标签必须具有相同的形状,我们应该创建一个包含所需功能的整个模型(不将该功能留给损失函数)。
稍后我们可以获取前一层的输出,这将是所需的参数。
因此,假设您已准备好您的模型,直到输出参数的图层(最可能为Dense(4)
,这将为每个输入样本输出4个参数 )
让我们在它之后添加两个lambda图层。
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行都将重复。