1 集成学习的概念与分类
前面我们讲述的线性回归、K近邻、决策树等算法都是单一的弱学习器,在样本容量有限的条件下,它们实现的算法模型的性能提升空间较为有限。于是,统计学家们想出了一种集成学习(组合学习、模型融合)的方式,即将单一的弱学习器组合在一起,通过群策群力形成强学习器,达到模型性能的提升。
集成学习注重弱学习器的优良性与差异性,通常情况下,如果每个弱学习器在保证较高的分类准确率的同时,相互之间又能有较大的差异性,那么集成学习的效果就会充分得到显现。
针对弱学习器的不同,集成学习可以分为同质学习和异质学习。如果弱学习器分别属于不同的类型,比如有线性回归模型、有决策树模型、有K近邻模型等,则通过分别赋予这些模型一定权重的方式(最优权重可以通过交叉验证的方式确定),加权得到最优预测模型,基于该思想的集成学习方式为异质学习集成。而如果这些弱学习器都属于一个类型,比如均为决策树模型,那么在基准模型不变的条件下,可以通过搅动数据的方式得到多个弱学习器,然后进行模型融合,得到最优预测模型,基于该思想的集成学习方法为同质学习集成。
针对集成方法的不同,集成学习可以分为并行集成和串行集成。如果弱学习器间存在强依赖的关系,后一个弱学习器的生成需依赖前一个弱学习器的结果,则集成学习方式为串行集成,代表算法为Boosting,包括AdaBoost、GBDT、XGBoost等。
如果弱学习器间不存在依赖关系,可以同时训练多个弱学习器,适合分布式并行计算,则集成学习方式为并行集成,代表算法为装袋法、随机森林算法,其中装袋法是随机森林算法一种特例。
2 分类任务
在分类问题中,随机森林的目标是预测离散的标签。以下是随机森林在分类任务中的工作流程:
构建森林:随机森林通过构建多棵决策树来形成森林。每棵树在训练时,都会随机选择一部分特征和样本(有放回抽样,也称为自助采样)。
训练每棵树:每棵树的训练过程与单棵决策树类似,但每棵树只使用部分特征进行分裂决策,这样可以增加树之间的多样性。那么随机抽取的特征变量个数m究竟为多少合适?实务中针对回归弱学习器通常采用m=p/3。不难发现,如果m=p,即将全部特征变量作为随机抽取变量,那么随机森林算法也就变成了装袋法,所以,装袋法是随机森林算法的一种特例。
投票机制:对于一个新的输入样本,每棵树都会给出一个分类预测。随机森林通过多数投票的方式来决定最终的分类结果,即得票最多的类别被选为预测类别。
输出结果:最终的输出是所有树预测结果的众数。
优点:
能够处理多分类问题。
可以提供类别概率估计。
对于不平衡数据集,可以通过调整类别权重来提高性能。
缺点:
对于具有许多类别的分类问题,随机森林可能会变得复杂且计算成本高。
3 随机森林算法特征变量重要性
量度随机森林算法包含很多弱学习器,那么如何量度各个特征变量的重要性水平呢?弱学习器以决策树为例,首先针对单棵决策树计算重要性水平,即因采纳该变量引起的残差平方和(或信息增益、信息增益率、基尼指数等指标)变化的幅度;然后将随机森林中的所有决策树进行平均,即得到该变量对于整个随机森林的重要性水平。残差平方和下降或基尼指数下降越多、信息增益或信息增益率提升越多,说明该变量在随机森林模型中越为重要。
4 部分依赖图与个体条件期望图
长期以来机器学习因其弱解释性而深受诟病,所以很多专家学者深耕于可解释机器学习领域,致力使模型结果具备可解释性。部分依赖图(Partial Dependence Plot)与个体条件期望图(ICEPlot)即是其中的方法之一,在随机森林等集成学习算法中也经常被使用。其中部分依赖图显示了一个或两个特征变量对机器学习模型的预测结果的边际效应。与前面介绍的特征变量重要性不同,特征变量重要性展示的是哪些变量对预测的影响最大,而部分依赖图展示的是特征如何影响模型预测,可以显示响应变量和特征变量之间的关系是线性的、单调的还是更复杂的。个体条件期望图展示的是每个样本预测值与选定特征变量之间的关系,其实现路径是:对特定样本,在保持其他特征变量不变的同时,变换选定特征变量的取值,并输出预测结果,从而实现样本预测值随选定特征变量变化的情况。
数据13.1”中的数据为例进行讲解。针对“数据13.1”,我们以credit(是否发生违约)为响应变量,以age(年龄)、education(受教育程度)、workyears(工作年限)、resideyears(居住年限)、income(年收入水平)、debtratio(债务收入比)、creditdebt(信用卡负债)、otherdebt(其他负债)为特征变量,使用分类随机森林算法进行拟合。
分类问题随机森林算法示例
1 变量设置及数据处理
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.metrics import cohen_kappa_score
from sklearn.inspection import PartialDependenceDisplay
from mlxtend.plotting import plot_decision_regions
#分类问题随机森林算法示例
#1 变量设置及数据处理
data=pd.read_csv('数据13.1.csv')
X = data.iloc[:,1:]#设置特征变量
y = data.iloc[:,0]#设置响应变量
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3, stratify=y, random_state=10)
2 二元Logistic回归、单颗分类决策树算法对比观察
#2 二元Logistic回归、单颗分类决策树算法观察
model = LogisticRegression(C=1e10, max_iter=1000,fit_intercept=True)
model.fit(X_train, y_train)
model.score(X_test, y_test)
#单颗分类决策树算法
model = DecisionTreeClassifier()
path = model.cost_complexity_pruning_path(X_train, y_train)
param_grid = {'ccp_alpha': path.ccp_alphas}
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=10)
model = GridSearchCV(DecisionTreeClassifier(random_state=10), param_grid, cv=kfold)
model.fit(X_train, y_train)
print("最优alpha值:", model.best_params_)
model = model.best_estimator_
print("最优预测准确率:", model.score(X_test, y_test))
最优alpha值:{'ccp_alpha': 0.004534462760155709}
最优预测准确率:0.861904761904762
3 装袋法分类算法
# 3 装袋法分类算法
model=BaggingClassifier(estimator=DecisionTreeClassifier(random_state=10),n_estimators=300,max_samples=0.8,random_state=0)
model.fit(X_train, y_train)
model.score(X_test, y_test)
0.8666666666666667
4 随机森林分类算法
# 4 随机森林分类算法
model = RandomForestClassifier(n_estimators=300, max_features='sqrt', random_state=10)
model.fit(X_train, y_train)
model.score(X_test, y_test)
5 寻求max_features最优参数
#5 寻求max_features最优参数
scores = []
for max_features in range(1, X.shape[1] + 1):
model = RandomForestClassifier(max_features=max_features,
n_estimators=300, random_state=10)
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
scores.append(score)
index = np.argmax(scores)
range(1, X.shape[1] + 1)[index]
plt.rcParams['font.sans-serif']=['SimHei'] #正常显示中文
plt.plot(range(1, X.shape[1] + 1), scores, 'o-')
plt.axvline(range(1, X.shape[1] + 1)[index], linestyle='--', color='k', linewidth=1)
plt.xlabel('最大特征变量数')
plt.ylabel('最优预测准确率')
plt.title('预测准确率随选取的最大特征变量数变化情况')
plt.show()
plt.savefig('预测准确率随选取的最大特征变量数变化情况.png')
print(scores)
6 寻求n_estimators最优参数
#6 寻求n_estimators最优参数
ScoreAll = []
for i in range(100,300,10):
model= RandomForestClassifier(max_features=2,n_estimators = i,random_state = 10)
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)
print(ScoreAll)
max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])
plt.rcParams['font.sans-serif']=['SimHei'] #正常显示中文
plt.figure(figsize=[20,5])
plt.xlabel('n_estimators')
plt.ylabel('预测准确率')
plt.title('预测准确率随n_estimators变化情况')
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()
plt.savefig('预测准确率随n_estimators变化情况.png')
进一步寻求n_estimators最优参数
#进一步寻求n_estimators最优参数
ScoreAll = []
for i in range(190,210):
model= RandomForestClassifier(max_features=2,n_estimators = i,random_state = 10)
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)
print(ScoreAll)
max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])
plt.figure(figsize=[20,5])
plt.xlabel('n_estimators')
plt.ylabel('预测准确率')
plt.title('预测准确率随n_estimators变化情况')
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()
plt.savefig('预测准确率随n_estimators变化情况.png')
7 随机森林特征变量重要性水平分析
# 7 随机森林特征变量重要性水平分析
sorted_index = model.feature_importances_.argsort()
plt.rcParams['font.sans-serif'] = ['SimHei']#解决图表中中文显示问题
plt.barh(range(X_train.shape[1]), model.feature_importances_[sorted_index])
plt.yticks(np.arange(X_train.shape[1]), X_train.columns[sorted_index])
plt.xlabel('特征变量重要性水平')
plt.ylabel('特征变量')
plt.title('随机森林特征变量重要性水平分析')
plt.tight_layout()
plt.show()
plt.savefig('随机森林特征变量重要性水平分析.png')
8 绘制部分依赖图与个体条件期望图
#8 绘制部分依赖图与个体条件期望图
PartialDependenceDisplay.from_estimator(model, X_train, ['workyears','debtratio'], kind='average')#绘制部分依赖图简称PDP图
PartialDependenceDisplay.from_estimator(model, X_train, ['workyears','debtratio'],kind='individual')#绘制个体条件期望图(ICE Plot)
PartialDependenceDisplay.from_estimator(model, X_train, ['workyears','debtratio'],kind='both')#绘制个体条件期望图(ICE Plot)
plt.show()
plt.savefig('部分依赖图与个体条件期望图.png')
9 模型性能评价
#9 模型性能评价
prob = model.predict_proba(X_test)
prob[:5]
pred = model.predict(X_test)
pred[:5]
print(classification_report(y_test,pred))
cohen_kappa_score(y_test, pred)#计算kappa得分
热力图
#热力图
import seaborn as sns
sns.heatmap(confusion_matrix(y_test, pred), annot=True, fmt='d', cmap='Blues')
plt.show()
plt.savefig('混淆矩阵热力图.png')
10 绘制ROC曲线
#10 绘制ROC曲线
plt.rcParams['font.sans-serif'] = ['SimHei']#解决图表中中文显示问题
from sklearn.metrics import roc_curve,roc_auc_score
# 假设 y_true 和 y_score 是你的真实标签和模型预测的概率得分
predict_target_prob=model.predict_proba(X_test)
fpr, tpr, thresholds = roc_curve(y_test, predict_target_prob[:,1])
# 计算AUC值
auc = roc_auc_score(y_test, predict_target_prob[:,1])
print("AUC值:", auc)
# 绘制 ROC 曲线
plt.plot(fpr, tpr, label='ROC Curve area=%.3f'%auc)
plt.plot(fpr, fpr, 'k--', linewidth=1)
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('随机森林分类树算法ROC曲线')
plt.legend()
plt.show()
plt.savefig('随机森林分类树算法ROC曲线.pdf')
11 运用两个特征变量绘制随机森林算法决策边界图
运用两个特征变量绘制随机森林算法决策边界图
X2 = X.iloc[:, [2,5]]#仅选取workyears、debtratio作为特征变量
model = RandomForestClassifier(n_estimators=300, max_features=1, random_state=1)
model.fit(X2,y)
model.score(X2,y)
plot_decision_regions(np.array(X2), np.array(y), model)
plt.xlabel('debtratio')#将x轴设置为'debtratio'
plt.ylabel('workyears')#将y轴设置为'workyears'
plt.title('随机森林算法决策边界')#将标题设置为'随机森林算法决策边界'
plt.show()
plt.savefig('随机森林算法决策边界.png')