跳转至

P6-8.1 先建立宽广语言基础的预训练

Section ID: P6-8.1 Version: v2026.07.26

到 P6-6 为止,我们已经看到 Transformer 和 GPT 结构如何生成下一个词元候选,以及输出选择规则如何改变实际回答的稳定性和多样性。但到这里仍然剩下一个问题。为什么即使生成结构相同,有些模型也能在更宽广的场景中给出像样的反应,而有些模型很快就显出局限?

从这个问题开始,只看计算结构已经不够了。现在还要一起看 先学习什么、以多大规模学习,以及 在其上叠加什么后续调整。Chapter 7 正是这条学习轴线的起点。

在 P6-5.2 中,我们看到对话型 LLM 是在单纯自动补全模型之上,加上指令跟随、安全调整和界面层之后形成的用户体验。这里再往下一层看,先回到这些调整被加上之前,模型必须先具备什么基础。

预训练(pretraining)是模型进入某个特定任务之前,先从大规模文本中学习一般语言模式和表达的阶段。也就是说,它不像是马上解决实际业务问题的阶段,更接近先广泛习得语言基本感觉的准备阶段。

先建立宽广语言基础的阶段

基础学习阶段从下面几个问题开始。

  • 预训练学习什么?
  • 为什么先从大量文本中学习,再按目的进行调整?
  • 预训练、微调(fine-tuning)、指令调优(instruction tuning)如何区分?

预训练是 先学习大规模一般模式的基础学习阶段。有了这个标准,才不会把微调和指令调优都笼统地归到同一种“学习”之下。

规模和计算约束回答的是 为什么要以那么大的规模建立宽广基础,指令调优和对齐回答的是 如何让这个基础符合用户请求和政策标准。如果先把预训练分离出来,后续问题就不会混成一团。

如果把预训练看成 把知识整体保存下来的魔法过程,后面的说明就会摇晃。更准确的出发点是:在生成结构连接到实际任务调整之前,模型会先学习宽广的语言模式和表达关系。

因此,核心不是 已经很聪明的模型 这种印象,而是 先学习宽广语言基础,再叠加按目的进行的调整 这种结构。

为什么在生成说明之后重新阅读学习轴

刚理解生成结构之后,常见误解是觉得 那么只要模型结构相同,反应也会差不多。但现实并非如此。即使用同样的 Transformer 结构,模型先学习了什么、学习得多宽广,会让基本反应范围大不相同;其上又叠加了什么调整,也会再次改变用户体验。

所以 Chapter 7 不是接在生成原理后面的额外主题,而是回答 为什么即使生成结构相同,基本反应范围也会不同 的学习轴起点。这里首先要抓住的是预训练,也就是在特定任务之前学习宽广语言基础。规模(scale)是为什么要把这个基础做大的问题,微调、指令调优和对齐则是如何把这个基础进一步贴合用户目的和政策标准的问题。

模型已经很聪明 这种印象,需要改读为 先学习大规模一般模式,之后再添加按目的进行的调整。

因此,本节的中心是 先建立语言基础 这种感觉。这个标准建立起来之后,后面的微调和指令调优也会开始显得不是添加新功能,而是在已经建立的基础上,朝着目的和用户反应进一步收窄的后续调整。

区分宽广语言基础和后续调整

  • 能以入门水平解释预训练。
  • 能说出预训练、微调、指令调优的区别。
  • 能解释为什么预训练会成为多种任务迁移(transfer)的基础。
  • 能把 数据和规模 问题读作预训练基础大小的问题。

需要这种区分,是因为它:

  • 让我们能从共同的预训练视角阅读多个后续模型
  • 把后面的 fine-tuning、instruction tuning、prompt、alignment 说明连成一条线

基础学习和后续调整的区分

要理解预训练,需要把 建立宽广基础的阶段 和 按目的收窄的阶段 分开。

要区分的阶段 确认标准
预训练 是否先建立宽广语言基础,而不是特定任务答案
微调 是否把已经建立的基础进一步收窄到特定任务数据
指令调优 是否调整为更好地回应用户的自然语言请求格式
案例判断 能否区分当前不足的是语言基础、任务调整,还是请求格式调整

预训练学习什么

预训练不是模型先学习某家公司的一项内部业务,或某一道特定考试题的阶段。它是先学习更宽广文本模式的阶段。

问题 简短回答
模型在这个阶段学习什么? 句子和表达如何接续的一般模式
还没有学习什么? 特定公司政策、特定任务规则
为什么先经过这个阶段? 为了建立以后可共同用于多种任务的基础

例如,模型可以间接习得下面这些内容。

  • 哪些词和表达经常一起出现
  • 句子通常按什么结构继续
  • 问题、说明、比较、摘要等格式如何出现
  • 在特定上下文中,哪个词元更自然地接在后面

也就是说,把预训练看作先学习 语言使用的大统计结构 会更稳妥。

为什么先大范围学习,再进行调整

必须先抓住这个问题,才能区分 一开始就做小任务模型 和 先广泛学习再按目的收窄。

为什么不直接只做一个客服分类模型,而要先训练一个大的通用模型?

理由很简单。

  • 如果先学习一般模式
  • 之后即使用较小数据
  • 模型也能更好地适应多个任务

可以这样理解。

预训练先建立通用语言感觉,之后把细部任务调整叠加在其上。

这也和 Part 3 中学过的迁移(transfer)与泛化(generalization)视角相连。

换句话说,预训练更接近 先建立能解决问题的基础,而不是 马上解题的阶段。

只有看到这个标准,P6-8.2 的规模说明才会自然接上。为什么非要使用那么大的数据和计算 这个问题,正连接着我们现在看到的 先建立宽广基础的阶段 实际上有多宽、多重。

例如,即使要做客服分类,如果模型先广泛学习过句子结构和表达差异,之后就更容易适应 退款、换货、账号问题 等更窄的分类规则。

预训练、微调、指令调优有什么不同

这三个表达经常一起出现,但并不是同一个意思。

区分 核心问题
预训练(pretraining) 是否先学习一般语言模式?
微调(fine-tuning) 是否根据特定任务数据进一步调整权重?
指令调优(instruction tuning) 是否调整为更好地遵循用户的自然语言指令?

如果不区分这些差异,用户很容易误以为 模型原本就什么都知道,或者 只要提示写得好,就能产生和学习一样的效果。

可以先用下面的一行比较抓住它。

  • 预训练:学得宽
  • 微调:按目的收窄
  • 指令调优:让模型更好地回应人的请求格式

预训练不等于事实存储

必须先把这一点分离出来,才不会把 广泛学习模式 误解为 把事实完整保存起来。

把预训练解释成下面这样是危险的。

模型把世界上的事实全都背下来。

更稳妥的说明如下。

模型从大规模文本中学习模式和表达。 因此,它可以很好地生成像样的句子和结构, 但并不总是保证这些知识已经完成事实核验。

也就是说,预训练更接近:

  • 语言模式学习
  • 表达学习
  • 下一个词元预测结构学习

而不是 真相保证系统。

为什么预训练会连接到多种任务

因为经过预训练的模型已经知道一般语言模式,所以在其上增加小的调整之后,更容易连接到多种任务。

例如:

  • 摘要
  • 分类
  • 问答
  • 信息抽取
  • 翻译

这些工作可以在一个大的基础模型上延续,而不是分别从完全不同的模型开始。

这是 LLM 时代的重要转变。

预训练建立的基础和留下的调整

把到这里为止的内容最短地整理如下。

  • 预训练先建立 宽广语言基础。
  • 微调让 特定任务反应 更清晰。
  • 指令调优建立 更好回应人的请求格式的方式。

有了这种区分,才能同时减少 模型原本什么都知道 的误解,以及 只改提示就能产生和学习一样效果 的误解。

非常简单地画出来

flowchart TD
  A["大规模文本语料"]
  B["预训练"]
  C["宽广语言基础"]
  D["微调或指令调优"]

  A --> B
  B --> C
  C --> D

这个图整理的是:预训练不是终点,而是后续多种使用方式的起点。因此,在这个图中要确认的结果是,从大文本建立宽广基础之后,后续阶段是否真的能被读作按目的调整这个基础的流程。

这张图最重要的读法如下。

  • 大文本是 材料
  • 预训练是 建立宽广基础
  • 后续阶段是 把这个基础按目的使用的调整

案例与示例

下面的图把本节的三个案例重新归到共同问题上:不是 是否从一开始只训练一个任务,而是 是否先建立宽广语言基础,再在其上放置目的。

flowchart TD
  A["相同的预训练问题"]
  B["文档摘要<br/>是否先需要语言结构?"]
  C["客户分类<br/>能否把不同表达归为相同意图?"]
  D["对话型回应<br/>对话质量是否建立在语言基础之上?"]

  A --> B
  A --> C
  A --> D

从这个图中要确认的是,三个场景都更接近 先建立宽广基础,之后调整目的,而不是 从一开始只背一个目的的学习。任务虽然不同,但先习得一般模式,再叠加细部目的的顺序是共同的。

案例 1. 文档摘要

假设我们想一开始就直接做一个摘要长会议记录的模型。人们看到这个问题时,通常可能先想 只要有几千个摘要示例不就够了吗? 但如果数据只停在这个程度,模型就不仅要学习摘要规则,还要同时学习句子结构和信息排列方式,起步会变重。例如,摘要里要保持 结论 -> 理由 -> 下一步行动 的顺序,但如果语言基础弱,在压缩核心句子之前,句子连接就可能经常摇晃。

这里发生的变化,是从 只要再给摘要示例就行 的标准,移动到 先具备宽广语言基础,再在其上叠加摘要目的 的标准。经过预训练的模型,从一开始就已经在宽广文本中某种程度上学过句子模式和压缩形式。因此,即使是同一个摘要任务,也可以减少 重新学习语言本身的阶段,更快进入摘要目的调整。这个案例中要确认的结果是,即使摘要数据较少,核心句子压缩和句子连接是否也能更快稳定。

这个案例重要,是因为人们很容易觉得只要收集到任务示例,就能立刻做出任务模型。但摘要不只是缩短长度,而是必须在语言层面已经某种程度上知道什么信息是核心、应按什么顺序保留,才会稳定。如果在语言基础弱的状态下直接只学摘要,模型就必须同时重新学习 要摘要什么 和 如何连接句子。所以预训练的价值不在于替我们背下摘要规则,而在于先减轻任务之前的语言基础负担。

从工作准备的角度重读这种差异,可以整理如下。

起步方式 容易先期待什么 实际上容易先不足的是什么
只用摘要数据直接开始 因为有任务示例,看起来会马上学会摘要 句子连接、核心信息排列、压缩表达
宽广文本基础之后再做摘要调整 可能看起来像绕远路 在任务之前先减轻语言结构负担
少量摘要数据 + 预训练基础 用小数据也可能做到一定程度 能更快集中到任务目的调整

这张表中要纠正的误解是 摘要数据看起来很多,语言基础也会一起解决。实际上,摘要任务之前必须先有能处理语言结构的基础,这样即使用同样数量的摘要示例,模型也更容易稳定收敛。

案例 2. 客户咨询分类

假设要把客户咨询分成 退款、配送、账号。如果标注数据不多,人们容易想 只要贴上标签,不就能马上做分类器吗? 但从头训练新模型时,学习句子表达本身的数据也可能不够。例如,我取消付款了,什么时候会反映出来? 和 我想确认取消处理状态 可能是同一流程,但表面句子不同。

用简单标准看,人们会先看相同词重叠多少,但只靠这个标准,常常会漏掉表达差异较大的句子。如果在预训练表达之上做微调,模型已经处在某种程度上能读取相似句子结构和词关系的状态。因此,即使用少量标注数据,也更容易快速判断 这句话更接近哪条业务流程。所以这个案例中要确认的结果是,即使没有完全相同的词,相似咨询是否也能更稳定地聚到同一个处理队列。

这个场景也直接贴近实际业务。客户咨询数据通常不是标签数更成问题,而是表达变体更多。同一个退款咨询,不同人也会用 取消、撤回、退货、退款请求 等不同说法。容易觉得只要标签定义清楚,分类器就会马上稳定,但实际上,在标签之前,需要先有 表达不同也能读出相同意图 的基础。预训练之所以重要,是因为它先宽广地建立这种表达基础,再让少量标注数据把业务边界进一步收窄。

同一个分类任务,会因准备状态不同而难度不同。

分类准备方式 先期待什么 实际遇到的问题
只用标注数据直接开始 只要给标签,分类边界似乎就会形成 经常漏掉表达不同的同类咨询
在预训练表达上微调 可能看起来像绕远路 可以用更少标签开始相似意图归类
以词重叠为主的简单标准 看起来能很快完成 对表面词不同的同一流程咨询较弱

这个案例中的重要标准,是把 背标签 和 表达不同也读出相同意图 分开看。预训练先减轻的正是第二个负担,所以即使标注数据较少,分类也更容易较快稳定。

案例 3. 对话型回应

看到对话型 LLM 自然回答的样子,可能会觉得它从一开始就只学习了对话。但人首先要想到的是,这些回应也放在学习过句子连接和一般语言模式的基础之上。例如,要回应 简单说明一下、分步骤整理、也加上注意点 这样的要求,模型在对话格式之前,必须先广泛知道句子结构和说明方式本身。

如果用简单标准看,人们容易觉得只要最后的语气调整变好,对话质量也会马上出现。但如果底层语言模式弱,即使加上礼貌语气,说明顺序和句子连接也容易崩塌。这里的变化,是从先看 最后的语气调整 的标准,移动到先看 其下的语言基础是否充分 的标准。实际的对话型调整,通常是在这种宽广语言基础之上,再加上额外的指令跟随和回应格式调整。因此,这个案例中要确认的结果是,在语气调整之前,说明句子的连接和基本回应结构是否也能在一定程度上保持自然。

把三个案例再从基础形成的视角归在一起,可以整理如下。

情况 如果只用任务数据开始,容易先不足的是什么 预训练基础先提供什么
文档摘要 句子连接和一般压缩模式 宽广语言结构和信息排列感
客户咨询分类 把表达不同的同类咨询归在一起 读取相似句子关系的基础
对话型回应 说明句子连接和基本回应结构 问答的一般语言流程

还需要明确抓住的是,三个案例最终都指向同一个方向。摘要、分类、对话在表面上是不同任务,但三者都会回到一个问题:现在看到的问题,是不是应该马上读作任务规则不足,还是要先判断在那之前宽广语言基础是否薄弱。有了这个共同问题,P6-8.2 中阅读 为什么要把那个宽广基础做大 的脉络才不会断开。

学习阶段分开的场景

读完本节之后,即使还不知道大规模学习流程的细节,也可以先练习区分现在需要的是 宽广基础学习、任务调整,还是 指令调整。如果有一些摘要示例,但句子连接和核心压缩本身经常摇晃,问题可能不是只靠增加摘要数据就能解决,而是要看宽广语言基础是否薄弱。如果 退款、换货、账号 分类能做,但经常漏掉表达不同的同类咨询,就要先问是否需要在能读取表达关系的基础上做微调,而不是只看标签定义。如果基本说明能做,但经常违反 三句话、平稳地、分步骤 这样的请求格式,那么首先显现的问题可能不是把预训练做得更大,而是指令调整层的问题。

这里重要的不是认为 预训练大就能解决一切,而是先把 宽广学习的阶段、按目的收窄的阶段、贴合人的请求格式的阶段 读作不同层位。

这里经常混在一起的还有下面几点。

  • 容易把预训练、微调、指令调优都当成同一种追加学习。
  • 容易觉得只要有少量任务示例,语言基础负担也会一起解决。
  • 容易把对话型格式问题看成和基础学习不足相同的原因。

因此,预训练先建立宽广基础 这句话应该成为实际问题分类的标准。

这种区分的目的,不是一次性确定原因。它不是把问题压扁成 还需要更多学习 这一句话,而是简短地区分你现在看到的现象首先出现在 宽广基础、任务调整,还是 请求格式调整 中。

练习与示例

这个示例的目标是直接观察 如何先从一般文本中收集模式,再用小规模任务数据进一步收窄这些模式。它不是实现真实 LLM 预训练的示例,而是一个缩小实验,用来分开观察学习数据束变化时,连接会如何变化。

示例数据在 p6-7-pretraining-stage-sentences-zh.csv 中。一行是一条短学习句子,stage 表示该句子属于哪个学习数据束。general_text 是宽广的一般句子,customer_support 是客服领域句子,instruction_reply 是符合请求格式的回应句子。

输入:

  • general_text:包含文档、会议、问题、说明等宽广一般表达的句子
  • customer_support:包含退款、配送、账号、换货等特定业务词汇的句子
  • instruction_reply:体现 逐步、平稳地、三句话 等回应格式的句子

输出:

  • 只看到一般语料时的连接数
  • 加入客服领域句子后新产生或变强的连接
  • 加入指令型回应句子后才出现的请求格式连接

要确认的核心是,学习更多 并不是一种单一变化。一般语料建立宽广语言连接,领域句子增加特定业务词汇连接,指令型回应句子则另外强化符合人的请求格式的连接。

# 这个示例逐阶段加入 CSV 句子,比较哪些下一个词元连接被保持、新建或强化。
from collections import Counter, defaultdict
from csv import DictReader
from pathlib import Path

DATA_PATH = Path("docs/assets/part-06/chapter-07/p6-7-pretraining-stage-sentences-zh.csv")

STAGE_BUNDLES = [
    ("general_only", ("general_text",)),
    ("with_domain", ("general_text", "customer_support")),
    ("with_instruction", ("general_text", "customer_support", "instruction_reply")),
]

FOCUS_LINKS = [
    ("broad_language", "内容", ("确认", "整理", "摘要", "说明")),
    ("domain_support", "退款", ("咨询", "请求", "状态", "处理")),
    ("instruction_style", "逐步", ("引导", "说明", "整理")),
]

DOMAIN_START_TOKENS = {"退款", "配送", "账号", "换货"}


def load_rows(path):
    with path.open(newline="", encoding="utf-8") as f:
        return list(DictReader(f))


def build_bigram_counts(sentences):
    counts = defaultdict(Counter)
    for sentence in sentences:
        tokens = sentence.split()
        for left, right in zip(tokens, tokens[1:]):
            counts[left][right] += 1
    return counts


def rows_for_stages(rows, stages):
    return [row for row in rows if row["stage"] in stages]


def link_count(counts, left, rights):
    return sum(counts[left][right] for right in rights)


rows = load_rows(DATA_PATH)

print("[stage_rows]")
for stage in ("general_text", "customer_support", "instruction_reply"):
    print(f"{stage}: {sum(row['stage'] == stage for row in rows)}")

print("\n[focus_link_counts]")
for link_name, left, rights in FOCUS_LINKS:
    values = {}
    for bundle_name, stages in STAGE_BUNDLES:
        bundle_rows = rows_for_stages(rows, stages)
        counts = build_bigram_counts(row["sentence"] for row in bundle_rows)
        values[bundle_name] = link_count(counts, left, rights)
    print(
        f"{link_name}: "
        f"general_only={values['general_only']}, "
        f"with_domain={values['with_domain']}, "
        f"with_instruction={values['with_instruction']}"
    )

print("\n[new_links_after_domain]")
general_counts = build_bigram_counts(
    row["sentence"] for row in rows if row["stage"] == "general_text"
)
domain_counts = build_bigram_counts(
    row["sentence"] for row in rows if row["stage"] == "customer_support"
)
new_links = []
for left, right_counts in domain_counts.items():
    if left not in DOMAIN_START_TOKENS:
        continue
    for right, domain_count in right_counts.items():
        if general_counts[left][right] == 0:
            new_links.append((f"{left} -> {right}", domain_count))

for link_name, count in sorted(new_links, key=lambda item: (-item[1], item[0]))[:6]:
    print(f"{link_name}: {count}")

这个示例已用本地 .venv 的 Python 执行,并确认与正文输出一致。

执行结果示例可以这样阅读。

[stage_rows]
general_text: 40
customer_support: 24
instruction_reply: 12

[focus_link_counts]
broad_language: general_only=35, with_domain=46, with_instruction=48
domain_support: general_only=0, with_domain=8, with_instruction=8
instruction_style: general_only=0, with_domain=0, with_instruction=3

[new_links_after_domain]
退款 -> 处理: 2
退款 -> 咨询: 2
退款 -> 状态: 2
退款 -> 请求: 2
换货 -> 受理: 1
换货 -> 咨询: 1

在这个输出中,首先要看的是 broad_language。内容 -> 确认/整理/摘要/说明 这样的宽广连接,只看一般语料时已经大量出现。加入领域句子后,这个值还会变大,但它不是完全新出现的连接,而是在既有语言基础上叠加的变化。

相反,domain_support 在只有一般语料时是 0。退款 -> 咨询/请求/状态/处理 这样的连接,要加入客服句子之后才会出现。这接近任务调整所做的事:在已经建立的语言基础上,让特定业务词汇和流程更清晰。

最后,instruction_style 即使加入领域句子后仍然是 0,只有加入指令型回应句子之后才出现。这个值说明,超出预训练和微调之外,可能还需要单独的层来调整模型,使其符合用户请求格式。

用图来看,三种连接并不是以同一种方式增长的差异会更清楚。

按学习阶段统计的下一个词元连接次数

这个示例中要读出的核心如下。

  • 一般语料先建立宽广语言连接。
  • 加入客服句子后,退款、配送、账号、换货 等领域连接会新产生或变强。
  • 加入指令型回应句子后,才会另外产生 逐步 引导 这样符合请求格式的连接。
  • 也就是说,预训练宽广地建立基础模式,后续调整更接近在其上让业务词汇或回应格式更突出。

学习阶段分离中看到的分布移动

这个示例再次说明,不能用 模型学了很多 这一句话把预训练和后续调整混在一起。即使用同样的 next-word 结构,由一般语料建立的阶段显示的是 宽广语言连接,加入领域句子的阶段显示的是 特定业务表达强化。以后阅读微调、instruction tuning、alignment 时,也需要先区分 扩展基础能力的阶段 和 把反应方式按目的调整的阶段。

预训练是解释 LLM 时代的关键转变。以前也有语言模型和表达学习,但随着先从大规模文本中学习一般模式,再连接到多种任务的方式成为中心,模型的使用方式本身也发生了变化。

更重要的是要抓住:扩展基础能力的阶段 和 在其上叠加按任务调整的阶段 并不是同一层。阅读 LLM 时代时,也要先理解为先建立大的基础模型,再在其上叠加多种任务调整的结构,这样 fine-tuning、instruction tuning、alignment 才更容易在同一条脉络中读懂。

把这个示例重新压缩成判断标准时,应该先浮现下面三个问题。

场景 首先要回答的问题
为什么即使有少量摘要示例,句子连接本身也会摇晃? 任务调整之前,宽广语言基础是否充分?
为什么标签定义清楚,却经常漏掉表达不同的同类咨询? 读取表达关系的基础是否比任务规则更弱?
为什么基本说明能做,却经常违反请求格式? 是否应该先处理指令调整层,而不是基础学习?

检查清单

  • 能否把预训练解释为 宽广基础形成,并与微调区分开?
  • 能否说明为什么提示使用和学习阶段调整不应被看作同一层?
  • 是否准备好把规模说明读作 为什么要以那么大的规模建立那个基础 的问题?

来源与参考资料