如何在Keras中定义具有不同值的自定义损失?

时间:2020-03-25 08:36:45

标签: python tensorflow keras

我想定义损失函数,以便它考虑自动编码器的输入和输出之间的MSE,以及代码与其调用S的真实值之间的MSE。

我的AE定义如下:

input_fts = Input(shape=(self.input_length,), name='ae_input')

encoded = Dense(1826, activation='relu', name='e_dense1')(input_fts)
encoded = Dense(932, activation='relu', name='e_dense2')(encoded)
encoded = Dense(428, activation='relu', name='e_dense3')(encoded)

encoded = Dropout(0.1)(encoded)
code = Dense(self.encoding_length, activation='relu', name='code')(encoded)

decoded = Dense(428, activation='relu', name='d_dense4')(code)
decoded = Dense(932, activation='relu', name='d_dense5')(decoded)
decoded = Dense(1826, activation='relu', name='d_dense6')(decoded)
output_fts = Dense(self.output_length, activation='relu', name='ae_output')(decoded)

ae = Model(inputs=input_fts, outputs=output_fts)
ae.compile(optimizer='adam', loss=ModelFactory.custom_loss(code, self.S, self.lambda_), metrics=['mae', 'acc'])

我的自定义损失为:

@staticmethod
def custom_loss(layer, S, lambda_):
    def loss(y_true, y_pred):
        return K.mean(K.square(y_pred - y_true), axis=-1) + lambda_ * K.mean(K.square(layer - S[0, :]), axis=-1)

    return loss

这有效,但不是我想要的。我希望根据当时正在评估的示例来选择S中的示例,因此S [0,:]将为S [i,:],其中“ i”是示例的索引。

变量“ layer”是形状的张量[None,312]。变量S是NumPy形状为数组的[1194,312],其中1194是我在训练集中拥有的示例数。我的猜测是我也必须将S转换为某种类型的张量。所以我尝试了:

self.S = K.variable(S)

并将custom_loss更改为:

... lambda_ * K.mean(K.square(layer - S), axis=-1)

现在的问题是我的批次和S之间的形状不匹配:

tensorflow.python.framework.errors_impl.InvalidArgumentError:  Incompatible shapes: [128] vs. [1194]

AE培训配置为:

self.model.fit(x_train, x_train, epochs=nepochs, batch_size=128, shuffle=True, verbose=1,
                                      validation_split=0.2, callbacks=[classification])

如何使S也随批次大小变化?

1 个答案:

答案 0 :(得分:0)

如果我理解正确,S本质上只是模型的另一个输入。在这种情况下,您可以为S添加第二个输入层,并在训练期间将S传递给模型。这将类似于:

input_fts = Input(shape=(self.input_length,), name='ae_input')
S_in = Input(shape=(312,), name='s_input')

encoded = Dense(1826, activation='relu', name='e_dense1')(input_fts)
encoded = Dense(932, activation='relu', name='e_dense2')(encoded)
encoded = Dense(428, activation='relu', name='e_dense3')(encoded)

encoded = Dropout(0.1)(encoded)
code = Dense(self.encoding_length, activation='relu', name='code')(encoded)

decoded = Dense(428, activation='relu', name='d_dense4')(code)
decoded = Dense(932, activation='relu', name='d_dense5')(decoded)
decoded = Dense(1826, activation='relu', name='d_dense6')(decoded)
output_fts = Dense(self.output_length, activation='relu', name='ae_output')(decoded)

ae = Model(inputs=[input_fts, S_in], outputs=output_fts)

ae.add_loss(self.lambda_ * K.mean(K.square(S_in-code)))
ae.add_loss(K.mean(K.square(input_fts - output_fts)))

ae.compile(optimizer='adam')

然后,您使用列表输入正常输入和S来进行预测(请参见https://keras.io/getting-started/functional-api-guide/)。