为什么交叉验证 RF 分类的性能比没有交叉验证的差?
Why does cross validation RF classification perform worse than without cross validation?
我很困惑为什么没有交叉验证的随机森林 classification 模型产生的平均准确度得分为 .996,但经过 5 次交叉验证后,模型的平均准确度得分为 .687。
有 275,956 个样本。 Class 0 = 217891,class 1 = 6073,class 2 = 51992
我正在尝试预测 "TARGET" 列,即 3 classes [0,1,2]:
data.head()
bottom_temperature bottom_humidity top_temperature top_humidity external_temperature external_humidity weight TARGET
26.35 42.94 27.15 40.43 27.19 0.0 0.0 1
36.39 82.40 33.39 49.08 29.06 0.0 0.0 1
36.32 73.74 33.84 42.41 21.25 0.0 0.0 1
根据文档,数据分为训练和测试
# link to docs http://scikit-learn.org/stable/modules/cross_validation.html
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import svm
# Create a list of the feature column's names
features = data.columns[:7]
# View features
features
Out[]: Index([u'bottom_temperature', u'bottom_humidity', u'top_temperature',
u'top_humidity', u'external_temperature', u'external_humidity',
u'weight'],
dtype='object')
#split data
X_train, X_test, y_train, y_test = train_test_split(data[features], data.TARGET, test_size=0.4, random_state=0)
#build model
clf = RandomForestClassifier(n_jobs=2, random_state=0)
clf.fit(X_train, y_train)
#predict
preds = clf.predict(X_test)
#accuracy of predictions
accuracy = accuracy_score(y_test, preds)
print('Mean accuracy score:', accuracy)
('Mean accuracy score:', 0.96607267423425713)
#verify - its the same
clf.score(X_test, y_test)
0.96607267423425713
关于交叉验证:
from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, data[features], data.TARGET, cv=5)
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.69 (+/- 0.07)
低多了!
并验证第二种方式:
#predict with CV
# http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_predict.html#sklearn.model_selection.cross_val_predict
from sklearn.model_selection import cross_val_predict
predicted = cross_val_predict(clf, data[features], data.queen3, cv=5)
metrics.accuracy_score(data.queen3, predicted)
Out[]: 0.68741031178883594
根据我的理解,交叉验证不应将预测的准确性降低这个数量,但会提高模型的预测,因为模型已经看到所有数据的 "better" 表示。
在 train_test_split
中,您仅将 60% 的数据用于训练 (test_size=0.4
) 一次。但是在 cross_val_score
中,数据将被分成 80% train (cv = 5) 5 次(每次 4 折将成为 train,剩下 1 折作为测试)。
现在你应该认为 80% 的训练数据超过 60% 所以准确率应该不会下降。但这里还有一件事需要注意。
默认情况下train_test_split
不会对拆分进行分层,但会在cross_val_score
中进行。分层使每个折叠中 类(目标)的比例保持相同。所以最有可能的是,train_test_split 中目标的比例没有保持,这导致分类器 over-fitting,因此得分很高。
我建议取 cross_val_score 作为最终得分。
通常我会同意 Vivek 并告诉你要相信你的 cross-validation。
然而,某种程度的 CV 是随机森林中固有的,因为每棵树都是从引导样本中生长出来的,所以当 运行ning cross-validation。我怀疑您的问题是由于数据排序中的某种时间或 location-dependency 引起的。
当您使用 train_test_split
时,数据是从数据集中随机抽取的,因此您的所有 80 个环境都可能出现在您的训练和测试数据集中。但是,当您使用 CV 的默认选项拆分时,我相信每个折叠都是按顺序绘制的,因此您的每个环境都不会出现在每个折叠中(假设您的数据按环境排序)。这会导致准确性降低,因为您是在使用另一个环境的数据来预测一个环境。
简单的解决方案是设置cv=ms.StratifiedKFold(n_splits=5, shuffle=True)
。
在使用串联数据集之前,我已经 运行 多次遇到过这个问题,而且肯定有数百人已经意识到或没有意识到问题所在。默认行为的想法是维护时间序列中的顺序(根据我在 GitHub 讨论中看到的内容)。
您的数据可能有一些固有的顺序。做CV的时候把"shuffle"改成true
我很困惑为什么没有交叉验证的随机森林 classification 模型产生的平均准确度得分为 .996,但经过 5 次交叉验证后,模型的平均准确度得分为 .687。
有 275,956 个样本。 Class 0 = 217891,class 1 = 6073,class 2 = 51992
我正在尝试预测 "TARGET" 列,即 3 classes [0,1,2]:
data.head()
bottom_temperature bottom_humidity top_temperature top_humidity external_temperature external_humidity weight TARGET
26.35 42.94 27.15 40.43 27.19 0.0 0.0 1
36.39 82.40 33.39 49.08 29.06 0.0 0.0 1
36.32 73.74 33.84 42.41 21.25 0.0 0.0 1
根据文档,数据分为训练和测试
# link to docs http://scikit-learn.org/stable/modules/cross_validation.html
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import svm
# Create a list of the feature column's names
features = data.columns[:7]
# View features
features
Out[]: Index([u'bottom_temperature', u'bottom_humidity', u'top_temperature',
u'top_humidity', u'external_temperature', u'external_humidity',
u'weight'],
dtype='object')
#split data
X_train, X_test, y_train, y_test = train_test_split(data[features], data.TARGET, test_size=0.4, random_state=0)
#build model
clf = RandomForestClassifier(n_jobs=2, random_state=0)
clf.fit(X_train, y_train)
#predict
preds = clf.predict(X_test)
#accuracy of predictions
accuracy = accuracy_score(y_test, preds)
print('Mean accuracy score:', accuracy)
('Mean accuracy score:', 0.96607267423425713)
#verify - its the same
clf.score(X_test, y_test)
0.96607267423425713
关于交叉验证:
from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, data[features], data.TARGET, cv=5)
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.69 (+/- 0.07)
低多了!
并验证第二种方式:
#predict with CV
# http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_predict.html#sklearn.model_selection.cross_val_predict
from sklearn.model_selection import cross_val_predict
predicted = cross_val_predict(clf, data[features], data.queen3, cv=5)
metrics.accuracy_score(data.queen3, predicted)
Out[]: 0.68741031178883594
根据我的理解,交叉验证不应将预测的准确性降低这个数量,但会提高模型的预测,因为模型已经看到所有数据的 "better" 表示。
在 train_test_split
中,您仅将 60% 的数据用于训练 (test_size=0.4
) 一次。但是在 cross_val_score
中,数据将被分成 80% train (cv = 5) 5 次(每次 4 折将成为 train,剩下 1 折作为测试)。
现在你应该认为 80% 的训练数据超过 60% 所以准确率应该不会下降。但这里还有一件事需要注意。
默认情况下train_test_split
不会对拆分进行分层,但会在cross_val_score
中进行。分层使每个折叠中 类(目标)的比例保持相同。所以最有可能的是,train_test_split 中目标的比例没有保持,这导致分类器 over-fitting,因此得分很高。
我建议取 cross_val_score 作为最终得分。
通常我会同意 Vivek 并告诉你要相信你的 cross-validation。
然而,某种程度的 CV 是随机森林中固有的,因为每棵树都是从引导样本中生长出来的,所以当 运行ning cross-validation。我怀疑您的问题是由于数据排序中的某种时间或 location-dependency 引起的。
当您使用 train_test_split
时,数据是从数据集中随机抽取的,因此您的所有 80 个环境都可能出现在您的训练和测试数据集中。但是,当您使用 CV 的默认选项拆分时,我相信每个折叠都是按顺序绘制的,因此您的每个环境都不会出现在每个折叠中(假设您的数据按环境排序)。这会导致准确性降低,因为您是在使用另一个环境的数据来预测一个环境。
简单的解决方案是设置cv=ms.StratifiedKFold(n_splits=5, shuffle=True)
。
在使用串联数据集之前,我已经 运行 多次遇到过这个问题,而且肯定有数百人已经意识到或没有意识到问题所在。默认行为的想法是维护时间序列中的顺序(根据我在 GitHub 讨论中看到的内容)。
您的数据可能有一些固有的顺序。做CV的时候把"shuffle"改成true