AI 学习专题一,AI 实现的原理

AI 系统原理:从命令到回复的完整流程

当你给 AI 输入一个命令时,从按下回车到看到回复,系统内部一步一步做了哪些事?本文按阶段梳理底层逻辑。


一、整体流程(高层)

复制代码
你的输入 → 转成数字(分词)→ 送进模型 → 模型内部算很多次 → 一个一个「猜」下一个词 → 拼成完整回复 → 显示给你

本文约定 :阶段 1~3 统一用一个例子------用户输入「写一个 Python 函数」,得到 4 个 token,对应阶段 2 的 (4, 4) 张量,阶段 3 的示例也沿用同一组数据,方便对照理解。

下面按阶段拆开说明。


二、阶段 1:你的命令怎么被「读进去」

1.1 收到原始文本

  • 系统拿到的是一整段字符串 ,例如:
    • "写一个 Python 函数,计算斐波那契数列第 n 项"
  • 同时可能还会自动加上:
    • 系统提示(system prompt):你是编程助手、要简洁、要写可运行代码等
    • 对话历史:之前几轮问答(如果有)
    • 上下文:当前打开的文件、选中的代码等(如 Cursor 会组好这些)

所以模型真正看到的是一大段「组装好的提示」,不只是你那一句。

1.2 分词(Tokenization)

  • 模型不能直接处理汉字/英文,只能处理数字
  • 分词 :把这段文本切成小片段(token),每个 token 对应一个整数 ID。
    • 例如:"写" → 某个 ID,"一个" → 另一个 ID,"Python" → 又一个 ID......
  • 结果:输入从字符串 变成一串整数 ,例如:[1234, 567, 890, 234, ...]
  • 不同模型有不同的词表(vocabulary),所以同一句话在不同模型里 token 序列可能不同。
阶段 1 结束后得到的数据是什么?
  • 类型 :一维整数序列(在代码里常是 list[int] 或张量 shape = (序列长度 L,))。
  • 含义:每个位置一个 token ID,顺序和原文一致。
  • 示例(与后文阶段 2、3 统一:只取「写一个 Python 函数」这 4 个 token,简化词表):
位置 0 1 2 3
文本 一个 Python 函数
数据 1201 88 3921 2102
  • 得到的数据 就是:[1201, 88, 3921, 2102],长度 L = 4。
  • 在实现里通常会再加一个「batch」维度,变成 shape (1, 4),表示 1 条样本、长度 4。

底层逻辑 1:AI 的「输入」在数学上就是一串整数;所有语义都通过这串数字在后续步骤里被处理。


三、阶段 2:数字怎么变成「语义表示」(Embedding + 位置)

2.1 词嵌入(Embedding)

  • 每个 token ID 会通过一个查表 + 线性变换 ,变成一个向量 (一列数字)。
    • 例如:ID 1234 → 向量 [0.12, -0.34, 0.56, ...](维度可能是 768、4096 等)
  • 这些向量是在训练时学出来的,相近含义的词在向量空间里会靠近
  • 这一步把「离散的 token」变成「连续的向量」,方便后面做数学运算。

2.2 位置编码(Positional Encoding)

  • 模型需要知道词的顺序(「没吃饭」和「饭没吃」不一样)。
  • 会给每个位置的向量加上「位置信息」:
    • 要么用公式算出来的固定位置编码;
    • 要么用可学习的位置嵌入(learned position embedding)。
  • 这样同一层的输入里,既包含「是什么词」,也包含「在第几位」。
阶段 2 结束后得到的数据是什么?
  • 类型 :一个三维张量(tensor) ,形状为 (batch, 序列长度 L, 隐藏维度 D)
    • 单条样本时 batch=1,常写成 (L, D)
  • 含义
    • 第 1 维:第几个位置(0 到 L-1);
    • 第 2 维:该位置对应的向量,长度为 D(如 768、4096)。
  • 示例(L=4 个 token,D=4 做演示,实际 D 很大):

假设阶段 1 得到 4 个 token ID:[1201, 88, 3921, 2102],对应「写」「一个」「Python」「函数」。

阶段 2 后每个位置变成一个 4 维向量(Embedding + 位置编码后):

复制代码
位置 0(写)   → [ 0.2, -0.1,  0.5,  0.0]
位置 1(一个) → [-0.3,  0.4,  0.1,  0.2]
位置 2(Python)→ [ 0.1,  0.0, -0.2,  0.6]
位置 3(函数) → [ 0.4,  0.3,  0.2, -0.1]
  • 得到的数据 就是一个矩阵(张量),形状 (4, 4)
维度0 维度1 维度2 维度3
位置0 0.2 -0.1 0.5 0.0
位置1 -0.3 0.4 0.1 0.2
位置2 0.1 0.0 -0.2 0.6
位置3 0.4 0.3 0.2 -0.1
  • 之后模型(阶段 3)的输入就是这个张量:每一行是一个位置的「带顺序的语义向量」,模型只在这些数字上做运算。

底层逻辑 2:模型内部一直在处理「带顺序的向量序列」,而不是原始文字;语义和顺序都编码在这些向量里。


四、阶段 3:模型核心------一层层「理解」并算下一个词

大语言模型是多层 Transformer 。每一层大致做两件事:注意力 + 前馈网络

3.1 自注意力(Self-Attention)

  • 在做什么 :对当前序列里每个位置 ,看「其它所有位置」的向量,算一个加权和,得到新的表示。
    • 权重是算出来的:模型会学「哪些词和哪些词更相关」。
    • 例如处理「斐波那契」时,可能会更关注「数列」「第 n 项」「函数」这些词。
  • 数学上:对每个 token 的向量,通过 Query、Key、Value 三个线性变换,用 Q 和所有 K 做相似度(常为点积),得到权重,再对 V 加权求和。
  • 多头注意力:会做多组这样的计算(多个「头」),从不同角度抓关系,最后拼在一起再做一次线性变换。

所以:同一段输入在每一层里都会被「重新混合」一次,让每个位置的信息都融合了整段上下文的语义。

为什么用 Q、K、V 三个?理论依据是什么?
  • Q、K、V 不是三个「维度」 :它们是对同一个向量 h 做的三套不同的线性变换 (三个矩阵 W_Q、W_K、W_V)。每一套得到的还是和 h 同维的向量(例如我们的例子里都是 4 维)。阶段 3 输出仍是 (4, 4),是因为设计上每一层保持「序列长度 × 特征维度」不变:4 个位置、每位置一个 4 维向量,经过注意力 + FFN 后仍然 4 个位置、每位置 4 维(通过输出投影、残差、归一化保证形状一致),方便层层堆叠。

  • 理论来源:检索(Retrieval)类比

    经典思路来自信息检索和键值存储:

    • Query(查询):当前位置「我要找什么」的表示;
    • Key(键):每个位置「我是什么、可被怎么匹配」的表示;
    • Value(值) :每个位置「被选中时,要贡献什么内容」的表示。
      先拿 Q 和所有 K 算相似度(匹配程度)→ 得到权重;再用这些权重对 V 做加权和 → 得到「从别处取来的内容」。这样就把「谁和谁相关 」(Q·K)和「取什么内容」(V)分开了。
  • 为什么要拆成 Q、K、V 而不是只用一个 h?

    • 职责分离
      • Q 和 K 专门负责「算相关度」:两个向量越像,点积越大,注意力权重越高。
      • V 专门负责「被取走的内容」:即使用户「查的是关键词」,真正返回的可以是另一段更合适的信息。
    • 若只用同一个向量既当「匹配键」又当「取出的值」,模型就没有自由度去学「匹配用一套标准、内容用另一套」;拆成 Q、K、V 后,W_Q、W_K、W_V 由数据学习,模型可以学到:例如用 K 突出「语法角色」,用 V 突出「语义内容」。
    • 出处:这种 Q/K/V 设计在 2017 年《Attention is All You Need》(Vaswani 等)中系统化用于 Transformer,并成为大语言模型的标准组件。
  • 一句话 :用 Q、K、V 是为了把「按什么标准选 」(Q·K)和「选到后取什么」(V)分开,理论依据是检索/键值思想,让模型能学得更灵活。

3.2 前馈网络(FFN)具体在做什么?

  • 位置 :在每一层里,自注意力算完之后,对每个位置得到的新向量(已经融合了上下文),再单独过一遍「前馈网络」。
  • 公式 :对每个位置的向量 x (4 维为例),做两步线性 + 中间非线性:
    • 中间表示u = Linear1(x ),把 4 维映射到更大的中间维度(如 16 维);再对 u 逐元素做 GELU(或 ReLU)激活。
    • 输出y = Linear2( GELU(Linear1(x)) ),把中间维再映射回 4 维。
  • 在做什么 :注意力只做了「按权重混合别的位置的向量」,全是线性组合;FFN 负责非线性,让模型能表达「如果这个位置在某种上下文里,就改写成另一种表示」这种更复杂的关系。可以理解为:注意力是「收集信息」,FFN 是「消化、改写」。
  • 逐位置独立 :每个位置自己的向量单独过 FFN,位置与位置之间在 FFN 里不交互(交互已经在注意力里做完了)。
3.2 示例(沿用 (4,4),中间维取 8)

设注意力 + 残差 + 归一化后,位置 0 的向量为 x₀ = [0.11, 0.11, 0.15, 0.16](即 3.4 步骤 C 里位置 0 的新向量近似值)。

步骤 1:Linear1,4 维 → 8 维

  • 有一个可学习矩阵 W1 ,形状 (4, 8)。u = x₀ × W1,得到 8 维向量。
  • 假想算得:u = [0.2, -0.1, 0.3, 0.0, 0.1, 0.4, -0.2, 0.1]

步骤 2:GELU 激活

  • u每一个分量做 GELU:GELU(t) 会把负的压小、正的保留但非线性。公式上 GELU(t) ≈ t·Φ(t)(Φ 是标准正态分布函数),这里只关心「非线性」效果。
  • 假想算得:GELU(u) = [0.12, -0.04, 0.18, 0.0, 0.06, 0.27, -0.08, 0.06]

步骤 3:Linear2,8 维 → 4 维

  • 有一个可学习矩阵 W2 ,形状 (8, 4)。y = GELU(u) × W2,得到 4 维向量。
  • 假想算得:y₀ = [0.13, 0.09, 0.17, 0.14]

这就是位置 0 经过 FFN 后的输出。位置 1、2、3 同理 ,各自用同一个 W1、W2,但输入不同(各自注意力后的向量),所以输出也不同。最后再对整层做残差 (FFN 输出 + 本层注意力前的输入)和层归一化,得到这一层最终的 (4, 4) 输出。


3.3 层层堆叠具体在做什么?

  • 含义 :「层层堆叠」就是把「注意力 + FFN(+ 残差、归一化)」这一整块重复很多次,上一块的输出当作下一块的输入,中间形状不变(一直是 4 个位置 × 4 维)。
  • 数据流
    • 第 0 层输入:阶段 2 的 (4, 4)(写、一个、Python、函数 的嵌入+位置)。
    • 第 0 层输出:经过一次注意力 + FFN + 残差 + 归一化,仍是 (4, 4),交给第 1 层。
    • 第 1 层输入 = 第 0 层输出;第 1 层输出 = 第 2 层输入;... 一直到第 N-1 层。
    • 第 N-1 层输出就是「阶段 3 的最终结果」,仍是 (4, 4);取最后一行的 4 维向量(即最后一个位置「函数」的表示)送到阶段 4。
  • 为什么多层的效果不同:每一层都在「再看一遍整段、再混合、再非线性改写」一次。靠前的层通常学到更局部、更语法/词义的东西(例如「写」和「函数」都是动词相关);靠后的层在更抽象的表示上操作,更接近「这句话在问什么、接下来该接什么」这种高层语义,所以最后一层的最后一个位置才适合拿去预测下一个 token。
3.3 示例:两层之间怎么衔接(形状与含义)
  • 第 0 层

    • 输入:4 个位置向量(阶段 2 的 (4,4))。
    • 经过注意力:每个位置都融合了 4 个 token 的信息。
    • 经过 FFN + 残差 + 归一化:得到新的 (4,4),记作 L0_out
    • L0_out 的每一行,可以粗略理解为「每个位置在看过整句后的第一轮表示」。
  • 第 1 层

    • 输入:就是 L0_out(仍是 (4,4))。
    • 再做一次注意力:每个位置又在「第一轮表示」的基础上,再和别的位置交互一次。
    • 再 FFN + 残差 + 归一化:得到 L1_out,仍是 (4,4)。
    • L1_out 的最后一行(位置 3「函数」)就是阶段 4 要用的向量 z
  • 若有很多层(如 32 层):就重复 32 次「输入 (4,4) → 注意力 → FFN → 残差 → 归一化 → 输出 (4,4)」;每一层的 (4,4) 在数值和语义上都会逐渐变化,越往后越「高层」,最后一层的最后一个位置才送去算下一个 token 的概率。

3.4 示例演示:某一层里具体在算什么

沿用阶段 2 的 (4, 4) 例子4 个 token (「写」「一个」「Python」「函数」),每个位置 4 维向量 (实际模型是 768/4096 等),只看一个注意力头

输入(阶段 2 的输出,本层的输入)

就是阶段 2 得到的 (4, 4) 张量,每行是一个位置的向量:

  • 位置 0(写):h₀ = [0.2, -0.1, 0.5, 0.0]
  • 位置 1(一个):h₁ = [-0.3, 0.4, 0.1, 0.2]
  • 位置 2(Python):h₂ = [0.1, 0.0, -0.2, 0.6]
  • 位置 3(函数):h₃ = [0.4, 0.3, 0.2, -0.1]

也就是一个 (4, 4) 的矩阵。


步骤 A:算 Q、K、V

每个位置 的向量 h,用三组可学习的权重矩阵(这里是 4×4)得到:

  • Q = h × W_Q(Query:我在找什么)
  • K = h × W_K(Key:我有什么可被找的)
  • V = h × W_V(Value:找到我时取多少)

用假想的权重算出来(数字仅为演示),每个 Q、K、V 都是 4 维:

位置 文本 Q (Query) K (Key) V (Value)
0 [0.3, 0.0, 0.4, 0.1] [0.2, 0.1, 0.5, 0.0] [0.2, 0.0, 0.3, 0.1]
1 一个 [-0.2, 0.4, 0.1, 0.2] [-0.1, 0.3, 0.2, 0.2] [-0.1, 0.3, 0.0, 0.2]
2 Python [0.0, 0.1, -0.1, 0.5] [0.1, 0.0, -0.1, 0.5] [0.0, 0.1, -0.1, 0.4]
3 函数 [0.3, 0.2, 0.2, -0.1] [0.4, 0.2, 0.1, -0.1] [0.3, 0.2, 0.1, 0.0]

步骤 B:用 Q 和 K 算「注意力权重」

每个位置 ,用它的 Q 去和所有位置K 做点积(再除以 √d 做缩放),得到「这个位置对每个位置的关注程度」:

  • 位置 i 的 Q 与 位置 0,1,2,3 的 K 点积 → 得到 4 个数
  • 对这 4 个数做 Softmax,得到权重和=1

假设算出来(示例):

对位置0(写) 对位置1(一个) 对位置2(Python) 对位置3(函数)
位置 0 看 0.5 0.25 0.15 0.1
位置 1 看 0.2 0.4 0.2 0.2
位置 2 看 0.1 0.2 0.5 0.2
位置 3 看 0.15 0.2 0.25 0.4

解读:位置 3(函数)较关注自己(0.4)和位置 2(Python)(0.25),符合「函数」和「Python」的搭配;位置 0(写)最关注自己(0.5)。这些权重是算出来的,不是写死的。


步骤 C:用权重对 V 做加权和,得到新向量

每个位置 ,用上面那一行的权重,对四个位置的 V 做加权求和,得到该位置本头的新表示。以位置 0 为例:

  • 新位置 0 = 0.5×V₀ + 0.25×V₁ + 0.15×V₂ + 0.1×V₃

    = 0.5×[0.2,0,0.3,0.1] + 0.25×[-0.1,0.3,0,0.2] + 0.15×[0,0.1,-0.1,0.4] + 0.1×[0.3,0.2,0.1,0]

    = [0.1,0,0.15,0.05] + [-0.025,0.075,0,0.05] + [0,0.015,-0.015,0.06] + [0.03,0.02,0.01,0]

    = [0.105, 0.11, 0.145, 0.16](近似)

  • 新位置 1、2、3 同理,用各自那一行权重对 V₀~V₃ 加权求和。

多个头算完后会拼在一起,再经过一次线性变换,然后加上残差 (加上本层原始输入),再做层归一化,得到这一层注意力部分的输出。


步骤 D:前馈网络(FFN)

每个位置 的新向量(上面得到的 4 维向量),独立做两次线性变换 + 中间非线性(如 GELU):

  • 先扩维:4 维 → 中间隐藏层(如 16 维,实际更大)
  • 做非线性激活
  • 再压回 4 维

公式形如:FFN(x) = Linear2(GELU(Linear1(x)))

然后再加残差、层归一化,得到这一层最终的输出 ,形状仍为 (4, 4),作为下一层的输入。


小结:阶段 3 在做什么
  • 输入 :阶段 2 得到的 (4, 4) 张量(本文统一示例),即 4 个位置、每位置 4 维向量。
  • 每一层
    1. 用 Q、K、V 让每个位置「看」整段序列,算注意力权重;
    2. 用权重对 V 加权求和,得到带上下文的新向量;
    3. 再过 FFN,做非线性变换;
    4. 残差 + 归一化,输出给下一层(形状仍为 (4, 4))。
  • 输出:最后一层、**最后一个位置(位置 3「函数」)**的向量,会送到阶段 4 去预测「下一个 token」。

底层逻辑 3:模型没有显式「理解」你的话,而是通过大量矩阵运算,把输入变成一组高维向量,再在最后一层用「最后一个位置的向量」来预测下一个 token 的概率分布。


五、阶段 4:从「最后一个向量」到「下一个词」

4.1 得到概率分布

  • 最后一层、最后一个位置的向量。
  • 通过一个线性层 + Softmax ,映射到词表大小(例如 10 万多个 token),得到每个 token 作为下一个词的概率
    • 例如:P("def") = 0.3,P("函数") = 0.15,P(" ") = 0.1......
示例:线性层 + Softmax 具体怎么算

沿用前文:阶段 3 最后一层、**最后一个位置(位置 3「函数」)**的向量,作为本步的输入。实际模型里这是高维向量(如 4096 维),这里仍用 4 维缩小版词表 演示。

步骤 1:最后一位置的向量

  • 记作 z ,形状 (4,)。假设经过多层后得到(示例数值):
    • z = [0.2, 0.5, -0.1, 0.3]

步骤 2:线性层(无偏置时可写成 z × W)

  • 有一个可学习的权重矩阵 W ,形状为 (隐藏维度, 词表大小),即 (4, V)。V 是词表大小(实际约 10 万+;这里用 V=6 做演示)。
  • 计算 logits = z × W(即 z 与 W 的每一列做点积):
    • 结果是一个长度为 V 的向量,每个分量对应一个 token 的「未归一化得分」。

假想的 W(4 行 6 列,每列对应一个 token):

token 0 "(" token 1 ":" token 2 "def" token 3 " " token 4 换行 token 5 "return"
维度0 1.0 -0.5 0.8 0.2 -0.3 0.6
维度1 0.2 0.4 0.5 0.1 0.0 0.3
维度2 -0.3 0.1 0.2 0.0 0.2 0.1
维度3 0.5 0.3 0.4 0.1 0.2 0.2
  • logits = z · W 的每一列:

    • logits[0] = 0.2×1.0 + 0.5×0.2 + (-0.1)×(-0.3) + 0.3×0.5 = 0.2 + 0.1 + 0.03 + 0.15 = 0.48
    • logits[1] = 0.2×(-0.5) + 0.5×0.4 + (-0.1)×0.1 + 0.3×0.3 = -0.1 + 0.2 - 0.01 + 0.09 = 0.18
    • logits[2] = 0.2×0.8 + 0.5×0.5 + (-0.1)×0.2 + 0.3×0.4 = 0.16 + 0.25 - 0.02 + 0.12 = 0.51
    • logits[3] = 0.2×0.2 + 0.5×0.1 + (-0.1)×0.0 + 0.3×0.1 = 0.04 + 0.05 + 0 + 0.03 = 0.12
    • logits[4] = 0.2×(-0.3) + 0.5×0.0 + (-0.1)×0.2 + 0.3×0.2 = -0.06 + 0 - 0.02 + 0.06 = -0.02
    • logits[5] = 0.2×0.6 + 0.5×0.3 + (-0.1)×0.1 + 0.3×0.2 = 0.12 + 0.15 - 0.01 + 0.06 = 0.32
  • 得到 logits = [0.48, 0.18, 0.51, 0.12, -0.02, 0.32]

步骤 3:Softmax

  • 对 logits 做 Softmax,把任意实数变成「和为 1」的概率:
    • 公式:P(token i) = exp(logits[i]) / Σⱼ exp(logits[j])

计算(保留两位小数):

  • exp(0.48)≈1.62, exp(0.18)≈1.20, exp(0.51)≈1.66, exp(0.12)≈1.13, exp(-0.02)≈0.98, exp(0.32)≈1.38
  • 分母 S = 1.62+1.20+1.66+1.13+0.98+1.38 ≈ 7.97
  • P("(") = 1.62/7.97 ≈ 0.20
  • P(":") = 1.20/7.97 ≈ 0.15
  • P("def") = 1.66/7.97 ≈ 0.21
  • P(" ") = 1.13/7.97 ≈ 0.14
  • P(换行) = 0.98/7.97 ≈ 0.12
  • P("return") = 1.38/7.97 ≈ 0.17
下一个 token "(" ":" "def" " " 换行 "return"
概率 0.20 0.15 0.21 0.14 0.12 0.17
  • 概率和 = 1。「def」概率最高 (0.21),若用贪婪解码就会选「def」作为下一个 token(符合「写一个 Python 函数」后面常接 def 的写法)。

小结 :4.1 做的事就是------用最后一位置的向量 z 乘上词表大小的线性层 W 得到每个 token 的 logits,再对 logits 做 Softmax 得到概率分布;实际词表是 10 万+,形状是 (1, 4096) × (4096, 100000+) → (1, 100000+),再 Softmax,逻辑与上述示例一致。

权重矩阵 W 从哪来?和阶段 2 的词嵌入表有什么关系?

W 是训练出来的。

  • 阶段 4 的 W (线性层权重)和阶段 2 的词嵌入(Embedding)表 、阶段 3 的 W_Q / W_K / W_V 、FFN 的权重等一样,都是模型的可学习参数
  • 训练时用大量文本(或对话数据):输入一段序列,模型预测「下一个 token」,把预测概率和真实下一个 token 做交叉熵损失 ,再通过反向传播 更新所有参数,其中就包括 W 。所以 W 不是人工填的表,而是数据驱动、梯度下降学出来的

W 和阶段 2 的 Embedding 表在形状与作用上是对称的。

  • 阶段 2 词嵌入表 E (常记作 embedding 或 token embedding):
    • 形状一般是 (词表大小 V, 隐藏维度 D),即 V 行、D 列
    • 作用:token ID → 向量。取第 i 个 token 时,查 E 的第 i 行,得到 D 维向量。
    • 即「从词表空间到隐藏空间」:输入侧,把离散 token 变成连续向量。
  • 阶段 4 的 W (常叫 lm_head / output projection):
    • 形状是 (隐藏维度 D, 词表大小 V),即 D 行、V 列 (和 E 的转置同形)。
    • 作用:向量 → 每个 token 的得分。用最后一位置的 D 维向量 z 乘 W,得到 V 个 logits。
    • 即「从隐藏空间回词表空间」:输出侧,把连续向量变回对每个 token 的分数。

所以:E 是「词 → 向量」,W 是「向量 → 词」,两者分别在输入和输出两侧连接「词表」和「隐藏表示」。

两种常见设计:独立 vs 共享(weight tying)

  • 独立 :E 和 W 是两套参数,各自随机初始化,各自用梯度更新。模型自由度大,但参数量多(E 和 W 各约 V×D)。
  • 共享(Weight Tying) :很多模型(如 GPT-2、部分 LLaMA)把输出层的 W 设为输入嵌入 E 的转置 ,即 W = Eᵀ (或等价地,用同一张表 E:输出时用 z × Eᵀ = z 与 E 的每一行做点积)。这样:
    • 「下一个 token 的得分」= 当前隐藏向量 z 与该 token 的嵌入向量的点积:得分高等价于「z 和这个词的嵌入越像」。
    • 参数量减半(只存一份 E),且输入/输出共用同一套「词表示」,训练更一致。
      因此,若采用 weight tying,阶段 4 的 W 和阶段 2 的 Embedding 表本质是同一张表:阶段 2 用行(按 token 取向量),阶段 4 用列(即 E 的行)做点积得到 logits。

一句话 :W 和词嵌入表 E 一样都是训练得到的;E 负责「词 → 向量」,W 负责「向量 → 词」;有的模型里 W 直接取 E 的转置(共享参数),有的模型里 W 和 E 分开学。

4.2 解码(Decoding)------选下一个 token

  • 贪婪:直接选概率最大的那个 token(简单、确定)。
  • 采样:按概率随机抽一个(温度高更随机,温度低更确定)。
  • Cursor/聊天产品通常会用采样 + 温度,让回答多样、自然;代码补全可能更偏贪婪或低温度。

选出来的 token 再转成文字(或保留为 ID),拼到已有序列末尾,作为「当前已生成的内容」。

采样具体是什么意思?「按概率随机抽」怎么抽?
  • 采样 :手里已经有一份「每个 token 的概率」(4.1 里 Softmax 得到的那一列),不是 直接取概率最大的那个,而是按这份概率做一次随机抽取,抽到哪个 token 就输出哪个。
  • 按概率随机抽 的做法(本质是「依分布抽样」):
    • 把每个 token 看成一条线段,线段的长度 = 该 token 的概率 ,把所有线段首尾相接拼成一根总长为 1 的棍子。
    • 在 [0, 1) 上均匀随机打一个点(例如 random 出 0.37),看这个点落在哪一段里,就选对应的 token。
    • 等价说法:概率大的 token 对应的区间更长,被随机点命中的机会就更大;概率小的更短,被命中的机会更小。抽很多次时,每个 token 被选中的比例会趋近于它的概率。

小例子(沿用 4.1 的 6 个 token 与概率):

token "(" ":" "def" " " 换行 "return"
概率 0.20 0.15 0.21 0.14 0.12 0.17
  • 区间划分:

    0, 0.20) → "(" ; \[0.20, 0.35) → ":" ; \[0.35, 0.56) → "def" ; \[0.56, 0.70) → " " ; \[0.70, 0.82) → 换行 ; \[0.82, 1.0) → "return" 。

    若随机数 = 0.18,落在 [0, 0.20),则结果为 "(" 。

    每次调用都会重新随机,所以同一段上下文多次生成可能得到不同结果。

  • 实现上 :等价于对「类别分布」(categorical distribution)做一次抽样,例如 numpy.random.choice(tokens, p=probs)torch.multinomial(probs, 1)

温度是什么?是哪个「维度」?
  • 温度(temperature) 是一个标量超参数 ,就是一个 (例如 0.5、1.0、2.0),不是 向量或矩阵的某一维;它用在 Softmax 之前 ,用来缩放 logits,从而改变概率分布的「尖锐程度」。
  • 用法 :对 4.1 里得到的 logits 先除以温度 T,再做 Softmax:
    • 新 logits = 原 logits / T
    • 新概率 = Softmax(新 logits)
  • 效果
    • T = 1:不缩放,就是 4.1 里原来的概率(例如 "def" 0.21 最高)。
    • T 很大 (如 2、5):logits 被缩小,彼此差距变小,Softmax 后概率会更平均 (更接近均匀),高概率的没那么高、低概率的没那么低 → 更随机、更多样
    • T 很小 (如 0.1、0.5):logits 被放大,差距拉大,Softmax 后最大的那个概率会更大 、别的更小 → 更确定、更「保守」,接近贪婪。

用 4.1 的 logits 看温度(logits = [0.48, 0.18, 0.51, 0.12, -0.02, 0.32],对应 6 个 token):

温度 T 效果简述 "def" 的大致概率 整体感觉
T=0.5 分布更尖 约 0.35+ 更确定,常选 "def"
T=1 原始分布 约 0.21 正常随机
T=2 分布更平 约 0.18 更随机,别的 token 更容易被抽到
  • 总结 :温度是一个标量 ,控制「logits 在 Softmax 前被缩小/放大的程度」,从而控制概率分布是更尖(更确定)还是更平(更随机) ;采样时用的是经过温度缩放后再 Softmax 得到的概率去做「按概率随机抽一个」。

T 是训练时自动算出来的吗?

  • 不是 。温度 T 不参与训练,不是用梯度、反向传播学出来的参数。
  • 训练时通常固定 T=1 (或等价地不除以 T),模型只学「在正常 Softmax 下预测下一个 token」;T 是在推理/生成阶段由人(或产品)设定的超参数,用来调节「这一轮生成要更稳还是更多样」。
  • 例如:Cursor / ChatGPT 的界面里「创造性」「随机性」滑块,背后往往就是在调 T;代码补全为了稳定,常把 T 设得很小或直接用贪婪(相当于 T→0)。所以:T 是「用模型时你选的开关」,不是「模型自己学出来的」

底层逻辑 4 :模型在每一步只会做一件事------根据当前整段序列,给出「下一个 token」的概率分布,然后由解码策略选一个。没有「想一整段再输出」,而是一个一个 token 生成。


六、阶段 5:循环生成,直到结束

5.1 自回归(Autoregressive)循环

  • 把刚生成的 token 追加到输入序列末尾。
  • 新的整段序列再送进模型(再走一遍 2→3→4)。
  • 再得到下一个 token 的概率分布,再选一个,再追加......
  • 如此反复,直到:
    • 出现「结束符」token(如 <eos>),或
    • 达到最大生成长度,或
    • 用户/系统触发停止。

5.2 为什么叫「预测下一个词」

  • 本质上,模型在每一步都在回答同一个问题:「给定到目前为止的全部内容,下一个最可能出现的 token 是什么?」
  • 它没有「计划全文」、没有「查斐波那契公式」,而是通过训练时见过的海量类似文本,学到了「这种问题后面通常跟什么」的统计模式,所以能生成看起来像「理解题意并写代码」的结果。

底层逻辑 5 :整段回复 = 多次「看当前序列 → 算下一个 token → 拼上去」的循环;逻辑和规划都是隐式地存在于这些概率里,而不是显式编程出来的。


七、阶段 6:从 token 流到你能看到的回复

6.1 解码器(Detokenizer)

  • 把生成的一串 token ID 用同一个词表反查成文字(或子词)。
  • 可能还要做一些后处理:合并子词、处理特殊符号、控制显示格式等。

6.2 流式输出(你看到「一个字一个字蹦」)

  • 每生成一个(或几个)token,就立刻解码并推给前端显示,不用等整段生成完。
  • 所以你看到的是「边算边出字」;底层仍然是「算一个 token → 解码 → 再算下一个」。

八、流程图总览

复制代码
你输入:"写一个 Python 函数,计算斐波那契数列第 n 项"
                    ↓
┌─────────────────────────────────────────────────────────────┐
│ 1. 组 prompt(系统提示 + 历史 + 你的话 + 上下文)              │
│ 2. 分词 → 一串 token ID                                      │
│ 3. Embedding + 位置 → 每个 token 一个向量,带顺序              │
└─────────────────────────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────────────────────────┐
│ 4. 多层 Transformer                                          │
│    - 每层:自注意力(看整段关系)+ 前馈网络(非线性变换)        │
│    - 最后一层最后一个位置的向量 = 「整段输入的总表示」           │
└─────────────────────────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────────────────────────┐
│ 5. 线性层 + Softmax → 下一个 token 的概率分布                  │
│ 6. 按策略选一个 token(贪婪/采样)→ 拼到序列末尾                │
└─────────────────────────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────────────────────────┐
│ 7. 把「原输入 + 刚生成的 token」当作新输入,回到步骤 3          │
│    重复 3→4→5→6→7,直到出现结束符或达到长度上限                 │
└─────────────────────────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────────────────────────┐
│ 8. 把整段生成的 token ID 解码成文字 → 你看到的回复              │
└─────────────────────────────────────────────────────────────┘

九、为什么「算下一个词的概率」就能正确回答问题?理论依据是什么?

整篇文章讲的都是:AI 只是在算「下一个 token 的概率分布」 ,再按概率选一个、拼上去,循环下去。一个很自然的问题是:凭什么这样做就能「正确回答问题」?理论依据在哪?

9.1 核心:预测得准,必然要学到「让句子成立」的规律

  • 训练目标 :模型在训练时被要求最小化「预测下一个 token」的误差 ------也就是在大量文本上,让模型给出的概率分布尽量接近「真实下一个词是什么」。要预测得准,模型就必须在内部抓住什么样的上文后面通常会接什么的规律。
  • 文本里已经编码了「对」的 pattern :人类写出来的文本(教材、问答、对话、代码)里,正确 的答案往往以「问题 → 正确答案」的形式反复出现;错误或胡说的写法在语料里要么很少,要么结构不同。所以,谁能在「给定上文,预测下一个词」这件事上做得好,谁就不得不 学到:在像「问句」的上文后面,接的往往是在数据里常出现的、看起来正确的那类续写 。也就是说,「正确回答问题」并不是模型额外学的一个能力,而是「把下一个词预测准」学好了之后的一种表现------因为「正确回答」在训练数据里本来就是高概率的续写。

9.2 要预测准,就必须隐式学到语法、语义和事实

  • 语法与结构 :若不知道主谓宾、时态、搭配,就预测不准下一个词。所以优化「下一个词概率」会迫使模型学到语法、句法这类结构。
  • 语义与常识:若不知道「苹果」和「吃」更常一起出现、「太阳从东边升起」这类模式,预测也会差。所以模型会隐式学到词义、常识、以及「什么和什么在现实中常一起被说到」。
  • 问答与推理 :训练数据里若大量存在「问句 + 正确答句」的序列,那么在这些问句后面,高概率的下一句就是正确答句 。模型为了把概率预测准,就会学到「在这种问句后面,该接这样一段话」,从而在行为上表现为「正确回答问题」。
    所以:正确回答,是因为在训练数据里「正确回答」本身就是高概率续写;模型只是被训练成把这种高概率如实反映出来。

9.3 信息论视角:预测准 ≈ 压缩得好 ≈ 抓住了规律

  • 在信息论里,预测下一个符号有多准把这段数据压缩得多好 是等价的(熵、交叉熵)。模型要在大规模文本上把下一个词预测准,就相当于在学一个对文本分布的压缩表示 ;而要压缩得好,必须抓住数据里的规律(重复出现的结构、因果关系、事实性表述等)。
  • 所以:「算下一个词的概率并追求预测准」本身就是一个目标,它倒逼模型去捕获语言和世界中的规律;这些规律里就包含「什么问题后面通常接什么正确答案」。

9.4 不保证「绝对正确」,只保证「和训练分布一致」

  • 没有绝对对错 :模型不会「判断真理」,只会输出在它学到的分布下高概率的续写 。所以「正确」是相对于训练数据里常见、一致、被当作正确的那种写法而言的。数据有偏见或错误,模型也会学进去;数据里正确答法多,模型才更容易答对。
  • 总结这套算法的理论依据是------在人类文本中,「正确回答」往往就是「问题之后的高概率续写」;把「下一个词的概率」算准了,模型就会把这种高概率续写输出出来,从而在行为上表现为正确回答问题。 所以不是「先会判断对错再回答」,而是「把概率学对了,对的答案自然概率高」。

十、五条底层逻辑总结

# 底层逻辑
1 一切输入都是数字:文本 → token ID → 向量;模型只处理数字和向量。
2 顺序很重要:通过位置编码和自注意力,模型在向量空间里保留了「谁在前谁在后」的信息。
3 理解 = 向量变换:没有符号化的「理解」,而是通过多层注意力 + 前馈,把输入变成一种高维表示,能用来预测下一个 token。
4 生成是逐步的:每次只预测「下一个 token」,再把它接上去,再预测再接,自回归循环。
5 能力来自训练:为什么能写斐波那契?因为训练数据里类似「写函数、数列、第 n 项」的模式出现很多次,模型学到了「这种上下文后,下一个 token 常是什么」的统计规律。

十一、核心组成:训练得到的「大表」+ 固定「算法」

可以把大语言模型看成两大部分:训练学出来的大矩阵(表) + 写死的计算流程(算法)。前者存的是「知识」,后者规定「怎么用这些表算一遍」。

11.1 训练得到的大表(矩阵 / 参数)

这些都是训练时用数据 + 梯度下降学出来的,推理时只做查表或矩阵运算,不再更新。

出现在哪 名称 / 作用 形状(示意) 说明
阶段 2 输入 Token 嵌入表 E (V, D) 词表 V 个 token,每个对应 D 维向量;token ID → 查一行 → 得到向量。
阶段 2 输入 位置编码/位置嵌入 (最大长度, D) 或公式 给每个位置一个 D 维向量;可学习表或固定公式(如 sin/cos)。
阶段 3 每层 W_Q, W_K, W_V 各 (D, d) 或 (D, D) 自注意力里把当前向量变成 Q、K、V 的线性层权重;多头时每头一套小矩阵。
阶段 3 每层 注意力输出投影 (D, D) 多头拼在一起后再做一次线性变换(有的实现合在 W_V 里)。
阶段 3 每层 FFN 两层 (D, D_mid), (D_mid, D) 前馈网络:先扩维到 D_mid 再压回 D;中间有激活(如 GELU)。
阶段 3 每层 LayerNorm 的 scale / shift 各 (D,) 层归一化里的可学习缩放和偏移。
阶段 4 输出 输出层 W(lm_head) (D, V) 最后一维向量 → 乘 W → 得到 V 个 logits;有的模型与 E 共享(W = Eᵀ)。
  • V = 词表大小(约几万~十多万),D = 隐藏维度(如 768、4096),D_mid = FFN 中间层维度(常为 4D)。
  • 层数多时,阶段 3 的那几类表会重复 N 次(N 层),所以总参数量里绝大部分来自这些重复的「层内表」。

11.2 固定算法(流程与公式)

这些是不随训练改变的步骤和公式:规定怎么用上面的表做计算、怎么得到下一个 token。

阶段 算法 / 步骤 在做什么
阶段 1 分词(Tokenization) 按词表把文本切成 token,转成 ID 序列;规则 + 词表(词表可视为一种「表」,但通常不通过梯度更新)。
阶段 2 Embedding 查表 对每个 token ID 查 E 的对应行,得到向量;再按位置加上位置编码。
阶段 3 自注意力 用 W_Q/W_K/W_V 算 Q、K、V → Q 与所有 K 点积(可除以 √d)→ Softmax 得权重 → 对 V 加权求和。
阶段 3 残差 + LayerNorm 注意力输出加上本层输入(残差),再做 LayerNorm;FFN 后同样残差 + LayerNorm。
阶段 3 前馈 FFN 对每位置向量:线性 → GELU(或 ReLU)→ 线性,公式固定,权重来自上表的 FFN 两层。
阶段 4 线性层 最后一位置向量 z × W(lm_head)→ 得到 V 个 logits。
阶段 4 温度缩放 logits / T(T 为推理时设定的超参数,不训练)。
阶段 4 Softmax 对 logits 做 Softmax,得到每个 token 的概率,和为 1。
阶段 4 解码策略 贪婪:取 argmax;采样:按概率做一次随机抽样(如轮盘赌 / categorical)。
阶段 5 自回归循环 把选出的 token 拼到序列末尾,整段再走阶段 2→3→4,直到结束符或长度上限。
阶段 6 反分词(Detokenize) 把生成的 token ID 序列按词表还原成文本(或子词拼成词)。

11.3 一句话对照

  • 「表」 :E、位置、每层的 W_Q/W_K/W_V、FFN、LayerNorm、最后的 W 等,都是训练出来的大矩阵/向量,占模型体积的绝大部分。
  • 「算法」 :分词、查表、Q/K/V 与注意力公式、残差、LayerNorm、FFN 公式、线性层、温度、Softmax、采样/贪婪、自回归、反分词,都是固定流程与公式,不占「可学习参数」。

所以:AI(这里指这类大语言模型)= 若干训练得到的大表 + 一套固定算法;能力来自表里的数,行为由算法决定。


十二、常见问题

Q1:矩阵表越大、维度越多,AI 就越聪明、包含的内容就越多吗?

大致趋势是对的,但不能简单画等号。

  • **参数量(矩阵越大、维度越多、层数越多)**确实和模型能力强相关,业界观察是:在数据与训练跟得上的前提下,规模变大 (更多参数、更大隐藏维 D、更多层、更大词表)往往能带来更强的理解、推理和生成能力,这种现象叫「 scaling law」(缩放定律)。所以可以说:在同等训练和数据条件下,更大的模型通常有更大的「容量」,能记住和利用更多模式,表现往往更好。
  • 但「聪明」和「包含的内容」不只由参数量决定:
    • 训练数据 :模型里「包含什么」主要来自训练时喂进去的数据。表再大,若数据少或质量差,也学不到那么多有用内容;数据多且好,小模型也能学到不少,只是容量上限更低。
    • 训练方式:同样的参数量,预训练、指令微调、对齐做得好不好,会明显影响最终是否「聪明」、是否少犯错。
    • 效率与过拟合:矩阵过大而数据或算力有限时,可能训不充分或过拟合,反而不如稍小一点、训得更好的模型。

一句话 :更大、维度更多的矩阵表,相当于给模型更大的「脑容量」,在数据和训练跟得上的前提下,一般会更聪明、能承载更多学到的模式;但「包含的内容」和「聪明程度」还强烈依赖数据质量、训练过程,不能只看规模。


Q2:为什么同一个问题,多问几次回答会不一样?

因为阶段 4 用了采样而不是每次都选概率最大的 token。采样是按概率随机抽,所以每次生成的 token 序列可能不同,同一问题就会得到不同回复。若把温度 T 调低或设为贪婪解码(总选最大概率),同一输入下输出会稳定很多。


Q3:模型会「忘记」或「更新」之前学的内容吗?

推理时 :不会。模型只是用现有的表做计算,参数不变,不会因为和你多聊几句就改掉表里的数。
训练/微调时 :会。重新训练或微调会更新矩阵表,相当于「学新东西」,但可能覆盖或削弱以前学到的(这就是微调时的「灾难性遗忘」问题)。平时对话里你感觉到的「记住对话内容」,一般是把历史写进当前这次输入的 prompt,不是模型参数在变。


Q4:模型真的「理解」我的话吗?

按本文的底层逻辑:模型没有符号化的「理解」,只是在做向量变换 + 下一个 token 预测 。它学到的是「像你这样的输入,后面常接什么样的 token」的统计规律,所以表现像「懂了」------但本质是模式匹配与概率,不是人类那种理解。说它「理解」是一种方便的说法,严格讲是「在统计上很好地拟合了语言与任务模式」。


Q5:输入一个词,AI 就是在算「和它关联的词有哪些、概率多少」,再挑一个展示?关联特别多时,是不是就得维度很大才能覆盖?

你的直觉对了一大半,可以这样理解,再补两点精确化:

  • 本质上 :模型确实是在算「在当前这段上下文 下,下一个 token 是哪一个的概率各是多少」,然后按概率选一个(贪婪或采样)展示。所以可以粗略说:AI 在算「和当前内容关联的下一段内容有哪些、概率大概多少」,再选一个相近的展示 。注意:模型看的是整段输入(可能很多词),不是单一个词;「关联」是「整段上下文 ↔ 下一个 token」的关联。
  • 关联多 ↔ 需要更大容量 :如果一个词(或更准确说,某种上下文模式 )在真实数据里会接很多种不同的后续------例如「苹果」后面可能是水果、公司、手机、品牌等------模型就要在内部把「这种上下文」表示成一种向量,再通过最后的矩阵表映射到词表上,让很多个 下一个 token 都能得到合理的概率。
    维度少 时,向量空间就那么大,能「区分」的不同模式有限,很多不同的关联会挤在一起,容易混淆(例如把「苹果公司」和「苹果水果」的后续搞混)。维度多、矩阵大 时,空间更大,可以给更多种「上下文→下一词」的关联各自留出足够的表示,所以要覆盖「一个词/一种上下文关联特别多」的情况,理论上就需要更大的矩阵、更多的维度 ,否则确实很难同时把这么多关联都区分开、概率都学准。
    可以简单记:关联越多、要区分的模式越多 → 需要更大的「表」和更高维的向量,才能装得下、分得清;只有几个维度的话,很难覆盖大量不同的关联内容。

Q6:所以现在的 AI 都是分领域/分专业的,维度可以少一些,只训练该领域内容,准确度也更高?

是的,这个思路对。 分领域、分专业的模型正是这么做的:

  • 领域小 → 要覆盖的「关联」少 :只做医疗、法律、代码、客服等某一类任务时,「上下文 → 下一个词」的模式只集中在这一块,不需要同时兼顾全网各种话题。所以用较小的矩阵、较少的维度和层数,就够把该领域内的主要关联学好,不必做成「通才」那种超大参数量。
  • 维度/参数相对少的好处
    • 同样算力下可以训得更充分(数据量相对需求更易满足);
    • 少混入无关模式,不会像大模型那样在「苹果」上既背水果又背公司又背手机,在垂直领域里歧义更少;
    • 推理更快、部署更省资源。
  • 准确度 :在该领域内,用高质量专业数据训出来的小模型,往往能在该领域任务上达到更高准确度或更稳定,因为容量都用在「这一块」上了。通用大模型则是在「什么都懂一点」和「单领域极致」之间做权衡。

所以:分领域、分专业的 AI 用相对少的维度和参数、只训练该领域内容,是常见做法,也往往能在该领域里做到更高准确度、更省资源。


Q7:AI 没有判断对错的能力,理论上要在训练时把完全正确的知识喂给它,才能保证准确性?

大体对。 可以这样理解,再补一点现实中的情况:

  • 没有内在的「对错判断」 :按本文的底层逻辑,模型只是在做下一个 token 的概率预测 ,学到的是「什么样的上下文后面常接什么」的统计规律。它不会 在内部先「判断这句话对不对」再决定说不说;输出什么,取决于训练数据里这类输入后面通常是什么。所以模型本身不具备「判断事实对错」的能力,它只会模仿数据里的模式。
  • 训练数据决定「对错」倾向 :如果训练时喂进去的多数是正确、一致的知识,模型就更可能在这些问题上给出正确、一致的答案;如果数据里错误、矛盾、偏见多,模型也容易复现这些错误。因此理论上,要在训练时尽量提供正确、高质量的知识,才能提高模型在事实性上的准确性,这一点是对的。
  • 现实中 :训练数据几乎不可能「完全正确」------会有噪声、过时信息、矛盾说法。模型有时会「平均」掉一部分错误,有时反而会放大错误或产生幻觉。所以除了尽量用好数据训练,还会用检索增强(RAG)引用外部知识库人类反馈与对齐(如 RLHF) 等手段,在推理时或训练中把「什么算对」再约束一下;但这类约束仍是靠数据和规则教给模型的,不是模型自己「会判断对错」。

一句话AI 没有天生的对错判断能力;理论上训练时给它的知识越正确、越一致,它在该类问题上的准确性越有保障;现实中会再配合检索、对齐等手段尽量提高可依性。


文档整理自对「给 AI 一个命令后系统一步一步做了哪些事」的讲解。

相关推荐
kjmkq2 小时前
办公智能体落地:九科信息让AI深度融入企业日常运营
人工智能
NAGNIP2 小时前
一文搞懂神经元模型是什么!
人工智能·算法
Ro Jace2 小时前
分岔机制学习
人工智能·学习·机器学习
ws2019073 小时前
聚焦测试测量新机遇,AUTO TECH China 2026广州汽车技术展锚定行业未来
人工智能·科技·汽车
摘星编程3 小时前
RAG大升级:不再只是文档问答,如何用它构建下一代AI知识中枢?
人工智能
反向跟单策略3 小时前
期货反向跟单-2025年回顾及2026年展望
大数据·人工智能·学习·数据分析·区块链
yunhuibin4 小时前
GoogLeNet学习
人工智能·python·深度学习·神经网络·学习
luoganttcc4 小时前
Taalas 将人工智能模型蚀刻到晶体管上,以提升推理能力
人工智能·fpga开发