为什么 MLP 只学习不平衡二元分类的偏差?

数据挖掘 分类 阶级失衡
2022-02-09 08:59:05

我刚刚开始在具有以下统计数据的数据集上训练 MLP 模型。请注意,训练集和验证集都是不平衡的(88.4% 的负数)。

注意:不平衡不是由采样引起的,而是因为这是类的自然比例。例如,当我回顾 3 个月的时间时,我发现我吃了 88 个苹果和 12 个橙子;展望未来,在相同的比例下,我可能仍然更喜欢苹果而不是橙子。我在这里可能错了,但我认为我不应该给班级权重或重新采样来平衡这两个班级,因为这是他们的自然比例。

Train data:
    Shape (features): (891473, 122)
    Shape (labels): (891473,)
    # of classes: [(0, 788118), (1, 103355)]
    % of classes: [(0, 0.88406266931247501), (1, 0.11593733068752503)]
Validation data:
    Shape (features): (251141, 122)
    Shape (labels): (251141,)
    # of classes: [(0, 222009), (1, 29132)]
    % of classes: [(0, 0.8840014175303913), (1, 0.1159985824696087)]

我在 ReLU 层之后使用了三个 8 大小的密集层,最后是一个 sigmoid,因为它是二进制分类。

然而,训练过程仅在 2 个 epoch 之后就收敛了,基本上只学习了偏差项,最终预测一切都是负面的。自第 2 个 epoch 到结束(20 个 epoch)以来,混淆矩阵保持不变:

Train confusion matrix:
           P = 0   P = 1 | Total
    L = 0  0.884   0.000 | 0.884
    L = 1  0.116   0.000 | 0.116
    ----------------------------
    Total  1.000   0.000 | 0.884
Validation confusion matrix:
           P = 0   P = 1 | Total
    L = 0  0.884   0.000 | 0.884
    L = 1  0.116   0.000 | 0.116
    ----------------------------
    Total  1.000   0.000 | 0.884

我试图增加密集层的大小(例如从 32、128、512、1024)。他们都产生了相同的结果。

我希望使用 3 x 1024 个神经元的模型足够复杂,可以学习超出单个偏差项的东西。所以我很困惑,因为我做错了什么,使它除了偏见之外没有学到任何东西。

问题:

  1. 模型学习不多的可能原因是什么?
  2. 我应该尝试什么和/或在这一点上我应该寻找什么样的信息来推动这一点?

提前感谢您的时间~!

以下是我的代码片段,用于显示我正在尝试做的事情:

learning_rate = 1e-4
batch_size = 10000
epochs = 5

DENSE_SIZE = 1024

train = (training_features.values, training_labels.values)
validation = (holdout_features.values, holdout_labels.values)
test = (eval_features.values, eval_labels.values)
eval_sets = [
    ('Train', train),
    ('Validation', validation),
    ('Test', test),
]

model = Sequential()
model.add(Dense(DENSE_SIZE, activation='relu', input_shape=train[0].shape[1:]))
model.add(Dense(DENSE_SIZE, activation='relu'))
model.add(Dense(DENSE_SIZE, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

# initiate optimizer
opt = RMSprop(lr=learning_rate)

# Let's train the model
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])

model.fit(
    train[0],
    train[1],
    batch_size=batch_size,
    epochs=epochs,
    validation_data=validation,
    shuffle=True,
    verbose=2,
    callbacks=callbacks,
)

编辑:

撰写本文时的三个答案都表明学习效率低下与不平衡类有关,我应该尝试通过使用类权重或重新采样来平衡类。

虽然我很高兴看到问题是什么的明显一致,但任何人都可以提供更多关于为什么不平衡类即使对于复杂模型也会导致困难的见解?理论上,一个足够复杂的模型至少可以记住所有很少为正的样本,并在训练集上实现高于偏差的准确度。

3个回答

一般来说,有很多方法可以处理类不平衡(例如这里有更多细节)。

特别是在您的情况下,我会尝试使用均匀分布在班级中的训练样本进行训练,或者我会尝试更改损失函数,以考虑不同班级的支持。对于后者,您也可以查看此讨论

尽管您知道数据集是自然平衡的,但您的模型仍会将其视为不平衡数据集。如果以金融欺诈检测为例,欺诈交易的数量总是少于合法翻译的数量,为了处理这种情况,数据科学家必须平衡类别以获得更好的结果。您必须平衡数据集才能从模型中获得更好的结果。

这不是模型复杂性的问题。为了解决类不平衡问题,您应该将类​​权重指定为fit函数的参数,以便相应地缩放交叉熵的 logits。

您可以在stackoverflow中找到更多信息以及如何在fit 此处提供权重的示例。