ChatGPT 的本质
函数的本质
在中学时我们都学过函数,通常都是给定一个输入 x,然后通过某种规则 f 进行计算,得到输出 y,即 y = f(x)。
而 ChatGPT,从数学上的层面来看,也是一个函数:回答 = ChatGPT(问题)
问题 -> x,ChatGPT 执行计算 -> f, 返回回答 -> y
但 ChatGPT 有一个区别,上面的函数里的参数通常只有几个,比如 y = 2x + 3 里只有两个参数:系数 2 和常数 3。而 ChatGPT 有 1750 亿个参数。(GPT-3 版本为例, 后面的版本不再公开参数细节)
可以把这 1750 亿个参数想象成有一个巨大的控制面板上有 1750 亿个可调节的旋钮,每个旋钮都会影响最终的输出,这 1750 亿个旋钮(参数)共同决定了 ChatGPT 如何理解语义、如何组织逻辑、如何选择措辞。
回答 = f(问题, 参数1, 参数2, 参数3, ..., 参数175000000000)
也就是本质上是一种确定性的输入-输出映射关系,只是极其复杂。
参数是什么
参数是存储知识的容器。
- 有些参数记录了“主语后面通常跟动词”。
- 有些参数记录了“苹果公司是一家科技公司”。
- 有些参数记录了“悲伤的情绪通常用某些词汇表达”。
参数/参数的组合编码了语言的某种规律。
每一种语言现象,每一点世界知识,都需要一些参数来存储和表达。
为什么需要这么多参数
为什么需要这么多参数呢?因为语言太复杂了,每一个维度,都需要大量参数来捕捉。
语言的世界里,近义词之间有微妙的差异,同一个词在不同语境下意思完全不同。
还有成语俗语背后的文化典故,医学、法律这些专业领域的术语。
以及说人说话时的那种感觉,褒义贬义、正式口语,模型都得学会分辨。
有人做过一个粗略的估算:人类语言中有数十万个词汇,数百万种常见的词语搭配,数千万个事实性知识,数亿种可能的句子结构……要让模型"理解"这一切,1750 亿个参数,可能还不够。
语言复杂性的几个例子:
- 一词多义
“这本书很重” -> 重量大
“这件事很重要” -> 重要
同一个重字,在不同语境下,意思完全不同。人类能够理解的意思,模型需要参数来捕捉这种微秒的差异。
- 指代消解
指代消解,就是判断代词(比如:“他”、“它”、“这个”等等)具体指代什么。
比如:“小明买了一个苹果手机。它的屏幕很大。”
它指的是苹果手机,不是小明,也不是水果苹果,这对于人类很容易理解,而模型需要参数来追踪这种指代关系。
- 隐含的常识
“他把玻璃杯掉在地上,碎了。”
这里指的是玻璃杯碎了,不是地板碎了,这需要常识:玻璃杯易碎、地板不易碎。模型需要参数来存储这些常识。
- 语用学
“你能把窗户关上吗?”
这里表面上是一个疑问句,实际上是一个请求,甚至隐含着不耐烦的情绪。模型需要参数来理解这些语用规则,甚至需要结合上下文,来推测出是否有不耐烦的情绪。
可以解方程吗
既然 ChatGPT 是一个函数,有 1750 亿个参数需要确定,那为什么不能像我们在学校学的那样,用解方程组的方法来求解这些参数呢?
有以下几种原因:
- 方程太复杂
相对于中学的方程组而言,中学的方程组是线性的如:2x + 3y = 10
而 ChatGPT 的“方程”是 96 层嵌套的非线性系统:
输出 = 第 96 层(...第 2 层(第 1 层(输入)))
其中每一层都有数十亿个参数,且包含 ReLU 这样的非线性转换。
这是一个极度复杂的非线性系统,没有公式可以直接算出答案。
线性:输入和输出成正比关系,如:买 1 斤苹果 5 元,买 2 斤 10 元 -> 成正比。
非线性:输入和输出的关系有转折,如:
- 学习时间与成绩:从 0 小时到 1 小时,成绩大幅提升;但从 10 小时到 11 小时,可能几乎不增长了。
- 药物剂量:1 粒没效果,2 粒有效,3 粒可能中毒 → 不是简单的翻倍关系。
- ReLU 函数:负数全部变成 0,正数保持不变 → 在零点有个"拐弯"。
为什么 ChatGPT 需要非线性?
因为语言规律不是简单的正比关系。比如"喜欢"这个词:
- 在"我喜欢你"里是亲密
- 在"我喜欢吃苹果"里是偏好
- 在"我喜欢得很"里是讽刺
同一个词,不同语境意思完全不同。这种复杂关系必须用非线性函数来表达。
- 计算量无法承受
即使理论上能列出方程组,求解 1750 亿个未知数的方程组:
传统方法(如高斯消元法)的计算复杂度是 O(n^3)。对于 1750 亿,就是 (1750 亿)^3 的计算量。
这个数字大到宇宙中的原子数都不够用来计数,更何况随着大模型的更新,参数量可能还会更加的庞大。
训练的本质
迭代逼近
既然不能直接解方程组,那就换个思路 --- 用海量数据进行训练。
训练不是直接解出参数,而是通过逐步调整,逐步逼近最优解。
就像在黑暗中摸索,每走一步感受一下方向对不对,对了就继续,错了就调整,最终也能到达目的地。
训练的流程
上图展示了训练的核心循环,这个循环会重复数千亿次,每次都会让模型变得更聪明一点点。
- 步骤一:随机初始化参数
训练开始时,这 1750 亿个参数都是随机的小数,通常在 -0.1 到 0.1 之间,这些数字此时很混乱,像噪音一样毫无意义,此时的 ChatGPT,对语言一无所知。
- 步骤二:输入训练数据
第一次学习 --- 比如:预测“今天天气”的下一个词。
训练开始,此时给模型喂第一个文本片段:“今天天气”,模型的任务:预测下一个词。
在初始的混乱状态下,由于参数是随机的,它可能给出这些候选:
- “手机” 概率:10%
- “电脑” 概率:7%
- “真好” 概率:3% ---> 这才是合理的,但概率最低
- “苹果” 概率:8%
- ...
模型可能选择“手机”(概率最高,概率越高模型越倾向于选择这个词)作为下一个词。但这显然是错误的,和天气不搭边。
- 步骤三:计算错误 --- 模型意识到自己错了
我们告诉它正确答案:“真好”。模型计算:我错了!我应该提高“真好”的概率,降低“苹果”的概率。这里用“损失”(Loss)来衡量错误的大小。
什么是 Loss(损失)? Loss 是一个数字,衡量“预测值”和“正确答案”之间的差距。差距越大,Loss 越大。训练的目标就是让 Loss 越来越小,最终接近 0。
- 步骤四:调整参数
那模型如何改进呢?
模型会分析:“我预测错误,是因为哪些参数设置的不对?”然后调整这些参数。
调整前,可能是这个值:
参数 A = 0.0123, 参数 B = -0.0456 调整后: 参数 A = 0.0123 + 0.0001 = 0.0124 ---> 增加了一点 参数 B = -0.0456 - 0.0001 = -0.0457 ---> 减少了一点
这个调整非常微小,但是方向是对的:让模型下次预测“真好”的概率更高一点。
- 步骤五:累积的奇迹 --- 数千亿次迭代后
以上的过程不断重复:
- 读第 1 个句子 -> 预测错了 -> 调整参数
- 读第 2 个句子 -> 预测还是错了 -> 再调整参数
- 读第 3 个句子 -> 预测错误减少了一点 -> 继续调整
- ...
- 读第 1000 个句子 -> 预测准确率从 0% 提升到了 5%
- ...
- 读第 100 万个句子 -> 准确率提升到 30%
- ...
- 读第 10 亿个句子 -> 准确率提升到 60%
- ...
- 读第 3000 亿个词 -> 准确率稳定在 75% 左右
每一次调整都很微小,但累积起来,那 1750 亿个参数慢慢地就会从随机的噪音变成了有意义的知识表示。
训练背后的机制
知道了训练的流程之后,那模型到底是怎么知道调哪些参数、往哪个方向调、调多少的呢?
这里涉及到三个核心机制:反向传播、梯度下降和学习率。
反向传播:找出该调哪些参数
模型预测错了,但有 1750 亿个参数,该调哪些?
反向传播的解决方案是:从错误结果往回推,追溯责任链。
比如投飞镖投的偏左了,需要分析: 结果:偏左了 往回分析:
- 是手腕角度不对?(负责 5% 的偏差)
- 还是手臂力度不对?(负责 30% 的偏差)
- 还是站位不对?(负责 65% 的偏差)
反向传播就是这个分析过程 --- 从错误结果往回推,计算出每个参数对错误的“责任大小”(梯度绝对值)。对责任最大的参数重点调整。
什么是梯度?
- 梯度就是反向传播计算出来的数字,表示参数对 Loss 的影响程度。可以理解为“责任值” --- 绝对值越大,责任越大。
梯度下降:让参数往正确的方向调整
反向传播知道了哪些参数需要调整,梯度下降则负责执行调整。
梯度下降的核心思想很简单:顺着能让错误变小的方向,调整参数。
参数新值 = 参数旧值 - 学习率 * 梯度
这个公式自动保证了调整方向的正确性 --- 无论梯度是正还是负,参数都会往让 Loss 下降的方向走,公式里的减号会处理好一切。
这就是“梯度下降”的含义:沿着梯度的反方向,让错误不断下降。
即梯度值决定了参数对 Loss 的影响,沿着梯度反方向下降,让参数对 Loss 的影响减少使得错误不断下降。
举个例子:
设定:损失函数为
Loss = −2 × 参数,当前参数 = 5,学习率 = 0.1,目标是让 Loss 变小。
- 当前损失:Loss = −2 × 5 = −10
- 推理方向:若参数增大到 6,新 Loss = −2 × 6 = −12。因为 −12 < −10,所以参数必须增大才能让损失下降。
- 计算梯度:对
−2 × 参数求导,梯度 = −2(负数)。- 代入公式:
新参数 = 5 − 0.1 × (−2)新参数 = 5 − (−0.4)→新参数 = 5 + 0.4→ 新参数 = 5.4- 验证结果:参数从 5 增大到 5.4,符合推理。新损失 = −2 × 5.4 = −10.8,−10.8 确实小于 −10,损失成功下降。
核心总结:因为梯度是负数(−2),公式里的“减号”自动将“减负”变成了“加正”,从而机械地实现了“参数增大”这个正确操作。整个过程电脑无需思考,只管算数就行。
学习率:控制调整幅度
学习率决定了每次调整的幅度。太大或太小都不好。
举个例子:
当前值: 参数值 = 0.0234
梯度 = +2.5(反向传播计算的)
学习率 = 0.0001(人工设定的)
这里假设 Loss = 参数值 * 梯度 = 0.0234 * 2.5 = 0.0585
计算新参数值:
参数新值 = 0.0234 - 0.0001 * 2.5 = 0.0234 - 0.00025 = 0.02315
新 Loss = 0.02315 * 2.5 = 0.057875
Loss 从 0.0585 下降到了 0.057875
学习率的权衡:
- 学习率太大,比如 0.1,步子会太大,跳过最优解,训练不稳定,甚至发散
- 学习率太小,比如 0.0000001,每次只移动一丁点,需要天文数字级迭代,训练极其缓慢,时间成本无法接受
- 学习率合适,比如 0.0001,每次都有明显下降,且稳定收敛、速度合理。
学习率的动态调整
训练 GPT-3 时,研究人员不会从头到尾使用同一个学习率,而是采用动态调整:
训练初期:学习率 = 0.001 (较大)
参数这时还很随机,需要快速调整,像下山时在山腰大步走。
训练中期:学习率 = 0.0001 (适中)
已经解决最优解,需要稳步前进
训练后期:学习率 = 0.00001 (很小)
已经很接近山谷,需要精细调整,像在山谷里小心翼翼找最低点
这就是“学习率衰减”策略:开始用大步子快速下山,越接近山谷步子越小,确保不会跳过最优解。
总结
训练的本质可以用一句话概括:以降低 Loss 为目的,通过反向传播和梯度下降手段,用数据驱动的方式迭代逼近最优解。
这个从”解“到”训练“的转变,不仅仅是技术细节,而是一个哲学上的根本转变。
- 传统方式追求精确的数学解:用公式描述规律,通过解方程得到精确答案,需要理解问题的本质,适合简单、可解释的问题。
- 深度学习方法用海量数据堆出智能:不再追求精确的数学解,而是用数十亿、数千亿的数据样本,让模型在海量数据中”自己悟出“规律。
- 当数据量足够大,参数量足够多,智能会自己涌现出来:这是一种”量变引发质变“的过程,这就是训练的本质。
目的:最小化 Loss(预测值与正确答案的差距)
手段:
-
反向传播:计算每个参数的梯度(责任大小)
-
梯度下降:沿梯度反方向调整参数,确保 Loss 下降 方法:
-
参数更新公式:参数新值 = 旧值 - 学习率 * 梯度
-
学习率控制:决定每次调整的幅度 策略:
-
学习率动态衰减:初期大步快跑,后期精细调整
-
海量数据迭代:数千亿次微调,量变引发质变 举个完整流程的例子:
- 预测错误
预测:“苹果”(错误)
正确:“真好”
Loss = 10.5
- 反向传播:计算梯度
参数1:梯度 = +2.5
参数2:梯度 = -1.8
参数3:梯度 = 0 (这次错误跟它无关,无需调整)
...
(一次性算出所有 1750 亿个参数的梯度)
- 应用公式:更新参数
公式:参数新值 = 参数旧值 - 学习率 * 梯度,学习率 = 0.0001
参数1:0.0234 - 0.0001 * 2.5 = 0.02315
参数2:-0.0567 - 0.0001 * (-1.8) = -0.05652
参数3:0.1234 - 0.0001 * 0 = 0.1234(保持不变)
...
(每次训练只更新梯度≠0的参数)
- 验证效果
用新参数重新预测:“这部电影___”
预测:”很好看“
正确:”一般般“
Loss = 9.2 (比 10.5 小,说明有进步!)
- 重复亿万次
每次用不同的训练数据,逐步优化所有参数:
Loss = 10.5 -> 9.2 -> 8.7 -> ... -> 2.5
参数的演化
从”记住答案“到”理解规律“
前面知道了:模型通过调整参数,让预测越来越准确。但还有一个关键问题:模型是在”死记硬背答案“,还是真的”学会了语言规律“?