机器学习 Day12 集成学习简单介绍

news2025/4/21 7:13:48

1.集成学习概述

1.1. 什么是集成学习

集成学习是一种通过组合多个模型来提高预测性能的机器学习方法。它类似于:

  • 超级个体 vs 弱者联盟

    • 单个复杂模型(如9次多项式函数)可能能力过强但容易过拟合

    • 组合多个简单模型(如一堆1次函数)可以增强能力而不易过拟合

集成学习通过生成多个分类器/模型,将它们的预测结果组合起来,通常能获得优于任何单一分类器的预测性能。

1.2. 机器学习的两个核心任务

  1. 如何优化训练数据 - 主要用于解决欠拟合问题——booting

  2. 如何提升泛化性能 - 主要用于解决过拟合问题——bagging

1.3. 集成学习的两种主要方法

Boosting方法

  • 逐步增强学习

  • 通过序列化方式构建模型,每个新模型都更关注前序模型处理不好的样本(错误数据增强)

  • 典型算法:AdaBoost, Gradient Boosting, XGBoost

Bagging方法

  • 采样学习集成

  • 通过并行方式构建多个模型,每个模型基于数据的随机子集

  • 典型算法:随机森林

集成学习的关键优势是:只要单分类器的表现不太差,集成后的结果通常优于单分类器。这种方法能有效平衡模型的偏差和方差,提高泛化能力

2.Bagging和随机森林

2.1Bagging集成原理

先看一个图

2.1.1. Bagging 基本概念

BaggingBootstrap Aggregating,自助聚合)是一种并行式集成学习方法,通过构建多个相互独立的基学习器,并综合它们的预测结果来提高模型的泛化能力。

核心思想

  • Bootstrap(自助采样):从训练数据中有放回地随机抽取多个子集,每个子集用于训练一个基学习器。

  • Aggregating(聚合):所有基学习器的预测结果通过投票(分类)或平均(回归)进行集成,得到最终预测。

📌 关键特点

  • 适用于高方差、低偏差的模型(如决策树、神经网络)。

  • 能有效降低方差,减少过拟合风险。(可以理解因为你随机选取数据)


2.1.2. Bagging 算法流程

  1. 自助采样(Bootstrap Sampling)

    • 从原始训练集 DD 中有放回地随机抽取 mm 个样本,构成一个子集 DiDi​。

    • 重复该过程 TT 次,得到 TT 个不同的训练子集。

  2. 基学习器训练

    • 每个子集 DiDi​ 训练一个基学习器(如决策树)。

    • 基学习器之间相互独立(可并行训练)。

  3. 集成预测

    • 分类任务:采用投票法(多数表决)

    • 回归任务:采用平均法(取均值)


2.1.3. Bagging 的典型算法:随机森林(Random Forest)

  • 改进点不仅对样本进行自助采样,还对特征进行随机选择(进一步降低相关性)

  • 优势

    • 比普通 Bagging 更鲁棒,抗过拟合能力更强。

    • 能处理高维数据,适用于分类和回归任务。


2.1.4. Bagging 的优缺点

✅ 优点

  • 有效减少方差,防止过拟合。

  • 适用于高噪声数据,鲁棒性强。

  • 可并行训练,计算效率高。

❌ 缺点

  • 低偏差、高方差的模型(如线性回归)提升有限。

  • 如果基学习器本身偏差较大,Bagging 可能无法显著提升性能。

2.2随机森林

2.2.1. 随机森林的核心概念
随机森林是一种基于 Bagging + 决策树(基学习器是决策树) 的集成学习方法,通过构建多棵决策树并综合它们的预测结果来提高模型的泛化能力。

2.2.2核心特点:

双重随机性:样本随机(自助采样),特征随机(随机选择部分特征)

投票机制:分类任务:众数投票(多数表决),回归任务:均值预测

2.2.3构造过程:

 2.2.4关键问题解答

Q1:为什么要随机抽样训练集?

  • 如果所有树使用相同的训练数据,会导致所有树高度相似,失去集成的意义。

  • 随机抽样 保证每棵树学习到数据的不同方面,提高多样性。

Q2:为什么要有放回地抽样?

  • 无放回抽样会导致每棵树的训练数据完全不同,可能引入偏差。

  • 有放回抽样 使不同树的数据分布相似但不相同,平衡偏差与方差。

2.3包外估计(之前讲的自助法)

5. 实际应用示例
(1)随机森林的 OOB 误差计算

from sklearn.ensemble import RandomForestClassifier

# 启用 OOB 估计
model = RandomForestClassifier(n_estimators=100, oob_score=True)
model.fit(X_train, y_train)

# 输出 OOB 准确率
print("OOB Score:", model.oob_score_)

(2)特征重要性可视化

import matplotlib.pyplot as plt

# 获取特征重要性
importances = model.feature_importances_

# 可视化
plt.barh(range(X.shape[1]), importances)
plt.yticks(range(X.shape[1]), X.columns)
plt.show()

6. 关键问题
包外数据能完全替代验证集吗?
可以:在随机森林中,OOB 估计已被证明是无偏的。但:对于超参数调优,建议结合交叉验证。

2.4随机森林API和案例

还是和以前一样,先实例化后使用

 案例:

import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.datasets import load_breast_cancer  # 示例数据集

# 1. 加载数据(这里使用sklearn自带的乳腺癌数据集作为示例)
data = load_breast_cancer()
X = data.data
y = data.target

# 2. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 3. 初始化随机森林分类器(启用OOB估计)
rf = RandomForestClassifier(oob_score=True, random_state=42)

# 4. 定义超参数网格
param_grid = {
    "n_estimators": [120, 200, 300, 500, 800, 1200],
    "max_depth": [5, 8, 15, 25, 30],
    "max_features": ["sqrt", "log2"]  # 添加特征选择方式
}

# 5. 使用GridSearchCV进行超参数调优
gc = GridSearchCV(
    estimator=rf,
    param_grid=param_grid,
    cv=5,  # 使用5折交叉验证
    n_jobs=-1,  # 使用所有CPU核心
    verbose=2  # 显示详细日志
)

# 6. 训练模型
gc.fit(X_train, y_train)

# 7. 输出最佳参数和模型评估结果
print("\n=== 最佳参数组合 ===")
print(gc.best_params_)

print("\n=== 模型评估 ===")
print(f"测试集准确率: {gc.score(X_test, y_test):.4f}")

# 8. 获取最佳模型并输出OOB得分
best_rf = gc.best_estimator_
print(f"包外估计(OOB)得分: {best_rf.oob_score_:.4f}")

3.通过一个案例,来看一下我们拿到一个数据如何分析:

3.1题目介绍

 

 3.2题目分析:我说一下目前了解到的各个部分

3.1获取数据 

数据描述,可视化

3.2数据基本处理:选取特征值(部分特征值无用,比如id),对于类别不平衡数据的处理(过采样和欠采样),缺失值和异常值的处理,分割数据,将标签值转化为数字(这个案例里会讲)只有进行数据的可视化才能看到数据是否平衡,有无异常值等,所以可视化很重要。

3.3特征处理:特征预处理(归一化,标准化),特征提取(字典特征提取,文本特征提取,图像特征提取),将类别特征转换为One-hot编码。

3.4模型训练:实际上涉及到参数调优,如果算力够强使用交叉验证和网格搜索即可,不行的话可以一个一个来,我们这个案例就是。

3.5模型评估

3.3代码实现

获取数据,以及数据描述:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.utils import class_weight

# 加载数据
data = pd.read_csv('./data/otto/train.csv')

# 查看数据形状
print(f"数据集形状: {data.shape}")  # (61878, 95)

# 查看数据概览
print(data.describe())

# 可视化类别分布
plt.figure(figsize=(12, 6))
sns.countplot(x='target', data=data)
plt.title('类别分布情况')
plt.xticks(rotation=45)
plt.show()

可以看到标签值是一个不平衡数据,所以需要进行处理。

数据预处理

 (1)确定特征值和标签值

# 首先需要确定特征值\标签值
y = data["target"]
x = data.drop(["id", "target"], axis=1)

(2)类别不平衡问题处理

# 欠采样获取数据
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=0)
X_resampled, y_resampled = rus.fit_resample(x, y)

# 图形可视化,查看数据分布
import seaborn as sns
sns.countplot(y_resampled)
plt.show()

 

看到处理完毕,并且 类别平衡。

(3)标签值的转化

使用转换器即可

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y_resampled = le.fit_transform(y_resampled)

 

(4)分割数据 

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X_resampled, y_resampled, test_size=0.2)

 特征工程   这个数据全是0-1数据,是被脱敏处理过后的数据,无需再进行处理

模型训练与评估(这里要使用要求的损失函数)

# 模型训练
rf = RandomForestClassifier(oob_score=True)#使用包外估计
rf.fit(x_train, y_train)

# 模型预测
y_pre = rf.predict(x_test)

# 计算模型准确率
accuracy = rf.score(x_test, y_test)
print(f"模型在测试集上的准确率: {accuracy}")

# 查看袋外分数
oob_score = rf.oob_score_
print(f"模型的包外估计分数: {oob_score}")

 按要求评估:

from sklearn.metrics import log_loss
log_loss(y_test, y_pre, eps=1e-15, normalize=True)
#normalize是将损失进行归一化

但我们会发现这样会报错,因为 这个评估函数要求输入是一堆矩阵,y_test是一个one-hot编码矩阵,后面的也要求是相应的大小。于是我们更改方式:

from sklearn.preprocessing import OneHotEncoder
one_hot = OneHotEncoder(sparse=False)#不是密集矩阵

y_test1 = one_hot.fit_transform(y_test.reshape(-1, 1))
y_pre1 = one_hot.fit_transform(y_pre.reshape(-1, 1))

对于 y_test.reshape(-1, 1) :y_test 原本可能是一维数组,reshape(-1, 1) 将其转换为二维列向量形式,因为 OneHotEncoder 要求输入数据是二维数组。

这样就可以了吗,但是我们可以通过将预测值的那个矩阵替换为概率矩阵,就是每一行代表一个样本,每一列是代表这个样本属于这个类别的概率:这样会降低特别大

# 改变预测值的输出模式,让输出结果为百分比概率
y_pre_proba = rf.predict_proba(x_test)

# 再次查看袋外分数
oob_score = rf.oob_score_
print(f"模型的袋外分数: {oob_score}")

# 第二次 logloss 模型评估
log_loss_value_2 = log_loss(y_test1, y_pre_proba, eps=1e-15, normalize=True)
print(f"第二次计算的 log_loss 值: {log_loss_value_2}")

 参数调优 最好使用网格搜索的方法,当算力小的时候可以如下调优

# 确定n_estimators的取值范围
tuned_parameters = range(10, 200, 10)
# 创建添加存放accuracy的一个numpy数组
accuracy_t = np.zeros(len(tuned_parameters))
# 创建添加error的一个numpy数组(就是要求的损失函数数组)
error_t = np.zeros(len(tuned_parameters))
# 调优过程实现
for j, one_parameter in enumerate(tuned_parameters):
    rf2 = RandomForestClassifier(n_estimators=one_parameter,
                                 max_depth=10,
                                 max_features=10,
                                 min_samples_leaf=10,
                                 oob_score=True,
                                 random_state=0,
                                 n_jobs=-1)
    rf2.fit(x_train, y_train)
    # 输出accuracy
    accuracy_t[j] = rf2.oob_score_
    # 输出log_loss
    y_pre = rf2.predict_proba(x_test)
    error_t[j] = log_loss(y_test, y_pre, eps=1e-15, normalize=True)
    print(error_t)

# 优化结果过程可视化
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 4), dpi=100)
axes[0].plot(tuned_parameters, error_t)
axes[1].plot(tuned_parameters, accuracy_t)
axes[0].set_xlabel("n_estimators")
axes[0].set_ylabel("error_t")
axes[1].set_xlabel("n_estimators")
axes[1].set_ylabel("accuracy_t")
axes[0].grid(True)
axes[1].grid(True)
plt.show()
for j, one_parameter in enumerate(tuned_parameters):

相当于给原本的要调优的值加了一个从0开始的索引,方便把每个值存到数组里

注意我们并不是选取数组里最小的作为最优调参,而是通过绘图查看趋势,通常选取趋势平缓的转折点

之后我们固定这个参数,继续进行调优,直到全部调优完毕!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2339267.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

交换机与路由器的主要区别:深入分析其工作原理与应用场景

在现代网络架构中,交换机和路由器是两种至关重要的设备。它们在网络中扮演着不同的角色,但很多人对它们的工作原理和功能特性并不十分清楚。本文将深入分析交换机与路由器的主要区别,并探讨它们的工作原理和应用场景。 一、基本定义 1. 交换…

【Oracle专栏】Oracle中的虚拟列

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 在EXP方式导出时,发现 出现如下提示 EXP-00107: virtual column 不支持,因此采用expdp方式导出。于是本文针对oracle虚拟列进行简单介绍。 2. 相…

2020 年 7 月大学英语四级考试真题(组合卷)——解析版

🏠个人主页:fo安方的博客✨ 💂个人简历:大家好,我是fo安方,目前中南大学MBA在读,也考取过HCIE Cloud Computing、CCIE Security、PMP、CISP、RHCE、CCNP RS、PEST 3等证书。🐳 &…

大语言模型的训练、微调及压缩技术

The rock can talk — not interesting. The rock can read — that’s interesting. (石头能说话,不稀奇。稀奇的是石头能读懂。) ----硅谷知名创业孵化器 YC 的总裁 Gar Tan 目录 1. 什么是大语言模型? 2. 语言建模&#xff…

firewall指令

大家好,今天我们继续来了解服务管理,来看看打开或关闭指定端口,那么话不多说,开始吧. 1.打开或者关闭指定端口 在真正的生产环境,往往需要防火墙,但问题来了,如果我们把防火墙打开,那么外部请求数据包就不能跟服务器监听通讯,这时,需要打开指定的端口,比如80,22,8080等. 2.fi…

【MySQL】MySQL表的增删改查(CRUD) —— 上篇

目录 MySQL表的增删改查(CRUD) 1. 新增(Create)/插入数据 1.1 单行数据 全列插入 insert into 表名 values(值, 值......); 1.2 单行数据 指定列插入 1.3 多行数据 指定列插入 1.4 关于时间日期(datetime&am…

软考高级系统架构设计师-第15章 知识产权与标准化

【本章学习建议】 根据考试大纲,本章主要考查系统架构设计师单选题,预计考3分左右,较为简单。 15.1 标准化基础知识 1. 标准的分类 分类 内容 国际标准(IS) 国际标准化组织(ISO)、国际电工…

Spring Boot 整合 DeepSeek 实现AI对话 (保姆及教程)

文章目录 文章目录 前言 一、创建 spring boot 工程 二、申请key 三、修改配置文件 application.properties 四、编写控制器(controller) 五、运行调试 前言 提示:随着人工智能的不断发展,ai这门技术也越来越重要,很多…

前端与传统接口的桥梁:JSONP解决方案

1.JSONP原理 1.1.动态脚本注入 说明&#xff1a;通过创建 <script> 标签绕过浏览器同源策略 1.2.回调约定 说明&#xff1a;服务端返回 函数名(JSON数据) 格式的JS代码 1.3.自动执行 说明&#xff1a;浏览器加载脚本后立即触发前端预定义的回调函数&#xff08;现代开…

编码器---正交编码器

一、正交编码器定义与核心作用 正交编码器&#xff08;Orthogonal Encoder&#xff09;&#xff0c;又称增量式编码器&#xff0c;是一种通过输出两路相位差90的脉冲信号&#xff08;A相、B相&#xff09;来测量旋转角度、速度和方向的传感器。其核心优势是通过A/B相的脉冲顺序…

开发环境解决浏览器层面跨域问题

适用于开发环境临时调试等情况 新建一个 Chrome 的快捷方式&#xff0c;目标后面跟上&#xff1a; –disable-web-security --disable-gpu --user-data-dir%LOCALAPPDATA%\Google\chromeTemp 打开后会给出不安全的提示

2025年渗透测试面试题总结-拷打题库07(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 2025年渗透测试面试题总结-拷打题库07 1. CMS目录扫描的意义 2. 常见网站服务器容器 3. MySQL写入We…

深入理解Linux中的线程控制:多线程编程的实战技巧

个人主页&#xff1a;chian-ocean 文章专栏-Linux 前言&#xff1a; POSIX线程&#xff08;Pthreads&#xff09; 是一种在 POSIX 标准下定义的线程库&#xff0c;它为多线程编程提供了统一的接口&#xff0c;主要用于 UNIX 和类 UNIX 系统&#xff08;如 Linux、MacOS 和 BS…

【条形码识别改名工具】如何批量识别图片条形码,并以条码内容批量重命名,基于WPF和Zxing的开发总结

批量图片条形码识别与重命名系统 (WPF + ZXing)开发总结 项目适用场景 ​​电商商品管理​​:批量处理商品图片,根据条形码自动分类归档​​图书馆系统​​:扫描图书条形码快速建立电子档案​​医疗档案管理​​:通过药品条形码整理医疗图片资料​​仓储管理​​:自动化识…

【C++】 —— 笔试刷题day_22

一、添加字符 题目解析 这道题&#xff0c;给定两个字符串A和B&#xff0c;字符串A的长度要小于B的长度&#xff1b; 现在我们要对A字符串添加字符&#xff0c;使得A字符串长度等于B字符串的长度&#xff0c;并且要求对应位置的字母尽量相等&#xff0c;然后求出来不相等的字符…

【Android面试八股文】Android应用进程的启动流程【二】

应用进程 1.1 Android系统进程的启动过程&#xff1a; 1、init进程fork出Zygote进程后&#xff0c;Zygote进程会创建一个服务端socket&#xff0c;等待AMS发起socket请求。 同时&#xff0c;由Zygote进程fork出的SystemServer进程会启动各项系统服务&#xff0c;其中就包含了A…

“星睿O6” AI PC开发套件评测 - 部署PVE搭建All in One NAS服务器

Radxa O6平台上部署PVE搭建All in One NAS服务器 Radxa O6是一款性能卓越的单板计算机&#xff0c;其强劲的硬件配置和多样化的接口设计&#xff0c;使其成为家庭和小型企业理想的All in One服务器解决方案。值得一提的是&#xff0c;O6原生配备了两个5G网口&#xff0c;便于直…

全志H5,NanopiKP1lus移植QT5.12记录

移植步骤 机器环境下载QT5.12.0源码安装交叉编译器修改qmake.conf文件配置编译选项qt5的configure选项说明基本配置选项编译器和链接器选项功能模块配置第三方库集成注意事项 配置过程报错解决配置完成编译过程报错解决编译完成将arm-qt文件夹传送到开发板配置板子环境变量运行…

使用EXCEL绘制平滑曲线

播主播主&#xff0c;你都多少天没更新了&#xff01;&#xff01;&#xff01;泥在干什么&#xff1f;你还做这个账号麻&#xff1f;&#xff01;&#xff01;&#xff01; 做的做的&#xff08;哭唧唧&#xff09;&#xff0c;就是最近有些忙&#xff0c;以及…… 前言&…

Warcraft Logs [Classic] [WCL] Usage Wizard <HTOC>

‌HTOC&#xff08;十字军的试炼&#xff09;副本中各个BOSS的ID如下‌&#xff1a; ‌629 - 诺森德野兽‌ ‌633 - 加拉克苏斯大王‌ ‌637 - 派系冠军‌ ‌641 - 瓦格里双子‌ ‌645 - 阿努巴拉克‌ encounterID!637 and encounterID!641 encounterID NOT IN (637,641) 伤害 …