之前写过“多层感知机概述”,可点击查看多层感知机概述——2020.2.15
下⾯实现⼀个多层感知机。⾸先导⼊实现所需的包或模块。
# 导包 import torch import numpy as np import sys sys.path.append("..") import d2lzh_pytorch as d2l
1. 获取和读取数据:
这⾥继续使⽤Fashion-MNIST数据集。我们将使⽤多层感知机对图像进⾏分类。
# 1.获取和读取数据 batch_size = 256 train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
2. 定义模型参数
Fashion-MNIST数据集中图像形状为\(28 \times 28\),类别数为 10 。本节中我们依然使⽤⻓度为 \(28 \times 28 = 784\) 的向量表示每⼀张图像。因此,输⼊个数为784,输出个数为10。实验中,我们设超参数隐藏单元个数为256。
# 2 定义模型参数 num_inputs, num_outputs, num_hiddens = 784, 10, 256 w1 = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_hiddens)),dtype=torch.float) b1 = torch.zeros(num_hiddens, dtype=torch.float) w2 = torch.tensor(np.random.normal(0, 0.01, (num_hiddens, num_outputs)), dtype=torch.float) b2 = torch.zeros(num_outputs, dtype=torch.float) params = [w1, b1, w2, b2] for param in params: param.requires_grad_(requires_grad=True)
3. 定义激活函数
使⽤基础的 max
函数来实现ReLU,⽽⾮直接调⽤ relu
函数。
# 3 定义激活函数 def relu(x): return torch.max(input=x, other=torch.tensor(0.0))
4. 定义模型
同softmax回归⼀样,我们通过 view
函数将每张原始图像改成⻓度为 num_inputs
的向量。然后实现概述中的多层感知机的计算表达式。
# 4 定义模型 def net(x): x = x.view((-1, num_inputs)) H = relu(torch.matmul(x,w1) + b1) return torch.matmul(H, w2) + b2
5. 定义损失函数
为了得到更好的数值稳定性,我们直接使⽤PyTorch提供的包括softmax运算和交叉熵损失计算的函数。
# 5 定义损失函数 loss = torch.nn.CrossEntropyLoss()
6. 训练模型
训练多层感知机的步骤和3.6节中训练softmax回归的步骤没什么区别。我们直接调⽤ d2lzh_pytorch
包中的 train_ch3
函数,它的实现已经在3.6节⾥介绍过。我们在这⾥设超参数迭代周期数为5,学习率为100.0。
注:由于原书的mxnet中的 SoftmaxCrossEntropyLoss 在反向传播的时候相对于沿batch维求和了,⽽PyTorch默认的是求平均,所以⽤PyTorch计算得到的loss⽐mxnet⼩很多(⼤概是maxnet计算得到的1/batch_size这个量级),所以反向传播得到的梯度也⼩很多,所以为了得到差不多的学习效果,我们把学习率调得成原书的约batch_size倍,原书的学习率为0.5,这⾥设置成100.0。(之所以这么⼤,应该是因为d2lzh_pytorch⾥⾯的sgd函数在更新的时候除以了batch_size,其实PyTorch在计算loss的时候已经除过⼀次了,sgd这⾥应该不⽤除了)
# 6 训练模型 num_epochs, lr = 5, 100.0 d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)
这一步稍稍费时一点,花了大概1min左右。
运行结果:
epoch 1, loss 0.0031, train acc 0.713, test acc 0.815 epoch 2, loss 0.0019, train acc 0.826, test acc 0.817 epoch 3, loss 0.0017, train acc 0.843, test acc 0.754 epoch 4, loss 0.0015, train acc 0.857, test acc 0.799 epoch 5, loss 0.0014, train acc 0.866, test acc 0.860
从上述结果中,即可看出不同损失函数下的准确率的变化,随着训练周期越长,损失函数值减小、准确率更高。
对第6步训练模型稍作修改,输出运行时间。修改后的代码:
# 6 训练模型 import time num_epochs, lr = 5, 100.0 start = time.time() d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr) print(time.time() - start)
第二次运行训练模型训练结果:
epoch 1, loss 0.0014, train acc 0.870, test acc 0.860 epoch 2, loss 0.0013, train acc 0.876, test acc 0.833 epoch 3, loss 0.0013, train acc 0.880, test acc 0.841 epoch 4, loss 0.0012, train acc 0.885, test acc 0.844 epoch 5, loss 0.0012, train acc 0.887, test acc 0.841 132.66817021369934
第三次运行结果
epoch 1, loss 0.0012, train acc 0.890, test acc 0.872 epoch 2, loss 0.0011, train acc 0.894, test acc 0.808 epoch 3, loss 0.0011, train acc 0.894, test acc 0.870 epoch 4, loss 0.0011, train acc 0.897, test acc 0.869 epoch 5, loss 0.0010, train acc 0.900, test acc 0.873 118.6175651550293
我做了一个尝试,将学习周期设为10、20,继续运行:
- 将学习周期设为10,运行结果:
epoch 1, loss 0.0010, train acc 0.901, test acc 0.876 epoch 2, loss 0.0010, train acc 0.904, test acc 0.857 epoch 3, loss 0.0010, train acc 0.906, test acc 0.854 epoch 4, loss 0.0010, train acc 0.907, test acc 0.862 epoch 5, loss 0.0010, train acc 0.909, test acc 0.826 epoch 6, loss 0.0009, train acc 0.911, test acc 0.865 epoch 7, loss 0.0009, train acc 0.912, test acc 0.884 epoch 8, loss 0.0009, train acc 0.914, test acc 0.884 epoch 9, loss 0.0009, train acc 0.916, test acc 0.881 epoch 10, loss 0.0009, train acc 0.916, test acc 0.856 234.6531686782837
- 将学习周期设为20,运行结果:
epoch 1, loss 0.0009, train acc 0.917, test acc 0.871 epoch 2, loss 0.0009, train acc 0.918, test acc 0.875 epoch 3, loss 0.0008, train acc 0.922, test acc 0.867 epoch 4, loss 0.0008, train acc 0.923, test acc 0.873 epoch 5, loss 0.0008, train acc 0.924, test acc 0.885 epoch 6, loss 0.0008, train acc 0.925, test acc 0.886 epoch 7, loss 0.0008, train acc 0.926, test acc 0.885 epoch 8, loss 0.0008, train acc 0.926, test acc 0.883 epoch 9, loss 0.0008, train acc 0.929, test acc 0.893 epoch 10, loss 0.0007, train acc 0.929, test acc 0.872 epoch 11, loss 0.0007, train acc 0.930, test acc 0.871 epoch 12, loss 0.0007, train acc 0.932, test acc 0.882 epoch 13, loss 0.0007, train acc 0.933, test acc 0.887 epoch 14, loss 0.0007, train acc 0.934, test acc 0.867 epoch 15, loss 0.0007, train acc 0.935, test acc 0.885 epoch 16, loss 0.0007, train acc 0.936, test acc 0.885 epoch 17, loss 0.0007, train acc 0.937, test acc 0.880 epoch 18, loss 0.0007, train acc 0.937, test acc 0.854 epoch 19, loss 0.0007, train acc 0.939, test acc 0.893 epoch 20, loss 0.0006, train acc 0.939, test acc 0.886 490.9914619922638
不过,这样训练下去,因为是全连接层,也很可能导致过拟合,关于防止过拟合,在后续的博客中将持续更新。
来源:https://www.cnblogs.com/somedayLi/p/12359167.html