【问题标题】:How to define custom loss in Keras with varying values?如何在 Keras 中定义具有不同值的自定义损失?
【发布时间】:2020-03-25 17:31:23
【问题描述】:

我想定义我的损失函数,使其考虑到我的自动编码器的输入和输出之间的 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 是一个形状为 [1194, 312] 的 NumPy 数组,其中 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 也随批量大小而变化?

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    如果我理解正确,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/)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-30
      • 2021-03-16
      • 1970-01-01
      • 2020-05-05
      • 1970-01-01
      • 2020-12-19
      相关资源
      最近更新 更多