【发布时间】:2021-07-21 23:59:48
【问题描述】:
我正在研究具有极端类别不平衡的数据集的二元分类问题。为了帮助模型学习少数类的信号,我对多数类进行了下采样,使得训练集有 20% 的少数类和 80% 的多数类。
现在还有另一个参数 "scale_pos_weight" 。不知道下采样后如何设置这个参数。
我应该根据实际的类比来设置,还是应该在下采样后使用类比?
【问题讨论】:
标签: python machine-learning xgboost
我正在研究具有极端类别不平衡的数据集的二元分类问题。为了帮助模型学习少数类的信号,我对多数类进行了下采样,使得训练集有 20% 的少数类和 80% 的多数类。
现在还有另一个参数 "scale_pos_weight" 。不知道下采样后如何设置这个参数。
我应该根据实际的类比来设置,还是应该在下采样后使用类比?
【问题讨论】:
标签: python machine-learning xgboost
由于您已经对数据进行了下采样,因此应根据您的下采样数据设置 scale_pos_weight 参数。使用以下方法计算值:
scale_pos_weight = count(negative examples)/count(Positive examples)
在你的情况下,
scale_pos_weight = 80/20 = 4
您还可以使用hyperparameter optimization 自动找到最佳参数集。
【讨论】:
在计算损失函数时使用类权重,以防止模型对主类赋予重要性。如果一个类在数据集上占主导地位,那么模型将倾向于更好地学习该类,因为损失主要取决于模型在该主导类上的表现。
让我们考虑一个极端情况,即数据集包含 99% 的正样本。如果模型只为每个样本预测 1,那么它的准确率将达到 99%。 类权重背后的理念是您希望每个样本对损失的贡献均等。因此,您应该根据您的训练集计算此比率,因为损失是根据您的训练集计算的。您的模型不知道您丢弃的样本。
如果你做出正确的预测,损失为0,否则不是。谈到你的情况,为了确保每个样本对损失的贡献相等,对少数类的错误预测应该比对多数类的错误预测多 4 倍的惩罚。这样,模型就不能忽略某个类或偏向多数类。
通常最好将类权重设置为与该特定类的样本数量成反比。因此,在您的情况下,这将是 4。但是,在实践中,您可能应该尝试几个不同的值来找到最佳权重。
另一个重要方面是这些样本在野外的比例。您说您进行了下采样,如果与您的训练数据集相比,野外的类比率不同,那么当您部署模型或在未见过的样本上测试它时,您可能会观察到更差的分数。这就是为什么理想情况下,您还应该使用您的领域知识以现实的比率分割您的验证集和测试集
【讨论】:
好问题。 XGBoost 有 been known to do well for imbalanced datasets,并包含许多超参数来帮助我们实现目标。
对于scale_pos_weight 功能,XGBoost documentation suggests:
sum(negative instances) / sum(positive instances)
对于极度不平衡的数据集,有人建议使用上述公式的sqrt。
对于权重,通常通过 XGBoost 中的sample_weight 参数,您可以通过sklearn utility 学习class_weights,如here 所述。
两者的区别是explored here,但总结起来:
sample_weight 参数允许您指定不同的权重 对于每个训练示例。 scale_pos_weight 参数可让您 为整个示例类别(“正”类别)提供权重。
在代码中,您可以在下面看到这些实现,包括平方根。请注意,我必须使用合成数据,因为问题中没有提供任何数据。
# General imports
import pandas as pd
from sklearn import datasets
from collections import Counter
# Generate datasets
from sklearn.datasets import make_classification
from imblearn.datasets import make_imbalance
# Train, test, splits and gridsearch optimization
from sklearn.model_selection import train_test_split, GridSearchCV
# Class weights
from sklearn.utils import class_weight
# Performance
from sklearn.metrics import classification_report
# Modeling
import xgboost
import warnings
warnings.filterwarnings('ignore')
# Generate synthetic data
X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, class_sep=2.0, n_classes=2, n_clusters_per_class=5, hypercube=True, random_state=30)
scaled_X, scaled_y = make_imbalance(X, y, sampling_strategy={0:200}, random_state=8)
data = pd.DataFrame(data=scaled_X, columns=['feature_{}'.format(i) for i in range(X.shape[1])])
X_train, X_test, y_train, y_test = train_test_split(data, scaled_y, random_state=8, stratify=scaled_y)
# Compare 3 XGBoost models: no changes to weights, using sample weights, and using weight_scale
# Build a model without using the scale_pos_weight parameter, fit it, and get a set of its performance measures.
model_no_scale = xgboost.XGBClassifier(random_state=30)
model_no_scale.fit(X_train, y_train)
# Print performance
print("Off the Shelf XGBoost")
print(classification_report(y_test, model_no_scale.predict(X_test)))
# Get class_weights
# https://datascience.stackexchange.com/questions/16342/unbalanced-multiclass-data-with-xgboost
model_weights = xgboost.XGBClassifier(sample_weight=class_weight.compute_sample_weight(class_weight='balanced', y=scaled_y), random_state=30)
model_weights.fit(X_train, y_train)
# Print performance
print("Weights XGBoost")
print(classification_report(y_test, model_weights.predict(X_test)))
# Get the counts of the training data per XGBoost documentation
counts = Counter(y_train)
model_scale = xgboost.XGBClassifier(scale_pos_weight=counts[0] / counts[1], random_state=30)
model_scale.fit(X_train, y_train)
# Print performance
print("Scale XGBoost")
print(classification_report(y_test, model_scale.predict(X_test)))
# Get the counts of the training data per XGBoost documentation
from math import sqrt
model_sqrt = xgboost.XGBClassifier(scale_pos_weight=sqrt(counts[0] / counts[1]), random_state=30)
model_sqrt.fit(X_train, y_train)
# Print performance
print("SQRT XGBoost")
print(classification_report(y_test, model_sqrt.predict(X_test)))
结果:
Off the Shelf XGBoost
precision recall f1-score support
0 0.95 0.38 0.54 50
1 0.98 1.00 0.99 1253
accuracy 0.98 1303
macro avg 0.96 0.69 0.77 1303
weighted avg 0.97 0.98 0.97 1303
Weights XGBoost
precision recall f1-score support
0 0.95 0.38 0.54 50
1 0.98 1.00 0.99 1253
accuracy 0.98 1303
macro avg 0.96 0.69 0.77 1303
weighted avg 0.97 0.98 0.97 1303
Scale XGBoost
precision recall f1-score support
0 0.73 0.64 0.68 50
1 0.99 0.99 0.99 1253
accuracy 0.98 1303
macro avg 0.86 0.82 0.83 1303
weighted avg 0.98 0.98 0.98 1303
SQRT XGBoost
precision recall f1-score support
0 0.96 0.46 0.62 50
1 0.98 1.00 0.99 1253
accuracy 0.98 1303
macro avg 0.97 0.73 0.81 1303
weighted avg 0.98 0.98 0.97 1303
【讨论】: