Pytorch学习笔记:API调用

Pytorch学习笔记:API调用

  • 1.相关概念
    • 1.1epoch,batch size,iteration
  • 2.torchvision.transforms
  • 3.torch.utils.data.DataLoader
  • 4.数据集预览
    • 4.1 iter,next
    • 4.2 反归一化
    • 4.3 批次可视化
  • 5.网络模型
  • 6.训练网络
    • 6.1设置损失函数与优化器
    • 6.2训练模型
    • 6.3模型存取
  • 7.补充说明
    • 7.1 PIL库
    • 7.2 torch.unsqueeze
    • 7.3 torch.squeeze
    • 7.4 torch.flatten
    • 7.5 datasets.ImageFolder


1.相关概念

1.1epoch,batch size,iteration

epoch:1个epoch等于使用训练集中的全部样本训练一次,通俗的讲epoch的值就是整个数据集被轮几次。

batchsize:批大小,因为数据集太庞大,求所有样本的全局损失函数需要巨大的内存,故在深度学习中采用批训练,即每次梯度更新仅在训练集中取batchsize个样本综合;

iteration:1个iteration等于使用batchsize个样本(一个batch)训练一次;

换算公式:批数量 = 样本总数/批大小,向上取整。

举例:50000张训练图片的数据集CIFAR10,取batchsize = 256
batch数 = 50000/256=196
每个epoch需要完成196个batch(196个iteration)
每个epoch权重更新196次

2.torchvision.transforms

用于数据预处理。

import torchvision.transforms as transforms
    transform = transforms.Compose(
        [transforms.Resize((32, 32)),
        transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

上述实现的功能为:
1.图像缩放为32*32的尺寸。
2.将数据类型转换为Tensor格式,Tensor的数据存储顺序为[C,H,W],其中C为channel数,如RGB图像通道数为3。H与W分别是图像的长宽,当用四个参数时第一个参数为图像的张数。PIL的数据存储顺序为[H,W,C]。并且原始图片的像素值在0-255,转换后像素范围变为0-1。
3.对于每个channel,每个像素二维矩阵的像素值减去0.5,再除0.5。实现标准化。

input[channel] = (input[channel]-mean[channel])/std[channel]

3.torch.utils.data.DataLoader

输入总数据集(包括了标签),批大小,是否打乱(通常会打乱训练集顺序),载入数据集线程数(非Linux系统通常为0),制作批数据集。

import torch
train_loader = torch.utils.data.DataLoader(train_set, batch_size=36,shuffle=True, num_workers=0)

4.数据集预览

4.1 iter,next

val_loader与3中的train_loader一样,是划分好的测试集。通过iter迭代器,并以next对每个batch逐步进行访问。

    val_data_iter = iter(val_loader)
    val_image, val_label = val_data_iter.next()

如第一次运行第二行代码获取第一个batch的图像像素与标签,第二次运动获取下一个batch,以此类推。

4.2 反归一化

先要对像素点进行反归一化,但是Tensor不可直接用于画图,取numpy数据后才能可视化,在取numpy后用np.transpose对通道的次序进行调整:[C,H,W]->[H,W,C]
故原来索引1的分量放到索引0,原来索引2的分量放到索引1,原来索引0的分量放到索引2。

    def imshow(img):
        img = img/2+0.5 #去归一化
        npimg = img.numpy()
        plt.imshow(np.transpose(npimg,(1,2,0)))
        plt.show()

4.3 批次可视化

imshow(torchvision.utils.make_grid(val_image))

其中val_image为某个batch的图像像素。

5.网络模型

书写格式如下,需要搭建前向传播函数

import torch.nn as nn
import torch.nn.functional as F


class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(32*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = F.relu(self.conv1(x))    # input(3, 32, 32) output(16, 28, 28)
        x = self.pool1(x)            # output(16, 14, 14)
        x = F.relu(self.conv2(x))    # output(32, 10, 10)
        x = self.pool2(x)            # output(32, 5, 5)
        x = x.view(-1, 32*5*5)       # output(32*5*5)
        x = F.relu(self.fc1(x))      # output(120)
        x = F.relu(self.fc2(x))      # output(84)
        x = self.fc3(x)              # output(10)
        return x

6.训练网络

6.1设置损失函数与优化器

import torch.optim as optim
import torch.nn as nn
from model import LeNet#从moldel.py文件导入模型
net = LeNet()
loss_function = nn.CrossEntropyLoss()#交叉熵损失函数
optimizer = optim.Adam(net.parameters(), lr=0.001)

交叉熵中包含了softmax,只需要将模型输出标签与真实标签直接填入即可,如6.2所述。

6.2训练模型

最外层循环为epoch,然后对每个epoch中的batch进行训练并更新梯度。

for step, data in enumerate(train_loader, start=0):
    inputs, labels = data

start表示该epoch中第一个batch的序号是0,从0开始累加。
梯度更新

optimizer.zero_grad()#梯度清0
outputs = net(inputs)
loss = loss_function(outputs, labels)#计算损失函数
loss.backward()#反向传播
optimizer.step()#优化器更新

首先要进行当前的梯度清零,然后计算损失函数,并进行反向传播。计算每个batch的损失函数之和时需要取loss.item(),loss的数据类型是Variable,若不取item值动态图会延伸导致显存爆炸。

6.3模型存取

模型储存

save_path = './Lenet.pth'
torch.save(net.state_dict(), save_path)

使用模型.state_dict()即可储存模型参数于对应路径,保存的文件为pth文件。
模型读取

net.load_state_dict(torch.load('Lenet.pth'))

使用模型.load_state_dict并填入相应的参数使用训练好的模型参数用于推理。

7.补充说明

7.1 PIL库

用于载入图片,仅需填入当前路径下的图片文件名称即可。

from PIL import Image
im = Image.open('1.png')#读取图片并转换为Tensor格式用于推理
im.show()#图片可视化

7.2 torch.unsqueeze

用于扩充维度。

x = torch.Tensor([[1, 2, 3, 4],
                  [5,6,7,8],
                 [9,10,11,12]])
torch.unsqueeze(x,0)#tensor([[[ 1.,  2.,  3.,  4.],
         #[ 5.,  6.,  7.,  8.],
         #[ 9., 10., 11., 12.]]])
torch.unsqueeze(x,0).size()#torch.Size([1, 3, 4])
torch.unsqueeze(x,1)#tensor([[[ 1.,  2.,  3.,  4.]],
        #[[ 5.,  6.,  7.,  8.]],
        #[[ 9., 10., 11., 12.]]])
torch.unsqueeze(x,1).size()#torch.Size([3, 1, 4])
torch.unsqueeze(x,2)"""tensor([[[ 1.],
         [ 2.],
         [ 3.],
         [ 4.]],
         
        [[ 5.],
         [ 6.],
         [ 7.],
         [ 8.]],

        [[ 9.],
         [10.],
         [11.],
         [12.]]])"""
torch.unsqueeze(x,2).size()#torch.Size([3, 4, 1])

原矩阵为3×4矩阵。
在维度0进行扩张,每个3维张量包含1个3×4矩阵;在维度1进行扩招,每个3维向量包含3个1×4矩阵;在维度2进行扩张,每个3维向量包含3个4×1矩阵。

7.3 torch.squeeze

对维度进行压缩。

x = torch.zeros(3,2,4,1,2,1)
y = torch.squeeze(x,dim=0)#因为第0维的长度不为1,故此操作无效
y = torch.squeeze(x,dim=3)#因为第3维的长度为1,故此操作有效
#返回的尺寸为[3,2,4,2,1]
y = torch.squeeze(x)#去除全部长度为1的维度
#返回的尺寸为[3,2,4,2[

7.4 torch.flatten

向量拉直。因为Tensor是以[S,C,H,W]格式储存的,S为图像的输入图像的数量(第0维),所以从第1维开始对每张图像的输出拉直成一维向量。

x = torch.flatten(x, start_dim=1)

7.5 datasets.ImageFolder

包含在torchvision库中。调用该API时需要先将数据集按照文件夹进行分类,每个文件夹包含不同类别的图像。
数据格式如下,其中root为根目录,dog/cat等均为根目录下不同类别图像的文件夹。

root/dog/xxx.png
root/dog/xxy.png
root/dog/xxz.png

root/cat/123.png
root/cat/nsdf3.png
root/cat/asd932_.png

.jpg格式也可。
根据目录路径对训练集进行加载,并进行数据预处理。

from torchvision import  datasets
train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),transform=data_transform["train"])

加载好的数据通过train_dataset.class_to_idx获取其类别的字典,格式为:{‘daisy’:0, ‘dandelion’:1, ‘roses’:2, ‘sunflower’:3, ‘tulips’:4}
字典的键为不同类别图像文件夹的名称。

之后再调用torch.utils.data.DataLoader进行batch的划分即可。

你可能感兴趣的:(pytorch,pytorch)