本节课主要将两件事情:
1. Pytorch 搭建分类神经网络
2. 神经网络基本架构
---
0 项目准备:
这里先下载数据,这里主要是下载手写 mnist 数据集;
这个数据集是打过标签的手写数字,并且以 pickle 形式存储。
# 新建一个 path 文件夹,用以存储数据
import os
path = 'data/mnist/'
os.makedirs(path, exist_ok=True)
# 通过 url 下载数据集到本地相对位置的文件夹下
URL='http://deeplearning.net/data/mnist/'
FILENAME='mnist.pkl.gz'
urlretrieve(URL+FILENAME, 'data/mnist/'+FILENAME)
# 读入相关数据
((x, y), (x_valid, y_valid), _) = pickle.load(gzip.open(path+FILENAME, 'rb'), encoding='latin-1')
读入数据之后,先了解一下数据。
type(x), x.shape, type(y), y.shape
---
(numpy.ndarray, (50000, 784), numpy.ndarray, (50000,))
训练集 x 是 50000 个图像,每个图像都是 784 个像素点,也就是 28*28 的图形,成 1d 排列。
训练集的标签 y 就是 50000 的标签,分别为 0-9 的 9 个数字。
# 显示单个图
def show(img, title=None):
plt.imshow(img, cmap="gray")
if title is not None: plt.title(title)
# 显示多组图,分两行显示
def plots(ims, figsize=(12,6), rows=2, titles=None):
f = plt.figure(figsize=figsize)
cols = len(ims)//rows
for i in range(len(ims)):
sp = f.add_subplot(rows, cols, i+1)
sp.axis('Off')
if titles is not None:
sp.set_title(titles[i], fontsize=16)
plt.imshow(ims[i], cmap='gray')
输出看一下结果:
show(x_imgs[0], y_valid[0])
nums = 20
plots(x_imgs[:nums], titles=y_valid[:nums])
1 Pytorch 神经网络
网络的搭建分别几步,复杂的结构都是在网络的基础上调整。
- 网络结构
- 参数设置
- 训练期间确认参数合理
1.1 网络结构
一般神经网络就是:
(一层网络 + 一层激活层)* n + 输出层
- 激活层:ReLU 或者 LeakyReLU
- 输出层:softmax 多个类别中识别一个结果
sigmoid 可以识别多个结果
由于网络层都是线性相连,所以从理论上来说,需要激活层(也叫非线性层),来进行转化,不然无法达到非线性模拟的效果。
# torch 的封装式实现
import torch.nn as nn
net = nn.Sequential( nn.Linear(28*28, 100),
nn.ReLU(),
nn.Linear(100, 100),
nn.ReLU(),
nn.Linear(100, 10),
nn.LogSoftmax())
1.2 参数设置
参数设置的时候,我们需要知道:
- epoch:训练的次数
- crit:误差函数
- opt:优化函数
- metrics:评价函数
在这里,epoch 可以设置成 10 以下的值,先做测试。
crit 此处由于是多类别的分类,因此我们选择 binary loss,也就是 NLLLoss() 。
opt 可以直接调用 porch 的内部设置,SGD 或者 ADAM 都可以。
metrics 就是我们关心的正确情况,在这里是 判断正确的个数比重。这个部分我们可以自己写。
loss = nn.NLLLoss()
preds = net(x)
metrics = np.mean(preds == y_valid)
opt = optim.SGD(net.parameters(), 1e-1, momentum=0.9, weight_decay=1e-3)
1.3 确认参数合理
在这个部分我们就需要在训练的时候不断输出合适的模型参数,用以追踪所有的评价情况指标。
因此我们在写自己的 epoch 循环的时候,我们需要输出我们需要检测的 metrics。
if epoch % 10 == 0:
print("loss: ", l.data[0], "\t accuracy: ", metric)
1.4 模型实现
import torch.nn as nn
# 建立模型
net = nn.Sequential( nn.Linear(28*28, 100), nn.ReLU(), nn.Linear(100, 100), nn.ReLU(), nn.Linear(100, 10), nn.LogSoftmax() )
loss = nn.NLLLoss()
epoch = 100
opt = optim.SGD(net.parameters(), 1e-1, momentum=0.9, weight_decay=1e-3)
for n in epoch:
# 输出output
pred = net(x)
# 计算误差
l = loss(pred, y_val)
# 原始优化清零
opt.zero_grad()
# 误差梯度计算
l.backward()
# 误差更新权重
opt.step()
# 每 10 步,输出一个结果来检测
if n%10 == 0:
print('accuracy', np.mean(pred == y_val))