系列文章目录
监督学习:参数方法
【学习笔记】 陈强-机器学习-Python-Ch4 线性回归
【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归
【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv)
【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归
【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析
【学习笔记】 陈强-机器学习-Python-Ch8 朴素贝叶斯
【学习笔记】 陈强-机器学习-Python-Ch9 惩罚回归
【课后题练习】 陈强-机器学习-Python-Ch9 惩罚回归(student-mat.csv)
监督学习:非参数方法
【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch10 KNN法
【学习笔记】 陈强-机器学习-Python-Ch11 决策树(Decision Tree)
集成学习
【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch12 随机森林(Random Forest)
文章目录
- 系列文章目录
- 前言
- 一、集成学习:提升法(Boosting)
- 二、回归提升树
-
- [1. 载入数据+数据处理](#1. 载入数据+数据处理)
- [2. 回归提升树的估计](#2. 回归提升树的估计)
- [3. 选出最优超参数组合](#3. 选出最优超参数组合)
- [4. 变量重要性](#4. 变量重要性)
- [5. 偏依赖图](#5. 偏依赖图)
- [6. 考察 *M* 对MSE的影响](#6. 考察 M 对MSE的影响)
- 三、二分类提升树
-
- [1. 载入数据+数据处理](#1. 载入数据+数据处理)
- [2. 自适应提设法AdaBoost](#2. 自适应提设法AdaBoost)
-
-
- [`笔记:AdaBoostClassifier ()`](#
笔记:AdaBoostClassifier ()
)
- [`笔记:AdaBoostClassifier ()`](#
-
- [3. 使用逻辑损失函数进行二分类问题的梯度提升法](#3. 使用逻辑损失函数进行二分类问题的梯度提升法)
- [4. 最优超参数组合](#4. 最优超参数组合)
- 5.变量重要性
- [6. 偏依赖图](#6. 偏依赖图)
- [7. 预测](#7. 预测)
- 四、多分类提升树
-
- [1. 载入数据+数据处理](#1. 载入数据+数据处理)
- [2. 多分类问题的梯度提升法](#2. 多分类问题的梯度提升法)
- [3. 最优超参数组合](#3. 最优超参数组合)
- 5.变量重要性
- [6. 偏依赖图](#6. 偏依赖图)
- [7. 预测](#7. 预测)
- [五、XGBoost 算法](#五、XGBoost 算法)
前言
本学习笔记 仅为以防自己忘记了,顺便分享给一起学习的网友们参考。如有不同意见/建议,可以友好讨论。
本学习笔记 所有的代码和数据都可以从 陈强老师的个人主页 上下载
参考书目:陈强.机器学习及Python应用. 北京:高等教育出版社, 2021.
数学原理等 详见陈强老师的 PPT
参考了:网友阡之尘埃的Python机器学习10------梯度提升
一、集成学习:提升法(Boosting)
集成学习(Ensemble Learning)方法通过结合多个模型的预测结果来减少单个模型可能出现的过拟合和偏差,提高预测性能和稳定性。
主要的集成学习方法包括:Bagging(Bootstrap Aggregating),Boosting,Stacking(Stacked Generalization),Voting。
集成学习 | 随机森林 | 提升法(Boosting) |
---|---|---|
组合策略 | 尽量使决策树之间不相关 | 考虑基学习器序列 ,使得每个基学习器正好弥补之前所有基学习器的缺点 |
位置 | 每棵决策树的作用完全对称,可随便更换决策树的位置 | 每棵决策树的作用并不相同,这些依次而 种的决策树之间的相对位置不能随意变动。 |
袋外误差 | 使用自助样本,故可计算袋外误差 | 基于原始样本,故一般无法 计算袋外误差,,但可使用不同的观测值权重 |
Boosting 是一种 "序贯集成法"(sequential ensemble approach) :通过顺序 训练多个基学习器,每个新学习器都关注之前学习器未能正确分类的数据。最终模型是所有学习器预测的加权和 。
Boosting 方法的核心思想是通过逐步改进模型来减少预测错误。
常见的Boosting方法:
- AdaBoost (Adaptive Boosting,自适应提升) :仅适用于分类 问题。通过加权样本来调整每个基学习器的关注点。
1)初始化时为每个样本分配相同的权重。
2)训练第一个基学习器,并计算其在训练数据上的错误率。
3)基于错误率调整每个样本的权重,使得之前被错分类的样本权重增加。
4)训练下一个基学习器,重点关注调整后的样本权重。
5)最终模型是所有基学习器的加权和,其中每个基学习器的权重与其准确率有关。 - Gradient Boosting(简记GBM,梯度提升) :通过最小化损失函数的梯度来训练新的基学习器。
1)初始化模型为一个简单的模型(例如均值预测)
2)计算当前模型对训练数据的残差(真实值 - 预测值)。
3)训练新的基学习器来预测这些残差。
4)更新模型,将新学习器的预测结果加到当前模型中。
5)重复上述步骤,直到达到指定的基学习器数量或误差收敛。 - XGBoost (Extreme Gradient Boosting,极端坡度提升) :一种高效的 Gradient Boosting 实现,支持各种优化和正则化技术。
1)XGBoost 是对 Gradient Boosting 的一种优化实现。它通过引入正则化、剪枝和并行计算来提高模型的效率和准确性。
2)采用了二阶梯度信息进行优化,使得训练过程更快、更准确。
二、回归提升树
使用波士顿房价数据boston (参考【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 &【学习笔记】 陈强-机器学习-Python-Ch11 决策树(Decision Tree) & 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch12 随机森林(Random Forest) )
我不知道该怎么跟你们解释,我的结果很多都和陈强老师书上的不一样......麻了......
1. 载入数据+数据处理
python
import numpy as np
import pandas as pd
# 从原始来源加载数据
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep=r"\s+", skiprows=22, header=None)
# 处理数据
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]
# 创建DataFrame
columns = [
"CRIM", "ZN", "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD", "TAX",
"PTRATIO", "B", "LSTAT"
]
df = pd.DataFrame(data, columns=columns)
df['MEDV'] = target
# 确定特征
X = df.drop(columns=['MEDV'])
y = df['MEDV']
# 将数据分割为训练集(70%)和测试集(30%)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=1)
2. 回归提升树的估计
python
from sklearn.ensemble import GradientBoostingRegressor
model = GradientBoostingRegressor(random_state=123)
model.fit(X_train, y_train)
model.score(X_test, y_test)
结果输出: 0.9214598819200858
笔记:GradientBoostingRegressor()
GradientBoostingRegressor 是 scikit-learn 库中的一个类,用于回归任务。它实现了梯度提升回归(Gradient Boosting Regression),用于通过组合多个弱学习器(通常是决策树)的预测来提高回归模型的性能。
python
#基本语法和参数
from sklearn.ensemble import GradientBoostingRegressor
# 初始化模型
model = GradientBoostingRegressor(
n_estimators=100, #训练的提升阶段的数量(即树的数量)默认值: 100
learning_rate=0.1, #学习率,用于缩小每棵树的贡献。默认值: 0.1
max_depth=3, #每棵树的最大深度。默认值: 3
min_samples_split=2, #内部节点再分裂所需的最小样本数。默认值: 2
min_samples_leaf=1, #叶节点上所需的最小样本数。默认值: 1
subsample=1.0, #用于拟合每棵基学习器的样本比例。默认值: 1.0
criterion='squared_error', #衡量节点分裂质量的标准。默认值: 'squared_error'。可选:'friedman_mse'
loss='squared_error') #损失函数,用于优化目标。默认值: 'squared_error'(适用于普通的回归任务)。可选:'absolute_error','huber'(对异常值有一定的鲁棒性), 'quantile'(适用于分位回归)
基本属性
train_score_
训练集上的得分,通常是对数损失的序列。用于诊断模型在训练过程中的表现。estimators_
所有基学习器(决策树)的列表。包含训练过程中的每棵树。类型:listn_estimators_
提升阶段的数量,即训练的树的数量。类型:intfeature_importances_
为特征的重要性learning_rate
学习率,控制每棵树对最终预测的影响。max_depth
每棵决策树的最大深度。min_samples_split
内部节点再分裂所需的最小样本数。min_samples_leaf
叶节点上所需的最小样本数。subsample
每棵基学习器的样本比例。类型: floatloss
损失函数的名称。类型: str
对比:线性回归
python
from sklearn.linear_model import LinearRegression
LinearRegression().fit(X_train, y_train).score(X_test, y_test)
结果输出: 0.7836295385076302 远低于回归提升树
3. 选出最优超参数组合
回归提升树 (boosted regression tree)的超参数 较多:
- 决策树的数量 M M M:一般可使用交叉验证选择
- 决策树的分裂次数 d d d(交互深度 i n t e r a c t i o n d e p t h interaction depth interactiondepth):一般建议选择 d = 4 8 d=4~8 d=4 8
- 学习率(learning rate,也称为收缩参数shrinkage parameter) 0 < η < 1 0<η<1 0<η<1:通常选择 η = 0.1 或 0.01 η=0.1 或 0.01 η=0.1或0.01
python
from sklearn.model_selection import KFold, StratifiedKFold
from sklearn.model_selection import RandomizedSearchCV #随机搜索超参数空间
param_distributions = { #param_distributions = {...}:定义一个字典,指定要搜索的超参数范围
'n_estimators': range(1, 300), # n_estimators(树的数量)的取值范围是从 1 到 299。
'max_depth': range(1, 10), # max_depth(树的最大深度)的取值范围是从 1 到 9。
'subsample': np.linspace(0.1,1,10), # subsample(样本的子采样比例)的取值范围是从0.1到1,共10个均匀间隔的值。
'learning_rate': np.linspace(0.1, 1, 10)} #learning_rate(学习率)的取值范围是从0.1到1,共10个均匀间隔的值。
kfold = KFold(n_splits=10, shuffle=True, random_state=1)
model = RandomizedSearchCV( #创建一个RandomizedSearchCV对象,用于在指定的超参数分布上进行随机搜索
estimator=GradientBoostingRegressor(random_state=123), #使用GradientBoostingRegressor作为基模型
param_distributions=param_distributions, #传入之前定义的超参数分布字典
cv=kfold,
n_iter=100, #在超参数空间随机搜索100次
random_state=0)
model.fit(X_train, y_train)
#最优超参数s
model.best_params_
结果输出:
{'subsample': 0.30000000000000004, 'n_estimators': 83, 'max_depth': 8, 'learning_rate': 0.1}
和陈强老师书上的不一样......
最优模型(最优超参数组合定义的)
python
model = model.best_estimator_ #.best_estimator_属性:使用最优超参数定义最优模型
model.score(X_test, y_test)
结果输出: 0.8520437464755751
和陈强老师书上的不一样......但陈强老师书上的R2也小于默认值的拟合优度
4. 变量重要性
python
import matplotlib.pyplot as plt
sorted_index = model.feature_importances_.argsort()
plt.barh(range(X.shape[1]), model.feature_importances_[sorted_index])
plt.yticks(np.arange(X.shape[1]), X.columns[sorted_index])
plt.xlabel('Feature Importance')
plt.ylabel('Feature')
plt.title('Gradient Boosting')
plt.tight_layout()
5. 偏依赖图
python
from sklearn.inspection import PartialDependenceDisplay
PartialDependenceDisplay.from_estimator(model, X, ['LSTAT', 'RM'])
6. 考察 M 对MSE的影响
1)超参数组合(我的)
python
# for循环:找出最优M
from sklearn.metrics import mean_squared_error
scores = []
for n_estimators in range(1, 301):
model_my = GradientBoostingRegressor(
n_estimators=n_estimators,
subsample=0.3,
max_depth=8,
learning_rate=0.1,
random_state=123)
model_my.fit(X_train, y_train)
pred = model_my.predict(X_test)
mse = mean_squared_error(y_test, pred)
scores.append(mse)
index = np.argmin(scores)
range(1, 301)[index]
结果输出: 27
python
plt.plot(range(1, 301), scores)
plt.axvline(range(1, 301)[index], linestyle='--', color='k', linewidth=1)
plt.axhline(min(scores), linewidth=1, linestyle='--', color='r')
# 标记交点
best_m = range(1, 301)[index]
min_mse = min(scores)
plt.scatter(best_m, min_mse, color='b', zorder=5)
plt.text(best_m, min_mse,
f'({best_m}, {min_mse:.6f})',
horizontalalignment='right',
verticalalignment='bottom', fontsize=11, color='b')
plt.xlabel('Number of Trees')
plt.ylabel('MSE')
plt.title('MSE on Test Set')
2)超参数组合(书上的)
python
# for循环:找出最优M
from sklearn.metrics import mean_squared_error
#
scores = []
for n_estimators in range(1, 301):
model = GradientBoostingRegressor(
n_estimators=n_estimators,
subsample=0.5,
max_depth=5,
learning_rate=0.1,
random_state=123)
model.fit(X_train, y_train)
pred = model.predict(X_test)
mse = mean_squared_error(y_test, pred)
scores.append(mse)
index = np.argmin(scores)
range(1, 301)[index]
结果输出: 137 还是和陈强老师的结果不一样......笑哭
python
plt.plot(range(1, 301), scores)
plt.axvline(range(1, 301)[index], linestyle='--', color='k', linewidth=1)
plt.axhline(min(scores), linewidth=1, linestyle='--', color='r')
# 标记交点
best_m = range(1, 301)[index]
min_mse = min(scores)
plt.scatter(best_m, min_mse, color='b', zorder=5)
plt.text(best_m, min_mse,
f'({best_m}, {min_mse:.6f})',
horizontalalignment='right',
verticalalignment='bottom', fontsize=11, color='b')
plt.xlabel('Number of Trees')
plt.ylabel('MSE')
plt.title('MSE on Test Set')
虽然我的图看起来差距有点大,但是这个主要是想说明:增加提升树的决策树数目,并不容易导致过拟合
另,我怀疑我的数据没对,但是我没有证据。我交叉验证出来的subsample是0.3,但是subsample 的值通常在 0.5 到 1.0 之间(直接从 0.1 开始可能不常见,因为较低的值(如 0.1 或 0.2)可能会导致训练集样本太少,影响模型的学习能力)。
三、二分类提升树
使用Hastie et al. (2009)的垃圾邮件数据spam.csv (参考【学习笔记】 陈强-机器学习-Python-Ch8 朴素贝叶斯 )
1. 载入数据+数据处理
python
import pandas as pd
import numpy as np
#读取CSV文件的路径
csv_path = r'D:\桌面文件\Python\【陈强-机器学习】MLPython-PPT-PDF\MLPython_Data\spam.csv'
spam = pd.read_csv(csv_path)
#定义X与y
X = spam.iloc[:, :-1]
y = spam.iloc[:, -1]
#全样本随机分20%测试集和80%训练集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=0)
2. 自适应提设法AdaBoost
python
from sklearn.ensemble import AdaBoostClassifier
model = AdaBoostClassifier(random_state=123)
model.fit(X_train, y_train)
model.score(X_test, y_test)
结果输出: 0.9489685124864278
笔记:AdaBoostClassifier ()
AdaBoostClassifier 是 scikit-learn 库中实现的 AdaBoost(Adaptive Boosting)算法的一个类。AdaBoost 是一种集成学习方法,通过加权组合多个弱分类器来提高分类性能。
它从训练集开始,首先训练一个弱分类器,然后根据分类错误的样本重新加权,接着训练下一个弱分类器,并重复这一过程。最终的分类器是所有弱分类器的加权组合。
python
#基本语法和参数
from sklearn.ensemble import AdaBoostClassifier
# 初始化 AdaBoostClassifier
model = AdaBoostClassifier(
base_estimator=None, #基础分类器,即弱学习器。默认值: None(即 DecisionTreeClassifier(max_depth=1))
n_estimators=50, #要训练的弱分类器的数量。默认值: 50
learning_rate=1.0, #学习率,用于缩小每个弱分类器的贡献。默认值: 1.0
algorithm='SAMME.R', #训练算法的类型。默认值: 'SAMME.R'(基于概率估计)
random_state=None)
基本属性
classes_
模型在训练期间观察到的类别标签。类型: numpy.ndarrayestimators_
训练后的基础分类器的列表。类型:listn_estimators_
训练过程中使用的弱分类器的数量。类型:intfeature_importances_
为特征的重要性coef_
在训练过程中计算的分类器的系数。仅在基础分类器支持系数(例如线性模型)时可用。类型: numpy.ndarraydecision_function
决策函数的值,即每个样本的预测分数。predict_proba
每个样本的类别概率。对于多类别任务,这个方法返回每个类别的概率。predict_log_proba
每个样本类别的对数概率。对数概率是类别概率的对数值。
3. 使用逻辑损失函数进行二分类问题的梯度提升法
python
from sklearn.ensemble import GradientBoostingClassifier
GBC=GradientBoostingClassifier(random_state=123)
GBC.fit(X_train, y_train)
GBC.score(X_test, y_test)
结果输出: 0.9543973941368078 高于AdaBoost
这之后的输出数据,就没有和陈强老师一样的了
4. 最优超参数组合
python
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import KFold, StratifiedKFold
param_distributions = {'n_estimators': range(1, 300),
'max_depth': range(1, 10),
'subsample': np.linspace(0.1, 1, 10),
'learning_rate': np.linspace(0.1, 1, 10)}
kfold = KFold(n_splits=10, shuffle=True, random_state=1)
model = RandomizedSearchCV(
estimator=GradientBoostingClassifier(random_state=123),
param_distributions=param_distributions,
cv=kfold, n_iter=10, random_state=66)
model.fit(X_train, y_train)
#最优超参数组合
model.best_params_
结果输出: {'subsample': 0.7000000000000001, 'n_estimators': 279, 'max_depth': 3, 'learning_rate': 0.30000000000000004}
和陈强老师书上的又不一样......
python
#最优模型
model = model.best_estimator_
model.score(X_test, y_test)
结果输出: 0.9359391965255157
......比默认参数还低......
5.变量重要性
python
import matplotlib.pyplot as plt
sorted_index = model.feature_importances_.argsort()
plt.barh(range(X.shape[1]), model.feature_importances_[sorted_index])
plt.yticks(np.arange(X.shape[1]), X.columns[sorted_index])
plt.xlabel('Feature Importance')
plt.ylabel('Feature')
plt.title('Gradient Boosting')
plt.tight_layout()
和书上比,虽然变量重要性排序没有吧,但是变量重要性的数值有变化
6. 偏依赖图
python
from sklearn.inspection import PartialDependenceDisplay
PartialDependenceDisplay.from_estimator(model, X, ['A.52', 'A.53'])
7. 预测
python
pred = model.predict(X_test)
table = pd.crosstab(
y_test,
pred,
rownames=['Actual'],
colnames=['Predicted'])
table
python
table = np.array(table)
Accuracy = (table[0, 0] + table[1, 1]) / np.sum(table)
Sensitivity = table[1 , 1] / (table[1, 0] + table[1, 1])
Specificity = table[0, 0] / (table[0, 0] + table[0, 1])
Recall = table[1, 1] / (table[0, 1] + table[1, 1])
print(f'准确率: {Accuracy}')
print(f'敏感度: {Sensitivity}')
print(f'特异度: {Specificity}')
print(f'召回率: {Recall}')
from sklearn.metrics import cohen_kappa_score
cohen_kappa_score(y_test, pred)
结果输出: 准确率: 0.9359391965255157
敏感度: 0.9201101928374655
特异度: 0.946236559139785
召回率: 0.9175824175824175
0.8659299339013035
python
#画ROC曲线
from sklearn.metrics import RocCurveDisplay
RocCurveDisplay.from_estimator(
model,
X_test,
y_test,
plot_chance_level=True)
plt.title('ROC Curve for Random Forest')
四、多分类提升树
使用玻璃种类数据Glass.csv (参考【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 )
1. 载入数据+数据处理
python
import pandas as pd
import numpy as np
#读取CSV文件的路径
csv_path = r'D:\桌面文件\Python\【陈强-机器学习】MLPython-PPT-PDF\MLPython_Data\Glass.csv'
Glass = pd.read_csv(csv_path)
#定义X与y
X = Glass.iloc[:, :-1]
y = Glass.iloc[:, -1]
#全样本随机分20%测试集和80%训练集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, stratify=y, random_state=0)
2. 多分类问题的梯度提升法
python
from sklearn.ensemble import GradientBoostingClassifier
GBC=GradientBoostingClassifier(random_state=123)
GBC.fit(X_train, y_train)
GBC.score(X_test, y_test)
结果输出: 0.7846153846153846
笔记:GradientBoostingClassifier()
GradientBoostingClassifier 是 scikit-learn 库中实现的梯度提升分类器。它是基于梯度提升(Gradient Boosting)算法的集成学习模型,通常用于分类任务。GradientBoostingClassifier 构建了一个集成的模型,通过迭代地训练弱分类器(通常是决策树),并在每一步上最小化损失函数来提高分类性能。
python
#基本语法和参数
from sklearn.ensemble import GradientBoostingClassifier
# 初始化 GradientBoostingClassifier
model = GradientBoostingClassifier(
n_estimators=100, #要训练的提升树的数量。默认值: 100
learning_rate=0.1, #学习率(也称为步长),用于缩小每个树的贡献。默认值: 0.1
max_depth=3, #每棵树的最大深度。默认值: 3
min_samples_split=2, #内部节点再划分所需的最小样本数。默认值: 2
min_samples_leaf=1, #每棵树叶子节点的最小样本数。默认值: 1
max_features=None, #每棵树在寻找最佳分裂时考虑的最大特征数。默认值: None
subsample=1.0, #每棵树训练时使用的样本比例。默认值: 1.0
random_state=None)
基本属性
oob_score_
仅当 subsample < 1.0 时存在,返回基于袋外样本的模型得分。estimators_
训练过程中生成的所有提升树的列表。类型:listn_estimators_
实际使用的基学习器数量。类型:intfeature_importances_
特征的重要性classes_
训练数据中出现的类别标签。类型: numpy.ndarray
3. 最优超参数组合
python
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import KFold, StratifiedKFold
param_distributions = {'n_estimators': range(1, 300),
'max_depth': range(1, 10),
'subsample': np.linspace(0.1, 1, 10),
'learning_rate': np.linspace(0.1, 1, 10)}
kfold = KFold(n_splits=5, shuffle=True, random_state=1)
model = RandomizedSearchCV(
estimator=GradientBoostingClassifier(random_state=123),
param_distributions=param_distributions,
cv=kfold, random_state=66)
model.fit(X_train, y_train)
#最优超参数组合
model.best_params_
结果输出: {'subsample': 0.7000000000000001, 'n_estimators': 279, 'max_depth': 3, 'learning_rate': 0.30000000000000004}
python
#最优模型
model = model.best_estimator_
model.score(X_test, y_test)
结果输出: 0.7384615384615385 竟然和书上的最优模型一样!!!明明最优参数都不一样!!!
5.变量重要性
python
import matplotlib.pyplot as plt
sorted_index = model.feature_importances_.argsort()
plt.barh(range(X.shape[1]), model.feature_importances_[sorted_index])
plt.yticks(np.arange(X.shape[1]), X.columns[sorted_index])
plt.xlabel('Feature Importance')
plt.ylabel('Feature')
plt.title('Gradient Boosting')
plt.tight_layout()
6. 偏依赖图
python
from sklearn.inspection import PartialDependenceDisplay
PartialDependenceDisplay.from_estimator(model, X, ['Mg'], target=1) #第一类玻璃对于Mg的依赖
7. 预测
python
pred = model.predict(X_test)
table = pd.crosstab(
y_test,
pred,
rownames=['Actual'],
colnames=['Predicted'])
table
五、XGBoost 算法
参考了:网友阡之尘埃的Python机器学习10------梯度提升
网友Forever__ _的XGBoost的简单安装及入门使用
网友王小王-123的机器学习分类算法之XGBoost(集成学习算法)
网友theskylife的XGBoost系列3------XGBoost在多分类问题中的应用
网友WilenWu的Python手册(Machine Learning)--XGBoost
1. 安装
python
#没有梯子:使用清华的镜像
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xgboost
#有梯子
pip install xgboost
1. 回归案例
1)载入、处理数据
python
import numpy as np
import pandas as pd
# 从原始来源加载数据
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep=r"\s+", skiprows=22, header=None)
# 处理数据
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]
# 创建DataFrame
columns = [
"CRIM", "ZN", "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD", "TAX",
"PTRATIO", "B", "LSTAT"
]
df = pd.DataFrame(data, columns=columns)
df['MEDV'] = target
# 确定特征
X = df.drop(columns=['MEDV'])
y = df['MEDV']
# 将数据分割为训练集(70%)和测试集(30%)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=1)
2)XGBoost 回归提升树 估计
python
import xgboost as xgb
model = xgb.XGBRegressor(
objective='reg:squarederror', #'reg'回归问题,'squarederror'误差平方为损失函数
n_estimators=300,
max_depth=6,
subsample=0.6,
colsample_bytree=0.8,
learning_rate=0.1,
random_state=0)
model.fit(X_train, y_train)
model.score(X_test, y_test)
结果输出: 0.9045137226664561
笔记:xgb.XGBRegressor()
xgb.XGBRegressor() 是 XGBoost 库中的一个类,用于解决回归问题。XGBoost(eXtreme Gradient Boosting)是一个高效的实现梯度提升算法的库,广泛用于机器学习中的回归、分类和排序任务。它是基于决策树算法的集成方法,通过构建多个模型并组合它们的预测结果来提高预测的准确性和稳定性。
python
#基本语法和参数
import xgboost as xgb
model = xgb.XGBRegressor(
n_estimators=100, #要构建的树的个数。默认100
max_depth=3, #每棵树的最大深度。默认3
learning_rate=0.1, #每棵树对最终结果的贡献。默认0.1
subsample=1.0, #控制对于每棵树,随机采样的比例。默认1
colsample_bytree=1.0, #每棵树随机采样的列数的比例。默认1。
gamma=0, #叶子节点进一步分裂所需的最小损失减少量。
reg_alpha=0.1, # 权重的 L1(Lasso回归)
reg_lambda=1.0, # L2(Ridge回归)正则化项
objective='reg:squarederror' #指定学习任务和相应的学习目标。回归问题通常是 'reg:squarederror'(回归任务中的平方误差)。
)
基本属性
best_score_
在启用早停机制(early stopping)的情况下,该属性记录了验证集上的最佳评分。
python
#例
model.fit(
X_train, y_train,
eval_set=[(X_valid, y_valid)],
early_stopping_rounds=50, # 如果在50轮迭代中验证集性能没有改进,停止训练
verbose=True
)
best_iteration_
在启用早停机制的情况下,记录了获得最佳评分的迭代轮数。best_ntree_limit_
在某些任务(如多类分类)中,记录了最佳迭代时的树的数量。对于回归任务,通常等于 best_iteration + 1。feature_importances_
特征的重要性evals_result_
如果在训练过程中传入了验证集,并设置了评估指标,evals_result_ 将存储每一轮迭代后所有评估集的评估指标结果。objective_
展示了模型使用的目标函数。
3) 预测
python
#在测试集中预测
pred = model.predict(X_test)
#计算RMSE
from sklearn.metrics import mean_squared_error
rmse = np.sqrt(mean_squared_error(y_test, pred))
rmse
结果输出: 2.958334966542201
4)交叉验证 xgb.cv()
python
#设定 参数组合
params = {'objective': 'reg:squarederror',
'max_depth': 6,
'subsample': 0.6,
'colsample_bytree': 0.8,
'learning_rate': 0.1}
#将数据矩阵 转换为xgboost模块的优化数据结构
dtrain = xgb.DMatrix(data=X_train, label=y_train)
type(dtrain) #查看数据类型
结果输出: xgboost.core.DMatrix
python
#交叉验证: xgb.cv()
results = xgb.cv(dtrain=dtrain,
params=params,
nfold=10,
metrics="rmse",
num_boost_round=300,
as_pandas=True,
seed=123)
print(results.shape)
results.tail() #查看最后5行结果
结果输出: (300, 4)
train-rmse-mean train-rmse-std test-rmse-mean test-rmse-std
295 0.024094 0.003777 3.227561 0.691520
296 0.023757 0.003767 3.227541 0.691629
297 0.023405 0.003694 3.227594 0.691549
298 0.023001 0.003616 3.227625 0.691553
299 0.022642 0.003568 3.227630 0.691486
笔记:xgb.cv()
xgb.cv() 是 XGBoost 库中一个用于交叉验证的函数,它允许用户评估模型的性能。这个函数非常有用,因为它可以帮助你了解模型在不同子集的数据上的稳定性和效果,而不是依赖于单一的训练集和验证集。
python
#基本语法和参数
import xgboost as xgb
xgb.cv(params, #提升算法的参数。类型:字典
dtrain, #训练数据集的 XGBoost DMatrix 对象
num_boost_round=10, #提升迭代的轮数,默认为 10。
nfold=3, #交叉验证的折数,默认为 3。
stratified=False, #是否进行分层抽样,适用于分类问题。
folds=None, #定义交叉验证分割策略(如果指定)。
metrics=(), #评估指标名称,如rmse、mae、logloss等。
obj=None, #自定义的目标函数
feval=None, #自定义的评估函数
maximize=False, #是否最大化 feval。默认为 False。
early_stopping_rounds=None, #交叉验证将在指标在指定轮数内没有改进时停止。
fpreproc=None, #数据预处理函数,用于在每一轮的交叉验证前对数据进行处理。
as_pandas=True, #是否以 pandas DataFrame 的形式返回结果,默认为 True。
verbose_eval=None, # 如何显示进程信息。如果为 True,则每一轮都打印;如果为整数,则每该数的迭代次数打印一次。
show_stdv=True, #是否显示每次迭代的标准差。
seed=0,
callbacks=None, #是否显示每次迭代的标准差。
shuffle=True) #是否在生成折叠前对数据进行洗牌。
5)图:训练误差 v.s. 测试误差
python
# 训练误差 v.s. 测试误差
import matplotlib.pyplot as plt
plt.plot(range(1, 301), results['train-rmse-mean'], 'k', label='Training Error')
plt.plot(range(1, 301), results['test-rmse-mean'], 'b', label='Test Error')
plt.xlabel('Number of Trees')
plt.ylabel('RMSE')
plt.axhline(0, linestyle='--', color='k', linewidth=1)
plt.legend()
plt.title('CV Errors for XGBoost')
2. 二分类问题
1)载入、处理数据
python
import pandas as pd
import numpy as np
# 读取数据
csv_path = r'D:\桌面文件\Python\【陈强-机器学习】MLPython-PPT-PDF\MLPython_Data\spam.csv'
spam = pd.read_csv(csv_path)
X = spam.iloc[:, :-1]
y = spam.iloc[:, -1]
# 标签编码(因为y_train中的标签是字符串(如 'email' 和 'spam'),但XGBClassifier需要数值型标签(通常是0和1))
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)
# 切分数据
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y_encoded, test_size=0.2, stratify=y_encoded, random_state=0)
2)XGBoost 分类回归
python
# 创建并训练模型
import xgboost as xgb
model = xgb.XGBClassifier(
objective='binary:logistic',
n_estimators=300,
max_depth=6,
subsample=0.6,
colsample_bytree=0.8,
learning_rate=0.1,
random_state=0)
model.fit(X_train, y_train)
结果输出:
python
#测试集的预测准确率
model.score(X_test, y_test)
结果输出: 0.9522258414766558
笔记:xgb.XGBClassifier()
xgb.XGBClassifier() 是一个实现 XGBoost (eXtreme Gradient Boosting) 算法的分类器,主要用于高效地执行梯度增强。这种分类器非常适合解决分类问题,尤其是在数据集很大或者特征维度较高的情况下。
python
#基本语法和参数
import xgboost as xgb
# 创建模型
model = xgb.XGBClassifier(
n_estimators=100,
max_depth=3,
learning_rate=0.1,
verbosity=1, #运行时打印的消息的详细程度;有效值为0(静默)、1(警告)、2(信息)、3(调试)。默认为1
objective='binary:logistic', #指定学习任务和相应的学习目标或自定义的目标函数。默认为'binary:logistic'
booster='gbtree', #选择每次提升使用的模型,有三种可选:'gbtree', 'gblinear' 或 'dart'。默认为'gbtree'
tree_method='hist', #树构建算法,如 'auto', 'exact', 'approx', 'hist' 等。'hist' 对于较大数据集效率更高。
gamma=0,
min_child_weight=0,#决定最小叶子节点样本权重和。较大的值会导致更保守的模型。
subsample=1.0, #训练每棵树时样本的抽样比例
colsample_bytree = 1.0, #构建每棵树时特征的抽样比例。
reg_alpha = 0, #L1
reg_lambda = 1, #L2
scale_pos_weight =99 #类别极不平衡的标签类中用于平衡正负权重。
)
3) 预测
python
prob = model.predict_proba(X_test)
prob[:5, :]
结果输出:
array([[4.8689306e-02, 9.5131069e-01],
[9.9934453e-01, 6.5544987e-04],
[9.4766611e-01, 5.2333903e-02],
[9.9834830e-01, 1.6516910e-03],
[9.9934453e-01, 6.5544987e-04]], dtype=float32)
python
pred = model.predict(X_test)
pred[:5]
结果输出: array([1, 0, 0, 0, 0])
python
#混淆矩阵
pd.crosstab(
y_test, pred,
rownames=['Actual'],
colnames=['Predicted'])