梯度提升树(GBDT)原理与Python实现

前言

看完统计学习方法有一段时间了,一直拖着没有总结。临近期末,复习完课程再去学新的知识过于疲劳,就想着把之前决定写的总结都给补一下。统计学习方法实现基本也差不多完成了(还有一两章寒假慢慢补吧),所有代码详见github(包括决策树,逻辑回归,SVM,梯度提升树,Adaboost,隐马尔可夫模型等)。所有实现都有很详细的注释,如果能够帮助到你的话就可以点个赞吧~

正文

回归树

  在讲梯度提升树之前,先简单了解下回归树。因为GBDT中每一轮对残差拟合的都是回归树(无论是用GBDT做回归还是分类)。
  在CART算法中,回归树均为二叉树,内部节点特征值作为分割点,左边分支对应特征值小于该切分点,右边分支对应特征值大于该切分点。对于每个分支递归的寻找特征值与切分点,最后将输入空间(即特征空间)划分为了有限的单元(也就是叶节点),然后在在每一个单元上给出预测的值作为最终输出。
  

下面我们思考一下回归树的生成

  首先我们有输入变量X与输出变量Y。共同构成训练集D{(x1,y1),(x2,y2)…(xn,yn)}
  假定我们已经划分好了一棵树,它将输入空间划分为R1,R2,…,Rm总共m个单元(叶节点)。在每一个单元上预测值为cm。那么回归树可以表示为 f ( x ) = ∑ m = 1 M c m I ( x i ϵ R m ) f(x)=\sum_{m=1}^{M} c_{m}I (x_i \epsilon R_m ) f(x)=m=1McmI(xiϵRm)
  在每一个叶节点上,我们的损失函数使用MSE(均方误差)来衡量我们预测的准确性,则在该叶节点上损失为 L m = ∑ x ϵ R m ( y i − c m ) 2 L_m=\sum_{x\epsilon Rm}(y_{i}-c_m)^2 Lm=xϵRm(yicm)2
  那么我们怎么获得使得每一个叶节点上的损失最小呢。我们以cm为参数,对损失函数求导,令其为0,即可获得cm最佳值。如果你对于求和符号很不习惯,你可以试试一项一项的写,然后对每一个二次项中的cm求导,所有二次项相加和为0,得到cm即叶节点上所有值的均值。还是做个示范吧
∂ L m ∂ c m = ( y 1 − c m ) + ( y 2 − c m ) + . . . + ( y n − c m ) = 0 \frac{\partial L_m}{\partial c_m}=(y_1-c_m)+(y_2-c_m)+...+(y_n-c_m)=0 cmLm=(y1cm)+(y2cm)+...+(yncm)=0
c m = a v g ( y i ∣ x i ϵ R m ) c_m=avg(y_i|x_i\epsilon R_m) cm=avg(yixiϵRm)
  当我们获得了叶节点,基于以上我们就知道了如何获取最佳预测值了。那么下面的任务就是如何对于对输入空间进行划分呢。
  我们采用启发式的划分法,遍历所有可能的划分特征以及每一个特征对应的值,尝试以该值作为切分点构建左右节点。注意,回归树的分裂准则也是MSE。那么,我们就只需要找到划分之后似的左右节点MSE之和最小的特征与特征值作为切分变量(split variable)与切分点(split point)。假设当前选取第j个变量与其取值s,则左右区域R1与R2为: R 1 ( j , s ) = ( x ∣ x ( j ) < = s ) R_{1(j,s)}= (x|x^{(j)}<=s) R1(j,s)=(xx(j)<=s), R 2 ( j , s ) = ( x ∣ x ( j ) > s ) R_{2(j,s)}= (x|x^{(j)}>s) R2(j,s)=(xx(j)>s)

则我们遍历所有切分特征与切分点,求解
min ⁡ j , s [ min ⁡ c 1 ∑ x i ∈ R 1 ( j , s ) ( y i − c 1 ) 2 + min ⁡ c 2 ∑ x i ∈ R 2 ( j , s ) ( y i − c 2 ) 2 ] \min _{j, s}\left[\min _{c_{1}} \sum_{x_{i} \in R_{1}(j, s)}\left(y_{i}-c_{1}\right)^{2}+\min _{c_{2}} \sum_{x_{i} \in R_{2}(j, s)}\left(y_{i}-c_{2}\right)^{2}\right] j,sminc1minxiR1(j,s)(yic1)2+c2minxiR2(j,s)(yic2)2
从而获得最解切分变量与切分点。其中,确定切分之后,c1,c2的值为
c 1 = a v g ( y i ∣ x i ϵ R 1 ( j , s ) ) ) c1=avg(yi|xi\epsilon R_{1(j,s))}) c1=avg(yixiϵR1(j,s)))
c 2 = a v g ( y i ∣ x i ϵ R 2 ( j , s ) ) ) c2=avg(yi|xi\epsilon R_{2(j,s))}) c2=avg(yixiϵR2(j,s)))

最小二乘回归树生成算法

最小二乘回归树生成算法

回归提升树

  在进入正题之前,再简单说说回归提升树。提升树模型使用的前向分步算法,模型是决策树的加法模型。首先确定初始提升树 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0。则在第m步的时候,模型就是 f m ( x ) = f m − 1 ( x ) + T ( x ; θ m ) f_m(x)=f_{m-1}(x)+T(x; \theta_m) fm(x)=f

### VMD去噪原理 变分模态分解(Variational Mode Decomposition, VMD)是一种自适应信号分解方法,能够将复杂信号分解成若干个固有模态函数(Intrinsic Mode Function, IMF),并保留原始信号的主要特征[^1]。VMD通过构建一个约束优化问题来实现信号的分解,在此过程中引入了中心频率的概念,使得各IMF之间具有明确的频域分离特性。 #### 原理概述 VMD的核心思想是假设待分解信号由多个不同频率范围内的子信号组成,并利用交替方向乘法器(ADMM)求解最优解。具体来说,它试图找到一组满足以下条件的最佳IMF集合: - 各IMF的能量集中在特定的窄带范围内; - 所有IMF之和等于原信号。 其数学表达形式如下: \[ \min_{\{u_k,\omega_k\}} \left\{\sum_{k=1}^{K}\int_0^\infty |\hat{u}_k(\omega)|^2 d\omega + \lambda \|f(t)-\sum_{k=1}^K u_k(t)\|^2 \right\} \] 其中 \( K \) 表示分解后的模式数量,\( \lambda \) 是惩罚因子用于平衡重构误差稀疏性之间的关系。 --- ### PyCharm 中实现 VMD 的步骤 在 Python 环境下可以借助 `pyvmd` 库完成 VMD 分解操作。以下是具体的实现方式以及代码示例。 #### 安装依赖库 首先需要安装必要的第三方库,可以通过 pip 工具快速完成安装: ```bash pip install pyvmd numpy matplotlib scipy ``` #### 实现代码 下面是一个完整的 VMD 去噪实例代码,展示如何加载数据、执行 VMD 分解并绘制结果图。 ```python import numpy as np from pyvmd import vmd import matplotlib.pyplot as plt # 数据生成:创建带有噪声的正弦波作为测试信号 fs = 1000 # 采样率 Hz t = np.linspace(0, 1, fs, endpoint=False) freqs = [5, 25, 50] # 频率成分 amplitudes = [1, 0.5, 0.2] # 幅度大小 signal_clean = sum([amp * np.sin(2 * np.pi * freq * t) for amp, freq in zip(amplitudes, freqs)]) noise = np.random.normal(0, 0.3, signal_clean.shape) signal_noisy = signal_clean + noise # 参数设置 alpha = 2000 # 惩罚参数 tau = 0 # 时间延迟平滑系数 DC = 0 # 是否去除直流偏移 init = 1 # 初始化方式 tol = 1e-7 # 收敛容忍阈值 K = 3 # 分解得到的模态数目 # 调用 VMD 函数进行分解 imfs, _, _ = vmd(signal_noisy, alpha, tau, K, DC, init, tol) # 绘制结果 plt.figure(figsize=(10, 6)) plt.subplot(K+1, 1, 1) plt.plot(t, signal_noisy, 'b') plt.title('Original Noisy Signal') for i in range(K): plt.subplot(K+1, 1, i+2) plt.plot(t, imfs[i], 'r') plt.title(f'IMF {i+1}') plt.tight_layout() plt.show() # 提取主要成分重建干净信号 reconstructed_signal = sum(imfs[:2]) # 取前两个 IMFs 进行合成 plt.figure() plt.plot(t, reconstructed_signal, label='Reconstructed Clean Signal', color='g') plt.legend() plt.show() ``` 上述代码实现了以下几个功能模块: 1. **信号生成**:构造了一个包含三个频率分量的纯净信号,并加入随机高斯白噪声形成污染信号。 2. **调用 VMD 方法**:指定合适的超参配置后对混合信号实施分解。 3. **可视化输出**:分别展示了原始含噪信号及其对应的各个内在模态函数曲线;最后还给出了基于选定几个重要模态重新组合而成的新版净化版本号。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值