pytorch

pytorch

学习方法

  1. 边用边学,边用边学,在用中学习
  2. 直接上案例,先做,遇到问题解决

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的大小
img

x[0]看到x的具体值
img

784是mnist数据集每个样本的像素点个数

from matplotlib import pyplot
import numpy as np

pyplot.imshow(x_train[0].reshape((28, 28)), cmap="gray")
print(x_train.shape)

img

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

img

注意数据需转换成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是像素点的个数

img

所有的array都变成了Tensor格式
img

完成了转换,变成了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就是权重这个也是随机生成的

img

x就是每个都是一个784个像素的矩阵,总共有64个所以是64*784

因为我们最终需要的是看他是0-9这几个字母里面的哪一个,所以输出的就是这10个结果

所以w是[784,10]和x进行矩阵相乘才是10

img

生成的就是一个随机的tensor

img

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

img

img

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

img

img

b就是bias偏置

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

img

函数的参数是一个预测值一个是标签

构建网络

全连接

我们这次用的就是FC=wx+b

我们每层都是FC

img

输出的个数取决于我们的问题,这问题是10个

这次只有1层,w就是[728,10]

2层就可以是:

w1:[728,256]

w2:[256,10]

3层也可以是:

w1:[728,256]

w2:[256,128]

w3:[128,10]

想要每层多少,可以自己决定

我们进行完神经网络的2提取特征后,我们就可以求出每一种对应的概率

img

创建一个model来更简化代码

  • 必须继承nn.Module且在其构造函数中需调用nn.Module的构造函数
    img

  • 无需写反向传播函数,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
        

img

构造函数里面提前想好我们等下要用到的东西

hidden1 就是728变成128的的那层,

hidden2 就是128变256的256,因为输入是1的输出所以是128

就是中间夹的那些层

输出就是256变成10 最后10个

我们要提前配置dropout防止过拟合
0.5是比例

self.Drop=nn.Dropout(0.5)

img

x就是样本
img
64是batch(样本数)

784是每个的个数(特征)

img

输入64[784],第一次FC后是64784·[784,128]这样就是64*[128]

以此类推,就得到了10个特征值,然后就可得到概率

并且每次都是要做dropout

img

自动定义了权重参数

可以打印我们定义好名字里的权重和偏置项

for name, parameter in net.named_parameters():
    print(name, parameter,parameter.size())

img

数据源定义方法

使用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)

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

img

定义一次包的大小

img

洗牌,开始时把数据打乱

训练的时候要打乱顺序

验证的时候不用打乱

  • 一般在训练模型时加上model.train(),这样会正常使用Batch Normalization和 Dropout

  • 测试的时候一般选择model.eval(),这样就不会使用Batch Normalization和 Dropout

img

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 优化

img

分类器

训练模型要每一次都要更新模型的w和b
img

验证不用更新
img

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

损失与训练模块分析

from torch import optim
def get_model():
    model = Mnist_NN()# 把刚刚构建的模型实例化为一个model
    return model, optim.SGD(model.parameters(), lr=0.001)

梯度
img

lr

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

img

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

img

开始更新

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

一个大循环是一个epoch
img

因为里面有一个小循环

1epoch=100item(迭代)
1item=100batch

1epoch=10000batch

img

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

进行打分

img

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

zip用法

img

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

img
一一对应

img

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

平均损失:
img

img

dataloader 方便我们去生成数据

img

train_ds 训练数据

valid 就是验证数据

bs batchsite 越大越好,但应机器决定

img

迭代器:
20 设置迭代次数 越大越好

模型

损失函数

两个数据集

img

每次的训练都是在损失值下降

计算准确率

img

img

看outputs是什么

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

img

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

img

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

img
img

img

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

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

img

看对了多少个

img

.item()就转换成了数组形式,就可以进行matploit,...进行绘图

多去拆解看变量值

img

SGD Adam

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

posted @ 2023-01-28 22:10  E_sheep  阅读(22)  评论(0)    收藏  举报