您的位置:首页 > 理论基础 > 计算机网络

pytorch入门_深层神经网络_mnist例子

2019-07-18 17:38 330 查看

知识点
1、如何把ndarray显示为灰度图
2、数据矩阵reshape为一行
3、把多个数据捆绑为batch,以便加快训练速度
4、反向传播流程
5、tensor.item()
6、tensor.max(1)
7、pred == label 统计预测与标签的正确数
8、统计正确率的注意点
9、str.format()
10、便捷loss变化图

import numpy as np
import torch
from torchvision.datasets import mnist
from torch import nn
from torch.autograd import Variable
import matplotlib.pyplot as plt

导入数据
下载速度很慢

train_set = mnist.MNIST('./data', train=True, download=True)
test_test = mnist.MNIST('./data', train=False, download=True)

知识点1
读入的数据是PIL库中的格式,可以用 a = np.array(b) 的形式方便转化为ndarray
用plt显示出来,直接print只会显示矩阵

a_data, a_label = train_set[0]
np_im = np.array(a_data)
plt.imshow(np_im, cmap='gray')
plt.show()

知识点2
为了方便训练,data_tf 把图像转化为ndarray,然后28 x 28的数据reshape为784 x 1的格式,再转化为tensor
重新导入数据,而不是在上面的数据上操作,因为这样可以直接调用方法,更方便,不需要自己写

def data_tf(x):
x = np.array(x, dtype='float32') / 255
x = (x - 0.5) / 0.5
x = x.reshape((-1,))
x = torch.from_numpy(x)
return x

train_set = mnist.MNIST('./data', train=True, transform=data_tf, download=True)
test_set = mnist.MNIST('./data', train=False, transform=data_tf, download=True)

a, a_label = train_set[0]
print(a.shape)
print(a_label)

知识点3(重点)

deep learning 的基操,一定要掌握
由于图片量太大了,一张一张输入网络效率很低,所以下面的操作把每64张图片(训练集)捆绑在一起。这样的好处就是网络一次处理64张图像,效率会高很多。

from torch.utils.data import DataLoader
train_data = DataLoader(train_set, batch_size=64, shuffle=True)
test_data = DataLoader(test_set, batch_size=128, shuffle=False)
a, a_label = next(iter(train_data))
print(a.shape)
print(a_label.shape)

各种初始化

# 定义网络结构
net = nn.Sequential(
nn.Linear(784, 400),
nn.ReLU(),
nn.Linear(400, 200),
nn.ReLU(),
nn.Linear(200, 100),
nn.ReLU(),
nn.Linear(100, 10)
)
# 定义损失函数(交叉熵)
criterion = nn.CrossEntropyLoss()
# 定义优化器(随机梯度下降) 优化器需要指明要优化的参数,和学习率
optimizer = torch.optim.SGD(net.parameters(), 1e-1)
# 定义各种数据,为后面统计结果做准备
losses = []
acces = []
eval_losses = []
eval_acces = []

前方高能

反向传播20次
疑问: net.train() 有没有必要
知识点4
反向转播的标准步骤:
1、把X,y转化为Variable
2、网络计算数据的结果out
3、计算loss
4、归零w、b梯度
5、反向传播
6、修改w、b梯度
知识点5
tensor.item() 把一个只含有1个值的tensor转化为python number
知识点6
_, pred = out.max(1) 这句真的是骚操作
_这个东西就是一个变量,别想复杂了
out是一个64 x 10的tensor
返回的结果就是
_是out tensor每行的最大值组成的tensor 64 x 1
pre是out tensor每行最大值索引组成的tensor 64 x 1
max(1)这里是把输出压缩为1维,记住
知识点7
num_correct = (pred == label).sum().data.item()
这行代码比较好理解,是基操,要记住
知识点8
acc = num_correct / im.shape[0]
计算一张图片的准确率 注意:这里一定是除 im.shape[0] ,而不能偷懒直接除batch_size也就是64。因为一组batch的最后一个的size有可能不是batch_size 比如:有15张图片,batch_size设置为4,那么前面3个batch的size确实是4,但是最后一个batch的size只有3

for e in range(20):
train_loss = 0 #记录loss函数下降的过程
train_acc = 0
net.train()  # 把网络设置为train模式
for im, label in train_data:   # 基操反向传播的标准流程
im = Variable(im)
label = Variable(label)
out = net(im)
loss = criterion(out, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss += loss.data.item()
_,pred = out.max(1)
num_correct = (pred == label).sum().data.item()
acc = num_correct / im.shape[0]
train_acc += acc
losses.append(train_loss / len(train_data))    # 记录每次传播的平均loss
acces.append(train_acc / len(train_data))      # 记录每次传播的平均准确率

注意下面这段代码前面有4个空格,也就是说它们是在上面的代码for e in range(20): 里面
预测就不需要反向传播了,这里计算loss只是为了看模型的效果
知识点9
str.fromat() 会把()里面的值对应输入到{}中
{:.6}表示保留6位小数

eval_loss = 0
eval_acc = 0
net.eval()   # 网络切换为预测模式
for im, label in test_data:
im = Variable(im)
label = Variable(label)
out = net(im)
loss = criterion(out, label)
eval_loss += loss.data.item()
_, pred = out.max(1)
num_correct = (pred == label).sum().data.item()
acc = num_correct / im.shape[0]
eval_acc += acc

eval_losses.append(eval_loss / len(test_data))
eval_acces.append(eval_acc / len(test_data))
print('epoch:{}, Train Loss:{:.6f}, Train Acc: {:.6f}, Eval Loss:{:.6f}, Eval Acc: {:.6f}'
.format(e, train_loss / len(train_data), train_acc / len(train_data), eval_loss / len(test_data),
eval_acc / len(test_data)))

知识点10
绘图,基操记住
plt.plot(np.arange(losses), losses) 可以很方便的画出loss的变化

import matplotlib.pyplot as plt
plt.title('train loss')
plt.plot(np.arange(len(losses)), losses)
plt.show()
plt.plot(np.arange(len(acces)), acces)
plt.title('train acc')
plt.show()
plt.plot(np.arange(len(eval_losses)), eval_losses)
plt.title('test loss')
plt.show()
plt.plot(np.arange(len(eval_acces)), eval_acces)
plt.title('test acc')
plt.show()

总结流程
1、导入数据并把数据矩阵拉直
2、把数据捆绑为batch
3、定义网络,实例化 损失函数、优化器
4、训练并反向传播(V, out, loss, zero, back, step), 统计数据
5、预测(V, out),统计数据
6、绘图
打完收工,爽!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: