赞
踩
本篇笔记主要对应于莫凡Pytorch中的3.3节。主要讲了如何使用Pytorch中的Sequential模块快速搭建一个分类模型的神经网络。
接下来我们自己通过两种方法搭建一个分类模型的神经网络。
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
这里生成两组正态分布的数据。
其中类别0的数据维度为2,其在各个维度上服从均值为2,方差为1的正态分布,该组数据标签为0,共计 100个数据;
类别1的数据维度为2,其在各个维度上服从均值为-2,方差为1的正态分布,该组数据标签为1,共计 100个数据。
n_data = torch.ones(100, 2)
x0 = torch.normal(2*n_data, 1) # class0 x data (tensor), shape=(100, 2)
y0 = torch.zeros(100) # class0 y data (tensor), shape=(100, 2)
x1 = torch.normal(-2*n_data, 1) # class1 x data (tensor), shape=(100, 2)
y1 = torch.ones(100) # class1 y data (tensor), shape=(100, 2)
x = torch.cat((x0, x1), 0).float() # FloatTensor
y = torch.cat((y0, y1), 0).long() # LongTensor
然后我们将两组数据拼接起来,作为全部的训练数据集。
其可视化展示如下。
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy())
plt.savefig("./img/03_data.png")
plt.show()
首先,第一种方式是上一篇笔记记录的使用自定义一个类,来完成网络的搭建方式,代码如下:
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
# 分别表示feature个数、隐藏层神经元数个数、输出值数目
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
self.predict = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
# x 是输入数据
x = F.relu(self.hidden(x))
x = self.predict(x)
y = F.softmax(x, dim=1)
return y
主要还是继承torch.nn.Module来书写自己的神经网络。在继承该类时,必须重新实现__init__构造函数和forward这两个方法。
网络搭建完成后,我们可以打印输出一下这个网络的基本结构
net = Net(2, 10, 2) # 输入为整个Batch的训练数据,每条数据为2个特征,xy坐标,输出为一个长度为200*2向量,其中每个[0, 1]表示输出为1,[1, 0]表示输出为0
print(net)
得到输出如下
Net(
(hidden): Linear(in_features=2, out_features=10, bias=True)
(predict): Linear(in_features=10, out_features=2, bias=True)
)
网络搭建完成后,我们可以打印输出一下这个网络的基本结构
net = Net(2, 10, 2) # 输入为整个Batch的训练数据,每条数据为2个特征,xy坐标,输出为一个长度为200*2向量,其中每个[0, 1]表示输出为1,[1, 0]表示输出为0
print(net)
得到输出如下
Net(
(hidden): Linear(in_features=2, out_features=10, bias=True)
(predict): Linear(in_features=10, out_features=2, bias=True)
)
本次,我们学习使用nn.Sequential模块来快速搭建一个相同结构的神经网络。
net2 = torch.nn.Sequential(
torch.nn.Linear(2, 10),
torch.nn.ReLU(), # 这里是大写的ReLU是一个类,而之前那个F.relu只是一个功能
torch.nn.Linear(10, 2),
torch.nn.Softmax(dim=1)
)
print(net2)
打印显示的模型为
Sequential(
(0): Linear(in_features=2, out_features=10, bias=True)
(1): ReLU()
(2): Linear(in_features=10, out_features=2, bias=True)
(3): Softmax(dim=1)
)
这里所展示的模型结构与之前方式的有所不同,主要是将ReLU和Softmax模块作为了一层单独展示出来了,但其实它们的功能和架构是完全相同的。后续的剩余代码模块跟之前一模一样。使用nn.Sequential模块,我们可以快速搭建一个基础的神经网络模型,无需再重新自定义类。当然,这样做的代价就是失去了部分灵活性,不能自己去定制 forward 函数里面的内容。
一般来说,我们使用 nn.Sequential 的来组成网络块 (block),然后像拼积木一样把不同的 block 拼成整个网络,让代码更简洁,更加结构化。同时,nn.Sequential里面的模块按照顺序进行排列的,所以必须确保前一个模块的输出大小和下一个模块的输入大小保持一致。
接下来我们设置网络的优化器和损失函数。
优化方法设置为随机梯度下降法,学习率设置为0.05。
一般分类问题使用交叉熵损失函数。
optimizer = torch.optim.SGD(net.parameters(), lr=0.05)
loss_func = torch.nn.CrossEntropyLoss() # 分类问题一般用CrossEntropy的loss
最后,我们展示输出并可视化中间过程。
plt.ion() for step in range(20): out = net(x) # out是输出的激活值 loss = loss_func(out, y) optimizer.zero_grad() # 首先将所有参数的梯度降为0(因为每次计算梯度后这个值都会保留,不清零就会导致不正确) loss.backward() # 进行反向传递,计算出计算图中所有节点的梯度 optimizer.step() # 计算完成后,使用optimizer优化这些梯度 if step % 5 == 0: # plot and show learning process plt.cla() prediction = torch.max(out, 1)[1] # 这里是输出的结果 pred_y = prediction.data.numpy() target_y = y.data.numpy() plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=pred_y, s=100, lw=0, cmap='RdYlGn') accuracy = float((pred_y == target_y).astype(int).sum()) / float(target_y.size) plt.text(1.5, -4, 'Accuracy=%.2f' % accuracy, fontdict={'size': 20, 'color': 'red'}) plt.pause(0.1) plt.ioff() plt.show()
可以看到随着训练的进行,loss逐渐降低,模型预测的效果越来越好。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。