目录
1 前言与摘要
本次笔记涉及苹果书3.3~3.6章节,以及实践任务。教学资料来源于datawhale AI夏令营。
本文按照书本顺序,尝试用自己的理解描述和对比相关概念,并且给出了一部分疑问和解答。进行了代码实践任务,同时整理了 baseline 中与 task1、2 中理论相关的代码,并且尝试给出未来可能的试验方向,为进一步理论结合实践打下基础。
task1笔记:Datawhale X 李宏毅苹果书 AI夏令营 task1-CSDN博客
相关课程链接也详见 task1 笔记↑
2 自适应学习率
2.1 概念
自适应学习率:给每一个参数不同的、变化的学习率,而不是固定的。
为什么要用自适应学习率:训练不一定只卡在临界点,也可能会在山谷之间“震荡”(图1)。
如何判断“震荡”:如图1的右边显示,虽然损失不再下降,但是梯度范数没有变得很小。
梯度范数:衡量梯度向量的大小或“长度”的数值。如果梯度范数在训练过程中逐渐减小并最终趋于稳定,这可能意味着模型正在收敛到一个稳定的状态。
2.2 方法
方法 | 说明 | 特点 | 关联 |
AdaGrad | 梯度大学习率就小 梯度小学习率就大 | 与过去所有梯度的均方根有关 综合考虑了之前全部的梯度 | |
RMSprop | 同一参数的同一方向, 学习率也动态调整 | 为最新的梯度增加了一定权重 使得对新变化的调整更加及时 | 优化了AdaGrad反应慢的缺陷 |
Adam | 优化器 | 使用了动量作为参数更新方向 在PyTorch上已经集成了 | 在RMSprop上增加了动量 |
3 学习率调度
学习率调度:让原本不变的 η 跟时间有关,AdaGrad 中的 η 见图2左边。
为什么需要学习率调度:解决梯度爆炸的问题(图2右边)。
什么是梯度爆炸:因为梯度很小的时候积累了很小的 σ 导致突然步伐变得很大。
学习率退火:η 越来越小来解决梯度爆炸的学习率调度方法。
学习率退火怎么解决梯度爆炸:虽然你的 σ 变小了,但是我的 η 也变小了!步伐就不会突然变得很大了。
学习率预热:刚开始的时候学习率先由小变大。
为什么需要学习率预热:众说纷纭,反正就是好用。有一种说法是较低的学习率让 σ 的统计足够多了足够精准之后再根据它来决定学习率。可能意思就是刚睡醒还要缓一会才开工。
4 优化总结
现在我们有了一个加动量加自适应学习率加学习率调度的版本!
5 分类
把分类视为回归:可以,但是会带来编号问题,如果分类之间没有关联,分类1、2、3中1和3的距离会显得有些远,影响训练,需要用独热编码解决。
独热编码:用向量编号,距离都是一样的,例如分类1、2、3就是[1,0,0]T、[0,1,0]T、[0,0,1]T。
softmax 函数:分类的时候经常会给结果套一层 softmax。softmax 函数见图4。
为什么需要 softmax 函数:把结果归一化为 0~1 之间的值,并且结果之和为1,同时它还会让大的值跟小的值的差距更大。
怎么理解 softmax 让大小值的差距更大:指数函数 的一个重要性质是,当x的值增大时, 的增长速度非常快,远超过线性增长。这意味着,在 softmax 函数中,如果某个输出值z相对于其他值较大,那么其对应的指数函数值 将会变得非常大,从而在分母中的占比显著增加。
让大小值的差距更大有什么好处:方便让结果更加突出,从而提高性能。
小贴士:当只有两个类的时候,sigmoid 和 softmax 是等价的,通常会用 sigmoid 函数。
分类损失的计算:可以采用均方误差、最小化交叉熵。在分类中更常用交叉熵(见图5)。
6 实践任务:CNN
HW3(CNN)卷积神经网络-图像分类
帮大家问到了Kaggle评估的链接:(不需要刻意打榜)
https://www.kaggle.com/competitions/ml2023spring-hw3
6.1 跑baseline!
结果如图6:
分析一下log
poch | Train Loss | Train Acc | Val Loss | Val Acc | Best? |
---|---|---|---|---|---|
1 | 1.87297 | 0.34733 | 1.88489 | 0.34458 | ✓ |
2 | 1.53785 | 0.47054 | 1.64059 | 0.45350 | ✓ |
3 | 1.31781 | 0.54847 | 1.46791 | 0.51246 | ✓ |
4 | 1.15302 | 0.59723 | 1.57830 | 0.48073 | |
5 | 1.02833 | 0.64152 | 1.36255 | 0.55365 | ✓ |
6 | 0.89243 | 0.68899 | 1.16706 | 0.60896 | ✓ |
7 | 0.77440 | 0.73865 | 1.21582 | 0.61005 | ✓ |
8 | 0.66873 | 0.76762 | 1.29735 | 0.58942 |
随着训练轮次的增加,训练损失(Train Loss)从最初的1.87297降低到0.66873,这表明模型正在逐渐学习并更好地拟合训练数据。 同时训练准确率(Train Acc)从0.34733提高到了0.76762。虽然训练准确率持续提高,但验证准确率在达到一个峰值(在第7轮0.61005)后开始下降(在第8轮降至0.58942),这可能是一个过拟合的信号。
6.2 涉及了哪些理论
此处的苹果书指的是:
《深度学习详解》人民邮电出版社(ISBN:9787115642110)2024年9月第1版 实体书
出版版次不同或者PDF电子书可能会存在不同章节和页码。
整理了一下baseline中涉及前文理论的部分,并且给出可能尝试试验的方向。
本身任务就是分类(苹果书3.6,57页)。
训练批次(苹果书3.2,39页):尝试不同的batch_size?更多的epochs?
# 初始化模型,并将其放置在指定的设备上
model = Classifier().to(device)
# 定义批量大小
batch_size = 64
# 定义训练轮数
n_epochs = 8
# 如果在'patience'轮中没有改进,则提前停止
patience = 5
交叉熵(苹果书3.6.3,60页):故意改成均方误差来看看会不会卡住?
# 对于分类任务,我们使用交叉熵作为性能衡量标准
criterion = nn.CrossEntropyLoss()
优化器 Adam(苹果书3.3.3,54页):修改超参数?是否可以进行学习率调度?
# 初始化优化器,您可以自行调整一些超参数,如学习率
optimizer = torch.optim.Adam(model.parameters(), lr=0.0003, weight_decay=1e-5)
softmax(苹果书3.6.2,58页)。
# 计算交叉熵损失。
# 在计算交叉熵之前不需要应用softmax,因为它会自动完成。
loss = criterion(logits, labels.to(device))
梯度范数(苹果书3.3,47页):如果改大或者改小max_norm会发生什么?
# 计算参数的梯度
loss.backward()
# 为了稳定训练,限制梯度范数
grad_norm = nn.utils.clip_grad_norm_(model.parameters(), max_norm=10)
7 小结
不足与可改进之处:
1,理论:在数学公式和概念并没有更多的深入思考与分析。
2,实践:受限于时间并没有对 baseline 进行进一步探索。