在 Keras 序列模型中使用哪种损失函数

Which loss function to use in Keras Sequential Model

我正在使用 Keras 顺序模型,预测输出的形状为 (1, 5)(5 个特征)。

我有一个准确度指标定义如下:

For N predictions, the accuracy of the model will be the percentage of predicted samples such that: for each prediction and its respective true labels, all of the features are with no more than 10 difference.

例如,如果 y_i = [1, 2, 3, 4, 5]ypred_i = [1, 2, 3, 4, 16] 不匹配,因为最后一个特征有差异 11。如果 y_i = [1, 2, 3, 4, 5]ypred_i = [10, 8, 0, 5, 7] 匹配,因为所有特征与其各自的真实特征相差不超过10。

我想知道在我的 Keras 序列模型中使用哪个损失函数可以最大程度地提高解释的准确性。我应该定义一个自定义损失函数,它应该是什么样子,或者我应该如何进行?

我的代码是:

class NeuralNetMulti(Regressor):
    def __init__(self):
        self.name = 'keras-sequential'
        self.model = Sequential()
        # self.earlystopping = callbacks.EarlyStopping(monitor="mae",
        #                                              mode="min", patience=5,
        #                                              restore_best_weights=True)

    def fit(self, X, y):
        print('Fitting into the neural net...')
        n_inputs = X.shape[1]
        n_outputs = y.shape[1]
        self.model.add(Dense(400, input_dim=n_inputs, kernel_initializer='he_uniform', activation='relu'))
        # self.model.add(Dense(20, activation='relu'))
        self.model.add(Dense(200, activation='relu'))
        # self.model.add(Dense(10, activation='relu'))
        self.model.add(Dense(n_outputs))
        self.model.summary()
        self.model.compile(loss='mae', optimizer='adam', metrics=['mse', 'mae', 'accuracy'])
        history = self.model.fit(X, y, verbose=1, epochs=200, validation_split=0.1)
        # self.model.fit(X, y, verbose=1, epochs=1000, callbacks=[self.earlystopping])
        print('Fitting completed!')

    def predict(self, X):
        print('Predicting...')
        predictions = self.model.predict(X, verbose=1)
        print('Predicted!')
        return predictions

我对损失函数的建议:

def N_distance(y_true, y_pred):
    score = 0
    vals = abs(y_true - y_pred)
    if all(a <= 10 for a in vals):
            return 0
return 1

它returns:

首先,您的损失需要是可微分的,以便可以计算相对于权重的梯度。然后可以使用梯度来优化权重,这是基于梯度的优化算法(如梯度下降)的重点。如果你写自己的损失,这是你需要记住的第一件事。这就是为什么你的损失不起作用。你需要重新考虑你的损失或整个问题。

接下来,别忘了,你需要在你的损失中使用keras或tensorflow函数,因此使用的函数定义了梯度并且可以应用链式法则。仅使用 abs() 不是一个好主意。这个问题可能会为您指明正确的方向 https://ai.stackexchange.com/questions/26426/why-is-tf-abs-non-differentiable-in-tensorflow.

此外,根据你的问题和评论,我看到预期的输出应该在 0 到 100 之间。在这种情况下,我会尝试缩放网络的输出和标签,使它们始终位于该范围内。有多种方法可以解决这个问题。将您的标签除以 100,然后在输出上使用 sigmoid 激活和/或检查例如这个答案 How to restrict output of a neural net to a specific range?.

那你就可以开始考虑怎么写你的损失了。根据您的描述,不清楚在这种情况下会发生什么:y_i = [1, 2, 3, 4, 100]pred = [1, 2, 3, 4, 110]。 110 的值在理论上是不可能的,但它仍然可以接受吗?

反正你就用mae或者mse亏本就行了。您的网络会尝试完美拟合,然后您可以使用您的特殊不可微分函数作为衡量您的网络根据您的规则训练得如何的指标。

一个明确的例子:

  • 你的网络的最后一层需要像这样指定一个激活 self.model.add(Dense(n_outputs, activation='sigmoid')) 它将所有网络输出缩放到从 0 到 1 的区间。
  • 由于您的标签是在 0 - 100 的区间内定义的,因此您只需将标签划分为也在 0 到 1 的区间内,然后再通过 y \= 100 在网络中使用它们。
  • 然后你可以使用 maemse 作为损失,你的特殊功能只是作为一个指标。 self.model.compile(loss='mae', optimizer='adam', metrics=[custom_metric])

custom_metric 函数可以如下所示:

def custom_metric(y_true, y_pred):
    valid_distance = 0.1
    valid = tf.abs(y_true - y_pred) <= valid_distance
    return tf.reduce_mean(tf.cast(tf.reduce_all(valid, axis=1), tf.float32))