Python 在sklearn中使用决策树回归和交叉验证

Python 在sklearn中使用决策树回归和交叉验证,python,scikit-learn,regression,Python,Scikit Learn,Regression,我是统计方法的新手,请原谅我的幼稚。在使用sklearn的决策树回归(例如DecisionTreeRegressor和RandomForestRegressor)时,我在理解交叉验证的执行方面遇到问题。我的数据集从具有多个预测因子(y=单个因变量;X=多个自变量)到具有单个预测因子,并且包含足够多的案例(>10k)。以下解释适用于所有情况 使用标准方法拟合和评分回归方程时: dt = DecisionTreeRegressor() rf = RandomForestRegressor() dt

我是统计方法的新手,请原谅我的幼稚。在使用sklearn的决策树回归(例如DecisionTreeRegressor和RandomForestRegressor)时,我在理解交叉验证的执行方面遇到问题。我的数据集从具有多个预测因子(y=单个因变量;X=多个自变量)到具有单个预测因子,并且包含足够多的案例(>10k)。以下解释适用于所有情况

使用标准方法拟合和评分回归方程时:

dt = DecisionTreeRegressor()
rf = RandomForestRegressor()

dt.fit(X,y)
rf.fit(X,y)

dt_score = dt.score(X,y)
rf_score = rf.score(X,y)
dt_分数和rf_分数返回有希望的R平方值(>0.7),但是我知道dt和rf的过度拟合特性。因此,我尝试通过交叉验证(10倍)对回归系数进行评分,以获得更真实的精度表示:

dt = DecisionTreeRegressor()
rf = RandomForestRegressor()

dt.fit(X,y)
rf.fit(X,y)

dt_scores = cross_val_score(dt, X, y, cv = 10)
rf_scores = cross_val_score(rf, X, y, cv = 10) 

dt_score = round(sum(dt_scores )/len(dt_scores ), 3)
rf_score = round(sum(rf_scores )/len(rf_scores ), 3)
此交叉验证的结果始终返回负值。根据sklearn指南,我假设它们是R平方值:默认情况下,每个CV迭代计算的分数是估计器的分数方法(两个回归器的分数方法都是R平方)。基本KFold交叉验证指南中给出的解释是:然后每个折叠使用一次作为验证,而k-1剩余折叠形成训练集。

当使用10个旧cv时,我如何理解这一点:我的数据集被分成10个相等的部分,对于每个部分,剩余的9个部分用于培训(我不确定这是拟合操作还是评分操作),剩余部分用于验证(不确定为验证做了什么)。这些回归器对我来说是一个完整的“黑匣子”,所以我不知道如何使用树进行回归,以及交叉验证从何处获得其R平方值

总之,我很难理解交叉验证如何能如此显著地降低准确度(R平方)?我是否使用回归器的交叉验证权?对决策树回归器使用交叉验证有意义吗?我应该使用另一种交叉验证方法吗


谢谢

决策树会根据您的功能值进行拆分,从而生成纯度最高的组。当我说纯洁时,我的意思是,该群体中的所有成员共享所有或几乎所有相似的东西(例如,所有白人、35岁、所有男性等)。它将一直这样做,直到您的所有叶节点都是完全纯净的,或者满足某些停止机制(例如,需要拆分的节点中的最小样本数)。您将在中看到的参数基本上是停止参数。现在,在回归方面,树将做的是将每个叶(不再有分裂的节点)的所有真
y
的平均值作为该特定路径的估计
y-hat
,以便在预测测试数据集时,来自该测试数据集的每条记录基本上沿着树的某条路径向下,直到它到达一个叶节点,该记录的估计
y-hat
将是该叶节点中所有观测值的平均真
y

随机林基本上是一组决策树,它们使用训练数据的子集进行训练。这些树通常没有单个决策树模型那么深,这有助于缓解单个决策树的过度拟合症状。RF的概念是,您使用的是许多弱学习者,他们可以很好地概括您的数据。因此,过盈少


R平方度量基本上是
1-(SS_res/SS_tot)
。分解这个公式,你基本上看到的是残差的平方和,以及总和的平方和。因此,您只需知道真实的
y
值,估计的
y-hat
值,以及真实
y
值的平均值,
y-bar
将一个小代码片段放在一起,说明如何使用决策树累加器和交叉验证

A.在第一个代码段中,使用了“cross_val_score”。但是,r2_分数可能为负数,说明模型学习能力差

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, 
test_size=0.20, random_state=0)

dt = DecisionTreeRegressor(random_state=0, criterion="mae")
dt_fit = dt.fit(X_train, y_train)

dt_scores = cross_val_score(dt_fit, X_train, y_train, cv = 5)
print("mean cross validation score: {}".format(np.mean(dt_scores)))
print("score without cv: {}".format(dt_fit.score(X_train, y_train)))

# on the test or hold-out set
from sklearn.metrics import r2_score
print(r2_score(y_test, dt_fit.predict(X_test)))
print(dt_fit.score(X_test, y_test))
B.在下一节中,使用交叉验证对参数“min_samples_split”执行Gridsrach,然后使用最佳估计器对有效性/保持集进行评分。 #使用GridSearch: 从sklearn.model_选择导入GridSearchCV 从sklearn.metrics导入make_scorer 从sklearn.metrics导入平均绝对误差 从sklearn.metrics导入r2_分数

scoring = make_scorer(r2_score)
g_cv = GridSearchCV(DecisionTreeRegressor(random_state=0),
              param_grid={'min_samples_split': range(2, 10)},
              scoring=scoring, cv=5, refit=True)

g_cv.fit(X_train, y_train)
g_cv.best_params_

result = g_cv.cv_results_
# print(result)
r2_score(y_test, g_cv.best_estimator_.predict(X_test))
希望这是有用的

参考:

交叉验证是一种计算可推广指标的技术,在本例中为R^2。当您在某些数据上训练(即拟合)您的模型,然后在相同的训练数据上计算度量(即验证)时,您收到的度量可能会有偏差,因为您的模型与训练数据过度拟合。换句话说,交叉验证旨在估计模型在onseen数据上的表现。因此,如果你做得正确,这告诉你的是,你的模型在看不见的数据上表现不佳,可能是由于过度拟合。正如你所说,DTs是臭名昭著的过度拟合者。您可以尝试调整sklearn中决策树回归器可用的各种参数。一个好的起点通常是最大深度。因此,总结一下,“交叉验证如何能如此显著地降低精度(R平方)?的答案是“因为您的模型在看不见的数据上表现非常差”。谢谢您的输入@juanpa.arrivillaga。您的评论“如果您做得正确”,您是指我如何在python中调用sklearn方法吗?因此,您同意完全可以想象的是,决策树和随机森林回归器的过度预测如此严重,以至于在应用交叉值时,R平方从0.8下降到<0