多类分类问题中的不平衡类别

10
我尝试使用TensorFlow的DNNClassifier来解决4种不同类别的多类(softmax)分类问题。我的数据集分布不均,如下所示:
  • Class 0: 14.8%
  • Class 1: 35.2%
  • Class 2: 27.8%
  • Class 3: 22.2%
我该如何为DNNClassifier的 `weight_column` 为每个类别指定权重?我知道如何编写代码,但想知道应该为每个类别赋予什么值。
3个回答

5

在不平衡的分类问题中,有许多构建权重的选择。其中最常见的一种是直接使用训练中的类别计数来估算样本权重。这个选项可以通过 sklearn 轻松计算。'balanced' 模式使用 y 的值自动调整权重,成反比于类别频率。

下面的示例中,我们尝试将 compute_sample_weight 方法融入到 DNNClassifier 的拟合中。作为标签分布,我使用了与问题中相同的分布。

import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.utils.class_weight import compute_sample_weight

train_size = 1000
test_size = 200
columns = 30

## create train data
y_train = np.random.choice([0,1,2,3], train_size, p=[0.15, 0.35, 0.28, 0.22])
x_train = pd.DataFrame(np.random.uniform(0,1, (train_size,columns)).astype('float32'))
x_train.columns = [str(i) for i in range(columns)]

## create train weights
weight = compute_sample_weight(class_weight='balanced', y=y_train)
x_train['weight'] = weight.astype('float32')

## create test data
y_test = np.random.choice([0,1,2,3], test_size, p=[0.15, 0.35, 0.28, 0.22])
x_test = pd.DataFrame(np.random.uniform(0,1, (test_size,columns)).astype('float32'))
x_test.columns = [str(i) for i in range(columns)]

## create test weights
x_test['weight'] = np.ones(len(y_test)).astype('float32') ## set them all to 1

## utility functions to pass data to DNNClassifier
def train_input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(x_train), y_train))
    dataset = dataset.shuffle(1000).repeat().batch(10)
    return dataset

def eval_input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(x_test), y_test))
    return dataset.shuffle(1000).repeat().batch(10)

## define DNNClassifier
classifier = tf.estimator.DNNClassifier(
    feature_columns=[tf.feature_column.numeric_column(str(i), shape=[1]) for i in range(columns)],
    weight_column = tf.feature_column.numeric_column('weight'),
    hidden_units=[10],
    n_classes=4,
)

## train DNNClassifier
classifier.train(input_fn=lambda: train_input_fn(), steps=100)

## make evaluation
eval_results = classifier.evaluate(input_fn=eval_input_fn, steps=1)

考虑到我们的权重是基于目标函数构建的,因此在测试数据中我们必须将它们设置为1,因为标签是未知的。


3
我强烈建议您使用欠采样(如果有足够的数据)或SMOTE过采样。在imblearn库中,您可以在此处找到它 here 作为一名经验丰富的ML工程师,我可以说,“加权”方法都不会对您有所帮助。XGBoost有一个称为scale_pos_weight的参数,或者您可以使用class_weight="balanced"的逻辑回归,但它们非常微不足道,因为问题不在于估算器,而在于您的数据。因此,我强烈建议您优化您的数据,而不是分配权重。

1

您可以尝试以下公式来平衡所有课程:

weight_for_class_X = total_samples_size / size_of_class_X / num_classes

例如:

for example:

num_CLASS_0: 10000   
num_CLASS_1: 1000
num_CLASS_2: 100

wgt_for_0 = 11100 / 10000 / 3 = 0.37  
wgt_for_1 = 11100 / 1000 / 3 = 3.7
wgt_for_2 = 11100 / 100 / 3 = 37

# so after one epoch training the total weights of each class will be:
total_wgt_of_0 = 0.37 * 10000 = 3700
total_wgt_of_1 = 3.7 * 1000 = 3700
total_wgt_of_2 = 37 * 100 = 3700

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接