类权重会降低多标签分类性能

数据挖掘 机器学习 神经网络 喀拉斯 多标签分类
2021-09-25 10:57:41

当我通过 keras 神经网络进行多标签分类问题时,我注意到了一些奇怪的事情。我的数据集由具有 12 个特征和 25 个可能标签的不平衡数据组成。当我在没有类权重的情况下实例化我的模型时,我得到了 97% 的精度,13% 的召回率,14% 的子集精度,使用微平均的 f1 分数为 23%。当我应用班级权重时,这些分数会显着降低到以下水平。

('Accuracy', 0.1757093081134893)
('Precision:', 0.19632925472747498)
('Recall', 0.1637291280148423)
F1 -score 0.178553363682

此外,我使用从上一篇文章中复制和修改的以下代码计算权重:

def class_out(s):
      y_classes = s#.idxmax(1, skipna=False)

      # Instantiate the label encoder
      le = LabelEncoder()

      # Fit the label encoder to our label series
      le.fit(list(y_classes))

      # Create integer based labels Series
      y_integers = le.transform(list(y_classes))

      #print y_integers
      # Create dict of labels : integer representation
      labels_and_integers = dict(zip(y_classes, y_integers))

      print labels_and_integers
      class_weights = compute_class_weight('balanced', np.unique(y_integers), y_integers)
      sample_weights = compute_sample_weight('balanced', y_integers)

      class_weights_dict = dict(zip(le.transform(list(le.classes_)), class_weights))
      class_sweights_dict = dict(zip(le.transform(list(le.classes_)), sample_weights))


      print class_weights_dict

      return class_weights_dict

另请参阅模型示例:

batch_size = 100

weights = class_out(df_all['tag'])

model = Sequential()
model.add(Dense(10, activation="relu", input_shape=(12,)))

#model.add(Dense(10, activation='relu'))

#model.add(Dense(8, activation='relu'))
#model.add(Dropout(0.50))
model.add(Dense(25, activation="sigmoid"))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy',precision,mcor,recall, f1])

model.fit(X_train, Y_train, batch_size=batch_size, epochs=15,class_weight=weights,
      verbose=1,validation_data=(test, target_test))

是否有理由相信模型性能在没有类权重的情况下是最好的?

2个回答

添加类权重但不改变衡量性能的方式通常会降低整体性能,因为它旨在允许增加低权重类的损失。

我还建议您权衡您的准确性度量。这在准确性/精度等方面有点棘手,因此可以计算加权对数损失并将其与未加权模型的未加权对数损失进行比较。

基本上它归结为一个问题:你对一个整体表现更差但在你的高权重类上表现更好的模型感到满意吗?

它还可能取决于数据的不平衡程度。如果一个类有 97% 的实例,那么模型将始终想要预测该类。仔细查看模型的预测:

pred_class = model.predict_classes(X_test)
pred = model.predict(X_test)

因此,如果预测始终是同一类,那么您就有问题了。

另外,我注意到您上面的代码中有一些奇怪的选择。编译模型时更改loss='binary_crossentropy'loss='categorical_crossentropy'多类分类。出于完全相同的原因,我也会使用 softmax 而不是 sigmoid。