【LLM】从零开始学大语言模型 | 3 | RNN

序列建模的演进与困境:彻底理解 RNN、LSTM 与 GRU 前言 在上一篇文章中,我们学会了把文字变成计算机可以处理的向量——词向量,相当于拿到了处理文字的"数字砖块"。接下来的问题自然是:如何把这些砖块砌成一面能理解"上下文"的墙?语言天生带有顺序,同样几个词,顺序不同,意思可能完全相反。本文将讲述早期的研究者如何试图给模型装上"记忆",以及这些尝试为何最终走入死局。只有把这份"痛"理解透彻,日后才能真正体会 Transformer 带来的范式革命。 全文将沿着三个问题展开:RNN 是干什么的?它靠什么机制实现?它又卡在了哪里? 一、MLP 是"失忆"的,而语言是有顺序的 回顾一下多层感知机(MLP,也就是神经网络的基本形态)。从数学上看,一个训练好的 MLP 就是一个固定的函数 $y = f(x)$:输入 $x$,经过逐层的线性变换与非线性激活,得到输出 $y$。这里要注意"函数"二字的含义——每一次调用都是独立的。你输入 $x_1$ 得到 $y_1$,再输入 $x_2$ 得到 $y_2$,这两次计算在底层完全不共享任何内部状态,前一次输入对后一次输出没有任何影响。换句话说,MLP 没有记忆:处理完一个输入就忘,根本不知道上一个输入是什么。 但语言恰恰是讲究顺序的。“我打了他"和"他打了我”,词完全一样,仅因顺序不同,意思就完全相反。如果把每个词独立地喂进 MLP,模型看到的只是一堆孤立的词,看不见顺序,也看不见上下文。这就像一页一页随机抽着读一本书,永远拼不出完整的情节。 因此,要处理语言,就需要一种带记忆的结构:它在处理当前输入时,能够同时参考"之前发生过什么"。这正是循环神经网络(Recurrent Neural Network, RNN)的出发点。 二、先明确目标:RNN 最终输出什么? 在讲机制之前,有必要先说清楚 RNN 是用来干什么的。不知道目的,就很容易在过程的细节里迷路。 RNN 的目的,是处理变长的序列数据(文本、语音等),把它压缩成包含上下文信息的向量,或者直接输出另一个序列,从而完成分类、翻译、预测等任务。具体而言,最典型的任务形态有三种: 多对一(Many-to-One):输入一整句话,输出一个标签。典型例子是情感分类:模型依次读入"这 / 电影 / 太 / 棒 / 了",读完最后一个词后,给出"正面 95%、负面 5%“这样的判断,目的是分辨这句话是夸还是骂。 序列到序列(Seq2Seq):输入一个序列,输出另一个序列。典型例子是机器翻译:一个 RNN 作为编码器(Encoder)读入中文"我 / 爱 / 你”,把整句话压缩成一个浓缩语义的上下文向量;另一个 RNN 作为解码器(Decoder)依据这个向量,逐个词地生成英文"I → love → you"。 多对多(Many-to-Many):每读入一个词,同时输出一个标签。典型例子是词性标注:对"我 / 吃 / 苹果",模型同步输出 [代词, 动词, 名词],用于分析句子的语法结构。 ...

August 21, 2026 · 3 min · 535 words · c.w.

【LLM】从零开始学大语言模型 | 2 | 词嵌入

从 One-Hot 到词嵌入:让计算机理解文字的语义空间 自然语言处理要解决的第一件事,其实非常朴素:怎样把人类语言变成计算机能够计算、能够学习、能够比较的数学对象。 一句话看起来很简单,比如:我喜欢吃苹果。但对计算机来说,这串文字本身并不能直接参与矩阵乘法、梯度下降和概率计算。计算机擅长处理的是数字,尤其是连续的、可以进行加减乘除和求导的数值。因此,自然语言处理的第一步,就是把“文字符号”转换成“数值表示”。 这篇文章将从最基础的 One-Hot 编码讲起,逐步过渡到现代深度学习中广泛使用的词嵌入,也就是 Word Embedding。我们会解释为什么 One-Hot 编码虽然简单却不够好,词向量为什么能够表达语义,Word2Vec 是如何训练出词向量的,以及现代大模型中的 Embedding 层和中文 Tokenization 又是怎么一回事。 理解这些内容,是后续理解 Transformer、注意力机制以及大语言模型中各种矩阵运算的重要前提。 一、计算机的“文字障碍” 计算机本质上处理的是数字。更准确地说,是基于二进制数值进行算术运算和逻辑运算。如果我们把一句话直接交给模型,例如:我喜欢吃苹果模型并不能天然理解“我”“喜欢”“吃”“苹果”这些符号意味着什么。它们只是字符,是离散的语言单位。 这里至少有三个困难。 1. 文字是离散符号 语言中的词或者字,本质上是离散符号。我们可以说“苹果”和“香蕉”都是水果,但很难说“苹果”比“香蕉”大多少。数字则不同。对于数值 3 和 5,我们可以说 5 比 3 大,差值是 2。这种连续性让数学运算变得自然。但词语之间没有这种天然的数值大小关系。因此,我们需要人为设计一种数值表示,使离散符号能够进入连续数学空间。 2. 词汇量很大,容易造成维度灾难 人类语言的词汇量非常庞大。中文有常用字、生僻字、词语、成语、专有名词;英文有单词、词形变化、缩写、外来词。一个实际语言系统的词表规模可能从几万到几十万不等。如果用最朴素的方法,每个词占用一个独立维度,那么向量维度会变得非常高。假设词表有 10 万个词,那么每个词都需要一个 10 万维向量来表示。这会带来严重的稀疏性和计算负担。 3. 普通编码无法表达语义关系 人类语言中,词与词之间存在复杂关系。例如: “猫”和“狗”都是常见动物; “苹果”和“香蕉”都是水果; “医生”和“医院”经常共同出现; “国王”和“女王”之间存在性别对应关系。 如果只是简单给每个词编号,计算机无法知道这些关系。我们需要一种表示方法,使得语义相近的词在数值空间中也更接近。 换句话说,我们希望把离散符号变成连续的、低维的、带有语义结构的数学对象,通常是向量。这就是词嵌入要解决的问题。 二、One-Hot编码:最朴素的词表示方法 最直观的想法是:给词典里的每个词编号,然后用一个向量来表示它。 假设我们的词典只有 4 个词["苹果", "香蕉", "猫", "狗"],我们可以这样表示: 1 2 3 4 苹果 = [1, 0, 0, 0] 香蕉 = [0, 1, 0, 0] 猫 = [0, 0, 1, 0] 狗 = [0, 0, 0, 1] 这种表示方法叫作 One-Hot 编码,也叫独热编码 它的意思是:每个词对应一个向量,向量中只有一个位置是 1,其余位置全是 0。这个 1 的位置代表该词在词表中的编号 如果词表大小为 $V$,那么每个词都可以表示成一个 $V$ 维向量。设某个词的索引为 $i$,则它的 One-Hot 向量记作: ...

August 21, 2026 · 4 min · 723 words · c.w.

【LLM】从零开始学大语言模型 | 1 | 神经网络和多层感知机

一、从生物神经元到人工感知机 深度学习的名字里带有“神经”二字,是因为它最初的灵感来自生物神经元。一个生物神经元大致是这样工作的:树突接收来自其他神经元的信号,细胞体对这些信号进行整合;当总信号超过某个阈值时,神经元就会被激活,并通过轴突向外发出脉冲。人工感知机就是对这一过程的高度简化。1957 年前后,Frank Rosenblatt 提出了人工感知机模型。它的数学表达非常简单: $$y = f(W^T x + b)$$ 也可以写成: $$y = f\left(\sum_{i=1}^{n} w_i x_i + b\right)$$ 其中: $x$ 是输入特征向量。例如一张图片的像素值、一个样本的若干数值特征; $W$ 是权重向量,表示每个输入特征的重要程度; $b$ 是偏置,可以理解为一个阈值,决定神经元是否容易被激活; $f$ 是激活函数,或者说输出函数; $y$ 是神经元的输出。 很多初学者第一次看到这个公式时会问:这里的 $f$ 到底是什么?是不是一个 0/1 函数?这个猜测是有道理的。在最早的感知机模型中,$f$ 确实常常是阶跃函数: $$ f(z)= \begin{cases} 1, & z > 0 \\ 0, & z \le 0 \end{cases} $$ 也就是说,从二维来看,如果加权求和的结果大于 0,输出 1;否则输出 0。这看起来就是一个硬性的二分类器。从几何上看,感知机在输入空间中定义了一个超平面: $$ W^T x + b = 0 $$ 这个超平面把数据分成两类:一侧输出 1,另一侧输出 0。在二维空间里,它是一条直线;在三维空间里,它是一个平面;在更高维空间里,它是超平面。因此,感知机本质上是一个线性分类器。 不过,阶跃函数虽然直观,却有一个严重问题:它在 $z=0$ 处不可导。不可导意味着我们无法用微积分中的链式法则去计算梯度,也就很难通过“误差反向传播”来更新参数。所以,在现代神经网络中,感知机公式里的 $f$ 通常不再是阶跃函数,而是更平滑、至少几乎处处可导的函数,例如 Sigmoid、Tanh、ReLU 等。这些函数统称为激活函数。就是说,今天当我们写: ...

August 21, 2026 · 6 min · 1252 words · c.w.

【量化】从零到LGBM | 9 | LGBM的金融应用(下):模型解释、进阶方向与完整工作流

LightGBM 量化实战篇(下):SHAP 解释、进阶方向与完整工作流 前两篇分别讨论了金融数据的截面预处理与保守调参、排序学习目标函数与 Purged 交叉验证。至此,量化 LightGBM 的基础框架已经搭建完成:数据被正确处理,模型以合理的方式训练和验证。 但基础框架的完成并不意味着工作的结束。模型上线后,一系列更深层次的问题会接踵而来:基金经理需要知道"模型今天为什么选这些股票"、模型运行数月后效果开始衰减该怎么办、是否可以让模型直接优化 Rank IC、深度学习能否与 LightGBM 互补。本篇将逐一讨论这些问题,并在最后将全部流程串联为一个完整的八步工作流。 一、SHAP:打开 LightGBM 的黑盒 在量化机构中,模型的可解释性并非可选项,而是刚需。基金经理、风控部门、投资委员会都会提出这样的问题:今天为什么选择这些股票?模型是否在依赖某个异常因子?近期的收益究竟来自真正的 Alpha 还是某个风格暴露?回撤发生后能否定位具体原因? LightGBM 由成百上千棵树组成,直接理解其决策逻辑几乎不可能。SHAP 是目前最为广泛使用的模型解释工具。 1. SHAP 的直觉:公平分配边际贡献 SHAP(Shapley Additive exPlanations)的理论基础源于博弈论中的 Shapley Value。可以借助一个直观的例子来理解:假设三人合作赚取了 100 万元,如何分配才算公平?平均分配未必合理,因为每个人的贡献并不相同。Shapley Value 的思路是:考察每个人在所有可能的加入顺序下的边际贡献,然后对所有排列取平均值。 映射到特征上,公式是: $$\phi_i = \sum_{S \subseteq F \setminus {i}} \frac{|S|!(|F|-|S|-1)!}{|F|!} \left[ v(S \cup {i}) - v(S) \right]$$ 其中 $S$ 是不包含特征 $i$ 的特征子集,$v(S)$ 是仅使用集合 $S$ 中特征时模型的预测值,$\phi_i$ 是特征 $i$ 的 Shapley 值。该公式的具体形式无需记忆,其核心含义可概括为一句话:SHAP 旨在公平地量化模型最终预测中每个特征的贡献度。 2. 在 LightGBM 选股中,SHAP 解释什么? 假设模型为某只股票输出了 $+3.0%$ 的预测分数,SHAP 可以将这一预测分解为: ...

August 21, 2026 · 2 min · 402 words · c.w.

【量化】从零到LGBM | 8 | LGBM的金融应用(中):排序学习、对冲与交叉验证

LightGBM 量化实战篇(中):排序学习、Beta 对冲与 Purged 交叉验证 上一篇讨论了金融数据的特殊性质、截面预处理方法和保守的超参数调优策略。完成这些环节后,我们已经知道如何将金融数据正确地处理并喂入 LightGBM。但还有一个关键问题尚未回答:模型的优化目标应该是什么? 回归目标(预测绝对收益率)和排序目标(学习股票的相对强弱)是两种截然不同的思路。选定目标函数后,还需要理解选股得到的相对强弱如何转化为实际收益,以及如何通过严格的交叉验证确保模型没有偷看未来数据。这三个问题构成了本篇的核心内容。 一、排序学习:让模型直接回答"谁更强" 量化选股中存在一个核心认知:我们关注的并非绝对收益预测的精度,而是排序的正确性。假设模型预测 A 涨 3.1%、B 涨 2.9%,而实际 A 涨 1.2%、B 涨 1.0%,绝对收益的预测值与实际值差距显著,但排序关系是正确的。当投资组合仅持有排名前若干只股票时,排序的正确性已经满足需求。因此,目标函数的设计应当与这一目标保持一致。 1. 回归目标的问题 LightGBM 默认支持回归目标,比如最小化均方误差: $$\mathcal{L} = \sum_i (y_i - \hat{y}_i)^2$$ 直接以未来收益率作为标签、训练模型预测绝对收益,会面临多方面的挑战:收益率本身噪声含量高,精确预测具体的涨跌幅极其困难;收益率分布具有显著的厚尾特征,少数暴涨或暴跌的股票会严重拉偏均方误差的优化方向;模型倾向于将优化资源集中在拟合中间区域的普通股票上,而投资者真正关注的恰恰是头部和尾部的标的;此外,投资组合的构建仅依赖相对排序,而非绝对预测值。因此,回归目标并非量化选股的最优选择。 2. LambdaRank:直接学排序 LightGBM 支持排序学习目标(objective = "lambdarank")。其核心思路并非预测具体的收益率数值,而是学习一个排序分数。在每个交易日,股票的因子特征输入模型后,输出一个连续的 score 值: $$s_{i,t} = f(x_{i,t})$$ 这个 score 既不是排名也不是概率,而是一个纯粹用于排序的数值。以下是一个输出示例: 股票 模型分数 A 2.51 B 2.13 C 0.87 D -0.42 按分数从大到小排列,即为模型给出的股票强弱顺序。 训练过程中,模型可以获取真实标签(例如经未来收益率排序后划分的等级)。使用 lambdarank 时,需要传入 group 信息,以告知模型哪些样本属于同一组。在日频选股场景中,每个交易日即为一个 group: 1 group = [4000, 4020, 3980, ...] # 每天有多少只股票 训练数据必须按照 group 信息进行排序,同一天的股票数据需要连续排列。 ...

August 21, 2026 · 3 min · 611 words · c.w.

【量化】从零到LGBM | 7 | LGBM的金融应用(上):数据预处理与保守调参

LightGBM 量化实战篇(上):金融数据特性、截面处理与保守调参 前六篇文章聚焦于 LightGBM 的算法本身——树的分裂机制、GBDT 的残差拟合框架、XGBoost 引入二阶导数的意义,以及 LightGBM 通过 Histogram 和 Leaf-wise 策略实现的效率提升。那些内容属于算法原理的范畴。 但当 LightGBM 被部署到真实的股票市场中时,算法本身的精巧并不能保证结果的可靠。数据是否被正确地喂入模型、标签如何定义、回测切分如何避免未来信息泄露、模型表现异常时如何诊断——这些问题在 Kaggle 等标准竞赛中鲜少遇到,但在量化投资中却是决定成败的关键环节。 本系列共三篇,围绕一个核心问题展开:如何在量化场景中正确地使用 LightGBM。第一篇讨论金融数据的特殊性质、截面预处理方法和保守的超参数调优策略——这些是模型训练之前必须解决的输入端问题。 一、金融数据与普通机器学习数据的差异 有过机器学习实践经验的读者或许熟悉这样的工作流:在猫狗图片分类、房价预测等任务中,完成特征工程、选择合适的模型、调优超参数,性能指标通常就能稳步提升。然而,将同样的流程移植到股票市场中,往往会出现一种令人困惑的现象——回测阶段表现优异,实盘阶段却大幅失效。 这一落差的根源并不在于 LightGBM 算法本身,而在于金融数据区别于一般机器学习数据的特殊性质。 1. 信噪比极低 在图像分类任务中,猫的视觉特征是稳定且可辨识的;房价与面积之间的关系也具有较好的统计稳定性。但股票收益率的构成远为复杂——宏观消息、资金流向、散户情绪、政策变动、短期流动性冲击、纯粹的随机波动交织在一起。其中真正具有预测价值的成分,仅占收益率总体波动的很小一部分。信号微弱而噪声强大,这是金融数据最本质的特征。 因此,量化建模的评估标准不应聚焦于模型在历史数据上的拟合精度,而应关注其在未见数据上的预测稳定性。 2. 分布不稳定(概念漂移) 图像分类的决策边界不会因为日历翻页而改变,但金融市场的运行规律始终处于动态漂移之中。小市值风格可能在今年有效而明年失效;动量策略可能连续三年盈利,随后进入长达一年半的回撤期;某个量价规律一旦被市场参与者广泛识别,拥挤交易效应便会迅速侵蚀其超额收益。 这就是所谓的 Concept Drift(概念漂移)。金融市场中的规律并非物理定律,它是参与者博弈的产物。当参与者的结构和行为模式发生变化时,原本有效的规律也会随之改变。 因此,量化模型的设计应当趋于保守。对于那些缺乏坚实经济学解释、仅在特定时段表现出统计显著性的规律,应当审慎对待。模型应当优先捕捉那些更为普适、更经得起时间检验的模式。 3. 排序比绝对值重要 在量化选股场景中,模型并不需要精确预测某只股票明天的涨幅是 2.1% 还是 2.3%。假设市场中有 5000 只股票,投资组合最终可能只持有排名前 100 只。模型的核心价值在于能否准确地将这 100 只股票从全部标的中识别出来——具体的绝对收益预测值并非关键,排序的正确性才是核心。 这一认知对后续目标函数的选择具有直接的指导意义。 二、截面处理:量化数据预处理的灵魂 在标准机器学习流程中,特征工程的常规做法是对整个数据集进行统一的标准化处理——对所有样本减去均值、除以标准差。然而,股票数据的结构决定了这种方法并不适用。 股票数据本质上是面板数据(Panel Data):横轴为某一天的全部上市股票,纵轴为时间序列。在任意一个交易日,所有股票的数据集合构成一个截面(Cross-Section)。许多量化因子在绝对数值层面的含义并不稳定,真正具有信息量的是截面内的相对位置。 1. 为什么绝对数值靠不住? 以市盈率(PE)为例。假设有两只股票,A 的 PE 为 15,B 的 PE 为 100。表面上看 A 似乎更便宜,但实际情况远比这复杂。牛市中流动性充裕,市场整体估值中枢上移,PE=100 并不罕见;熊市中估值中枢下移,PE=15 也未必代表低估。此外,不同行业天然具有不同的合理估值区间——同一年内,电子行业与银行行业的 PE 量级差异极大。如果直接将绝对数值输入模型,模型很容易学到表面化的规律,例如"某年 PE 低的股票表现好",并将低 PE 泛化为一条通用规则。然而,当宏观环境切换后,这类规律往往会迅速失效。 ...

August 21, 2026 · 3 min · 475 words · c.w.

【量化】从零到LGBM | 6 | LGBM代码实现和调用

LightGBM 代码实现 在上一篇文章中,我们从数学和工程设计的角度拆解了 LightGBM 的四大核心机制。本文主要来记录其代码实现。 本文分两部分回答这个问题。第一部分,我们用几百行伪代码,从零手搓一个"麻雀虽小、五脏俱全"的迷你LightGBM第二部分,我们带着手搓时拧过的每一颗"螺丝",去学习如何正确使用 LightGBM 的 Python 官方接口。 第一部分:手搓 LightGBM 0. 总体设计:先看清整张图纸 在写代码之前,我们先明确这个迷你版本要包含哪些功能,以及它们的组装顺序: EFB 特征捆绑:在数据进入模型之前,把互斥的稀疏特征合并降维(预处理阶段); 离散分箱:把连续特征值映射为整数桶编号(直方图的地基); GOSS 采样:每轮迭代时,保留大梯度样本、采样小梯度样本; 直方图构建与作差:以 $O(N)$ 的代价统计梯度信息,分裂时用减法省一半计算; Leaf-wise 生长:用优先队列实现"谁增益大谁分裂"的精英制,并用正则化参数套上缰绳; 提升主循环:每轮对"当前预测值"求一二阶导数,建一棵树,累加进模型。 这个顺序与 LightGBM 真实源码的数据流向是一致的。下面逐块实现。 1. 目标函数:先明确 $g$ 和 $h$ 从哪来 上一篇我们反复强调:一阶导 $g_i$ 和二阶导 $h_i$ 是对当前模型预测值求导的结果,下标 $i$ 表示第 $i$ 个样本。在代码里,这就是一个极其简单的函数。以平方损失 $L=\frac{1}{2}(\hat{y}_i-y_i)^2$ 为例: 1 2 3 4 5 6 7 import numpy as np def grad_hess(pred, y): """对预测值求导:g 是一阶导(误差推力),h 是二阶导(曲率)""" g = pred - y # dL/d(pred) h = np.ones_like(y) # d2L/d(pred)2,平方损失下恒为 1 return g, h 注意这个接口的通用性:如果换成分类任务,只需要把损失换成对数似然,$g$ 和 $h$ 换成对应的导数即可,后面所有的树构建代码一行都不用改。这正是 GBDT 框架"泛函梯度下降"的优雅之处——树只关心梯度,不关心具体任务。 ...

August 20, 2026 · 8 min · 1506 words · c.w.

【量化】从零到LGBM | 5 | LGBM

LightGBM 解析:更快的工程学 在机器学习的集成学习领域,如果说 GBDT 奠定了“泛函梯度下降”的理论基石,XGBoost 通过二阶泰勒展开和正则化将其推向了精度的巅峰,那么 LightGBM(Light Gradient Boosting Machine) 则是将这一框架在工程实现与计算效率上做到极致的集大成者。 随着量化金融、推荐系统等领域的数据量呈指数级爆炸(如全市场高频 Tick 数据、千万级用户行为日志),传统的树模型在内存和算力上开始捉襟见肘。2017 年,微软亚洲研究院的团队推出了 LightGBM。它的名字直白地揭示了其使命:Light(轻量、极速) + GBM(梯度提升树)。 本文将剥离繁杂的表象,深入 LightGBM 的数学内核与底层数据结构,探讨它是如何通过四大核心“黑科技”,在不损失(甚至提升)模型精度的前提下,实现对传统算法的降维打击。 一、 痛点剖析:XGBoost 在海量数据下的工程瓶颈 要理解 LightGBM 的伟大,首先必须看清 XGBoost 在面对海量数据时暴露出的两块致命短板。尽管 XGBoost 引入了加权分位数素描(Weighted Quantile Sketch)等近似算法,但其底层架构依然存在两个难以逾越的鸿沟: 1. 预排序(Pre-sorted)的内存与时间枷锁 在 XGBoost 中,为了寻找最佳的特征切分点,算法必须在每一棵树开始构建之前,将所有样本按照每一个特征的值进行全局精确排序,并将其存储在特定的内存块(Block)中。 时间代价:对千万级样本的单个特征进行排序,时间复杂度为 $O(N \log N)$。如果有 100 个特征,排序本身的开销就极其庞大。 空间代价:存储排序后的数据结构需要消耗巨大的内存。当数据量达到几十 GB 时,极易导致内存溢出(OOM),且频繁的内存读写会严重破坏 CPU 的缓存命中率。 2. Level-wise(按层生长)的计算浪费 XGBoost 默认采用 Level-wise 的树生长策略,即“大锅饭”模式:第一层分裂 2 个节点,第二层分裂 4 个节点,以此类推。 这种策略的死板之处在于:哪怕当前层中某些节点分裂后带来的增益(Gain)微乎其微,算法也会为了“凑齐这一层”而强行分裂。这不仅产生了大量无效的废节点,浪费了宝贵的计算资源,还增加了模型过拟合的风险。 针对这两个痛点,LightGBM 从数据结构、生长策略、采样机制和特征工程四个维度进行了彻底的重构。 二、 核心突破一:Histogram 直方图算法 —— 彻底抛弃全局排序 这是 LightGBM 提速和节省内存的最核心武器。许多初学者在接触直方图算法时,容易产生概念上的混淆,我们需要从数学本质和算法复杂度上进行深度拆解。 ...

August 20, 2026 · 2 min · 328 words · c.w.

【量化】从零到LGBM | 4 | XGBoost

XGBoost :把 GBDT 做到更优 在机器学习的集成学习领域,GBDT(Gradient Boosting Decision Tree)以其"泛函梯度下降"的本质,奠定了基于树的模型的理论基石。然而,将理论推向工程巅峰、在 2015 年前后横扫几乎所有结构化数据竞赛和量化私募 Baseline 的,是陈天奇博士提出的 XGBoost(eXtreme Gradient Boosting)。 XGBoost 并非推翻 GBDT,而是在其框架下,对**目标函数(如何计算梯度)和树的生长方式(如何寻找分裂点)**进行了极其精妙的改造。本文将深入 XGBoost 的数学内核与工程细节,带你理解这个"一代霸主"的真正精髓。 一、从一阶到二阶:泰勒展开带来的精度飞跃 1.1 GBDT 的局限:只看"坡度" 在前序课程中,我们了解到 GBDT 利用**一阶梯度(负梯度)**来决定树的生长方向。这就好比下山时,你只用脚试探哪边是下坡(一阶导数),然后朝那个方向走。这种方式虽然有效,但过于粗糙,你无法判断前方是平缓的斜坡还是陡峭的悬崖。 1.2 XGBoost 的改进:同时看"坡度"和"曲率" XGBoost 引入了二阶泰勒展开,这正是牛顿法的思想。假设当前模型为 $F_{t-1}(x)$,我们要添加一棵新树 $f_t(x)$,新的目标函数可以近似展开为: $$Obj \approx \sum_{i=1}^N \left[ L(y_i, F_{t-1}(x_i)) + g_i f_t(x_i) + \frac{1}{2} h_i f_t^2(x_i) \right]$$ 其中: $g_i$:损失函数对当前预测值的一阶导数(梯度),代表"误差有多大" $h_i$:损失函数对当前预测值的二阶导数(海塞矩阵),代表"误差变化的剧烈程度(曲率)" 直观理解:如果将优化过程比作开车下山,一阶导数相当于方向盘和油门,告诉你该往哪边走;二阶导数则相当于路况感知系统,告诉你前方是平缓斜坡(可以踩大油门)还是急转弯(必须减速)。有了二阶信息,模型能够更精准地预测下一步该迈多大,从而更快、更稳地到达最优解。 1.3 为什么止步于二阶? 一个自然的疑问是:既然二阶比一阶好,为什么不继续引入三阶导数甚至更高阶? 答案在于边际收益递减与工程成本的权衡。从数学角度看,二阶导数(牛顿法)已经能够找到非常精确的局部最优解,更高阶导数对找到"谷底"的帮助微乎其微。从工程角度看,计算、存储和聚合三阶导数的开销会呈指数级上升。 更重要的是,在金融等信噪比极低的场景中,用三阶导数去追求那 0.01% 的精度提升,大概率只是将市场噪音拟合得更准,实盘表现反而更差。二阶导数恰好在"拟合能力"和"抗噪鲁棒性"之间达到了完美的平衡。 二、正则化项:给模型戴上"紧箍咒" 2.1 目标函数的完整形式 这是 XGBoost 被称为"X-treme(极致)“的最重要原因。传统 GBDT 的目标函数只有损失项,而 XGBoost 的目标函数为: $$Obj = \sum_{i=1}^N L(y_i, \hat{y}i) + \sum{t=1}^T \Omega(f_t)$$ ...

August 20, 2026 · 2 min · 373 words · c.w.

【量化】从零到LGBM | 3 | GBDT

GBDT:梯度提升树与函数空间中的梯度下降 在集成学习的两大流派中,Boosting 的核心思想是串行训练多个弱学习器,让每一棵新树都集中纠正前面所有树留下的误差。上一篇文章我们提到,这个过程可以直观地理解为“拟合残差”。但这背后有一个容易被忽视的数学前提:只有当损失函数选用均方误差(MSE)时,“拟合残差”才严格成立。在更一般的场景下,我们需要一个更普适的框架,这就是梯度提升(Gradient Boosting)的出发点。 本文将系统梳理 GBDT(Gradient Boosting Decision Tree,梯度提升决策树)的数学原理、训练流程、在量化交易中的优势与局限,并深入解释一个初学者经常困惑的问题:模型更新时所说的“加到旧模型上”到底是什么意思。 1. 从残差到负梯度 Boosting 的原始思路可以概括为:每棵新树的目标不是直接预测原始标签,而是预测当前模型输出与真实值之间的差距,也就是残差。用公式表示: $$r_i = y_i - F_{m-1}(x_i)$$ 其中 $F_{m-1}$ 表示前 $m-1$ 棵树组合后的模型,$y_i$ 是样本 $i$ 的真实值。 这个思路在平方损失(MSE)下是完全自洽的。如果损失函数定义为: $$L = \frac{1}{2}\sum_i (y_i - F(x_i))^2$$ 那么对当前模型 $F$ 求导,可以得到: $$\frac{\partial L}{\partial F(x_i)} = F(x_i) - y_i$$ 负梯度方向就是: $$-\frac{\partial L}{\partial F(x_i)} = y_i - F(x_i)$$ 恰好等于残差。因此,在 MSE 下,“拟合残差”等价于“沿着负梯度方向更新模型”。 问题在于,量化交易中经常使用其他损失函数。例如分类任务使用对数损失(logistic loss),或者为了稳健性使用绝对误差损失(MAE)。在这些情况下,残差不再直接等于负梯度,原来的 Boosting 框架就需要扩展。 Jerome Friedman 在 2001 年提出的 GBDT 解决了这个问题:每一棵新树不再固定拟合残差,而是拟合当前损失函数关于模型输出的负梯度。负梯度指向损失函数下降最快的方向,因此无论损失函数是什么,只要可导,GBDT 都能工作。 一个直观的类比是“蒙眼下山”。假设你站在一座山的某个位置,目标是走到山谷的最低点。你看不到全局地形,只能通过脚底感知坡度。梯度指向坡面上升最快的方向,而负梯度指向下降最快的方向。每走一步,你都沿着当前最陡的下坡方向前进。GBDT 的每一棵新树,就相当于在当前模型所在的位置计算负梯度方向,然后沿着这个方向“迈出一步”。 2. GBDT 的训练流程 GBDT 的训练过程可以拆解为五个步骤,这也是 XGBoost 和 LightGBM 的共同基础。 ...

August 20, 2026 · 2 min · 287 words · c.w.