• 【d2l动手学深度学习】 Lesson 10 多层感知机 + 代码实现 试验结果对比



    1. 介绍

    在第十节课 多层感知机 的代码实现部分,做的小实验,介绍了对FashionMNIST(衣物)数据集进行十分类的神经网络实现效果,主要展示的是训练的Loss以及准确度的训练批次图,10个epoch

    期间遇到问题如下:

    AttributeError: module ‘d2l.torch‘ has no attribute ‘train_ch3‘

    ⚠️注意:本章节用到的train_ch3,可能在后续新的版本将不复存在,如果你想按照老师的视频实现的效果,应该使用下面的命令安装旧的版本

    pip install d2l==0.17.5 --user
    
    • 1

    2. 单层Softmax回归

    2.1 手写Softmax

    Softmax函数,输入是一个二维张量

    1. 首先,对输入的矩阵进行求指数exp(X) , 不会改变矩阵大小
    2. 接着,对dim_1 进行求和,得到每个example的指数总和(下面公式的分母部分)
    3. 最后,将整个矩阵相除,得到指数归一化的输出(不改变矩阵形状)

    softmax求和

    softmax函数内部求和

    def softmax(X):
        X_exp = torch.exp(X) # 1. 求指数
        partition = X_exp.sum(1, keepdim=True) # 2. 求和
        return X_exp / partition # keepdim to boardcast 3. 输出指数归一化矩阵 
    
    • 1
    • 2
    • 3
    • 4

    这个函数在自定义的网络中net( X )调用

    def net(X):
        # -1 means convert the dimension atomatically
        # the input shape X (256, 1, 28, 28) --> (28*28, 256)
        return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
    
    • 1
    • 2
    • 3
    • 4

    最后,写一个epoch迭代
    ⚠️:这里面没有写梯度更新的函数,直接调用torch中的自动求道实现,也就是下文代码中的updater.step()

    for X, y in train_iter:
            y_hat = net(X) # 将batch传入进去
            l = loss(y_hat, y) # 计算loss值
            if isinstance(updater, torch.optim.Optimizer):
                updater.zero_grad()
                l.backward() # 求梯度
                updater.step() # 根据梯度更新权重参数矩阵W
                metric.add(
                    float(l) * len(y), accuracy(y_hat, y),
                    y.size().numel())
            else:
                l.sum().backward()
                updater(X.shape[0])
                metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    训练效果

    手动实现的Softmax训练效果

    手动实现的Softmax训练效果


    2.2 调用pytorch内置的softmax回归层实现

    ⚠️:nn.CrossEntropyLoss()会在输出的时候自动应用Softmax进行求Loss(公式如下图所示)

    net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))  
    
    loss = nn.CrossEntropyLoss() # 损失函数 内嵌了Softmax函数
    
    trainer = torch.optim.SGD(net.parameters(), lr=0.1) # 梯度下降优化器选择
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    Pytorch文档.CROSSENTROPYLOSS

    调用pytorch内置softmax实验结果

    内置Softmax实现

    内置Softmax实现10分类的回归效果

    总结

    可以看到,调用torch内部实现的Softmax函数经过优化之后,相比手写的Softmax函数,迭代的过程更加稳定(抖动更小)


    3. 一层感知机(MLP)+ Softmax

    W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True))
    b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
    W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True))
    b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
    
    # function ReLU
    def relu(X):
        a = torch.zeros_like(X)
        return torch.max(X, a)
    
    
    # model
    def net(X):
        X = X.reshape((-1, num_inputs)) # 行数自动调整(batch_size),列数规定
        H = relu(X @ W1 + b1)
        return (H @ W2 + b2)
    
    loss = nn.CrossEntropyLoss() # 隐式实现 Softmax
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Exp3.1. 一层感知机实验结果

    一层感知机+Softmax

    ❓:有个疑惑,实现起来没有老师在视频里面展示的那种效果按照视频中的代码运行还是没有看到有loss曲线

    后来改了一下损失函数loss = nn.CrossEntropyLoss(reduction='none')才看到部分loss曲线(如上图),但是还是出不来视频中老师的效果

    总的来说,在同样的训练轮次下,MLP实现的效果跟前面用单层的Softmax实现,效果差了

    Exp3.2 增大训练轮次

    根据上述的结果,猜测是否是因为模型参数增加了,所以需要更多的训练轮次呢?🤨

    于是我们将训练轮次由原来的10轮上升为30轮

    结果如下:

    增大训练轮次
    增大训练轮次后,loss确实减少了,取得了比原来好的效果!

    Exp3.3 权重参数初始化为0

    视频中李沐老师有提及,如果将==权重矩阵初始化为0(而不是上述代码使用正态分布)==会怎么样,于是我将原来的训练轮次改回了10,然后将权重改为初始化为0的效果

    # test:全部设成0
    # 全部设置成rendn
    W1 = nn.Parameter(torch.zeros(num_inputs, num_hiddens, requires_grad=True))
    b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
    W2 = nn.Parameter(torch.zeros(num_hiddens, num_outputs, requires_grad=True))
    b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实验结果如下:

    权重参数初始化为0
    可以看到,图中不再显示原来的3条曲线了不是因为bug,而是因为训练的loss太大了!

    上面也显示的最终训练Loss=2.3027

    3.4 用AdamW优化器

    updater = torch.optim.AdamW(params, lr=lr)

    用AdamW优化器

    Adam优化器

    Adam优化器

    这个优化效果确实显著!

    3.5 一层感知机(MLP)+ Softmax 的简洁实现

    记得加loss = nn.CrossEntropyLoss(reduction='none')

    net = nn.Sequential(nn.Flatten(), nn.Linear(784, 256), nn.ReLU(), nn.Linear(256, 10))
    
    def init_weights(m):
        if type(m) == nn.Linear:
            nn.init.normal_(m.weight, std=0.01)
    
    net.apply(init_weights);
    
    batch_size, lr, num_epochs = 256, 0.1, 10
    loss = nn.CrossEntropyLoss(reduction='none')
    trainer = torch.optim.SGD(net.parameters(), lr=lr)
    
    train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
    d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    试验结果如下

    一层感知机(MLP)+ Softmax 的简洁实现
    效果应该是这几个实验中最好的了(不知道是不是有torch中计算优化的缘故)😊

    在这里插入图片描述

    用了Adam反而效果不那么好?


    如果有同学🧑‍🎓能够有更好的训练结果(或者能复现李沐老师视频里面的结果的话),欢迎在下面评论区讨论,谢谢啦!


    Reference

    1. 李沐老师的课程网站地址 课程网址
    2. 动手学深度学习B站课程地址

    写在最后

    各位看官,都看到这里了,麻烦动动手指头给博主来个点赞8,您的支持作者最大的创作动力哟!
    才疏学浅,若有纰漏,恳请斧正
    本文章仅用于各位作为学习交流之用,不作任何商业用途,若涉及版权问题请速与作者联系,望悉知

  • 相关阅读:
    DAMA-总结(数据管理的总结)
    性能测试脚本用例【模板】
    iNFTnews | 国内NFT发展仅限于数字藏品吗?
    selenium基础方法总结
    Python一切皆对象-面向对象
    SICP 2.2: 层次性数据和闭包性质(Python实现)
    【性能基石之IO~~~Linux操作系统相关知识体系补充&虚拟文件系统&文件描述符&PageCache内核缓存页】
    MCE | HPV 疫苗要不要打?
    十四、使用 Vue Router 开发单页应用(1)
    如何编辑图片合成图片?让我们来看看这些合成方法
  • 原文地址:https://blog.csdn.net/LeungSr/article/details/133743509