在 RandomForest 中,特征选择精度永远不会提高到 %0.1 以上

Posted

技术标签:

【中文标题】在 RandomForest 中,特征选择精度永远不会提高到 %0.1 以上【英文标题】:Feature selection accuracy never improve above %0.1 in RandomForest 【发布时间】:2021-04-13 12:09:45 【问题描述】:

我的数据集不平衡,我应用RandomOverSampler 来获得平衡的数据集。

oversample = RandomOverSampler(sampling_strategy='minority')
X_over, y_over = oversample.fit_resample(X, y)

之后我遵循了这个 kaggle post RandomForest implementation for feature selection

https://www.kaggle.com/gunesevitan/titanic-advanced-feature-engineering-tutorial(转到页面底部你会看到类似的实现。)

我有一个类似于泰坦尼克号的真实数据集:) 并试图从中获取特征重要性!

我遇到的问题是,尽管分类器准确度非常高 ~0.99%,但我得到的特征重要性在 ~0.1% 左右。是什么原因造成的?还是可以?

这是我正在使用的代码,类似于我在链接中提供的代码。转到页面底部。

classifiers = [RandomForestClassifier(random_state=SEED,
                                      criterion='gini',
                                      n_estimators=20,
                                      bootstrap=True,
                                      max_depth=5,
                                      n_jobs=-1)]
    
              #DecisionTreeClassifier(),
              #LogisticRegression(),
              #KNeighborsClassifier()]
              #GradientBoostingClassifier(),
              #SVC(probability=True), GaussianNB()]

log_cols = ["Classifier", "Accuracy"]
log      = pd.DataFrame(columns=log_cols)

SEED = 42
N = 15
skf = StratifiedKFold(n_splits=N, random_state=None, shuffle=True)

importances = pd.DataFrame(np.zeros((X.shape[1], N)), columns=['Fold_'.format(i) for i in range(1, N + 1)], index=data.columns)


acc_dict = 

for fold, (train_index, test_index) in enumerate(skf.split(X_over, y_over)):
    X_train, X_test = X_over[train_index], X_over[test_index]
    y_train, y_test = y_over[train_index], y_over[test_index]
    
    for clf in classifiers:
        #pipe1=make_pipeline(sampling,clf)
        print(clf)
        name = clf.__class__.__name__
        clf.fit(X_train, y_train)
        train_predictions = clf.predict(X_test)
        acc = accuracy_score(y_test, train_predictions)
        
        
        if 'Random' in name:
            importances.iloc[:, fold - 1] = clf.feature_importances_
       
    
        if name in acc_dict:
            acc_dict[name] += acc
        else:
            acc_dict[name] = acc
        
        #doing grid search for best input parameters for RF
        #CV_rfc = GridSearchCV(estimator=clf, param_grid=param_grid, cv= 5)
        #CV_rfc.fit(X_train, y_train)
        

for clf in acc_dict:
    acc_dict[clf] = acc_dict[clf] / 10.0
    log_entry = pd.DataFrame([[clf, acc_dict[clf]]], columns=log_cols)
    log = log.append(log_entry)

我得到的特征重要性值几乎相同,最好是 ~0.1%

通过@AlexSerraMarrugat 建议的混淆矩阵检查

编辑

测试:0.9926166568222091 火车:0.9999704661911724

编辑2

之后尝试了randomoversplit:

from imblearn.over_sampling import RandomOverSampler
oversample = RandomOverSampler(sampling_strategy='minority')
x_over, y_over = oversample.fit_resample(X_train,Y_train)
# summarize class distribution
print(Counter(y_over))
print(len(x_over))

#创建混淆矩阵

from sklearn.metrics import plot_confusion_matrix
clf = RandomForestClassifier(random_state=0) #Here change the hyperparameters
clf.fit(x_over, y_over)
predict_y=clf.predict(x_test)
plot_confusion_matrix(clf, x_test, y_test, cmap=plt.cm.Blues)
print("Test: ", clf.score(x_test, y_test))
print("Train: ", clf.score(x_over, y_over))

测试:0.9926757235676315 火车:1.0

编辑3 训练数据的混淆矩阵

from sklearn.metrics import plot_confusion_matrix

plot_confusion_matrix(clf, X_train, Y_train, cmap=plt.cm.Blues)
print("Train: ", clf.score(X_train, Y_train))

【问题讨论】:

我可以向你保证,在拆分为训练和验证之前过采样是不正确的。您应该首先拆分,然后仅对您的训练数据进行过采样。这样做是为了模拟您的算法在现实世界中的使用——您不会对要预测 irl 的数据进行过度采样。解释了可疑的高准确度。 @GaussianPrior 感谢您的澄清。from sklearn.model_selection import train_test_split X_train, x_test, Y_train,y_test = train_test_split(X,y, test_size = 0.2) 如果先拆分并通过执行from imblearn.over_sampling import RandomOverSampler oversample = RandomOverSampler(sampling_strategy='minority') x_over, y_over = oversample.fit_resample(X_train,Y_train) 执行oversampling,然后执行此操作clf.fit(x_over, y_over),则精度会从 %99 下降到 %0.1。 等等什么?从 99% 到 10% 还是从 99% 到 0.1%?你有几节课? @GaussianPrior 当我拆分训练和测试数据集 (0.2) 时,我在测试数据集中得到 16k 0 和 300 1。 【参考方案1】:

首先,正如 Gaussian Prior 所说,您只需对您的训练数据集进行过采样。然后,一旦您对模型进行了训练,就可以使用您的数据集测试其准确性。

如果我理解你的话,你的测试数据现在有 0.1% 的准确度。请检查您是否过度拟合(如果准确度训练数据集远大于准确度测试数据,则表明可能存在过度拟合)。尝试更改一些超参数。使用此代码:

clf = RandomForestClassifier(random_state=0) #Here change the hyperparameters
clf.fit(X_train, y_train)
predict_y=clf.predict(X_test)
plot_confusion_matrix(clf, X_test, y_test, cmap=plt.cm.Blues)
print("Test: ", clf.score(X_test, y_test))
print("Train: ", clf.score(X_train, y_train))

关于特征重要性。我怀疑你的结果是正确的。他们说你有 5 个对你的模型最重要的特征。在我看来,你有最好的输出之一,你有一些重要的特性。

如果只有一个独特的重要特征,你只会得到一个大的值(模型只从一个特征中获取信息,这一点都不好)。

【讨论】:

谢谢。你可能会看到我对oversampling ---from imblearn.over_sampling import RandomOverSampler oversample = RandomOverSampler(sampling_strategy='minority') x_over, y_over = oversample.fit_resample(X_train,Y_train) 的评论。我在这里错过了什么吗?你有同时使用oversamplingRandomforest 的好例子吗? 没错。你能告诉我训练数据的准确率(必须是平衡的数据集)和测试数据的准确率(必须是不平衡的,而且必须是你说的0.1%)。 嗨,已编辑 OP。请检查edit2。所以分类器只从右下角正确预测了“1”个案例?过采样后。 绘制训练数据的混淆矩阵。看起来你的模型过度拟合了,因为你有 100% 的模型。我建议调整超参数:比如 max_depth。我推荐这个链接:***.com/questions/20463281/… 谢谢。我添加了training data 的混淆矩阵。我也在 OP 中使用的参数(代码顶部)。那里没有任何变化。

以上是关于在 RandomForest 中,特征选择精度永远不会提高到 %0.1 以上的主要内容,如果未能解决你的问题,请参考以下文章

更改 randomForest R 代码中节点特征子集选择的采样方法

R语言 | randomForest包的随机森林回归模型以及对重要变量的选择

如何在RandomForest中了解特定样本的特征及其贡献

如何知道 RandomForest 中特定样本的特征及其贡献

sklearn 的 RandomForest 中如何计算特征重要性?

pyspark randomForest 特征重要性:如何从列号中获取列名