Python机器学习---6.集成学习与随机森林
随机森林:是⼀种利⽤多棵树对样本进⾏训练并预测的分类器,属于Bagging的并⾏式集成学习⽅法。它通过有放回的采样⽅式添加样本扰动,同时引⼊属性扰动,在基决策树的训练过程中,先从候选属性集中随机挑选出⼀个包含K个属性的⼦集,再从这个⼦集中选择最优划分属性。随机森林中基学习器的多样性不仅来⾃样本扰动,还来⾃属性扰动,从⽽进⼀步提升了基学习器之间的差异度。
Bootstraping/⾃助法:
Bootstraping的名称来⾃成语“pull up by your own bootstraps”,意思是依靠你⾃⼰的资源,称为⾃助法,它是⼀种有放回的重抽样⽅法。
附录:Bootstrap本义是指⾼靴⼦⼝后⾯的悬挂物、⼩环、 带⼦,是穿靴⼦时⽤⼿向上拉的⼯具。“pull up by your own bootstraps”即“通过拉靴⼦让⾃⼰上升”,意思是 “不可能发⽣的事情”。后来意思发⽣了转变,隐喻 “不需要外界帮助,仅依靠⾃身⼒量让⾃⼰变得更好”。
Bagging/套袋法:bootstrap aggregation
从样本集中重采样(有重复的)选出n个样本
在所有属性上,对这n个样本建⽴分类器 (ID3、C4.5、SVM、Logistic回归等)
重复以上两步m次,即获得了m个分类器
将数据放在这m个分类器上,最后根据这m个分类器的投票结果,决定数据属于哪⼀类
集成学习之结合策略:
投票法(Voting):分类任务的 “少数服从多数”;投票法是分类任务中最直观的结合策略,核心逻辑是 “收集多个基础模型的类别预测结果,通过‘投票’确定最终类别”,本质是利用模型多样性抵消单一模型的误判。
硬投票(Hard Voting):仅关注 “类别预测结果”,统计每个类别的得票数量,得票最多的类别为最终预测结果。例:3 个基础模型预测二分类任务,结果分别为【正类、正类、负类】,硬投票最终输出 “正类”(得票 2:1)。
软投票(Soft Voting):关注 “类别概率输出”,先计算每个模型对各类别的预测概率,再对概率加权求和(默认等权,也可按模型性能设权),概率最高的类别为最终结果。例:3 个模型对 “正类” 的概率分别为 0.6、0.7、0.4,等权软投票的正类总概率 =(0.6+0.7+0.4)/3≈0.56,负类总概率≈0.44,最终输出 “正类”。
平均法(Averaging):回归任务的 “结果取均值”;平均法是回归任务的核心结合策略,核心逻辑是 “收集多个基础模型的连续值预测结果,通过‘平均’生成最终输出”,适用于输出为实数的任务(如房价预测、销量预测)。
简单平均(Simple Averaging):对所有基础模型的预测结果取算术平均值,即 “平等对待每个模型”。例:3 个模型预测房价分别为 150 万、160 万、155 万,简单平均最终输出 =(150+160+155)/3=155 万。
加权平均(Weighted Averaging):根据基础模型的性能(如交叉验证的 MSE、R²)分配不同权重,性能越好的模型权重越高,最终结果为 “加权求和”。例:模型 A(交叉验证 R²=0.9)、模型 B(R²=0.8)、模型 C(R²=0.7),权重设为 0.5、0.3、0.2,最终输出 = 150×0.5 + 160×0.3 + 155×0.2=154 万。
学习法/Stacking:用 “元模型” 学习基础模型的输出;学习法(又称 Stacking,堆叠法)是高精度需求场景的进阶结合策略,核心逻辑是 “将基础模型的输出作为‘新特征(元特征)’,训练一个‘元模型(Meta-Model)’来学习如何组合这些元特征,最终输出预测结果”,本质是 “用模型学习‘结合规则’”。
核心步骤(以分类任务为例)Stacking 的流程需严格避免 “数据泄露”,通常分为 4 步:
划分数据集:将原始数据分为 “训练集” 和 “测试集”,再将训练集拆分为 “基础模型训练集(Train1)” 和 “元特征生成集(Train2)”(常用 K 折交叉验证,如 5 折)。
训练基础模型:用 Train1 训练多个不同类型的基础模型(如模型 1:逻辑回归,模型 2:随机森林,模型 3:SVM)。
生成元特征:用训练好的基础模型对 Train2 和测试集进行预测,得到 “元特征矩阵”——Train2 对应的元特征作为 “元模型的训练特征”,测试集对应的元特征作为 “元模型的测试特征”。例:3 个基础模型对 Train2 的 1000 个样本预测,生成 1000×3 的元特征矩阵(每列是一个基础模型的预测结果)。
训练元模型:用元特征矩阵和原始标签训练元模型(如线性回归、随机森林),最终用元模型对测试集的元特征进行预测,得到集成结果。
适用场景:
任务类型:复杂分类或回归任务
模型要求:基础模型需具备多样性(避免用同类型模型,如仅用多个决策树,否则元特征区分度低);元模型通常选择简单模型(如线性模型,避免过拟合)。
典型场景:单一模型精度不足,且有足够计算资源(Stacking 训练成本高于投票 / 平均)
下面来实现一下投票法:硬投票
# 生成随机的数据并且划分特征列和目标列
X, y = make_moons(n_samples=500, noise=0.3, random_state=2)# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, random_state=2)# 用上面的数据,按照类别画散点图
plt.figure(figsize=(10, 6))
plt.plot(X[:, 0][y == 0], X[:, 1][y == 0], 'yo', alpha=0.6, label='类别0')
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'bs', alpha=0.6, label='类别1')
# plt.show()# # 硬投票
# log_clf = LogisticRegression(random_state=2) # 逻辑回归分类算法
# tree_clf = DecisionTreeClassifier(random_state=2) # 分类决策树
# svc_clf = SVC(random_state=2) # 支持向量机分类算法
#
# # 集成
# voting_clf = VotingClassifier(estimators=[('log_clf', log_clf), ('tree_clf', tree_clf), ('svc_clf', svc_clf)], voting='hard')
#
# # 拟合、预测和模型评估
# for clf in (log_clf, tree_clf, svc_clf, voting_clf):
# clf.fit(X_train, y_train)
# Y = clf.predict(X_test)
# print(clf.__class__.__name__, f1_score(y_test, Y))软投票:
# # 软投票
# log_clf = LogisticRegression(random_state=2)
# tree_clf = DecisionTreeClassifier(random_state=2)
# svc_clf = SVC(random_state=2, probability=True)
#
# # 集成
# voting = VotingClassifier(estimators=[('log_clf', log_clf), ('tree_clf', tree_clf), ('svc_clf', svc_clf)], voting='soft')
#
# # 拟合、预测和评估
# for clf in (log_clf, tree_clf, svc_clf, voting):
# clf.fit(X_train, y_train)
# Y = clf.predict(X_test)
# print(clf.__class__.__name__, accuracy_score(y_test , Y))随机森林分类算法:原理:
⽤N表示训练⽤例的个数(样本),M特征数⽬
⼀次随机选出⼀个样本,重复N次
学习器,建⽴决策树
随机去选出m个特征 m<<M
# 随机森林分类算法
# 实例
tree_clf = RandomForestClassifier(random_state=2)# 拟合
tree_clf.fit(X_train, y_train)# 预测
Y = tree_clf.predict(X_test)# 评估
print(accuracy_score(y_test, Y))随机森林回归算法:
# 读取数据,数据清洗
data = pd.read_csv('insurance.csv', encoding='gbk')# 查看数据结构
# print(data.info())# 删除重复值
# data = data.drop_duplicates()
# print(data.duplicated().sum())# 相关性分析
# print(data[['年龄', '体重指数', '小孩数', '医疗费用']].corr())# 使用标签编码,将文本类型的特征转换成数值类型
le_sex = LabelEncoder()
data['性别'] = le_sex.fit_transform(data['性别'])le_smoker = LabelEncoder()
data['是否吸烟'] = le_smoker.fit_transform(data['是否吸烟'])le_region = LabelEncoder()
data['区域'] = le_region.fit_transform(data['区域'])# 查看数据是否有跨度比较大的值,以便考虑后续是否需要做标准化处理
# print(data.describe())# 指定特征列和目标列
X = data.drop(['医疗费用'], axis=1)
y = data['医疗费用']# 标准化处理
sc = StandardScaler()
X_sc = sc.fit_transform(X)# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, random_state=10)# 实例化
forest_reg = RandomForestRegressor(n_estimators=200)# 拟合
forest_reg.fit(X_train, y_train)# 预测
Y = forest_reg.predict(X_test)# 评估
print(forest_reg.score(X_test, y_test))RandomForestRegressor()参数说明:
n_estimators:决策树的数量,也就是“森林”的⼤⼩。
criterion:决定节点分裂的条件。可以是"gini"(基尼指数)或"entropy"(信息熵)。基尼指数衡量的是样本的不纯度(purity),信息熵衡量的是信息的量。
max_depth:决策树的最⼤深度。
min_samples_split:⼀个节点在被考虑分裂前必须具有的最⼩样本数
min_samples_leaf:叶⼦节点(即最终的预测节点)⾄少需要包含的最⼩样本数量。
max_features:在分裂节点时考虑的最⼤特征数量。设置为'auto'时,通常会根据树的深度动态调整。
bootstrap:是否使⽤⾃举样本(bootstrap samples)训练森林。
oob_score:是否使⽤Out-of-Bag (OOB)样本进⾏模型评估。
