在机器学习的浩瀚星空中,决策树作为一颗璀璨的星辰,以其直观易懂、解释性强以及高效处理分类与回归任务的能力,赢得了众多数据科学家与工程师的青睐。随着大数据时代的到来,如何从海量数据中提炼出有价值的信息,构建出既准确又可靠的预测模型,成为了机器学习领域不断探索的热点。而决策树,作为这一探索旅程中的重要工具,其背后的超参数调整与优化策略,更是直接关系到模型性能的优劣。
【第二篇章】的开启,我们聚焦于“优秀的机器学习策略”,旨在深入挖掘那些能够引领模型性能飞跃的关键要素。本篇章中,我们将目光聚焦于决策树,特别是其超参数的精妙调控,这不仅是对模型内在机制的深刻理解,更是向机器学习高峰攀登的一次重要尝试。期望读者能够深刻理解决策树背后的逻辑与智慧,掌握超参数调整的艺术,从而在机器学习的实践中更加游刃有余,创造出更加精准、高效的预测模型。
调整决策树超参树
超参数不同于参数。在机器学习中,模型被调整时,参数也被调整。例如:线性回归和逻辑回归中的权重,就是构建阶段为了最小化误差而调整的参数。相比之下,超参数是在构建阶段之前选择的,如未选择则使用默认值。
决策树回归器
毛主席说过没有调研就没有发言权,所以了解超参数的最佳途径就是实验。
尽管有关于超参数选择范围的理论,但结果往往胜过理论。不同的数据集需要不同的超参数值才能获得改进。在选择超参数之前,先通过使用DecisionTreeRegressor和cross_val_score找到一个基准评分,具体步骤如下:
import pandas as pd
df_bikes = pd.read_csv('bike_rentals_cleaned.csv')
# 将数据集中的特征(X)和目标变量(y)分开。X_bikes包含除最后一列外的所有列,y_bikes包含最后一列
X_bikes = df_bikes.iloc[:,:-1]
y_bikes = df_bikes.iloc[:,-1]
# 从sklearn.tree导入DecisionTreeRegressor类
from sklearn.tree import DecisionTreeRegressor
# 从sklearn.model_selection导入cross_val_score函数,用于评估交叉验证的分数
from sklearn.model_selection import cross_val_score
# 初始化DecisionTreeRegressor对象,设置随机种子为2以确保结果可复现
reg = DecisionTreeRegressor(random_state=2)
# 使用cross_val_score函数对DecisionTreeRegressor进行交叉验证,使用均方误差作为评分指标,cv=5表示5折交叉验证
# 注意:scoring='neg_mean_squared_error'表示返回的是负均方误差,因为sklearn的某些评分函数习惯返回最小化指标
scores = cross_val_score(reg, X_bikes, y_bikes, scoring='neg_mean_squared_error', cv=5)
# 由于返回的评分是负均方误差,因此取负号并开方得到RMSE(均方根误差)
rmse = np.sqrt(-scores)
# 显示RMSE的平均值,保留两位小数
print('RMSE mean: %0.2f' % (rmse.mean()))
上述代码执行结果如下:
RMSE mean:1233.36
均方根误差为1233.36,这比之前线性回归得到的972.06和XGBoost得到的887.31更糟。
接下来分析模型是否因为方差太大而过拟合数据。
这个问题可以通过观察决策树在训练集上预测的表现来解决。在对测试集进行预测之前,以下代码检查训练集的误差率:
from sklearn.linear_model import LinearRegression
X_train, X_test, y_train, y_test = train_test_split(X_bikes, y_bikes, random_state=2)
# 初始化DecisionTreeRegressor对象。如果不指定参数,则使用默认参数。
reg = DecisionTreeRegressor()
# 使用训练集(X_train和y_train)来拟合(训练)DecisionTreeRegressor模型。
# 这意味着模型将学习如何从X_train的特征中预测y_train的值。
reg.fit(X_train, y_train)
# 使用训练好的模型对训练集X_train进行预测,得到预测值y_pred。
# 这一步通常用于评估模型在训练数据上的表现,但需要注意的是,过高的训练精度可能表明过拟合。
y_pred = reg.predict(X_train)
# 从sklearn.metrics导入mean_squared_error函数,用于计算预测值和实际值之间的均方误差(MSE)。
from sklearn.metrics import mean_squared_error
# 计算训练集上预测值y_pred和实际值y_train之间的均方误差(MSE)。
# MSE是衡量模型预测精度的一种常用指标,值越小表示模型预测越准确。
reg_mse = mean_squared_error(y_train, y_pred)
# 计算均方根误差(RMSE),它是MSE的平方根。
# RMSE提供了与原始数据相同单位的误差度量,便于理解模型性能。
# 类似于MSE,RMSE的值越小表示模型预测越准确。
reg_rmse = np.sqrt(reg_mse)
# 包含了模型在训练集上的RMSE值,是衡量模型预测性能的一个重要指标。
reg_rmse
结果为:0.0
RMSE为0.0意味着该模型完美地拟合了每个数据点!
结合1233.36的交叉验证误差,这个完美的评分表明决策树对数据进行了高方差的过拟合。训练集拟合完美,但测试集表现不佳。我们有了调查研究,下面引入本篇的主题“超参数”。
一般超参数
max_depth
定义:
max_depth 指的是决策树的最大深度,即树中从根节点到最远叶子节点的最长路径上的节点数。通过限制树的最大深度,我们可以控制模型的复杂度,从而避免过拟合(overfitting)现象。
使用方法:
- 在使用决策树模型时,可以通过设置max_depth参数来限制树的最大深度。这个参数通常是一个整数,表示从根节点到最远叶子节点的最长路径上的节点数。
- 如果不设置max_depth(在某些实现中可能是默认值None),则决策树将一直生长,直到满足其他停止条件(如所有叶子节点都是纯的,或者叶子节点包含的样本数少于某个阈值)。
优点:
- 设置max_depth可以有效地防止决策树模型过拟合。过拟合是指模型在训练数据上表现过于复杂,以至于无法很好地泛化到新数据上。通过限制树的最大深度,可以减少模型对训练数据中噪声和异常值的敏感度,从而提高模型的泛化能力。
- 较浅的决策树更容易被人类理解。每个节点都代表了一个简单的决策规则,这使得模型的决策过程更加透明和可解释。这对于需要高度可解释性的应用场景(如医疗诊断、金融风险评估等)尤为重要。
- 较深的决策树需要更多的计算资源来训练和预测。通过减小max_depth,可以减少模型的复杂度和计算量,从而降低训练和预测的时间成本。这对于处理大规模数据集或实时预测任务尤为重要。
- max_depth是一个灵活的参数,可以根据具体问题和数据集的大小和复杂度进行调整。通过尝试不同的max_depth值,可以找到最适合当前问题的模型配置。
GridSearchCV
定义:
GridSearchCV是一种超参数优化技术,用于搜索机器学习模型的超参数值的最佳组合。它是Python中scikit-learn库的一部分,通过交叉验证来评估不同超参数组合下的模型性能,从而找到最优的超参数设置。
使用方法:
- 定义一个参数网格(param_grid),其中包含要搜索的超参数名称和对应的值列表。
- 创建一个GridSearchCV对象,将模型、参数网格、交叉验证的折数(cv)以及并行工作的数量(n_jobs)作为参数传递给GridSearchCV。
- 使用训练数据拟合GridSearchCV对象,它会自动搜索并评估所有超参数组合,找到使模型性能最佳的超参数设置。
- 使用最佳超参数设置下的模型进行预测。
优点:
- 自动化程度高,能够系统地搜索超参数空间。
- 通过交叉验证评估模型性能,结果更加可靠。
继续试验:
# 导入GridSearchCV,这是用于自动调参的工具,可以在指定的参数范围内,通过交叉验证来找到最优的模型参数
from sklearn.model_selection import GridSearchCV
# 选择max_depth作为要优化的超参数,并定义一个字典params,其中包含max_depth可能取的值。None表示不限制深度,其他是具体的深度值
params = {'max_depth':[None,2,3,4,6,8,10,20]}
# 初始化回归模型DecisionTreeRegressor,设置random_state为2以确保结果的可重复性。random_state用于控制随机数生成,有助于复现结果
reg = DecisionTreeRegressor(random_state=2)
# 初始化GridSearchCV对象grid_reg,传入回归模型reg、要优化的参数params、评分指标scoring(这里使用'neg_mean_squared_error'即负均方误差,因为GridSearchCV默认寻找最大化评分的参数组合,而均方误差越小越好,所以使用其负值)、交叉验证的折数cv为5(即将数据集分成5份进行交叉验证)、以及n_jobs=-1表示使用所有可用的CPU核心进行并行计算
grid_reg = GridSearchCV(reg, params, scoring='neg_mean_squared_error', cv=5, n_jobs=-1)
# 使用GridSearchCV对象grid_reg拟合训练数据X_train和y_train。这一步会进行交叉验证,并尝试所有指定的max_depth值,找到最优的参数组合
grid_reg.fit(X_train, y_train)
# 从grid_reg中提取最佳参数组合
best_params = grid_reg.best_params_
# 打印最佳的超参数组合
print("Best params:", best_params)
上述代码输出结果如下:Best params(最佳参数): {‘max_depth’: 6}
由上面结果可知,在训练集中,max_depth值为6是最佳的交叉验证评分。
继续往下看训练得分:
# 由于GridSearchCV使用'neg_mean_squared_error'作为评分指标,这里需要先取负值(因为GridSearchCV默认寻找最大化评分的参数组合),
# 然后对结果开方,因为均方误差(MSE)的平方根是均方根误差(RMSE),这是回归任务中常用的一个性能指标。
# grid_reg.best_score_存储了最佳参数组合下的评分(即负均方误差),所以我们需要先取反再开方得到RMSE。
best_score = np.sqrt(-grid_reg.best_score_)
# 打印出使用最佳参数组合在训练集上得到的评分(这里实际上是均方根误差RMSE),保留三位小数。
# 注意:“Training score”,实际上这个评分是在交叉验证过程中得到的,是对模型泛化能力的一个估计,
# 而不仅仅是训练集上的性能。
print("Training score: {:.3f}".format(best_score))
训练评分为:951.938
测试评分:
# 从GridSearchCV对象中提取最佳模型。GridSearchCV在搜索过程中找到了最佳参数组合,并训练了相应的模型。
# best_estimator_属性包含了这个最佳模型的实例。
best_model = grid_reg.best_estimator_
# 使用最佳模型对测试集X_test进行预测,得到预测结果y_pred。
# 这些预测结果是模型根据测试集特征所做出的目标值估计。
y_pred = best_model.predict(X_test)
# 从sklearn.metrics模块导入mean_squared_error函数,该函数用于计算均方误差(MSE)。
# 导入计算MSE的函数,并且稍后会用它来计算RMSE(均方根误差)。
from sklearn.metrics import mean_squared_error
# 计算测试集上的均方根误差(RMSE)。首先,使用mean_squared_error函数计算测试集真实值y_test和预测值y_pred之间的均方误差(MSE)。
# 然后,通过取MSE的平方根得到RMSE,RMSE是回归任务中常用的一个性能指标,它衡量了预测值与实际值之间的差异大小。
rmse_test = mean_squared_error(y_test, y_pred)**0.5
# 打印出测试集上的RMSE值,保留三位小数。这个值反映了模型在完全独立的测试集上的性能表现。
print('Test score: {:.3f}'.format(rmse_test))
测试评分为:864.670,方差较之前有所减少。
min_samples_leaf
定义:
min_samples_leaf是决策树算法中的另一个重要超参数,它限定了一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生。这个参数有助于防止模型过拟合,提高模型的泛化能力。
影响:
- 当min_samples_leaf设置得较小时,决策树将更容易生成分支,模型可能更加复杂,容易过拟合。
- 当min_samples_leaf设置得较大时,决策树将更难生成分支,模型将变得更加简单,但可能欠拟合。
选择策略:
- 通常需要根据数据集的大小和特征来选择合适的min_samples_leaf值。对于较小的数据集,可以选择较小的值;对于较大的数据集,可以选择较大的值。
- 可以通过实验和交叉验证来找到最佳的min_samples_leaf值,使得模型在测试集上的表现最佳。
测试min_samples_leaf的一系列值需要进行与之前相同的过程。下面我们定义一个函数方面后续调用:
# 定义一个名为grid_search的函数,该函数接受两个参数:params(一个字典,包含要优化的超参数及其候选值)和reg(一个回归树模型实例,默认为DecisionTreeRegressor,随机状态设置为2以确保结果可复现)。
def grid_search(params, reg=DecisionTreeRegressor(random_state=2)):
# 实例化GridSearchCV对象grid_reg,传入回归模型reg、要优化的参数params、评分指标scoring(这里使用'neg_mean_squared_error'即负均方误差,因为GridSearchCV默认寻找最大化评分的参数组合,而均方误差越小越好,所以使用其负值)、交叉验证的折数cv为5、以及n_jobs=-1表示使用所有可用的CPU核心进行并行计算。
grid_reg = GridSearchCV(reg, params, scoring='neg_mean_squared_error', cv=5, n_jobs=-1)
# 使用GridSearchCV对象grid_reg拟合训练数据X_train和y_train。这一步会进行交叉验证,并尝试所有指定的参数组合,找到最优的参数组合。
grid_reg.fit(X_train, y_train)
# 从grid_reg中提取最佳参数组合。
best_params = grid_reg.best_params_
# 打印出最佳的超参数组合。
print("Best params:", best_params)
# 计算最佳参数组合下的评分(实际上是负均方误差的负值,需要取反并开方得到均方根误差RMSE,这里直接计算了RMSE作为训练集上的性能评估)。
best_score = np.sqrt(-grid_reg.best_score_)
# 打印出训练集上的最佳性能评分(均方根误差RMSE),保留三位小数。
print("Training score: {:.3f}".format(best_score))
# 使用最佳模型(即grid_reg内部训练好的最佳参数组合对应的模型)对测试集X_test进行预测,得到预测结果y_pred。
y_pred = grid_reg.predict(X_test)
# 计算测试集上的均方根误差(RMSE),即测试集真实值y_test和预测值y_pred之间的均方误差的平方根。
rmse_test = mean_squared_error(y_test, y_pred)**0.5
# 打印出测试集上的RMSE值,保留三位小数。这个值反映了模型在完全独立的测试集上的性能表现。
print('Test score: {:.3f}'.format(rmse_test))
需要注意的地方:
选择超参数范围时,了解构建模型的训练集大小是很必要的,也就是行列数。
本次训练集548行,调用之前定义好的函数传入参数:
grid_search(params={'min_samples_leaf':[1,2,4,6,8,10,20,30]})
运行代码结果为:
Best params: {‘min_samples_leaf’: 8}
Training score: 896.083
Test score: 855.620
测试评分优于训练评分,说明方差已经减小。
同时设置min_samples_leaf和max_depth,代码如下:
grid_search(params={'max_depth':[None,2,3,4,6,8,10,20],'min_samples_leaf':[1,2,4,6,8,10,20,30]})
Best params: {‘max_depth’: 6, ‘min_samples_leaf’: 2}
Training score: 870.396
Test score: 913.000
结果出人意料,尽管训练评分已经提高,但测试评分没有改善。
继续调整传入参数将min_samples_leaf限制为大于3的值:
grid_search(params={'max_depth':[5,6,7,8,9],'min_samples_leaf':[3,5,7,9]})
Best params: {‘max_depth’: 9, ‘min_samples_leaf’: 7}
Training score: 888.905
Test score: 878.538
结果显示测试评分已经提高(越低越好),接下来将探讨决策树剩余的超参数,但不进行测试,一个好的模型太费时间了。
max_leaf_nodes
用途:限制决策树的最大叶子节点数。当树达到最大叶子节点数时,停止生长。
用法:通过设置一个整数来指定最大叶子节点数。max_leaf_nodes=10表示模型不能超过10个叶节点。
效果:较小的值会导致较简单的树,有助于防止过拟合,但可能会增加欠拟合的风险。
max_features
用途:在寻找最佳分割时要考虑的特征数量。这个参数在随机森林等集成方法中特别有用,但在单个决策树中也可以用来减少计算量或引入随机性。
用法:可以是整数、浮点数或字符串。整数表示要考虑的特征的绝对数量;浮点数表示要考虑的特征比例(例如,0.5 表示考虑一半的特征);字符串 “auto” “sqrt” "log2"表示自动选择特征数量(“auto” 表示所有特征(默认值),“sqrt” 表示 sqrt(n_features),"log2"以2为底的特征总数的对数)。
效果:减少考虑的特征数量可以加速训练过程,降低方差,并可能通过引入随机性来减少过拟合。
min_samples_split
用途:分割内部节点所需的最小样本数(默认值为2,因为两个样本可能会被分割,各自成为单个叶节点)如果限制增加到5,则意味着对于具有5个或更少样本的节点,不允许进一步分割。
用法:设置一个整数。
效果:增加这个值会导致树生长得更慢,因为节点需要更多的样本来分裂。这有助于减少过拟合,但也可能导致欠拟合。
splitter
用途:用于在每个节点选择最佳分割的策略,将splitter更改为"random"是防止过拟合和使树多样化的好方法。
用法:可以是 “best” 或 “random”。“best” 表示选择最佳分割(基于给定的标准),而 “random” 表示随机选择分割。
效果:“random” 可以增加模型的随机性,有助于减少过拟合,但可能会牺牲一些性能。
criterion
用途:用于评估分割质量的函数。
用法:对于分类问题,通常是 “gini” 或 “entropy”;对于回归问题,通常是 “mse”(均方误差)或 “friedman_mse”(弗里德曼均方误差)。
效果:不同的标准可能会导致不同的树结构和性能。
min_impurity_decrease
用途:如果节点的分割导致杂质(impurity)大于或等于这个值(默认值为0),则节点将被分割。杂质是衡量每个节点预测纯度的指标。准确度为100%的树的杂质值为0。准确度为80%的树的杂质值为0.20。
用法:设置一个浮点数。
效果:这个参数用于控制树的生长,较小的值允许树有更多的分支,而较大的值则限制树的生长。
min_weight_fraction_leaf
用途:一个叶子节点必须具有的总权重的最小比例(用于加权样本)。可以减少方差并防止过拟合。默认值为0.假设权重相等,限制为1%,表明500个样本中至少有5个应成为叶节点。
用法:设置一个浮点数,范围在 0 和 0.5 之间。
效果:这个参数在处理加权样本时特别有用,它允许用户指定叶子节点必须包含的最小样本权重比例。
ccp_alpha
用途:成本复杂度剪枝的阈值。
用法:设置一个非负浮点数。较大的值会导致更简单的树。
效果:ccp_alpha 是一种新的剪枝策略,称为成本复杂度剪枝(Cost-Complexity Pruning)。它通过比较树的不同子树的成本(包括错误率和复杂度)来选择最佳的剪枝点。
Tips:
理解数据:
在开始调整超参数之前,先彻底理解你的数据集。了解数据的特征、目标变量的分布、以及任何调整潜在的所有异常超值参数或。缺失相反值,。应该逐个
逐步调整:
不要一次性或成对地调整超参数,并观察它们对模型性能的影响。
使用交叉验证:
交叉验证是评估模型性能的重要工具。它可以帮助你了解模型在不同数据集上的表现,并减少过拟合的风险。在调整超参数时,应该使用交叉验证来评估每个设置的效果。
默认设置作为起点:
大多数决策树实现都提供了合理的默认超参数设置。这些设置通常是基于广泛研究的,并适用于许多常见情况。因此,建议从默认设置开始,并根据需要进行调整。
考虑问题的性质:
决策树模型超参数的选择应该与你要解决的问题的性质相匹配。例如,在分类问题中,你可能更关心模型的分类准确率,而在回归问题中,你可能更关心模型的预测误差。
平衡过拟合和欠拟合:
过拟合和欠拟合是决策树模型中常见的问题。通过调整超参数(如max_depth、min_samples_split等),你可以控制树的复杂度,并在过拟合和欠拟合之间找到平衡。
使用网格搜索和随机搜索:
网格搜索(GridSearchCV)和随机搜索(RandomizedSearchCV)是两种流行的超参数优化技术。它们可以自动地搜索超参数空间,并找到最优的超参数组合。这些技术可以节省大量时间,并帮助你找到更好的模型配置。
监控训练时间:
决策树的训练时间可以随着超参数的变化而变化。例如,增加max_depth或max_leaf_nodes可能会导致训练时间显著增加。因此,在调整超参数时,请务必监控训练时间,并确保它在可接受的范围内。
考虑集成方法:
如果你发现单个决策树模型的性能不够理想,可以考虑使用集成方法(如随机森林、梯度提升树等)。这些方法通常通过组合多个决策树来提高模型的准确性和稳定性。
持续学习:
机器学习是一个不断发展的领域。随着新算法和技术的出现,你可能需要不断地学习新的知识和技能来优化你的决策树模型。因此,请保持对最新研究的关注,并持续学习新的技术和方法。
实际上,决策树的超参数太多,根本无法全部用到,本文仅将常用的奉上,现在已经学习了决策树和决策树超参数的基础知识,是时候部署一个小项目了,欲知后文如何,请看下篇分解。
标签:学习策略,max,模型,拟合,参数,篇章,reg,决策树 From: https://blog.csdn.net/2202_76035290/article/details/140779427