全部文章
AI LLM

LLM基础数学原理解析

更新于 2026年4月29日 3,394 字 约 9 分钟
AI LLM基础数学原理解析 LLM § 03
阅读进度 0% 继续阅读

要了解AI,首先要对AI的底层原理有一定的了解,现代大模型一般都是基于神经网络和深度学习的,准确来说是多层神经网络。

一.神经网络的基础数学模型

最开始的模型会有以下几样东西:

  • 几层神经网络
  • 每层多少个神经元
  • 用什么激活函数

其实在这个时候模型就有参数了,这些参数通常是:

  1. 随机初始化
  2. 按照某种规则进行初始化

所谓的训练大模型,准确点来说就是训练模型中的参数,这个训练参数的过程一般是通过反向传播算法,后面会细说。

并且这里的参数并不是指的模型的神经元,一个神经元里面通常是有很多个参数。

一个最简单的神经元可以写成如下的形式

y=σ(w1x1+w2x2+...+wnxn+b)y = \sigma(w_1x_1+w_2x_2+...+w_nx_n+b)

还可以写成fθ(x)f_{\theta}(x),其中θ\theta代表的是参数的集合

这里σ\sigma指的是激活函数,w1,…wn,b就是模型的参数。

可以看到,其中的w1…wn在和最后的偏置参数b构成了一个线性函数,而外面的σ\sigma相当于进行了一下非线性变换。

当然一个神经网络中往往是有多层神经元的

假设输入向量是:

x∈Rnx \in \mathbb{R}^{n}

注意这里输入的是向量,这和后面的RAG在数学形式上也有些关联。

假设这一层有m个神经元,那整层可以聚合表示为:

h=σ(Wx+b)h = \sigma(Wx+b)

其中:

  • W∈Rm×nW \in \mathbb{R}^{m \times n}
  • b∈Rmb \in \mathbb{R}^{m}
  • h∈Rmh \in \mathbb{R}^{m}

这里的W是一个参数矩阵,是这一整层很多参数的集合。

最终输入n维,输出m维。

为啥输出是m维呢,其实还有一个更简单的理解方式

每个神经元都是一个函数,都对输入的向量进行运算,这里的参数w可以理解成是一种权重,参数b就是偏置,最终把向量运算得到一个数值。

hj=σ(wjTx+bj)h_j = \sigma(w_j^{T}x + b_j) 其中j∈(1,2,3...m)j \in (1,2,3...m)

m个神经元就是m个数值,聚合到一起就是一个m维的向量。

h=[h1h2⋮hm]∈Rmh = \begin{bmatrix} h_1 \\ h_2 \\ \vdots \\ h_m \end{bmatrix} \in \mathbb{R}^{m}

二.输入是怎么进入神经网络的

这个在之前的RAG文章中是有描述过一些的,首先用户输入的文本需要经过tokenizer切成token

比如最近GPT5.5不就是因为token的处理方式变了,所以更加节省token了吗

2.1 tokenizer

tokenizer一般分为两步:

1.文本拆分

比如输入:

how are you

输出可能变为:

"how","are","you"

当然这是比较理想的状况,gpt的tokenizer我记得是开源的,如果感兴趣的话可以自己去试一下

2.映射为token_id

["how", "are", "you"] → [101, 57, 302]

2.2 embedding

token_id本身它只是编号罢了,需要去embedding表里面去查找出对应的向量才行,而这个编号正是它用来进行查表的,查它属于这个表的第几行

E∈RV×DE \in \mathbb{R}^{V \times D}

其中V代表的是词表大小,就是词表的高度,D是向量维度,也就是词表的长度

当然一句话往往是有多个token的,如一句话被tokenizer成4个token_id

当一次性输入多句话的时候,查出来就是一个三维的张量

在真实情况下,模型一次通常处理一个batch,及一次性送进模型处理的一组样本

2.3 加位置编码

之前在RAG的那篇文章中写过,token_id它本身是不带位置信息的,所以需要有一个位置编码之类的东西来标注所处的位置

三.神经网络是如何学习的

大致是分如下几步:

  1. 输入数据:如一段文本,或者是一张图片
  2. 前向传播:即模型 根据当前参数,根据神经元来算出输出
  3. 计算损失:把预测结果和正确答案相比较,得到loss
  4. 反向传播:计算每个参数对loss的影响
  5. 梯度下降:往loss变小的方向去更新模型的参数

这里的输入数据和前向传播我们刚刚已经大致讲过了,所以先讲讲损失它是如何计算的

3.1 计算损失

这里的损失计算是通过一个函数来实现的:

L(y^,y)L(\hat{y},y)

这里的符号表示如下:

LL:损失函数

y^\hat{y}:模型预测结果

yy:真实答案

LLM的损失计算方式一般是通过交叉熵损失来进行计算的

  1. logits

首先我们都知道模型的输出一般都是一组token

如

token1,token2,token3...

LLM的训练目标是根据前面的token去预测下一个token

模型不是直接输出token,模型本身是有一个词表,这个词表准确来说是个token表,在每一个预测位置上,模型会给整个词表中的token进行打分,假设词表大小是V,那么模型会输出

z1,z2,z3...zvz_1,z_2,z_3...z_v

这里其实也可以用向量来进行表示

z∈RVz \in \mathbb{R}^{V}

这里的ziz_i表示第i个token作为下一个token的原始分数值,这些分数叫做logits,它们还不是概率,可能是正数,也可能是负数,加起来也不一定等于1

  1. softmax

下面所需要做的事情,就是把这些原始的分数值变为一堆概率

p1,p2,p3...pnp_1,p_2,p_3...p_n

这里每一个p都是在0-1之间的

并且相加起来是等于1的

这里如果是用普通归一化,如:

zi∑zj\frac{z_i}{\sum z_j}

这样的话会出现几个问题

1.有正有负

2.分数差异不太明显,大的分数就不够突出

这里我们使用指数函数就可以解决这个问题

pi=ezi∑j=1nezjp_i = \frac{e^{z_i}}{\sum_{j=1}^{n} e^{z_j}}

首先指数函数的结果一定是正数,并且指数函数增长是很快的,差异也会比较的明显

∑i=1npi=∑i=1nezi∑j=1nezj=∑i=1nezi∑j=1nezj=1\sum_{i=1}^{n} p_i = \sum_{i=1}^{n} \frac{e^{z_i}}{\sum_{j=1}^{n} e^{z_j}} = \frac{\sum_{i=1}^{n} e^{z_i}}{\sum_{j=1}^{n} e^{z_j}} = 1

  1. 交叉熵损失计算

softmax负责把logits变成概率,交叉熵损失负责看模型给正确答案的概率有多大

如果是第k个token模型经过softmax后给它的概率是pkp_k

那么交叉熵损失就是

L=−log⁡pkL = -\log p_k

这里因为pkp_k是大于0小于1的,所以log⁡pk\log p_k是小于0的,故需要加一个负号

模型给正确 token 的概率 (pk)损失 (L=-log pk)
1.00
0.90.105
0.50.693
0.12.303
0.014.605
0.0016.908

可以看到

  • 如果模型很确定而且正确,损失接近 0
  • 如果模型只给正确答案 0.1 的概率,损失明显变大
  • 如果模型几乎不相信正确答案,比如 0.001,损失会非常大

还有这里为什么用log呢,可以在表格中看到如果正确答案概率从0.9到0.8损失变化不大,但如果从0.1降低到0.001,差距会明显变大,比简单的1-p更加敏感

还有一个很重要的点,我们都知道模型在输出的时候输出的是一串的token,如果是1-p的话,概率相乘会越来越小,很难计算

P=P(x1)P(x2∣x1)(x3∣x1x2)P = P(x_1)P(x_2|x_1)(x_3|x_1x_2) 如果取一个log,就可以从相乘变成相加

log⁡ab=log⁡a+log⁡b\log ab = \log a+ \log b

那么整个序列的损失就可以写成

L=−∑tlog⁡P(xt∣x<t)L = -\sum_t \log P(x_t \mid x_{<t})

平均一下就是(整个序列的损失通常取平均):

L=−1T∑t=1Tlog⁡P(xt∣x<t)L = -\frac{1}{T}\sum_{t=1}^{T} \log P(x_t \mid x_{<t})

3.2 反向传播

反向传播,即Backpropagation,本质其实是:

用链式法则,从损失函数开始,反过来计算每个参数对loss的影响

前面我们已经知道,神经网络不是一层公式,而是一层嵌套函数

h1=σ(W1x+b1)h_1 = \sigma(W_1 x + b_1)

h2=σ(W2h1+b2)h_2 = \sigma(W_2 h_1 + b_2)

y^=W3h2+b3\hat{y} = W_3 h_2 + b_3

L=Loss(y^,y)L = \mathrm{Loss}(\hat{y}, y)

这里W1W_1在最前面,L即loss在最后面,如果想知道W1W_1应该怎么改,那么就需要知道

W1→h1→h2→y^→LW_1 \to h_1 \to h_2 \to \hat{y} \to L

在这一整条链里面W1W_1对最终loss的影响,这就需要链式法则,而链式法则,就是反向传播的核心

3.2.1 链式法则

最简单的链式法则是,如果:

z=f(y),y=g(x)z=f(y),y=g(x)

那么

dzdx=dzdy⋅dydx\frac{dz}{dx} = \frac{dz}{dy} \cdot \frac{dy}{dx}

说人话就是:

如果x影响y,y影响z,那么x对z的影响= x对y的影响 × y对z的影响

当然我一开始看到这个式子,有点印象,但还是忘了这些d是啥了,所以这里做一下补充

这里的d是微积分里的微分符号,也可以表示一个极小的变化量

这里的dydx\frac{dy}{dx}就是y对x的导数,记得高中课本上讲的是y随x的变化率这样

更直白的说法是:

x每变化一个很小的单位,y大约变化多少,也可以说是对切线的逼近

不过d的话通常用于的是单变量函数,如:

y=f(x)y = f(x)

只有一个输入变量,所以写:

dydx\frac{dy}{dx}

如果是多变量函数我们就要换一个符号,这也是下面计算梯度的时候会经常看见的

如果一个函数同时依赖很多变量,如:

L=f(W1,W2,b1,b2,x,y)L = f(W_1,W_2,b_1,b_2,x,y)

这个时候,如果想问

如果只改变W1W_1,其它东西固定不动,L怎么变?

毕竟我们都知道神经网络中不止一个参数,而我们这里是要算每个参数分别对loss整体的影响

这个时候就写:

∂L∂W1\frac{\partial L}{\partial W_1}

这叫偏导数,偏的意思是:只看其中一个变量的影响,其它变量暂时当成常数

举个例子:

L=x2+y2L = x^2 + y^2,可见L同时依赖x和y,如果只看x对L的影响,y^2就可以当成是常数,那么结果就是2x

3.2.2 计算参数梯度

在前面的网络:

h1=σ(W1x+b1)h_1 = \sigma(W_1 x + b_1)

h2=σ(W2h1+b2)h_2 = \sigma(W_2 h_1 + b_2)

y^=W3h2+b3\hat{y} = W_3 h_2 + b_3

L=Loss(y^,y)L = \mathrm{Loss}(\hat{y}, y)

如果想更新最前面的参数W1W_1,就需要知道

∂L∂W\frac{\partial L}{\partial W}

它表示的是如果W1W_1发生一个很小的变化,最终损失L会如何变化

并且W1W_1是通过一条链影响的:

W1−>h1−>h2−>y^−>LW_1 -> h_1 -> h_2 -> \hat{y} -> L

通过链式法则可知:

∂L∂W1=\frac{\partial L}{\partial W_1} = ∂L∂y^⋅∂y^∂h2⋅∂h2∂h1⋅∂h1∂W1\frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial h_2} \cdot \frac{\partial h_2}{\partial h_1} \cdot \frac{\partial h_1}{\partial W_1}

L -> y^\hat{y} ->…,由此可见反向传播的反向之道

3.2.3 梯度下降更新参数

我们前面已经知道了每个参数对损失函数的影响是:

∂L∂W1\frac{\partial L}{\partial W_1},接着,我们可以根据梯度来更新参数,最基础的参数更新的方式是梯度下降:

W1←W1−η∂L∂W1W_1 \leftarrow W_1 - \eta \frac{\partial L}{\partial W_1}

W1W_1:当前参数

←\leftarrow:把左边更新成右边的新值

η\eta:学习率,控制每次走多大一点

∂L∂W1\frac{\partial L}{\partial W_1}:损失L对参数W1W_1的梯度

-:沿梯度的反方向走,因为梯度是loss上升最快的方向

所以如果要让loss下降,需要走反方向

新参数 = 旧参数 - 一小步*梯度

还有这里的学习率η\eta也是很重要的,如果没有学习率,可能变的太大,直接冲过最低点

回到W1W_1本质,其实W1W_1本质上是一个参数矩阵:如果输入xx有3个数,隐藏层h1h_1有4个神经元,那W1W_1就是一个4×3的矩阵,里面装着12个数字,每个数字代表”输入的某一项对某个神经元的影响有多大”。所谓训练一个模型,说穿了就是把这12个数字(以及网络里其它所有参数)一次次按照梯度调整,直到损失LL足够小。

到这里,一条完整的链路就闭环了:

输入xx → 参数矩阵WW做线性变换 → 激活函数引入非线性 → 得到输出y^\hat{y} → 损失函数衡量差距 → 反向传播用链式法则算梯度 → 梯度下降更新参数 → 再输入下一批数据……

大语言模型看起来神秘,但拆开之后,每一层做的都是这件事。区别只在于矩阵的规模从4×3变成了几千×几千,参数量从十几个变成了几千亿个。规模带来了涌现,但原理没有变。理解了这一层,再去看”温度”、“上下文窗口”、“微调”这些词,就都能落回到矩阵和梯度上了。

目录