我正在尝试将TensorFlow的DNNClassifier用于我的带有4个不同类的多类(softmax)分类问题。我的数据集不平衡,分布如下:
0级:14.8% 第1类:35.2% 第2类:27.8% 第3类:22.2%
如何为每个类分配DNNClassifier的weight_column的权重?我知道如何编写代码,但我想知道应该为每个类提供什么值。
答案 0 :(得分:4)
对于不平衡分类问题,有多种方法可以构建权重。最常见的方法之一是直接使用训练中的班级计数来估计样本权重。 sklearn可以轻松计算此选项。 “平衡”模式使用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。
答案 1 :(得分:3)
我强烈建议您使用欠采样(如果您有足够的数据这样做)或对SMOTE进行过采样,请在imblearn库中找到它here
作为一名经验丰富的ML工程师,我可以说“加权”方法都不适合您,XGBoost具有一个名为scale_pos_weight的参数,或者您可以将logistic回归与class_weight =“ balanced”结合使用,但它们相当无关紧要,因为问题与估算器无关,而与您的数据有关。因此,我强烈建议您使用数据而不是分配权重。
答案 2 :(得分:0)
您可以尝试使用以下公式来平衡所有类:
weight_for_class_X = total_samples_size / size_of_class_X / num_classes
例如:
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