pytorch
pytorch
学习方法
- 边用边学,边用边学,在用中学习
- 直接上案例,先做,遇到问题解决
Mnist分类任务
-
网络基本构建与训练方法,常用函数解析
-
torch.nn.functional模块
-
nn.Module模块
验证pytorch
import torch
print(torch.__version__)
读取mnist数据集
%matplotlib inline
from pathlib import Path
import requests
DATA_PATH = Path("data")
PATH = DATA_PATH / "mnist"
PATH.mkdir(parents=True, exist_ok=True)
URL = "http://deeplearning.net/data/mnist/"
FILENAME = "mnist.pkl.gz"
if not (PATH / FILENAME).exists():
content = requests.get(URL + FILENAME).content
(PATH / FILENAME).open("wb").write(content)
下载数据
以后不会出现这样的下载方式
import pickle
import gzip
with gzip.open((PATH / FILENAME).as_posix(), "rb") as f:
((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")
对下载好的数据进行解析
x的大小

x[0]看到x的具体值

784是mnist数据集每个样本的像素点个数
from matplotlib import pyplot
import numpy as np
pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)

因为刚刚那个数组是一维的,但是我们的图像是二维的所以我们需要把它reshape成二维的图像,然后打印出具体的图象

注意数据需转换成tensor才能参与后续建模训练
import torch
x_train, y_train, x_valid, y_valid = map(
torch.tensor, (x_train, y_train, x_valid, y_valid)
)
n, c = x_train.shape
x_train, x_train.shape, y_train.min(), y_train.max()
print(x_train, y_train)
print(x_train.shape)
print(y_train.min(), y_train.max())
通过map映射成一个Tensor的一个格式
n是样本的个数
c是像素点的个数

所有的array都变成了Tensor格式

完成了转换,变成了torch可以用的形式
损失函数
torch.nn.functional 很多层和函数在这里都会见到
就是用来做测试的
import torch.nn.functional as F
loss_func = F.cross_entropy
def model(xb):
return xb.mm(weights) + bias
mm就是矩阵乘法
就是wx+b
bs = 64
xb = x_train[0:bs] # a mini-batch from x
yb = y_train[0:bs]
weights = torch.randn([784, 10], dtype = torch.float, requires_grad = True)
bs = 64
bias = torch.zeros(10, requires_grad=True)
print(loss_func(model(xb), yb))
bs就是我这一次样本个数
一般来说是越大越好,毕竟样本越全面结果就越好
xb也是取我前64个样本
w就是权重这个也是随机生成的

x就是每个都是一个784个像素的矩阵,总共有64个所以是64*784
因为我们最终需要的是看他是0-9这几个字母里面的哪一个,所以输出的就是这10个结果
所以w是[784,10]和x进行矩阵相乘才是10

生成的就是一个随机的tensor

并且是有梯度的,因为我们是第一次训练肯定是有梯度的


可见每次的结果都是不一样的


b就是bias偏置
我们一般设置为一个常数
b对于结果的影响是十分小的

函数的参数是一个预测值一个是标签
构建网络
全连接
我们这次用的就是FC=wx+b
我们每层都是FC

输出的个数取决于我们的问题,这问题是10个
这次只有1层,w就是[728,10]
2层就可以是:
w1:[728,256]
w2:[256,10]
3层也可以是:
w1:[728,256]
w2:[256,128]
w3:[128,10]
想要每层多少,可以自己决定
我们进行完神经网络的2提取特征后,我们就可以求出每一种对应的概率

创建一个model来更简化代码
-
必须继承nn.Module且在其构造函数中需调用nn.Module的构造函数

-
无需写反向传播函数,nn.Module能够利用autograd自动实现反向传播
-
Module中的可学习参数可以通过named_parameters()或者parameters()返回迭代器
from torch import nn
class Mnist_NN(nn.Module):
def __init__(self):
super().__init__()
self.hidden1 = nn.Linear(784, 128)
self.hidden2 = nn.Linear(128, 256)
self.out = nn.Linear(256, 10)
self.Drop=nn.Dropout(0.5)
def forward(self, x):
x = F.relu(self.hidden1(x))
x = F.relu(self.hidden2(x))
x = self.out(x)
return x

构造函数里面提前想好我们等下要用到的东西
hidden1 就是728变成128的的那层,
hidden2 就是128变256的256,因为输入是1的输出所以是128
就是中间夹的那些层
输出就是256变成10 最后10个
我们要提前配置dropout防止过拟合
0.5是比例
self.Drop=nn.Dropout(0.5)

x就是样本

64是batch(样本数)
784是每个的个数(特征)

输入64[784],第一次FC后是64784·[784,128]这样就是64*[128]
以此类推,就得到了10个特征值,然后就可得到概率
并且每次都是要做dropout

自动定义了权重参数
可以打印我们定义好名字里的权重和偏置项
for name, parameter in net.named_parameters():
print(name, parameter,parameter.size())

数据源定义方法
使用TensorDataset和DataLoader来简化
我们第一次先用简单的来进行实验
from torch.utils.data import TensorDataset
#这个不常用
from torch.utils.data import DataLoader
#这个比较重要会单独讲解
train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)
valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs * 2)
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)
valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs * 2)

dataloader就是把数据一个个的打包,把打好的包交给GPU

定义一次包的大小

洗牌,开始时把数据打乱
训练的时候要打乱顺序
验证的时候不用打乱
-
一般在训练模型时加上model.train(),这样会正常使用Batch Normalization和 Dropout
-
测试的时候一般选择model.eval(),这样就不会使用Batch Normalization和 Dropout

import numpy as np
def fit(steps, model, loss_func, opt, train_dl, valid_dl):
for step in range(steps):
model.train()
for xb, yb in train_dl:
loss_batch(model, loss_func, xb, yb, opt)
model.eval()
with torch.no_grad():
losses, nums = zip(
*[loss_batch(model, loss_func, xb, yb) for xb, yb in valid_dl]
)
val_loss = np.sum(np.multiply(losses, nums)) / np.sum(nums)
print('当前step:'+str(step), '验证集损失:'+str(val_loss))
step 就是一次的步长
model 模型
loss_func 就是F_cross
opt 优化

分类器
训练模型要每一次都要更新模型的w和b

验证不用更新

我们不知道里面的东西是什么时,我们可以,把其中的每一个值都打印出来

损失与训练模块分析
from torch import optim
def get_model():
model = Mnist_NN()# 把刚刚构建的模型实例化为一个model
return model, optim.SGD(model.parameters(), lr=0.001)
梯度

lr
就是学习率,开始时小一点

如果有优化器,先先进行反向传播,每一层权重参数就算出来了

开始更新
pytorch有个特性就是下一更新的值会和上一次的值进行累加,因为我们两次的值是没有关系得所以每次结束都要清零

一个大循环是一个epoch

因为里面有一个小循环
1epoch=100item(迭代)
1item=100batch
1epoch=10000batch

当第一个训练完成之后,就要进行第一个验证
进行打分

返回一个损失值和序号
并且是打包的
zip用法

一个个配对
1,4 2,5 3,6

一一对应

两次zip就可以进行解包,我们就可以得到原先对应的值

'*'就是解包
平均损失:


dataloader 方便我们去生成数据

train_ds 训练数据
valid 就是验证数据
bs batchsite 越大越好,但应机器决定

迭代器:
20 设置迭代次数 越大越好
模型
损失函数
两个数据集

每次的训练都是在损失值下降
计算准确率


看outputs是什么
10个样本有10个概率值,看10个里面那个最大,所以看谁靠近1

_就是一个占位符,因为这个返回值必须有两个

这是得到这一组数据的最大的值



128最大值和他的索引,我们要的是索引

这个==就是看和预测值一不一样

看对了多少个

.item()就转换成了数组形式,就可以进行matploit,...进行绘图
多去拆解看变量值

SGD Adam
不同的优化器速度不一样,而且一上来结果就更好


浙公网安备 33010602011771号