Datawhale X 李宏毅苹果书 AI夏令营第五期 DL进阶方向 Task2笔记

news2024/9/27 23:33:09

       Datawhale X 李宏毅苹果书 向李宏毅学深度学习(进阶) 是 Datawhale 2024 年 AI 夏令营第五期的学习活动(“深度学习 进阶”方向

       往期task1链接:深度学习进阶-Task1

       我做的task1的笔记博客:传送门

       Datawhale官方的task2链接:深度学习进阶-Task2

       Github-《深度学习详解》开源地址:传送门

《深度学习详解》主要内容源于《机器学习》(2021年春),选取了《机器学习》(2017年春) 的部分内容,在这些基础上进行了一定的原创,补充了不少除这门公开课之外的深度学习相关知识。为了尽可能地降低阅读门槛,笔者对这门公开课的精华内容进行选取并优化,对所涉及的公式都给出详细的推导过程,对较难理解的知识点进行了重点讲解和强化,以方便读者较为轻松地入门。

       在理论严谨的基础上,本书保留了公开课中大量生动有趣的例子,帮助读者从生活化的角度理解深度学习的概念、建模过程和核心算法细节,包括——

  • 卷积神经网络、Transformer、生成模型、自监督学习(包括 BERT 和 GPT)等深度学习常见算法,

  • 对抗攻击、领域自适应、强化学习、元学习、终身学习、网络压缩等深度学习相关进阶算法。


目录

1. 深度学习优化器的演变

2. AdaGrad

AdaGrad的优点:

AdaGrad的缺点:

3. RMSProp

RMSProp的优点:

RMSProp的缺点:

4. Adam

Adam的优点:

Adam的缺点:

5. 学习率调度

6. 分类问题的损失函数

7. 拓展-  RAdam

RAdam的优点:

RAdam的缺点:

8. 知识点总结

9.(实践任务):HW3(CNN)卷积神经网络-图像分类

       获取数据集和代码文件命令:

       训练模型代码

       运行结果

       十分钟跑通baseline视频(跑baseline过程中出现问题的可以对照着看看):


       在第五期的进阶方向的学习内容中,Task2在Task1的基础上继续叙述,主要学习自适应学习率、学习率调度、优化和分类问题的知识点,对应《深度学习详解》一书中的3.3&4&5及3.6的内容。

       在深度学习模型训练中,优化算法起着至关重要的作用。它决定了模型参数更新的方向和速度,进而影响模型的性能和泛化能力。本笔记将结合图文,深入浅出地解释深度学习中的优化概念和算法,包括局部极小值、鞍点、批量梯度下降、随机梯度下降、动量法以及自适应学习率。

1. 深度学习优化器的演变

       深度学习模型的训练过程本质上是一个优化问题,目标是最小化损失函数。传统的梯度下降法存在着一些局限性,例如:

  • 学习率固定: 无法适应不同参数和不同阶段的训练需求。
  • 梯度消失/爆炸: 对于深层网络,梯度在反向传播过程中会逐渐减小或增大,导致训练困难。
  • 陷入局部最优解: 梯度下降法容易陷入局部最优解,无法找到全局最优解。

 不同学习率对训练的影响

       最原始的梯度下降连简单的误差表面都做不好,因此需要更好的梯度下降的版本。在梯 度下降里面,所有的参数都是设同样的学习率,这显然是不够的,应该要为每一个参数定制 化学习率,即引入自适应学习率(adaptive learning rate)的方法,给每一个参数不同的学习率。

       为了克服这些局限性,研究者们提出了许多改进的优化器,其中最常用的包括AdaGrad、RMSProp和Adam。

2. AdaGrad

        AdaGrad是最早提出的自适应学习率优化器,其核心思想是根据参数的历史梯度信息动态调整学习率。具体来说,AdaGrad会对每个参数维护一个累加的平方梯度,并将其用于更新学习率。梯度较大的参数对应的学习率会逐渐减小,梯度较小的参数对应的学习率会逐渐增大。

def sgd_adagrad(parameters, sqrs, lr):
	eps = 1e-10
	for param, sqr in zip(parameters, sqrs):
 	sqr[:] = sqr + param.grad.data ** 2
 	div = lr / torch.sqrt(sqr + eps) * param.grad.data
 	param.data = param.data - div
AdaGrad的优点
  • 避免了梯度消失/爆炸问题,更适合处理稀疏数据。
  • 无需手动调整学习率,可以自动适应不同参数和不同阶段的训练需求。
AdaGrad的缺点
  • 学习率逐渐减小,可能导致训练速度变慢,甚至停止。
  • 会导致参数更新步长越来越小,难以跳出局部最优解。

3. RMSProp

        RMSProp是AdaGrad的改进版本,它引入了超参数α来控制历史梯度的权重,使学习率更具动态性。具体来说,RMSProp会对每个参数维护一个指数衰减的平均平方梯度,并将其用于更新学习率。α值越小,历史梯度的影响越大;α值越大,历史梯度的影响越小。

RMSProp的优点
  • 解决了AdaGrad学习率过快衰减的问题,提高了训练速度。
  • 可以更好地处理非平稳目标函数。
RMSProp的缺点
  • 学习率调整不够平滑,可能导致训练过程不稳定。
  • 需要手动设置超参数α,选择不当会影响训练效果。

4. Adam

        Adam是近年来最常用的优化器之一,它结合了AdaGrad和RMSProp的优点,并引入了动量项,使参数更新更加平滑。具体来说,Adam会对每个参数维护两个状态:一个是指数衰减的平均梯度,用于更新学习率;另一个是指数衰减的平均梯度平方,用于更新动量。

Adam的优点
  • 具有自适应学习率和动量的特性,训练速度快,效果稳定。
  • 无需手动调整学习率,可以自动适应不同参数和不同阶段的训练需求。
  • 避免了梯度消失/爆炸问题,更适合处理深层网络。
Adam的缺点
  • 需要设置多个超参数,选择不当会影响训练效果。
  • 对于某些问题,Adam的效果可能不如专门的优化器。

5. 学习率调度

        学习率调度是指在训练过程中动态调整学习率,以提高训练速度和效果。常见的学习率调度方法包括:

  • 学习率退火: 随着训练次数的增加,逐渐减小学习率,使模型更加精细地调整参数。
  • 学习率预热: 训练初期先增大学习率,快速探索误差空间,然后逐渐减小学习率,进行精细调整。
  • 周期性调整: 将学习率设置为周期性变化的函数,例如余弦退火。

6. 分类问题的损失函数

分类问题常用的损失函数包括:

  • 均方误差: 计算预测值与真实值之间的平方差,适用于回归问题。
  • 交叉熵: 计算预测概率分布与真实概率分布之间的距离,更适合分类问题。
  • Hinge Loss: 计算预测值与真实标签的夹角,适用于支持向量机。
  • Log Loss: 计算预测概率与真实概率的对数差,适用于概率预测问题。

均方误差与交叉熵在分类问题上有什么不同呢?

均方误差与交叉熵的区别

  • 均方误差: 适用于回归问题,但不适合分类问题,因为它没有考虑到类别之间的差异。
  • 交叉熵: 适用于分类问题,因为它可以有效地衡量预测概率分布与真实概率分布之间的差异。

7. 拓展-  RAdam

       RAdam是Adam的改进版本,它引入了阶跃下降的概念,使学习率调整更加平滑。具体来说,RAdam会根据梯度变化情况,动态调整学习率的更新步长。当梯度变化较大时,增加学习率的更新步长;当梯度变化较小时,减小学习率的更新步长。

RAdam对不同的学习率具有鲁棒性,同时仍能快速收敛并获得更高的精度(CIFAR数据集)

       正如你所看到的,RAdam提供了一个动态启发式方法来提供自动化的方差衰减,从而消除了在训练期间热身所涉及手动调优的需要。此外,RAdam对学习速率变化(最重要的超参数)具有更强的鲁棒性,并在各种数据集和各种AI体系结构中提供更好的训练精度和泛化。

       PyTorch的官方github提供了RAdam的实现:https://github.com/LiyuanLucasLiu/RAdam。

RAdam的优点
  • 解决了Adam在训练初期学习率过小的问题,提高了训练速度。
  • 可以更好地处理非平稳目标函数。
RAdam的缺点
  • 需要设置额外的超参数,选择不当会影响训练效果。
  • 对于某些问题,RAdam的效果可能不如Adam。

8. 知识点总结

        选择合适的优化器和学习率调度方法对深度学习模型的训练至关重要。AdaGrad、RMSProp和Adam各有优缺点,需要根据具体问题选择。学习率退火和预热可以有效提高训练速度和效果。RAdam作为Adam的改进版本,也值得尝试。

9.(实践任务):HW3(CNN)卷积神经网络-图像分类

       Homework3的内容是通过利用卷积神经网络架构,通过一个较小的10种食物的图像的数据集训练一个模型完成图像分类的任务。       

       获取数据集和代码文件命令:
git clone https://www.modelscope.cn/datasets/Datawhale/LeeDL-HW3-CNN.git
       训练模型代码
  1. 初始化追踪器:stale 和 best_acc 用于追踪训练过程中的损失和准确率。stale 表示连续没有改进的轮数,当 stale 大于设定的阈值 patience 时,提前停止训练。

  2. 训练阶段:在训练阶段,首先确保模型处于训练模式,然后遍历训练数据加载器 train_loader 中的每个批次。对于每个批次,将图像数据 imgs 和对应的标签 labels 传递给模型,计算输出 logits。然后计算交叉熵损失 loss,并清除上一步中参数中存储的梯度。计算参数的梯度,并进行梯度裁剪以稳定训练。最后更新模型参数。

  3. 验证阶段:在验证阶段,首先确保模型处于评估模式,然后遍历验证数据加载器 valid_loader 中的每个批次。对于每个批次,将图像数据 imgs 和对应的标签 labels 传递给模型,计算输出 logits。计算损失 loss 和准确率 acc

  4. 打印训练和验证信息:在训练和验证阶段,打印当前轮次的损失和准确率。在验证阶段,如果当前轮次的准确率高于最佳准确率 best_acc,则更新 best_acc 和保存模型。

  5. 保存模型:在训练过程中,如果找到更好的模型,则保存模型参数。

 初始化追踪器,这些不是参数,不应该被更改
stale = 0
best_acc = 0

for epoch in range(n_epochs):
    # ---------- 训练阶段 ----------
    # 确保模型处于训练模式
    model.train()

    # 这些用于记录训练过程中的信息
    train_loss = []
    train_accs = []

    for batch in tqdm(train_loader):
        # 每个批次包含图像数据及其对应的标签
        imgs, labels = batch
        # imgs = imgs.half()
        # print(imgs.shape,labels.shape)

        # 前向传播数据。(确保数据和模型位于同一设备上)
        logits = model(imgs.to(device))

        # 计算交叉熵损失。
        # 在计算交叉熵之前不需要应用softmax,因为它会自动完成。
        loss = criterion(logits, labels.to(device))

        # 清除上一步中参数中存储的梯度
        optimizer.zero_grad()

        # 计算参数的梯度
        loss.backward()

        # 为了稳定训练,限制梯度范数
        grad_norm = nn.utils.clip_grad_norm_(model.parameters(), max_norm=10)

        # 使用计算出的梯度更新参数
        optimizer.step()

        # 计算当前批次的准确率
        acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()

        # 记录损失和准确率
        train_loss.append(loss.item())
        train_accs.append(acc)

    train_loss = sum(train_loss) / len(train_loss)
    train_acc = sum(train_accs) / len(train_accs)

    # 打印信息
    print(f"[ 训练 | {epoch + 1:03d}/{n_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}")

    # ---------- 验证阶段 ----------
    # 确保模型处于评估模式,以便某些模块如dropout能够正常工作
    model.eval()

    # 这些用于记录验证过程中的信息
    valid_loss = []
    valid_accs = []

    # 按批次迭代验证集
    for batch in tqdm(valid_loader):
        # 每个批次包含图像数据及其对应的标签
        imgs, labels = batch
        # imgs = imgs.half()

        # 我们在验证阶段不需要梯度。
        # 使用 torch.no_grad() 加速前向传播过程。
        with torch.no_grad():
            logits = model(imgs.to(device))

        # 我们仍然可以计算损失(但不计算梯度)。
        loss = criterion(logits, labels.to(device))

        # 计算当前批次的准确率
        acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()

        # 记录损失和准确率
        valid_loss.append(loss.item())
        valid_accs.append(acc)
        # break

    # 整个验证集的平均损失和准确率是所记录值的平均
    valid_loss = sum(valid_loss) / len(valid_loss)
    valid_acc = sum(valid_accs) / len(valid_accs)

    # 打印信息
    print(f"[ 验证 | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")

    # 更新日志
    if valid_acc > best_acc:
        with open(f"./{_exp_name}_log.txt", "a"):
            print(f"[ 验证 | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f} -> 最佳")
    else:
        with open(f"./{_exp_name}_log.txt", "a"):
            print(f"[ 验证 | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")

    # 保存模型
    if valid_acc > best_acc:
        print(f"在第 {epoch} 轮找到最佳模型,正在保存模型")
        torch.save(model.state_dict(), f"{_exp_name}_best.ckpt")  # 只保存最佳模型以防止输出内存超出错误
        best_acc = valid_acc
        stale = 0
    else:
        stale += 1
        if stale > patience:
            print(f"连续 {patience} 轮没有改进,提前停止")
            break
       运行结果

       简单的 baseline 不过多赘述,以下是运行结果:

         十分钟跑通baseline视频(跑baseline过程中出现问题的可以对照着看看):

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2089252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tensorflow实现深度学习8:猫狗识别

本文为为🔗365天深度学习训练营内部文章 原作者:K同学啊 一 导入数据 import matplotlib.pyplot as plt import tensorflow as tf # 支持中文 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] Fals…

开放式耳机会漏音吗?开放式耳机测评

开放式耳机由于其独特的设计,允许声音在一定程度上自然地与外界环境融合。这种设计带来的一个常见误解是,人们可能会认为开放式耳机会有较大的声音泄露。然而,实际上,高质量的开放式耳机通过精心的声学设计,可以有效地…

Video Recording,视频录制

一.录屏软件 1.1 Xbox Game Bar 对于 win 来说,快捷键是 Win G,即可以启动 Xbot Game Bar 来进行录制。但是有一个比较致命的缺点就是,当我们切换页面的时候,录制就会失败,这款还是很适合于单页面的视频录制。 1.2 …

Python以及Python历史版本的安装的安装

文章目录 前言Python的安装Python历史版本下载总结 前言 Python 是一种广泛使用的高级编程语言,以其简洁易读的语法和强大的功能而受到开发者的青睐。从数据分析到网页开发,从自动化脚本到人工智能,Python 的应用领域几乎无处不在。然而&…

深度学习论文被评“创新性不足、工作量不够”怎么办?

投稿时遇到审稿人提出文章创新性不足、工作量不够,该怎么办? 今天我就来分享三种应对方法:下采样策略、归一化策略、改进网络模型。 改进网络模型 增加创新性: 从模型架构和训练策略这两方面入手: 模型架构创新&a…

c++ 135 错误: 成员函数的作用 内存四区

1。 类中不写成员函数 现在要求c1 的属性 原来怎么求的: 虽然把r改成10 但是没有执行area的那句话 area还是一个未知变量 当执行c1.area时 只是内存变量标示的内存空间拿值 跟r10 没有半毛钱关系 面向过程转换成面向对象

代码随想录 | 贪心算法总结

贪心理论基础 在贪心系列开篇词贪心算法理论基础中,我们就讲解了大家对贪心的普遍疑惑。 贪心很简单,就是常识? 贪心思路往往很巧妙,并不简单。 贪心有没有固定的套路? 贪心无套路,也没有框架之类的&a…

MarsCode代码练习能力初体验

MarsCode代码练习能力初体验 地址:https://sourl.cn/JJeBEF 最近MarsCode上线了代码练习能力,对准备算法题的同学来说是一个福音。下面是编程主界面。 除了左边内置的算法外,还可以手动添加题目自己练习,AI会去理解题目&#xf…

Java整体基础知识体系图

一 java 介绍 ‌Java是一种高级编程语言,由Sun Microsystems公司于1995年推出。‌ Java具有跨平台性、面向对象、健壮性、安全性、可移植性等特点,被广泛应用于企业级应用开发、移动应用开发、大数据处理、云计算等领域。Java程序可以在不同的操作系统上…

鸿蒙开发—黑马云音乐之music页面播放音乐(上)

目录 1.封装播放对象管理类 2.musicPage中调用AvPlayerManager完成播放歌曲 3.index.ets的播放信息样式 4.musicPage向index传数据 1.封装播放对象管理类 封装一个播放对象,之后播放音乐直接调用该对象。 src/main/ets/services/AvPlayerManager.ets&#xff…

本地Linux系统搭建Plik临时文件上传站点并实现远程访问共享文件

文章目录 前言1. Docker部署Plik2. 本地访问Plik3. Linux安装Cpolar4. 配置Plik公网地址5. 远程访问Plik6. 固定Plik公网地址7. 固定地址访问Plik 前言 本文介绍如何使用Linux docker方式快速安装Plik并且结合Cpolar内网穿透工具实现远程访问,实现随时随地在任意设…

虚幻地形高度图生成及测试

虚幻地形高度图生成及测试 虚幻引擎地形系统将高度数据存储在高度图中,这是一个灰阶图像,使用黑白色值来存储地貌高程。在高度图中,纯黑色值表示最低点,纯白色值表示最高点。支持16位灰阶PNG、8位灰阶r8及16位灰阶r16格式。 本文…

纯vue实现笔记系统

前言 最近研究了一个笔记记录系统,然后突然想到一个问题,我该如何才能只用前端就实现笔记的记录系统?经过这两天的研究将其做出来了,接下来将分享实现的过程 ✨✨✨✨✨✨✨✨✨✨ 项目演示 在我的项目中,是可以适…

PCIe prefix总结

这周研究了一下spec中关于prefix的部分,在此做一个总结,欢迎大家指正补充。 TLP Prefix基本介绍 • TLP 第 0 字节的 Fmt [2:0] 字段值为 100b 表示当前 DW 为 TLP Prefix 。 • TLP Prefix 分为两大类: Local 和 End-End ,其中…

深入理解归并排序

目录 一、概念 二、递归版实现 三、非递归实现 三、文件归并排序 小结 一、概念 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将…

海外新闻稿发布:企业如何充分利用数字化媒体进行

在全球数字化进程加速的时代,企业要在激烈的国际市场中脱颖而出,利用数字化媒体进行海外新闻稿发布是一个不可或缺的战略。精确的策略和有效的执行能够帮助企业获得更高的曝光度和市场份额。以下将从多个角度探讨如何充分利用数字化媒体进行海外新闻稿发…

万亿生成式AI市场,商汤迎来“长坡厚雪”

AI掀起了全球科技玩家的军备竞赛,然而声浪越强噪音越多,这个领域的混乱程度也变得远超以往。就连刚刚公布财报的英伟达,市场也没有买账,因为担心AI驱动的增长高峰已过,接下来,下游会更看重实际成果。 “囤…

【电子数据取证】微信8.0.50版本数据库解密

文章关键词:电子数据取证、手机取证、微信取证、数据库解密 通过对8.0.50这一特定版本的分析,我们期望揭示软件迭代背后的逻辑思考,以及安全策略的演进方向。这不单纯是对技术细节的揭秘,更是一次关于未来通信安全趋势的展望&…

在Linux中如何安装JDK

一、卸载JDK (可以不删除,直接安装新的JDK,然后修改环境变量) 1.1卸载使用yum安装的jdk 1.1.1卸载系统预安装的JDK 使用命令:yum list installed |grep java 注意:该命令只能查看使用yum命令安装的jav…

python模块和包的区别有哪些

模块:就是.py文件,里面定义了一些函数和变量,需要的时候就可以导入这些模块。 包:在模块之上的概念,为了方便管理而将文件进行打包。包目录下第一个文件便是 __init__.py,然后是一些模块文件和子目录&…