在 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)
的评论。我在这里错过了什么吗?你有同时使用oversampling
和Randomforest
的好例子吗?
没错。你能告诉我训练数据的准确率(必须是平衡的数据集)和测试数据的准确率(必须是不平衡的,而且必须是你说的0.1%)。
嗨,已编辑 OP。请检查edit2。所以分类器只从右下角正确预测了“1”个案例?过采样后。
绘制训练数据的混淆矩阵。看起来你的模型过度拟合了,因为你有 100% 的模型。我建议调整超参数:比如 max_depth。我推荐这个链接:***.com/questions/20463281/…
谢谢。我添加了training data
的混淆矩阵。我也在 OP 中使用的参数(代码顶部)。那里没有任何变化。以上是关于在 RandomForest 中,特征选择精度永远不会提高到 %0.1 以上的主要内容,如果未能解决你的问题,请参考以下文章
更改 randomForest R 代码中节点特征子集选择的采样方法
R语言 | randomForest包的随机森林回归模型以及对重要变量的选择
如何知道 RandomForest 中特定样本的特征及其贡献