【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

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. 输出指数归一化矩阵 

这个函数在自定义的网络中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)

最后,写一个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())

训练效果

手动实现的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) # 梯度下降优化器选择

在这里插入图片描述

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

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))

实验结果如下:

权重参数初始化为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)

试验结果如下

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

在这里插入图片描述

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


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


Reference

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

写在最后

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值