抱歉,这可能是一个基本问题,但我无法在文献或互联网上找到明确的答案。
在处理不平衡的数据集时,一种可能的策略是对少数类或多数类重新采样,以人工生成可用于训练机器学习模型的平衡训练集。
我的怀疑源于这样一个事实,即测试集应该代表真实世界数据的样子。在这个假设下,我的理解是,与训练集不同,测试集不会被重新采样,因为我们试图处理的不平衡首先存在于实时数据中。
有人可以澄清这种直觉是否正确吗?
抱歉,这可能是一个基本问题,但我无法在文献或互联网上找到明确的答案。
在处理不平衡的数据集时,一种可能的策略是对少数类或多数类重新采样,以人工生成可用于训练机器学习模型的平衡训练集。
我的怀疑源于这样一个事实,即测试集应该代表真实世界数据的样子。在这个假设下,我的理解是,与训练集不同,测试集不会被重新采样,因为我们试图处理的不平衡首先存在于实时数据中。
有人可以澄清这种直觉是否正确吗?
训练数据的重新采样是为了更好地代表少数类,因此您的分类器将有更多的样本可供学习(过采样)或更少的样本,以更好地将您的少数类样本与其余样本区分开来(欠采样)。不仅您的测试数据在过采样或欠采样期间必须保持不变,而且您的验证数据也必须保持不变。阻止您接触测试数据的一个逻辑论点是,在实际场景中,您无法访问目标变量(这就是您想要预测的),并且为了执行重采样,您需要知道哪个样本所属的类别,您可以将其删除 (欠采样)或查找它是最近的邻居 (过采样)
下面是交叉验证期间过采样的示例:我基本上在这里做的是避免将信息从训练集泄漏到测试集(和 valset),每次迭代,在每个折叠处,我对剩余的折叠进行过采样,用过采样训练模型新的火车,得到我的预测,一遍又一遍地迭代。每次我得到一个新的验证折叠时,我都会对所有其他折叠进行过采样,并获得对该验证折叠的预测。
for ind,(ind_train,ind_val) in (enumerate (kfolds.split(X,y))): # Stratified Kfold
X_train,X_val = X.iloc[ind_train],X.iloc[ind_val]
y_train,y_val = y.iloc[ind_train],y.iloc[ind_val]
sm = SMOTE(random_state=12, ratio = 1.0)
X_train_res, y_train_res = sm.fit_sample(X_train, y_train)##oversampled trainset
xgb = XGBClassifier(max_depth=5,colsample_bytree=0.9,min_child_weight=2,learning_rate=0.09,objective = "binary:logistic",n_estimators=148)
xgb.fit(X_train_res,y_train_res)
val_pred = xgb.predict(X_val) ##out of fold predictions on my validation set
train_pred = xgb.predict(X_train)##oof preds on my trainset
test_pred = xgb.predict(X_test)##oof preds on my whole test set
你说的对!正如您所说,模型的最终目标是与现实生活中的数据分布一起工作,因此测试数据必须保持不变。
重采样的目标不是从所有类中获得相同数量的对象,而是使模型适合您的数据。所以一个直观的例子可能是:如果你有 k 个第一类对象和 5*k 个第二类对象,但你的模型很好地学习了数据,那么重新采样是没有必要的。这就是为什么我们不应该在测试期间使用它的原因(我们已经训练了模型)
需要记住的另一件事是 F1 分数可以在多类任务中以不同的方式计算(它可能说明标签不平衡),这是来自 sklearn https://scikit-learn.org/stable/modules/的示例生成/sklearn.metrics.f1_score.html