linear / relu / sgd -> tokenization -> LLM workflow -> inference / deployment
SGD、Linear、ReLU
神经网络为什么能工作
神经网络本质上不是神秘黑盒,而是很多简单函数的组合。
最基础的一条链可以写成:
x -> Linear -> ReLU -> Linear -> loss -> backward -> SGD step
Linear 是什么
nn.Linear 做的是一个仿射变换。
它会把输入特征映射到新的特征空间。
例如:
- 输入是
in_features - 输出是
out_features
对应代码
需要记住的点
Linear层本身有参数- 这些参数通常包括
weight和bias - 训练时被更新的,就是这些参数
为什么只有线性层不够
如果一个模型里只有线性层,那么无论叠多少层,整体仍然只是一个线性变换。 这意味着模型表达能力有限,不能表示复杂函数。
所以,神经网络真正变强的关键,不只是“层数变多”,而是:
在线性层之间加入非线性。
ReLU 是什么
ReLU(x) = max(0, x)
也就是:
- 正数保留
- 负数变成 0
为什么需要 ReLU
ReLU 是非线性激活函数。 加入 ReLU 后,模型就不再只是简单线性变换的堆叠,而可以表达更复杂的函数关系。
对应代码
SGD 是什么
SGD(Stochastic Gradient Descent)做的事情是:
- 用当前 batch 计算 loss
- 根据 loss 反向传播得到梯度
- 按学习率更新参数
也就是:
为什么叫 stochastic
因为它通常不是每次用整个数据集精确计算梯度, 而是只用当前一个 batch 来近似当前梯度。
学习率为什么重要
学习率过大:
- 参数更新步子太大
- 容易在某个范围内震荡
- 甚至可能直接发散
学习率过小:
- loss 下降太慢
- 训练时间过长
- 可能很久都看不到明显改善
需要记住的点
- 梯度决定方向
- 学习率决定步长
Tokenization
tokenization 是什么
语言模型不能直接处理原始文本。 文本在进入模型之前,必须先被转换成模型能处理的离散单位和数字表示。
这个过程就是 tokenization。
最小视角下,tokenizer 做两件事:
- 把文本切成 token
- 把 token 转成 token id
token 是什么
token 是模型输入的基本单位。 在现代 LLM 中,token 往往既不是完整单词,也不是单个字符,而更常是 subword(子词)。
为什么不用纯单词切分
如果按完整单词切分:
- 词表会非常大
- 遇到新词、罕见词时处理很差
- 语言泛化能力不够好
为什么不用纯字符切分
如果按单个字符切分:
- 序列会变得很长
- 训练和推理成本会变高
- 对模型来说不一定是更好的表示方式
所以现代 tokenizer 通常在两者之间取折中,使用 subword。
subword tokenization
需要认识 3 个名字:
- BPE
- WordPiece
- Unigram
它们的共同目标都是:
在控制词表大小的同时,尽可能保留有意义的文本片段。
对 CJK 的处理
对于中文、日文、韩文,tokenizer 通常不会简单按空格切分, 而更可能按字符边界、子词规则,或者直接在原始文本上学习切分方式。
所以:
- 中文里常常接近按字或短片段切
- 日文和韩文也常结合 subword 方法处理
- 同一句 CJK 文本,在不同 tokenizer 下可能切分结果不同
special tokens 是什么
除了普通文本 token,tokenizer 通常还会管理一些特殊 token,例如:
- BOS
- EOS
- CLS
- SEP
- PAD
这说明模型输入不只是正文 token,还包含一些控制信息。
token 数为什么重要
token 数会直接影响:
- 输入序列长度
- 上下文窗口占用
- 推理成本
- 延迟和吞吐
- 系统性能
所以 tokenizer 不是一个无关紧要的文本前处理步骤, 它实际上是模型系统的一部分。
最小例子
LLM 的最小全景图
LLM 是什么
LLM(Large Language Model)是在大量文本数据上训练出来的语言模型。 它可以理解和生成文本,并且在不做任务专门训练的情况下,处理很多语言任务。
这里要注意:
- 不是所有任务都能直接做好
- 也不是永远不需要进一步适配
- 但相比传统 NLP,LLM 的泛化能力更强
training / fine-tuning / inference
training / pretraining:
- 从大量数据中训练模型
- 学习通用语言模式
- 得到一个基础模型
fine-tuning:
- 在已有预训练模型基础上继续训练
- 用更具体的数据做适配
- 让模型更适合某个任务、领域或风格
inference:
- 使用现有模型做预测或生成
- 不再更新模型参数
- 只做前向计算
deployment / serving:
- 把 inference 包装成一个可调用的服务
- 对外提供接口或应用
- 让模型真正可用
为什么“做 LLM”不等于“只看模型结构”
做 LLM 不只是看 transformer 结构或者参数量。
一个真实的 LLM 工作流还包括:
- data
- tokenizer
- model
- training / fine-tuning
- inference
- serving
- 工具链与模型管理
也就是说:
模型只是系统的一部分,不是全部。
最小流程图
Deployment Awareness
为什么训练脚本不等于部署
训练脚本的职责是:
- 加载数据
- 计算 loss
- 反向传播
- 更新参数
而部署需要的是:
- 一个稳定的推理入口
- 接受输入
- 返回预测结果
- 对外提供服务
所以训练代码和部署代码不是一回事。
inference script 最小需要什么
一个最小推理脚本通常需要:
- 加载模型结构
- 加载模型权重
- 切到
model.eval() - 接受输入
- 做前向计算
- 返回预测结果
如果是文本模型,还通常需要:
- 加载 tokenizer
为什么 model.eval() 在部署里很重要
推理阶段一般需要稳定、可复现的输出。
如果不切到 eval():
- Dropout 可能还在随机丢弃神经元
- BatchNorm 可能还在使用当前 batch 的统计量
这会导致推理结果不稳定。
所以部署时通常会写:
最小 Web demo 的核心抽象
最小 Web demo 的核心不是“服务器”,而是:
input -> predict_function -> output
也就是说,本质上你只需要先写一个预测函数,然后再把它包装成界面或接口。
一个最小 Gradio 例子
这里最关键的是:
fn:预测函数inputs:输入类型outputs:输出类型
最重要的结论
- 线性层负责做特征映射。
- 只有线性层不够,因为整体仍然是线性函数。
- ReLU 这样的非线性激活函数让模型具备更强表达能力。
- SGD 用 batch 的梯度近似来更新参数。
- tokenizer 负责把文本切成 token,并转换成 token id。
- 现代模型常使用 subword,而不是纯单词或纯字符。
- token 数会影响上下文长度、推理成本和系统性能。
- LLM 是在大规模文本上训练出来的语言模型。
- training、fine-tuning、inference、deployment 是不同阶段。
- 做 LLM 工程不是只看模型结构,而是整条工作流。
- 训练代码负责更新参数,推理代码负责接受输入并输出预测。
- 最小 Web demo 的核心抽象是:
input -> prediction function -> output。
到这里,应该已经能做到
- 理解
Linear层在做什么 - 理解为什么神经网络需要非线性激活函数
- 理解 ReLU 的作用
- 理解 SGD 为什么能让 loss 下降
- 理解学习率对训练速度和稳定性的影响
- 理解 token、word、character 的区别
- 理解 tokenizer 的最小职责
- 知道常见 subword 算法名字
- 知道 token 数为什么影响 LLM 系统表现
- 理解 LLM 的基本定义和工作流
- 区分 training / fine-tuning / inference / deployment
- 理解训练脚本和推理脚本的区别
- 理解为什么部署前必须
model.eval() - 理解最小 Web demo 的抽象方式