d2l 学习笔记:深度学习的工程化方法
你现在学习到 D2L 的线性回归和 Softmax 回归,其实已经接触到了现代深度学习训练流程中最核心的骨架。后续无论是 CNN、RNN、Transformer,甚至大语言模型训练,本质上都没有脱离这个流程,只是模型结构、损失函数和优化方法变得更加复杂。
因此这一节我会把 D2L 3.2(线性回归手动实现)、3.3(线性回归框架实现)、3.4(Softmax回归)、3.6/3.7(Softmax工程实现)中的代码抽象出来,形成一个完整的深度学习模型训练工程流程。
整体来看,一个训练系统可以抽象成:
这就是现在几乎所有深度学习框架(PyTorch、TensorFlow、Paddle)的核心训练范式。
1. 数据准备阶段:把现实问题转换为数学问题
任何机器学习任务第一步都是:
将现实世界中的信息转换成计算机可以处理的数据表示。
例如线性回归:
现实:
房屋面积预测价格。
转换:
输入:
表示房屋特征:
输出:
表示价格。
最终形成训练数据:
在 D2L 中:
features, labels = synthetic_data(true_w,true_b,1000)
对应:
生成训练数据。
2. synthetic_data 做了什么?
代码:
X = torch.normal(0,1,(num_examples,len(w)))
y = torch.matmul(X,w)+b
y += torch.normal(0,0.01,y.shape)
数学对应:
首先生成输入:
然后假设真实世界规律:
其中:
这里实际上是在模拟:
现实世界存在噪声。
例如:
真实规律:
但是现实:
还有:
-
装修
-
楼层
-
随机因素
所以:
3. 数据加载阶段:为什么需要 DataLoader
现实训练中:
数据可能:
-
几万张图片
-
几TB文本
-
百亿token
不可能一次全部放入GPU。
所以需要:
mini-batch训练。
D2L手写:
data_iter(batch_size,features,labels)
框架:
DataLoader(dataset,batch_size)
本质一样。
例如:
100万个样本。
batch_size=100。
一次训练:
只取:
个样本。
计算:
然后更新。
为什么?
因为:
完整梯度:
计算成本太高。
所以使用:
近似:
这就是小批量随机梯度下降。
4. 模型定义阶段:建立数学映射关系
模型本质:
就是一个函数。
例如线性回归:
代码:
手动:
def net(X,w,b):
return torch.matmul(X,w)+b
框架:
net=nn.Linear(2,1)
区别:
手写:
你管理参数。
框架:
PyTorch管理参数。
但是数学完全一样。
Softmax:
模型:
输出:
logits。
代码:
net=nn.Linear(784,10)
表示:
输入:
784个像素。
输出:
10个类别分数。
5. 前向传播阶段:计算预测结果
训练循环:
首先:
输入数据:
进入模型:
这个过程叫:
forward。
线性回归:
Softmax:
先:
然后:
得到类别概率。
代码:
y_hat=net(X)
6. 损失函数:评价预测错误程度
模型预测之后,需要回答:
这个结果好不好?
所以定义:
损失函数。
7. 线性回归
预测:
真实:
误差:
平方:
得到:
均方误差:
代码:
squared_loss(y_hat,y)
8. Softmax分类
预测:
例如:
真实:
我们关心:
真实类别概率。
交叉熵:
如果:
真实类别概率低:
损失大。
如果:
真实类别概率高:
损失小。
代码:
cross_entropy(y_hat,y)
9. 反向传播:计算参数应该如何变化
这是训练最核心步骤。
损失:
是参数:
的函数。
所以:
求:
表示:
如果改变参数:
损失如何变化。
代码:
l.backward()
PyTorch自动计算:
计算图:
然后链式求导:
10. 参数更新阶段:优化模型
得到梯度:
更新:
其中:
叫学习率。
D2L手写:
param -= lr*param.grad/batch_size
PyTorch:
optimizer.step()
例如:
optimizer=torch.optim.SGD(
net.parameters(),
lr=0.03
)
11. 训练循环:重复优化
完整训练:
for epoch:
for X,y in data_iter:
y_hat=net(X)
loss=loss_fn(y_hat,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
对应数学:
不断重复:
直到:
损失下降。
12. 模型评估阶段
训练损失下降不代表模型真的好。
因为可能:
过拟合。
所以需要测试集。
代码:
evaluate_accuracy(net,test_iter)
计算:
预测正确数量:
总数量:
准确率:
13. 完整工程流程图
把D2L代码抽象:
数据集
|
↓
Dataset / DataLoader
|
↓
Batch数据
|
↓
Model
|
↓
Forward传播
|
↓
Prediction
|
↓
Loss Function
|
↓
Autograd计算梯度
|
↓
Optimizer更新
|
↓
新参数
|
↓
下一批数据
|
↓
Epoch循环
|
↓
Evaluation
14. 手写实现和框架实现最大的区别
15. D2L手写线性回归
你负责:
-
参数初始化
-
前向计算
-
损失函数
-
梯度更新
-
数据迭代
目的:
理解数学。
16. PyTorch实现
框架负责:
-
参数管理
-
自动求导
-
优化器
-
GPU计算
-
数据加载
你负责:
-
定义模型结构
-
定义loss
-
定义optimizer
-
写训练循环
17. 从工程角度理解一个模型
实际上一个生产级训练系统就是下面几个模块:
18. 数据模块
负责:
-
数据读取
-
清洗
-
增强
-
batch
例如:
PyTorch:
Dataset
DataLoader
19. 模型模块
负责:
定义:
例如:
nn.Module
20. 损失模块
负责:
定义:
例如:
MSELoss
CrossEntropyLoss
21. 优化模块
负责:
例如:
SGD
Adam
22. 训练管理模块
负责:
-
epoch
-
checkpoint
-
logging
-
evaluation
工业中:
还有:
-
TensorBoard
-
WandB
-
MLFlow
-
Kubernetes训练任务管理
23. 最后总结
你目前学习的线性回归和Softmax回归,本质上是在学习现代AI系统最基础的训练闭环:
线性回归让你理解:
模型如何通过误差调整参数。
Softmax回归让你理解:
模型如何输出概率并通过交叉熵优化分类。
而PyTorch框架让你理解:
如何把数学模型工程化为一个可重复运行的大规模训练系统。
后面 CNN、Transformer、大模型训练,变化主要集中在:
-
模型函数 更复杂;
-
参数量更大;
-
数据更多;
-
优化策略更高级;
但是训练闭环本质仍然是这一套。你现在D2L第三章实际上是在建立整个深度学习工程体系的底层抽象。
关联文档
- d2l 学习笔记:引言:D2L 学习入口。
- d2l 学习笔记:线性回归的损失函数:线性回归与损失函数基础。
