最近有一个朋友询问关于XGBoost的MATLAB代码。我想起三年前在五一数学建模比赛中使用过这个模型。当时找了很久的MATLAB代码却没找到,最终只能找人用Python来跑。因此,这次不仅是为了回答朋友的问题,也是为了弥补三年前的遗憾。同时考虑到其他同学也可能遇到类似的问题,所以决定写这篇博客。
我在国内的网站查了下,发现很多答案要安装xgboost工具箱,比如:在Matlab中运行xgboost的函数 - 文件交换 - MATLAB Central (mathworks.com)
【MATLAB第9期】基于MATLAB的xgboost算法安装超详细教学(踩坑避雷指南)暂时仅限于Windows系统 #末尾含源码获取链接_xgboost matlab-CSDN博客
要么就是直接上mbd进行付费。
然后查了下国外的发现一篇回答:
其中提到:
原来,xgboost不是机器学习算法。而是是梯度增强的有效实现。那就好办多了,因为MATLAB提供了几种与XGBoost类似的梯度提升解决方案::
分类:
fitcensemble
:用于分类的集成模型,包括AdaBoostM1、GentleBoost和LogitBoost。
回归:
fitrensemble
:用于回归的集成模型,如LSBoost和Bagging。
这时候,就有人问了,那么什么是梯度提升回归呢?!
这里,已经有了非常清楚的解释了!:https://en.wikipedia.org/wiki/Gradient_boosting
小刘,就简简单单的翻译下:
梯度提升回归(Gradient Boosting Regression)
梯度提升回归是一种通过逐步构建多个弱学习器(如决策树)来提高模型预测性能的集成学习方法。
初始化模型
用常数预测初始模型,通常为目标变量 (y) 的均值:
F
0
(
x
)
=
arg
min
c
∑
i
=
1
n
L
(
y
i
,
c
)
F_0(x) = \arg\min_c \sum_{i=1}^{n} L(y_i, c)
F0(x)=argcmini=1∑nL(yi,c)
其中,(L) 是损失函数,通常为均方误差。
计算残差
对于第 (m) 次迭代,计算当前模型的残差(即目标值与当前模型预测值之间的差):
r
i
(
m
)
=
−
[
∂
L
(
y
i
,
F
m
−
1
(
x
i
)
)
∂
F
m
−
1
(
x
i
)
]
r_i^{(m)} = -\left[ \frac{\partial L(y_i, F_{m-1}(x_i))}{\partial F_{m-1}(x_i)} \right]
ri(m)=−[∂Fm−1(xi)∂L(yi,Fm−1(xi))]
训练新的弱学习器
在残差上训练一个新的弱学习器(如决策树)
h
m
(
x
)
h_m(x)
hm(x),以拟合残差:
h
m
(
x
)
=
arg
min
h
∑
i
=
1
n
(
r
i
(
m
)
−
h
(
x
i
)
)
2
h_m(x) = \arg\min_h \sum_{i=1}^{n} \left( r_i^{(m)} - h(x_i) \right)^2
hm(x)=arghmini=1∑n(ri(m)−h(xi))2
更新模型
将新学习器加权后加入当前模型中:
F
m
(
x
)
=
F
m
−
1
(
x
)
+
γ
m
h
m
(
x
)
F_m(x) = F_{m-1}(x) + \gamma_m h_m(x)
Fm(x)=Fm−1(x)+γmhm(x)
其中,
γ
m
\gamma_m
γm 是学习率,控制模型对新学习器的权重。
重复迭代
重复计算残差、训练新模型和更新模型的过程,直到达到预定的迭代次数或其他停止条件。
优点
- 高预测性能:通过结合多个弱学习器,能有效提高模型的预测精度。
- 灵活性强:可以处理多种数据类型和复杂关系。
缺点
- 计算量大:训练过程较慢,尤其是在大数据集上。
- 参数调优复杂:需要仔细调节多个超参数,以防止过拟合。
总而言之,梯度提升回归(Gradient Boosting Regression)是一种集成学习方法,通过逐步构建多个弱学习器(如决策树),每个新学习器都在前一模型的残差上进行训练,以最小化损失函数。模型初始化为常数预测,逐步更新,每次迭代中计算残差,训练新学习器,并将其加权加入当前模型。其高预测性能和灵活性使其适用于复杂的回归问题。
好了,现在就是code环节了^^
这里的数据集我用的kaggle里面的案例
https://www.kaggle.com/datasets/naniruddhan/fetal-health-prediction-data/code
如果下不到的请发邮件给lizus01@163.com
clc
clear
close all
% 加载数据集
data = readtable("fetal_health.csv");
% 将特征和目标变量分开
X = data{:, 1:end-1}; % 特征
Y = data{:, end}; % 目标变量
% 划分训练集和测试集
cv = cvpartition(size(Y, 1), 'HoldOut', 0.2);
X_train = X(training(cv), :);
Y_train = Y(training(cv));
X_test = X(test(cv), :);
Y_test = Y(test(cv));
% 初始化均方误差数组和预测结果存储
mseValues = zeros(1, 1);
Y_pred_all = zeros(size(Y_test));
% 训练模型并保存
t = templateTree('MaxNumSplits', 5); % 基学习器为决策树
Mdl = fitrensemble(X_train, Y_train, 'Method', 'LSBoost', 'Learners', t, 'NumLearningCycles', 100, 'LearnRate', 0.1);
% 保存模型
save('Model.mat', 'Mdl');
% 加载模型并进行预测
loadedData = load('Model.mat');
Mdl = loadedData.Mdl;
% 预测测试集
Y_pred = predict(Mdl, X_test);
Y_pred_all = Y_pred;
% 计算均方误差
mseValues = mean((Y_test - Y_pred).^2);
% 显示均方误差
disp('均方误差:');
disp(mseValues);
% 将数据分成两部分
midPoint = floor(length(Y_test) / 2);
Y_test_part1 = Y_test(1:midPoint);
Y_pred_part1 = Y_pred_all(1:midPoint);
Y_test_part2 = Y_test(midPoint+1:end);
Y_pred_part2 = Y_pred_all(midPoint+1:end);
% 绘制预测与实际值的对比图(第一部分)
figure;
plot(Y_test_part1, 'b', 'DisplayName', '实际值');
hold on;
plot(Y_pred_part1, 'r--', 'DisplayName', '预测值');
xlabel('样本');
ylabel('胎儿健康');
legend show;
title('胎儿健康预测值与实际值对比 - 第一部分');
% 绘制预测与实际值的对比图(第二部分)
figure;
plot(Y_test_part2, 'b', 'DisplayName', '实际值');
hold on;
plot(Y_pred_part2, 'r--', 'DisplayName', '预测值');
xlabel('样本');
ylabel('胎儿健康');
legend show;
title('胎儿健康预测值与实际值对比 - 第二部分');