【背景】自上一期基于随机森林算法找关键因素解归因问题发表后,收获网友的反馈。其中有网友希望能够针对随机森林模型的调参做一期分享,那么本文就简单跟大家说一下我的解决策略。
【问题】随机森林模型属于比较强大的有监督的机器学习模型,既可以接近分类问题,也可以处理预测性问题,但在实际建模过程中确实需要注意模型参数的选择,例如由多少棵树组成的森林合适?树的深度多少合适?叶子节点最低可以有多少个样本?如果使用模型默认的参数值,也能有比较好的模型结果,但如果能够自选一些更合适的模型参数,那模型的预测准确性将会有很大的提升。
【解答】通常我的解决办法是借助自动搜索法,即给定模型可用的参考参数值,模型通过参数值的各种排列组合,依次带入模型中,最终基于模型的某个评估标准(如准确率、均方差等)挑选出最佳的参数组合。
【案例】可能文字说起来比较晦涩难懂,不如按照程序员经常说的:Show me your codes。数据仍然使用基于随机森林算法找关键因素解归因问题中的内容。
# 导入核心库import pandas as pdimport numpy as npfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.model_selection import train_test_split, GridSearchCVfrom sklearn import metricsfrom sklearn.metrics import mean_squared_error, r2_scorefrom sklearn.metrics import confusion_matrix, classification_report, ConfusionMatrixDisplayimport matplotlib.pyplot as pltimport matplotlibmatplotlib.rcParams['font.sans-serif']=['Heiti TC','Songti SC']import seaborn as sns
# 数据读取data = pd.read_excel('Test_Data.xlsx')Columns=['X1','X2','X3','X4','X5','X6','X7','X8','X9','X10']X = data[Columns]y = data['Y']
# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 初始化基础模型rf_base = RandomForestClassifier(random_state=42)
# 设置参数网格(参考自调参指南)param_grid = { 'n_estimators': [100, 200, 300], # 树的数量 'max_depth': [None, 10, 20, 30], # 树的最大深度 'min_samples_split': [2, 5, 10], # 节点分裂最小样本数 'max_features': ['sqrt', 'log2'], # 特征选择策略 'min_samples_leaf': [1, 2, 4] # 叶节点最小样本数}
# 配置网格搜索(使用交叉验证)grid_search = GridSearchCV( estimator=rf_base, param_grid=param_grid, cv=5, # 5折交叉验证 n_jobs=-1, # 使用全部CPU核心 scoring='neg_mean_squared_error', verbose=2)
# 执行网格搜索grid_search.fit(X_train, y_train)
# 输出最佳参数组合print("最佳参数组合:", grid_search.best_params_)
# 使用最优参数建立最终模型best_rf = grid_search.best_estimator_# 预测y_pred = best_rf.predict(X_test)
# 混淆矩阵评估模型cm=pd.crosstab(y_pred,y_test)# 绘制混淆矩阵图cm_model = confusion_matrix(y_test, y_pred)disp_model = ConfusionMatrixDisplay(confusion_matrix=cm_model, display_labels=best_rf.classes_)disp_model.plot(cmap="GnBu")plt.title("混淆矩阵图")plt.show()
# 模型预测准确率print('模型准确率为:\n',metrics.accuracy_score(y_test, y_pred))print('混淆矩阵评估报告:\n',metrics.classification_report(y_test, y_pred))
# 绘制ROC曲线y_score=best_rf.predict_proba(X_test)[:,1]fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)# 计算AUC值roc_auc=metrics.auc(fpr,tpr)# 绘制面积图plt.stackplot(fpr,tpr,color='steelblue',alpha=0.5,edgecolor='black')# 添加编辑线plt.plot(fpr,tpr,color='black',lw=1)# 添加对角线plt.plot([0,1],[0,1],color='red',linestyle='--')# 添加文本信息plt.text(0.5,0.3,'ROC曲线下面积 %0.2f' % roc_auc)plt.xlabel('1-Specificity')plt.ylabel('Sensitivity')plt.show()
【讲解】模型中给定的可供参考的参数值分别是
1、树的数量:[100, 200, 300]
2、树的最大深度: [None, 10, 20, 30]
3、节点分裂最小样本数:[2, 5, 10]
4、特征选择策略:['sqrt', 'log2'],即运用某个计算方法统计每个特征在决策树中的贡献度,进而评估特征的重要性
5、叶节点最小样本数:[1, 2, 4]
通过上面的各种参数组合,带入到模型中,并采用均方差最小的原则选择最佳的模型参数,结果如下:最佳的树数量为300棵,最佳的树深度不受限制,最佳的分裂最小样本数为2,最佳的叶子节点最小样本数为1,最佳的特征选择方法是'sqrt'。截图如下:
【评估】模型结果的好坏需要定量的评估,针对分类问题,通常我使用的方法是混淆矩阵法(即直观反馈某个类别的预测准确率)和ROC曲线(直观反馈曲线覆盖的面积,值越大越好)。评估结果如下:模型对用户是否流失的预测准确率为97.5%,其中预测不流失的准确率96%,预测流失的准确率是99%;ROC曲线下的面积为1(通常覆盖面积0.8以上就代表模型较好)