3263 字
16 分钟
如何自己训练一个小模型完整教程(小白也能看懂)

如何自己训练一个小模型完整教程(小白也能看懂)#

上一篇我们学了 AI Agent。你可能好奇:那些 AI 模型到底是怎么”训练”出来的?我能不能自己训练一个?

答案是:。而且训练一个”小模型”(比如识别手写数字、判断垃圾邮件)并没有想象中那么难——只要有一台普通电脑、装好 PyTorch,跟着这篇教程就能跑通。

这一篇用大白话讲清训练的本质,再手把手带你训练一个真实可运行的模型。


一、先搞清楚:训练一个模型到底是在干嘛?#

用”教小孩认猫”来理解#

训练模型,就像教一个小孩认识猫:

  1. 你给小孩看很多张图,指着说”这是猫""这不是猫”
  2. 小孩一开始瞎猜,猜错了你纠正它
  3. 看多了、错多了,小孩慢慢学会”什么样的特征是猫”
  4. 最后,给一张没见过的图,它也能判断是不是猫

训练 AI 模型完全一样:

  1. 喂给它大量”样本”(数据 + 正确答案)
  2. 它先瞎猜,猜错了就调整自己
  3. 反复调整,直到猜对的越来越多
  4. 训练完,拿它去处理没见过的新数据

一句话:训练 = 让模型从大量”有答案的例子”里,自己学会规律。

三个关键角色#

角色比喻说明
模型小孩的”大脑”一堆待调整的数字(参数)
数据教材和练习题带正确答案的例子
训练反复练习+纠错不断调整模型参数的过程

二、先搞懂几个核心概念(用买菜算账理解)#

别被专业名词吓到,这几个概念用生活例子一讲就懂。

1. 数据集:教材(训练集、验证集、测试集)#

训练前要把数据分三份:

数据集用途比喻
训练集给模型学习课堂练习
验证集训练时检查效果、调参单元测验
测试集训练完最终评估(模型没见过)期末考试

关键: 测试集必须是模型从没看过的,否则”考试前把答案背了”,测出来分数虚高,没有意义。

2. 损失函数(Loss):错得有多离谱#

损失函数衡量”模型猜得有多错”。损失值越小,模型越准。

  • 全猜对 → 损失 = 0
  • 猜得越离谱 → 损失越大

训练的目标就是不断降低损失值

3. 优化器 + 梯度下降:怎么改进#

有了”错多少”(损失),还得知道”往哪改、改多少”。这就是梯度下降(Gradient Descent)

用”下山”比喻: 你站在山上(损失很大的地方),要下山到谷底(损失最小)。你看脚下的坡度(梯度),朝着”最陡的下坡方向”走一小步,反复走,就能到谷底。

  • 学习率:每步走多大。太大容易”走过头”跳来跳去,太小走得慢。
  • 优化器:负责计算”往哪走、走多少”。最常用的是 Adam

4. epoch 和 batch#

训练时数据不是一次性全喂进去,而是分小块:

  • batch(批次):一次喂多少条数据
  • epoch(回合):把整个数据集完整过一遍,算一个 epoch
训练 5 个 epoch = 把全部数据来回学 5 遍

5. 过拟合(Overfitting):背答案而不是学知识#

这是新手最容易遇到的问题:模型把训练数据背下来了,但对新数据表现差。

判断方法: 训练损失一直降,但验证/测试损失反而升 → 过拟合了。

解决办法: 数据更多、模型更简单、加正则化、早停(验证集不再变好就停)。


三、训练一个模型的完整流程(总览)#

不管什么模型,训练流程都是这五步:

1. 准备数据 → 收集、清洗、分成训练/验证/测试集
2. 搭建模型 → 定义网络结构(几层、每层多少神经元)
3. 选择损失和优化器 → 定"怎么算错"和"怎么改"
4. 训练循环 → 反复喂数据、算损失、反向传播、更新参数
5. 评估和保存 → 在测试集上打分,保存模型文件

下面就用 PyTorch 把这个流程完整走一遍。


四、准备环境#

安装 Python 和 PyTorch#

先确认有 Python(3.8+):

Terminal window
python --version

安装 PyTorch(CPU 版就够跑本文例子,GPU 更快但非必需):

Terminal window
pip install torch torchvision

验证安装:

Terminal window
python -c "import torch; print(torch.__version__)"

能看到版本号就装好了。


五、准备数据:MNIST 手写数字#

我们训练一个识别手写数字的模型:输入一张 28×28 的手写数字图,输出它是 0-9 里的哪一个。

MNIST 是深度学习界的”Hello World”——一个经典的公开数据集,有 6 万张训练图和 1 万张测试图。PyTorch 可以直接下载,很方便。

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# 1. 数据预处理:转成张量 + 归一化(让数值范围在 0~1)
transform = transforms.Compose([
transforms.ToTensor(), # 转成张量
transforms.Normalize((0.1307,), (0.3081,)) # 标准化
])
# 下载并加载训练集和测试集
train_data = datasets.MNIST(
root="./data", train=True, download=True, transform=transform)
test_data = datasets.MNIST(
root="./data", train=False, download=True, transform=transform)
# 分批加载
train_loader = DataLoader(train_data, batch_size=64, shuffle=True)
test_loader = DataLoader(test_data, batch_size=64, shuffle=False)
print(f"训练集:{len(train_data)} 张,测试集:{len(test_data)} 张")

你可能注意到: batch_size=64 就是”一次喂 64 张”;shuffle=True 是打乱顺序(防止模型按顺序背)。


六、搭建模型:神经网络#

我们搭一个简单的神经网络,把 28×28 的图压平成 784 个数字,经过两层全连接层,输出 10 个数字(对应 0-9)。

class SimpleNN(nn.Module):
def __init__(self):
super().__init__()
# 第一层:784 个输入 → 128 个神经元
self.fc1 = nn.Linear(784, 128)
# 激活函数(让模型能学非线性规律)
self.relu = nn.ReLU()
# 第二层:128 → 10(10 个数字类别)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
# 把 28x28 压平成 784 的一维
x = x.view(x.size(0), -1)
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x

几个名词先记住(不用深究):

  • nn.Linear:全连接层,“把上一层的数字加权求和”
  • ReLU:激活函数,引入”非线性”
  • 层数越多:模型越”深”、能力越强(但也越容易过拟合)

七、选择损失函数和优化器#

model = SimpleNN()
# 损失函数:交叉熵(分类任务最常用)
criterion = nn.CrossEntropyLoss()
# 优化器:Adam,学习率 0.001(走小步)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

就这两行: 定了”怎么算错”(CrossEntropyLoss)和”怎么改进”(Adam)。


八、训练循环:核心中的核心#

这是训练最重要的一段代码,理解它就读懂了训练的本质

def train_one_epoch(model, loader, criterion, optimizer):
model.train() # 切换到训练模式
total_loss = 0
correct = 0
total = 0
for images, labels in loader:
# 1. 清空上一次的梯度
optimizer.zero_grad()
# 2. 前向传播:把图片喂给模型,得到预测
outputs = model(images)
# 3. 计算损失:预测和正确答案差多少
loss = criterion(outputs, labels)
# 4. 反向传播:算出每个参数该往哪改
loss.backward()
# 5. 优化器更新:真正调整参数
optimizer.step()
# 统计
total_loss += loss.item()
_, predicted = torch.max(outputs, 1)
correct += (predicted == labels).sum().item()
total += labels.size(0)
accuracy = 100 * correct / total
print(f" 损失:{total_loss / len(loader):.4f},准确率:{accuracy:.2f}%")

记住这 5 步(每个训练循环都一样):

zero_grad() → 清空梯度
forward() → 前向传播(模型预测)
loss() → 算损失
backward() → 反向传播(算梯度)
step() → 更新参数

这是所有深度学习训练的”标准五步”,一定要理解。


九、评估函数:看看学得怎么样#

def evaluate(model, loader):
model.eval() # 切换到评估模式(关闭 Dropout 等)
correct = 0
total = 0
with torch.no_grad(): # 评估时不计算梯度,省内存
for images, labels in loader:
outputs = model(images)
_, predicted = torch.max(outputs, 1)
correct += (predicted == labels).sum().item()
total += labels.size(0)
accuracy = 100 * correct / total
return accuracy

torch.no_grad() 表示”这轮不训练、不算梯度”,评估时用。


十、正式训练:跑起来!#

把前面拼起来,训练几个 epoch,并记录准确率:

epochs = 5
for epoch in range(epochs):
print(f"Epoch {epoch + 1}/{epochs}")
train_one_epoch(model, train_loader, criterion, optimizer)
# 每轮训练完,在测试集上评估
test_acc = evaluate(model, test_loader)
print(f" → 测试集准确率:{test_acc:.2f}%\n")

运行输出大致是这样:

Epoch 1/5
损失:0.3542,准确率:89.12%
→ 测试集准确率:95.30%
Epoch 2/5
损失:0.1123,准确率:97.05%
→ 测试集准确率:97.20%
Epoch 3/5
损失:0.0701,准确率:98.10%
→ 测试集准确率:97.60%
Epoch 4/5
损失:0.0489,准确率:98.72%
→ 测试集准确率:97.90%
Epoch 5/5
损失:0.0360,准确率:99.05%
→ 测试集准确率:98.10%

看这个输出,你会非常有成就感: 从第一轮 89% 到第五轮 99%,损失一路下降、准确率一路上升——你的模型真的在”变聪明”! 而且测试集准确率 98% 说明它学的是”规律”而不是”背答案”。


十一、保存和加载模型#

训练完,把模型存下来,以后直接用,不用重新训练:

# 保存
torch.save(model.state_dict(), "mnist_model.pth")
print("模型已保存")
# 加载
loaded_model = SimpleNN()
loaded_model.load_state_dict(torch.load("mnist_model.pth"))
loaded_model.eval()
print("模型已加载")

实战:用模型预测一张新图

def predict_image(model, image_tensor):
model.eval()
with torch.no_grad():
output = model(image_tensor) # 前向传播
_, predicted = torch.max(output, 1) # 取概率最大的类别
return predicted.item()
# 拿测试集第一张图试试
first_image, first_label = test_data[0]
print(f"模型预测:{predict_image(model, first_image.unsqueeze(0))}")
print(f"真实答案:{first_label}")

first_image.unsqueeze(0) 是给图片加一个”批次维度”(因为模型一次处理一批)。预测和真实答案一致就说明模型真的会识别了。


十二、如果我想训练”大模型”怎么办?#

你可能会想:这只能识别数字,那 ChatGPT 那种大模型怎么训练的?

两种路线要分清:

1. 从零训练(train from scratch)#

  • 需要海量数据(几 TB)和大量 GPU(成千上万块,花费几百万美元)
  • 个人几乎不可能从零训练一个大模型

2. 微调(Fine-tuning):站在巨人肩膀上#

  • 在已有的预训练大模型基础上,用你自己的小数据再”教”它一下
  • 成本低很多,普通电脑甚至云 GPU 就能做
  • 这是普通人训练”自己的模型”的正确方式

微调的常用方法:LoRA#

微调整个大模型参数太多(几十亿个),普通人跑不动。LoRA(Low-Rank Adaptation) 是现在最火的技巧:不修改原模型,只额外加一小部分可训练参数,用少量数据就能微调,省显存、速度快。

  • 全量微调:要改全部 70 亿个参数
  • LoRA:只训练约 1% 的新增参数,效果接近

想微调大模型: 用现成框架(Lora、HuggingFace PEFT、Unsloth、LLaMA Factory),准备几百到几千条你自己的数据(比如”问答对""客服对话”),跑个微调脚本就行。本文教的基础(损失、优化器、训练循环)完全通用,只是数据量和模型规模更大。


十三、新手常见问题和建议#

1. 训练不起来 / 准确率不涨#

  • 检查数据有没有正确预处理
  • 学习率太大或太小(试试 0.01 / 0.001 / 0.0001)
  • 模型太简单学不动,或数据太少

2. 过拟合(训练准、测试差)#

  • 加更多数据
  • 简化模型
  • 加 Dropout / 正则化
  • 早停

3. 显存不够#

  • 减小 batch_size
  • 减小图片尺寸
  • 用 CPU(慢但能跑)

4. 新手建议路线#

  1. 先跑通本文的 MNIST(理解标准五步)
  2. 换一个数据集练手(如 CIFAR-10 彩色图片分类、垃圾邮件文本分类)
  3. 再尝试微调一个预训练模型
  4. 最后才考虑自己设计更复杂的网络

十四、总结#

这一篇我们从零学会了”如何训练一个小模型”:

  • 训练的本质:让模型从大量”有答案的例子”里自己学规律(教小孩认猫)
  • 核心概念:训练/验证/测试集、损失函数、梯度下降(下山比喻)、学习率、epoch/batch、过拟合
  • 完整流程:准备数据 → 搭模型 → 选损失和优化器 → 训练循环 → 评估保存
  • PyTorch 实战:训练了识别手写数字(MNIST)的模型,准确率从 89% 到 99%
  • 标准五步:zero_grad → forward → loss → backward → step
  • 保存加载:把模型存成文件,预测新图
  • 微调大模型:从零训练 vs 微调,LoRA 让普通人也能微调大模型

最后给你打气: 训练模型真的没有想象中那么难。只要你把本文的 MNIST 例子跑通,理解了那”标准五步”,你就已经掌握了深度学习训练的核心原理。剩下的,就是数据更多、模型更大、调参更精细而已——地基你已经打好了

下一步: 装好 PyTorch,把 MNIST 例子原样跑一遍,看看准确率是怎么一轮轮涨上去的。跑通那一刻,你就正式踏入”训练自己的 AI 模型”的大门了。

如何自己训练一个小模型完整教程(小白也能看懂)
https://021028.xyz/posts/default/82/
作者
021028
发布于
2026-08-11
许可协议
CC BY-NC-SA 4.0