如何基于损失精度和召回率确定过拟合模型

时间:2018-10-16 08:42:42

标签: python tensorflow machine-learning keras

我已经用Keras编写了一个LSTM网络(以下代码):

    df = pd.read_csv("../data/training_data.csv")

    # Group by and pivot the data
    group_index = df.groupby('group').cumcount()
    data = (df.set_index(['group', group_index])
            .unstack(fill_value=0).stack())

    # getting np array of the data and labeling
    # on the label group we take the first label because it is the same for all
    target = np.array(data['label'].groupby(level=0).apply(lambda x: [x.values[0]]).tolist())
    data = data.loc[:, data.columns != 'label']
    data = np.array(data.groupby(level=0).apply(lambda x: x.values.tolist()).tolist())

    # shuffel the training set
    data, target = shuffle(data, target)

    # spilt data to train and test
    x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=4)

    # ADAM Optimizer with learning rate decay
    opt = optimizers.Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0001)

    # build the model
    model = Sequential()

    num_features = data.shape[2]
    num_samples = data.shape[1]

    model.add(LSTM(8, batch_input_shape=(None, num_samples, num_features), return_sequences=True, activation='sigmoid'))
    model.add(LeakyReLU(alpha=.001))
    model.add(Dropout(0.2))
    model.add(LSTM(4, return_sequences=True, activation='sigmoid'))
    model.add(LeakyReLU(alpha=.001))
    model.add(Flatten())
    model.add(Dense(1, activation='sigmoid'))

    model.compile(loss='binary_crossentropy', optimizer=opt,
                  metrics=['accuracy', keras_metrics.precision(), keras_metrics.recall(),f1])

    model.summary()


    # Training, getting the results history for plotting
    history = model.fit(x_train, y_train, epochs=3000, validation_data=(x_test, y_test))

受监控的指标包括损失,准确性,准确性,召回率和f1得分。

我注意到验证损失指标开始攀升约300个纪元,因此我认为过度拟合!,但是召回率仍在攀升,而精度则略有提高。


enter image description here enter image description here enter image description here


那是为什么?我的模特过拟合吗?

3 个答案:

答案 0 :(得分:4)

  

验证损失指标开始攀升约300个纪元(...),召回率仍在攀升,并且精度有所提高。 (...)为什么?

精确度和召回率是衡量分类器根据预测的类标签执行情况的方式。另一方面,模型损失是cross entropy(分类概率误差)的度量:

![![![enter image description here

其中

y = predicted label
p = probability of predicted label

例如,对于一个不同的时期,模型的(softmax)输出可能看起来像这样

# epoch 300
y = [0.1, 0.9] => argmax(y) => 1 (class label 1)
loss = -(1 * log(0.9)) = 0.10

# epoch 500
y = [0.4, 0.6] => argmax(y) => 1 (class label 1)
loss = -(1 * log(0.6)) = 0.51

在两种情况下,精度和召回率指标均保持不变(类别标签仍可正确预测),但是模型损失有所增加。一般而言,该模型对其预测已经“不确定”,但仍然正确。

请注意,模型中的损失是针对所有观察结果而计算的,而不仅仅是单个观察结果。为了简化我限制讨论。通过将所有观测值的损失取平均值,将损失公式简单地扩展为n> 1个观测值。

  

我的模型过拟合吗?

为了确定这一点,您必须比较训练损失和验证损失。您不能仅凭验证损失来判断。如果训练损失减少而验证损失增加,则表明模型过度拟合。

答案 1 :(得分:2)

实际上,如果验证损失再次开始增加,那么您可能希望尽早停止。这是一种“标准”方法,称为“提前停止”(https://en.wikipedia.org/wiki/Early_stopping)。显然,如果验证和数据的损失在增加,则该模型的工作可能不尽如人意,那就是过度拟合。

精确度和召回率还不够,如果您的模型给出的是更多阳性结果,而阴性结果较少(例如9个阳性结果表示1个阴性结果),则准确度和召回率会增加。这样,这些比率似乎可以得到改善,但这仅仅是因为您的真实负面因素更少。

将这两个部分放在一起可以帮助您了解此处发生的情况。好的答案可能仍然是好的答案,但是质量较低(单个样本的损失平均增加,但仍然使好的答案保持良好),并且可能会从错误的答案变为带有偏差的正确答案(真否定)被转化为误报)。

答案 2 :(得分:1)

正如@Matthieu提到的,仅看一类的精度和召回率可能会产生偏差。也许我们也必须考虑其他班级的表现。

在二元分类的情况下,更好的度量可能是一致性(roc的auc)。一致性衡量模型对基于类的可能性对数据点进行排序的良好性。

另一种选择是宏/微精度/调用,以获取模型性能的完整图片。