现在每个人都在用大模型。但我一直没搞明白一件事:
它到底在做什么?
说法都挺含糊的。"它在预测下一个词"——听起来简单到不像能聊天。我试过自己想象:一个只会猜下一个词的程序,能聊出人来吗?
这个疑问在脑子里挂了很久。它不是我算出来的疑问,是用出来的:每次我用它写东西、问它一个问题,我都在猜它背后到底发生了什么。
上周我想了个笨办法:
我不研究大模型。我自己写一个。
用它能理解的全部东西——我自己 22 年写过的博客——去训练,然后看它能做到什么程度。
一、论文里那句被我记错的话
先说清楚"猜下一个词"这个说法是从哪来的。
我一直以为 OpenAI 2018 年那篇 GPT-1 的博客里写着 "The objective is to predict the next word.",后来拿它写东西,还到处跟人引用。
这次我让一个人去把原文逐字查一遍。结论是:这句话不在 GPT-1 的博客里,也不在论文里。博客和论文全文检索 objective、next word、predict,没有这一句。
真正写下这个意思的,是 2003 年 Bengio 那篇《A Neural Probabilistic Language Model》(JMLR 3:1137–1155):
A statistical model of language can be represented by the conditional probability of the next word given all the previous ones
(一种语言的统计模型,可以表示为"在前面所有词都已知的情况下,下一个词的条件概率"。)
论文第 3 页还有一句更具体的:
The probability function is expressed as a product of conditional probabilities of the next word given the previous ones, (e.g. using a multi-layer neural network to predict the next word given the previous ones, in the experiments).
(这个概率函数被写成"下一个词在前面词已知的条件下的条件概率"之积——在他们的实验里,是用多层神经网络来预测下一个词的。)
这就是全部了。语言模型 = 猜下一个词。我记了十几年、还到处引用的一句话,其实来自一篇 2003 年的论文,而 GPT-1 自己没这么说过。
(顺便记一下,免得我也跟着错:GPT-1 那篇博客的标题其实是《Improving Language Understanding with Unsupervised Learning》;《Improving Language Understanding by Generative Pre-Training》是论文的标题。我把这两个搞混过。)
二、我照着写了一遍
那就动手。
我写了一个纯 Python 的小模型(实验/ngram_self.py,不用任何第三方库),逻辑简单到可以自己讲完:
- 1.语料是我自己 22 年的博客,9186 篇,301 万字符。
- 2.切词:中文按字切,英文按单词切,标点单独算一个。
- 3.模型就是数数:数"我"后面跟过什么、"昨天"后面跟过什么、"的"后面跟过什么。1-gram 看前一个词,2-gram 看前两个,3-gram 看前三个;高阶的数据不够就退回去看低阶。
- 4.训练就是把数过的次数存下来。
- 5.评测:拿它没见过的文章(按时间切分,后 15% 留出来)逐字预测,看猜对的比例、前五个候选里有没有真的那个字,以及困惑度(它对真实下一个字的"意外程度",越低说明它越觉得"这话我见过")。
跑了一遍,结果是这样:

| 喂给它多少篇我的文章 | 下一个字猜对的比例 | 前五个候选里有的比例 | 困惑度 |
|---|---|---|---|
| 50 | 7.19% | 12.62% | 528.28 |
| 200 | 9.08% | 15.77% | 473.65 |
| 1000 | 11.44% | 19.88% | 505.36 |
| 2000 | 15.35% | 24.91% | 286.78 |
| 6000 | 16.42% | 27.65% | 247.33 |
喂得越多,它越准。这条特别朴素,但它就是后来所有故事的地基。
先交代语料本身有多脏。9186 篇里,5065 篇是"每日汇总"(Twitter Daily、Mastodon Daily 这类自动发出来的链接汇总),真正是我自己手写的长文只有 443 篇,而且几乎都集中在 2004 到 2009 年——2010 年之后,我的博客里几乎没有我自己的长文了。
这意味着两件事:一是"我"这个样本本身是残缺的,我训练的是"我博客",不完全是"我";二是下面所有的数字都带着这层偏差,我会在用到的地方再说一遍。
三、让它猜一个字看看
表格看着抽象,我把它调到"一个字一个字猜"的样子。
我拿它没读过的一篇旧文(2008 年 10 月《三聚氰胺续》)当例子,一句一句往下看:
| 我写了什么 | 它猜的下一个字 |
|---|---|
| 渐渐的,三聚氰胺的事情似乎落下了帷幕 | ,(66.7% 是"了",33.3% 是",") |
| 再也看不到铺天盖地的报 | 道(70.6%),纸(17.6%),告(11.8%) |
| 企业的无关痛痒的道歉。而 | 它猜的是且(37.5%),真值是"针" |
第二个字它猜对了,而且第二名"纸"、第三名"告"也挺合理——"报道""报纸"都是常见搭配。
第三个字它就错了:它接的是"而且",我写的是"而针对于最终受害者的追责"。
这就是这个模型的水平:局部很准,整体很糟。它知道"铺天盖地的报"后面大概率是"道",但它不知道我接下来要说什么。
四、上下文才是关键
那我换个问题:它靠什么变准?
我把模型的"记忆长度"改一改,再跑:
| 模型 | 猜对的比例 | 前五里有 | 困惑度 |
|---|---|---|---|
| 1-gram(不看上下文) | 3.84% | 9.54% | 1409.48 |
| 2-gram(看前一个词) | 17.34% | 30.82% | 245.77 |
| 3-gram(看前两个词) | 22.43% | 33.75% | 168.03 |
从 3.84% 到 22.43%,全是"看上下文"带来的。
一个完全不看上下文、只会说"我博客里最常见的字是"的模型,能猜对 3.84%;让它多看两个词,就跳到 22%。
这里有个反直觉的小细节:我后来只用我自己手写的长文(443 篇,排除每日汇总和推文归档)重做了一遍,2-gram 的"前五命中率"反而高过 3-gram(37.66% 对 35.65%)。因为手写长文太少,三元组太稀疏,回退机制反而更稳。数据不够的时候,"记得更多"不一定更好——这个结论我记下来了。
五、一个我没猜到的结果
这一期我最想说的,其实是这个。
我本来以为:越近的文章越好猜。因为最近几年我博客里大多是"每日汇总",格式固定、时间戳一堆,模型应该很容易蒙对。
我按年测了一遍。前 60% 的文章训练,后 40% 逐年评测:

| 年份 | 猜对的比例 | 困惑度 |
|---|---|---|
| 2018 | 31.54% | 45.66 |
| 2019 | 28.73% | 72.02 |
| 2021 | 29.44% | 48.03 |
| 2023 | 19.60% | 172.28 |
| 2025 | 12.74% | 402.04 |
| 2026 | 13.94% | 436.64 |
完全反了。越往后,它越猜不中。2018 年困惑度 46,2026 年是 437——差了近十倍。
我先猜了一个原因:因为越往后,我写的东西越不是我自己的话。2023 年之后我的博客大部分是"今日摘要""转推""日报",里面装的是别人的话;模型没读过,凭什么猜得中。
然后我去查了查这个猜测成不成立。我统计了每年里"搬运痕迹"的占比(RT@、via、链接、时间戳这类标记):
| 年份 | 搬运痕迹占 token 的比例 | 猜对的比例 |
|---|---|---|
| 2018 | 3.3% | 31.54% |
| 2021 | 0.9% | 29.44% |
| 2024 | 0.2% | 15.15% |
| 2026 | 1.7% | 13.94% |
这个解释也不成立。最近几年的搬运痕迹占比反而更低(2024 年只有 0.2%),猜对率却最低。
真正的原因是笨得多的那一条:这个模型的训练数据截止到 2018 年 11 月 9 日。我按时间排序切的前 60% 正好到那一天。它拿的是"截至 2018 年 11 月的我的话",去猜 2019、2020……2026 年的话——离它学过的词越远,它就猜得越差。
所以真正的原因是笨得多的那一条:越往后,我的词变了、话题变了、写法变了。
一个模型要一直像我,就得一直吃我写的新东西。"像我"是有保质期的。
(顺便一说,ChatGPT 第一次出现在我的信息流里,是 2023 年 1 月 24 日——我转的一条链接,标题叫《Ansible Wisdom and ChatGPT: Putting it to the test》。而 OpenAI 公布 ChatGPT 是 2022 年 11 月 30 日。所以在我的博客上,它是先以一个"别人的文章标题"的形式出现的,我转了它,但我当时不知道它是什么。这跟我第二期查到的"3 月是拐点"是一回事的两面:那时候开始,我的信息流里 AI 的东西变多,而我自己写的东西变少。)
六、它到底学到了什么
我把它学到的"词汇表"打印出来看:
最高频的字:,的 是 。了 不 一 我 个 在 这 有 人 就 也 国 中 为 上 以
最高频的三字开头:、但是、是一个、不知道、,因为、的时候、自己的、这样的、,也许、,所以、,甚至
我不知道别人写博客是不是也这样。但"不知道"、",也许"、",但是"这三个,是我自己写东西时最常冒出来的——它们连成一个语气。
这就是它从我这儿学走的全部东西:不是我写了什么主题,是我怎么把话连起来。
七、盲测:它能混进我的文章吗
光看数字不够。我想试试它能不能冒充我。
我从自己手写长文的留出部分取了 6 组真实开头,每组有三份续写:
- •甲/乙/丙(打乱后我不知道哪份是哪份):一份是我的原文,一份是 n-gram 模型的,一份是当代大模型续写的(用的是 MiniMax 的模型,不是 ChatGPT)。
我先写下自己的判断,再看答案。猜对 5 组,错 1 组。
错的那一组很有意思。开头是:
之前入手了魅族的M8,因为官方经
我原文是:
常有意泄漏一些固件更新,所以最近去官方论坛也比较多。经过几天的观察,
大模型写的是:
销商那边一直缺货,后来托朋友从香港带回来一台,折腾一番后总算用上了,这机器用起来倒也还算顺手。
大模型这段比我的原文顺。句子完整,细节具体,读起来就像人写的。可它接不上"因为官方经"——"官方经销"这个断口,它接成了"销商那边一直缺货",把意思拧了。
n-gram 那份则是另一种毛病:
济适用。在我也没有一个平台上跳舞。如果你能否认的"。什么.工作服她根
它抓到了我的用词("适用"、"平台"、"能否认"),但整句是碎的。
我判断的依据其实只有一条:接不接得上。能接上前文的那个才是真的。
顺便说一个客观数字。我算了每份续写和我的原文之间的字符重合率:n-gram 是 0 到 0.146,大模型是 0 到 0.121。也就是说,两台机器都没有"抄"我的句子——它们只是写出了听起来很像的东西。
所以这期盲测的结论其实有点扫兴:我赢的那 5 组,赢在"接得上",不是赢在"像"。真正决定像不像的,是句子之间能不能连起来——这是上下文的事,也是后面所有故事都要讲的事。
八、那它跟大模型差在哪
我做的这个模型,和 ChatGPT 那种东西,训练目标其实是一样的:猜下一个词。
机制我在第三期拆过注意力,这里不重复,只说差在哪。
一、它记的是"词",不是"字"。我按字切,中文切得比 BPE 粗得多(GPT-1 那篇用的是 40,000 次 BPE 合并)。而且我的词表只有 15135 个,中文里大量同音、同形的字在我眼里是一个东西。
二、它只看得到最近几个词。Transformer 那篇论文的贡献是:
We propose a new simple network architecture, the Transformer, based solely on attention mechanisms, dispensing with recurrence and convolutions entirely.
(我们提出一种新的简单网络架构,Transformer,完全基于注意力机制,把循环和卷积全都丢掉了。)
我的模型只用"前两个词"当上下文;Transformer 能让每一个词去看整句话里的每一个词。这就是它"接得上"而我接不上的原因。
三、它的语料不是我的博客,是整个互联网,而且多到不能算。Kaplan 他们 2020 年那篇《Scaling Laws for Neural Language Models》说的就是这件事:
The loss scales as a power-law with model size, dataset size, and the amount of compute used for training, with some trends spanning more than seven orders of magnitude.
(损失随着模型大小、数据集大小和训练所用算力呈幂律下降,这些趋势跨越了七个数量级以上。)
我这次做的其实就是这条规律的一个极小切片:我的困惑度从 528 降到 168,靠的就是"语料更多"。只不过我这条曲线的右端是 9186 篇博客,他们那条曲线的右端是几百亿 token。
四、它是两阶段的。GPT-1 论文里那句:
Our training procedure consists of two stages. The first stage is learning a high-capacity language model on a large corpus of text. This is followed by a fine-tuning stage, where we adapt the model to a discriminative task with labeled data.
(我们的训练过程分两个阶段。第一阶段是在大语料上学习一个高容量的语言模型;第二阶段是微调,用带标注的数据把模型调整到某个判别任务上。)
我那个小模型只有第一阶段,而且第一阶段的"高容量"就是三个计数器。
九、所以它凭什么会聊天
到这里,我这一期想问的问题算有了一个临时答案:
"猜下一个词"不是关键,"用多少词来猜"和"怎么把词连起来"才是关键。
我那个只会数词的模型,喂到 9186 篇的时候,已经能写出"、但是"、",也许"、"不知道"这种连词了——它已经抓到了我的语气。大模型做的事情,在这一层其实没有本质不同,只是把"最近两个词"换成了"整句话",把"字"换成了"词",把"9186 篇"换成了"整个互联网"。
GPT-3 那篇论文里有一句我一直记得:
GPT-3 can generate samples of news articles which human evaluators have difficulty distinguishing from articles written by humans.
(GPT-3 能生成新闻文章样本,人类评测者很难把它们和人类写的文章区分开。)
这句话听着让人发凉。但我这期做的实验,给了它一个小小的注脚:骗过人的不是"内容",是"接得上"。我在第 4 组被骗的那次,就是因为它接得太顺。
可我到现在也没想明白的是另一件事。
如果目标从头到尾都只是"猜下一个词",那为什么猜着猜着,就能猜出"企业的无关痛痒的道歉"这种带着态度的句子?
一个只会数"道歉"前面出现过哪些词的东西,凭什么知道什么叫"无关痛痒"?
我知道答案大概在"表示"里,也知道答案大概在"规模"里。可这两个词太大了,大到我现在说出来,其实等于什么都没说。
这也是我想写下一期的原因。
上面那些东西——Transformer、几十亿 token、幂律、成千上万台机器——不是天上掉下来的。它们是某家公司、某些人,在某些年份,用某些钱,一点点凑出来的。
下一期我想去看那个公司:OpenAI。它 2015 年成立的时候,说的是一个很小的目标;今天我们用的这些东西,是从那个小目标里长出来的,还是长成了别的东西?
(这一期的东西都在 实验/ngram_self.py、实验/llm_continue.py、实验/blind_test.py 里,数据在 记录/ngram.json、记录/ngram_continuations.json、记录/blind_09.json,随机种子固定,重跑数字一样。我的模型只有三个计数器,比任何一个大模型都简单几百万倍——它证明不了大模型有多强,只能证明一件事:"猜下一个词"这件事,从零开始也是能出效果的,而它学到的全部东西,长在喂给它的语料上。)
没有评论:
发表评论