在写第一行代码之前,先把训练这个词彻底说明白

先把"训练"这个词说清楚

你每天用大模型,它好像无所不知。但只要一问"它到底是怎么训练出来的",大多数人脑子里就是一团浆糊——数据、参数、GPU、损失函数,每个词都听过,连不成一条线。

这个系列就是来把这条线接上的。而且不打算讲个大概,是真的从零开始,用 Python 写一个能跑的迷你 GPT,在你自己的电脑上把它训练出来,看着它从输出乱码到写出通顺的句子。每一步代码都讲清楚,不跳过。

但在写第一行代码之前,得先把一个最关键的概念摆正,否则后面全是空中楼阁。这个概念是:模型到底在学什么。

一个语言模型,本质上就是在猜下一个字

把所有包装拆掉,一个语言模型做的事情只有一件:给它一段文字,它预测下一个字最可能是什么。

就这么简单。你输入"今天天气真",它会算出下一个字是"好"的概率很高,是"狗"的概率很低。仅此而已。

那它怎么写出一整段话?答案是反复做这件事。预测出"好",就把"好"接到后面,变成"今天天气真好",再拿这句去预测下一个字,可能是逗号;再预测,可能是"我"……一个字一个字地接龙,就成了一整段文字。你在对话界面里看到字一个一个蹦出来,看到的就是这个接龙过程本身。

这里要补一个小术语。严格来说,模型预测的不是"字",而是 token——一个 token 可能是一个汉字、半个英文单词,或一个标点。为什么不直接用字、要绕一道 token,第二篇会专门讲。在这一篇里,你先按"字"来理解,不影响任何道理。

所以"模型很聪明"这件事,可以翻译成一句朴素得多的话:它把"下一个字是什么"猜得非常准。

训练,就是把猜的本领练出来

现在问题变成了:它凭什么猜得准?

模型内部是一大堆数字。几百万个、几十亿个,专业一点叫"参数",也叫"权重"。你可以把模型想象成一台装了几百万个旋钮的机器:输入文字,这些旋钮按某种固定方式把它加工一遍,输出一个对"下一个字"的猜测。

旋钮的位置不同,猜测就不同。一台旋钮位置完全随机的机器,猜出来的只能是乱码。

训练,就是调旋钮的过程。说得具体些,是这样一个循环:

拿一段真实的文字,比如"今天天气真好"。把"今天天气真"喂给模型,让它猜下一个字。它猜了个"狗"。但正确答案是"好"。于是我们手里有了一条明确的信息——猜错了,而且能算出错在哪个方向。根据这个方向,把那几百万个旋钮各自微微拧一点点,让模型下次遇到类似情况时,"好"的概率高一些、"狗"的概率低一些。

然后换下一段文字,再来一遍。再换,再来。把海量的文字这样过上千遍万遍,旋钮就被一点一点拧到了一组很好的位置上——好到模型对几乎任何开头都能猜得相当准。

这个不断"拧旋钮"的过程,就是训练。训练完成后,那组旋钮的位置固定下来,存成一个文件,这个文件就是大家口里说的"模型权重"。所谓某个模型有"七十亿参数",说的就是这台机器有七十亿个旋钮。

打个你熟悉的比方:这和学骑自行车是一回事。没有人能靠讲道理学会骑车,是身体在一次次摇晃、一次次偏倒里,根据"这次往左倒了"这个信息,把平衡的"旋钮"一点点调对的。模型训练,就是把这个"犯错、感知错的方向、微调"的过程,搬到了几百万个数字上,并且让计算机自动、高速地做。

这个系列要带你做的事

道理就这么多。但只听道理,"猜下一个字""拧旋钮"还是抽象的。真正让它变清楚的办法,是自己动手做一个。

所以这个系列不是科普,是实操。我们会用 PyTorch(Python 里最主流的深度学习库)从零搭一个迷你版的 GPT。它和真正的 GPT 是同一套原理、同一个结构,只是小很多——小到能在一台普通笔记本上、几分钟到十几分钟训练出结果。

整个系列的路线是这样的:

  • 这一篇,把"模型在学什么"说清楚,并准备好环境和数据。
  • 第二篇,把文字变成数字。计算机不认识汉字,只认识数字,所以第一道工序是给每个字编号。
  • 第三篇,搭一个最简单的模型,先让训练循环跑起来。这个模型很笨,但"喂数据、算错误、拧旋钮"的完整循环会第一次真正转起来。
  • 第四篇,专门讲反向传播,也就是"按错误的方向拧旋钮"这件事到底怎么自动完成。这是整个训练的心脏。
  • 第五篇,注意力机制。让模型不只看前一个字,而是学会回头看整段上下文。这是 GPT 之所以强的关键。
  • 第六篇,把注意力、残差连接、层归一化这些零件,拼成一个真正的 GPT 结构。
  • 第七篇,完整训练这个迷你 GPT,调参数,看着它生成的文本一轮比一轮像样。
  • 第八篇,从迷你 GPT 回到现实:真正的 ChatGPT 在我们做的这些之外,还经历了什么。

这个系列假设你会 Python,但不要求你懂神经网络,需要的概念我们都会现讲。如果你想在某个点上往深里挖,博客里的 ml-basics 系列有更系统的数学推导,可以配合着看。

动手第一步:准备环境

讲了这么多,开始动手。先装好工具。Python 建议 3.10 以上版本,然后装 PyTorch:

# 建议先建一个独立的虚拟环境,避免污染系统的 Python
python -m venv venv
source venv/bin/activate          # Windows 用 venv\Scripts\activate

# 安装 PyTorch,CPU 版即可
pip install torch

没有显卡完全没关系。我们的模型很小,CPU 训练几分钟就够。如果你有 NVIDIA 显卡,后面第七篇会讲怎么把它用上,训练能更快,但不是必需的。

装完验证一下:

import torch

print(f"PyTorch 版本:{torch.__version__}")
print(f"有没有可用的 GPU:{torch.cuda.is_available()}")

能打印出版本号,环境就绪了。torch.cuda.is_available() 是 False 也没关系,按上面说的,CPU 足够。

动手第二步:准备一份训练数据

模型要从文字里学规律,所以得给它一份文字。用什么都行——一部小说、一本书、一整本诗集。模型会学到这份文字的"风格",最后生成出来的东西,就是那个味道。

你需要做的是:找一份纯文本,存成 input.txt,编码用 UTF-8。建议用中文语料,比如一部公版小说(《三国演义》《西游记》全文都可以),或者一份唐诗合集。文件大小几百 KB 到几 MB 就行,太小模型学不到东西,太大训练会慢。

准备好之后,把它读进来,先看一眼:

# 读取训练数据
with open("input.txt", "r", encoding="utf-8") as f:
    text = f.read()

print(f"全文一共 {len(text)} 个字符")
print(f"开头 200 个字符:\n{text[:200]}")

# 这份文字里一共出现了多少种不同的字符?
chars = sorted(set(text))
print(f"不同字符数:{len(chars)}")
print(f"字符表前 50 个:{chars[:50]}")

解释一下这几行在做什么。len(text) 是语料的总规模,也就是模型能用来学习的原料有多少。set(text) 把文字里所有字符去重,得到一张"字符表"——这份语料里出现过的每一个不同字符。这张表很重要:模型将来能输出的,只可能是这张表里的字符,表里没有的字它永远写不出来。

这张表的大小,下一篇会变成一个关键数字,叫词表大小(vocab size)。中文语料的字符表通常有几千项,因为汉字本身就多。

跑通这几行,你就已经站在训练一个模型的起点上了。我们手里现在有了原材料:一份文字,和它包含的字符表。

本篇要点

  • 语言模型本质上只做一件事——根据前文预测下一个字(token);生成长文本就是反复预测、接龙。
  • 模型内部是大量可调的数字,叫参数或权重;参数不同,预测就不同,随机的参数只能输出乱码。
  • 训练就是一个循环:喂真实文字、看模型猜错在哪、按错误的方向微调参数,让预测越来越准。
  • 训练完成后,那组参数固定下来存成文件,就是"模型权重"。
  • 这个系列会用 PyTorch 从零训练一个能在笔记本上跑的迷你 GPT,原理和真正的 GPT 一致。
  • 动手第一步是装好 PyTorch、准备一份纯文本语料,并看清它的规模和字符表。

下一篇

我们手里现在是一份文字,但模型只会算数字、不认识汉字。下一篇要解决这道工序:把文字变成数字——给每个字符编号,做成模型能读的形式,并且认识第一个关键概念,token。

参考资料

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:模型到底在学什么

本文链接:https://www.sshipanoo.com/blog/ai/mini-gpt/01-模型到底在学什么/

本文最后一次更新为 天前,文章中的某些内容可能已过时!