我有一个非常不平衡的数据集(5000正,300000负)。我正在使用sklearn RandomForestClassifier尝试预测正类的概率。我拥有多年的数据,而我设计的功能之一是上一年的课程,因此除了培训期间的测试集外,我还将保留数据集的最后一年以进行测试上。
这是我尝试过的结果(以及结果):
使用SMOTE和SMOTEENN进行上采样(怪异的分数分布,请参见第一张图片,阳性和阴性类别的预测概率都相同,即模型预测大多数阳性类别的概率非常低)
向下采样到平衡数据集(测试集的召回率为〜0.80,但从非平衡的一年期测试集中的总负数的绝对数量来看,年终测试集为0.07,请参见第二张图片)>
保持不平衡(再次怪异的得分分布,对于测试和过期测试集,精度达到〜0.60,召回率分别降至0.05和0.10)
XGBoost(在年终测试集上,回忆起来要好一点,为0.11)
接下来我应该尝试什么?我想针对F1进行优化,因为在我的情况下,误报和误报都同样糟糕。我想合并k倍交叉验证,并已阅读在上采样之前应该这样做,a)我应该这样做/是否可能有帮助,b)如何将其合并到类似于以下内容的管道中:
from imblearn.pipeline import make_pipeline, Pipeline
clf_rf = RandomForestClassifier(n_estimators=25, random_state=1)
smote_enn = SMOTEENN(smote = sm)
kf = StratifiedKFold(n_splits=5)
pipeline = make_pipeline(??)
pipeline.fit(X_train, ytrain)
ypred = pipeline.predict(Xtest)
ypredooy = pipeline.predict(Xtestooy)
答案 0 :(得分:3)
我在这里找到了更多信息,以及如何改善结果: https://sci2s.ugr.es/sites/default/files/ficherosPublicaciones/1773_ver14_ASOC_SMOTE_FRPS.pdf
降低采样率时,您似乎会遇到与我所理解的相同的过拟合问题(至少对于上一年的目标结果而言)。但是,如果不查看数据,很难推断出其背后的原因。
您的过拟合问题可能来自所使用的功能数量,这些功能可能会增加不必要的噪音。您可以尝试减少使用的功能数量,然后逐渐增加(使用RFE模型)。此处提供更多信息:
https://machinelearningmastery.com/feature-selection-in-python-with-scikit-learn/
对于您使用的模型,您提到了Random Forest和XGBoost,但是没有提到使用了更简单的模型。您可以尝试使用更简单的模型,并专注于数据工程。 如果您还没有尝试过,也许可以:
测试简单模型(如朴素贝叶斯和Logistic回归)的“蛮力”调整
# Define steps of the pipeline
steps = [('scaler', StandardScaler()),
('log_reg', LogisticRegression())]
pipeline = Pipeline(steps)
# Specify the hyperparameters
parameters = {'C':[1, 10, 100],
'penalty':['l1', 'l2']}
# Create train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33,
random_state=42)
# Instantiate a GridSearchCV object: cv
cv = GridSearchCV(pipeline, param_grid=parameters)
# Fit to the training set
cv.fit(X_train, y_train)
无论如何,对于您的示例而言,管道可以是(我使用Logistic回归进行了建模,但是您可以使用其他ML算法对其进行更改,并因此更改参数网格):
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV, StratifiedKFold, cross_val_score
from imblearn.combine import SMOTEENN
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import Pipeline
param_grid = {'C': [1, 10, 100]}
clf = LogisticRegression(solver='lbfgs', multi_class = 'auto')
sme = SMOTEENN(smote = SMOTE(k_neighbors = 2), random_state=42)
grid = GridSearchCV(estimator=clf, param_grid = param_grid, score = "f1")
pipeline = Pipeline([('scale', StandardScaler()),
('SMOTEENN', sme),
('grid', grid)])
cv = StratifiedKFold(n_splits = 4, random_state=42)
score = cross_val_score(pipeline, X, y, cv=cv)
希望对您有所帮助。
(编辑:我在GridSearchCV中添加了score =“ f1”)