pytorch 入门教程 学习笔记整理【附代码】

pytorch 入门教程_学习笔记整理[附代码]

文章目录

  • pytorch 入门教程_学习笔记整理[附代码]
    • 前言
    • 1.pytorch介绍
      • 1.1torch
      • 1.2torchvision
      • 1.3torchaudio
      • 1.4 torchtest
    • 2.“数据”相关操作
      • 2.1数据集datasets
      • 2.2数据导入 dataload
      • 2.3数据变换transform
    • 3 神经网络
      • 3.1神经网络的类型
      • 3.2 损失函数
      • 3.3 优化器 torch.optim
      • 3.4 网络模型的保存和读取
      • 3.5 完整的模型训练套路

前言

通过在B站上观看一些关于Pytorch的初级教学视频,自己对此强大工具大致有了一个入门级的了解,将一些重要,或者说之后编程经常需要用到的一些知识进行了归纳整理,就当是对所学知识的一个回顾整理啦。

1.pytorch介绍

pytorch是一个开源的机器学习框架,包含了大量针对深度学习的张量库,其中主要的“子库”/程序包有:

1.1torch

torch 包含了针对多维张量的数据结构以及和与张量相关的数学运算;此外,它还提供了较多实用工具(torch.utils)

1.2torchvision

是一个专门针对**计算机视觉(图像、视频相关)**的库,其包含了计算机视觉领域中的:

(1)常用的数据集datasets,eg:cifar10

(2)常见的模型架构,eg:vgg16

(3)常用的图像处理变化操作(transforms)

1.3torchaudio

是一个专门针对**音频方面**的库,其包含了音频领域中的:

(1)音频输入输出控制

(2)常用的音频数据集

(3)常用的音频转换操作(transforms)

1.4 torchtest

是一个专门针对**自然语言处理(NLP)领域**的库,其包含了NLP领域中的:

(1)常见的文本数据处理工具

(2)常用的文本数据集

2.“数据”相关操作

2.1数据集datasets

如上文介绍pytorch主要package中的那样,pytorch中针对不同的应用领域,提供了不同类型的常见的数据集。

以cv领域为例,可使用如下语句导入CIFAR10数据集:

import torchvision
# 数据集的下载
data_train = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
data_test = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)

注:(1)参数train=True/False表示要得到训练数据集/测试数据集

​ (2)参数transform表示需要对数据集进行那些统一的变换,这里是将原始PIL类型图片数据转换成张量类型

​ (3)参数download可以一直设置为True,因为如果已经下载好时,程序会检测到,进而不会再重复下载

2.2数据导入 dataload

2.1提到的dataset只是得到数据集,而若要将这些数据集送入神经网络进行训练和验证,还需经过dataload这一步,其主要用来定义如下参数:

(1)batch_size:规定一次送入神经网的数据规模,此参数直接决定了神经网路输入层的规模(通道数);

另外,值得一提的是,对于一个图片数据,其维度一般是3维(h,w,c),但是,引入这个batch_size参数之后,其维度会变成四维,因而,如果一个网络的batch_size为1,并且想把一张图片输入到这个网络中时,需要先把其reshape成4维地张量:

import torch
# 假定原始图片数据的维度为(32,32,3),用张量img来保存

img = torch.reshape(img,(1,32,32,3))

(2)shuffle:表示是否进行乱序处理

结合数据导入的代码,对数据进行load的代码如下:

import torchvision
import torch
# 数据集的下载
data_train = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
data_test = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# 数据集的导入
train_load = DataLoader(data_train, batch_size=64)
test_load = DataLoader(data_test, batch_size=64)

在后续进行相关操作时,需要对load后的数据进行循环遍历操作:

# 法1
for data in train_load:
    imgs, targets = data
    pass
# 法2
for imgs, targets in train_load:
    pass
# 以上两种方法本质上是一样的,法1遍历的对象data是一个元组(包括了imgs,targets这两项)

2.3数据变换transform

由于不同领域存在不同的数据处理方式,因而不同领域的变换处理操作包含在不同的package下,以cv领域为例,其变化工具为torchvision.transforms,下面对此transforms进行介绍

(1) transforms包含的工具

使用如下程序,输出transforms包含的工具

import torchvision
function_list = dir(torchvision.transforms)
print(function_list)

得到如下结果

['AutoAugment', 'AutoAugmentPolicy', 'CenterCrop', 'ColorJitter', 'Compose', 'ConvertImageDtype', 'FiveCrop', 'GaussianBlur', 'Grayscale', 'InterpolationMode', 'Lambda', 'LinearTransformation', 'Normalize', 'PILToTensor', 'Pad', 'RandomAdjustSharpness', 'RandomAffine', 'RandomApply', 'RandomAutocontrast', 'RandomChoice', 'RandomCrop', 'RandomEqualize', 'RandomErasing', 'RandomGrayscale', 'RandomHorizontalFlip', 'RandomInvert', 'RandomOrder', 'RandomPerspective', 'RandomPosterize', 'RandomResizedCrop', 'RandomRotation', 'RandomSizedCrop', 'RandomSolarize', 'RandomVerticalFlip', 'Resize', 'Scale', 'TenCrop', 'ToPILImage', 'ToTensor', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'autoaugment', 'functional', 'functional_pil', 'functional_tensor', 'transforms']

可以看到,transforms包含的函数较多,但是好在函数的命名比较规范,大部分函数通过函数名称便可大概了解函数的功能,常用到的函数有

a. Totensor()

常用于将PIL类型的图片转换成tensor型

from torchvision import transforms
from PIL import Image

# 原始图片
img = Image.open("./dog.png")
print(img)

# Totensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
print(img_tensor.type)
print(img_tensor.shape)

运行结果如下:

<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=105x124 at 0x23AEBB10A58>
<built-in method type of Tensor object at 0x0000023AF3A33E58>
torch.Size([4, 124, 105])

注:对于png图片,其包含4个通道。除了(r,g,b)三个通道之外,还有一个透明通道

b.Normalize

具体参数如下:

Normalize(mean, std, inplace=False)

对于给定的张量型图片数据(仅支持tensor型数据,由此可见Totensor()函数的重要性)。指定每个通道的均值 (mean[1],...,mean[n]) 和标准差(std[1],..,std[n]) (假定有n个通道),此函数进行如下操作并输出:, output[channel] = (input[channel] - mean[channel]) / std[channel]

下面演示一个使得输出图片的均值为0的操作

from torchvision import transforms
from PIL import Image

# 原始图片
img = Image.open("./dog.png")
print(img)

# Totensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
# print(img_tensor.type)
# print(img_tensor.shape)

# Normalize
mean_list = [img_tensor[0].mean().item(), img_tensor[1].mean().item(), img_tensor[2].mean().item(), img_tensor[3].mean().item(),]
trans_nor = transforms.Normalize(mean_list,[0.1,0.1,0.1,0.1])
img_nor = trans_nor(img_tensor)
print(img_tensor[0].mean())
print(img_nor[0].mean())
print(img_nor[1].mean())

输出结果如下:

tensor(0.6909)
tensor(-6.7717e-08)
tensor(-6.8958e-07)
torch.Size([124, 105])

可以看到,变化后通道的均值可以认定为0.

c.Resize

具体参数如下:

Resize(size, interpolation=<InterpolationMode.BILINEAR: 'bilinear'>, max_size=None, antialias=None)

对于给定的张量型图片数据(支持tensor型数据和PIL类型数据),生成指定大小形状的图片(由参数size指定),当指定size小于原始图片的size时,函数会进行自动的缩放处理

下面演示一个将原始图片(124*105)分别 缩小成(100*100)放大到(200*200)两种情况

from torchvision import transforms
from PIL import Image

# 原始图片
img = Image.open("./dog.png")
print(img)

# Totensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
# print(img_tensor.type)
# print(img_tensor.shape)

# Resize
trans_resize0 = transforms.Resize((100,100))
trans_resize1 = transforms.Resize((200,200))
img_resize0 = trans_resize0(img_tensor)
img_resize1 = trans_resize1(img_tensor)
# ToPILimage,为了后续使用PIL输出图片,这里使用ToPILImage()函数
trans_toPIL = transforms.ToPILImage()
img0 = trans_toPIL(img_resize0)
img1 = trans_toPIL(img_resize1)
Image._show(img)
Image._show(img0)
Image._show(img1)

d.Compose

可以将图片要实现的多个变化用此Compose函数包在一起,这样便可通过这一个函数来实现多个变化

下面演示用此函数实现Totensor(),和Normalize()两种变化

from torchvision import transforms
from PIL import Image

# 原始图片
img = Image.open("./dog.png")
print(img)

# Compose
trans = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize([1,1,1,1],[1,1,1,1]),
    transforms.ToPILImage()
])
img_out = trans(img)
Image._show(img_out)

(2)transforms的使用流程:

根据上述几个函数的应用实例可知,transforms像是一个工具箱,其并不能直接拿来用,而是从其中抽出一个或多个工具之后,再用来对数据处理。

这样做的原因是,transforms包含的工具都是对象,因而在使用之前需要进行创建对象操作

3 神经网络

3.1神经网络的类型

(1)Containers

容器相关的模块,比较重要的两个模块介绍如下:

a. nn.Module

非常重要的类,是所有神经网络的基类,也即在定义个人的类时,都需要继承此类,基本形式如下:

class Mylayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        pass

b. nn.Sequential

线性神经网络容器,将要定义的网络依次放入此函数中,便可实现网络的搭建,举例如下:

model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

(2) Convolution Layers

神经网络中的卷积层,常见的类别如下:

卷积网络类型 功能描述
nn.Conv1d 进行1维卷积操作
nn.Conv2d 进行2维卷积操作
nn.Conv3d 进行3维卷积操作

(3) Pooling Layers

神经网络中的池化层,常见的类别如下:

卷积网络类型 功能描述
nn.MaxPool1d/AvgPool1d 进行1维最大/平均池化
nn.MaxPool2d/AvgPool2d 进行2维最大/平均池化
nn.MaxPool3d/AvgPool3d 进行3维最大/平均池化

(4) Non-linear Activations

神经网络中的非线性激活层,含有的种类非常多,仅列举最常见的类别如下:

卷积网络类型 功能描述
nn.Softmax 经Sof
nn.Relu 经Relu函数输出
nn.Sigmoid 经Sigmoid函数输出

(5) others

除了上述各个层之外,pytorch还包含了很多别的种类的网络层:

卷积网络类型 举例
Normalization Layers BatchNorm1d/2d/3d
Recurrent Layers RNN,LSTM,GRU
Transformer Layers Transformer,transformerEncoder,transformerDecoder
Linear Layers Linear、Bilinear
Dropout Layers Dropout、Dropout2d、Dropout3d

3.2 损失函数

根据模型输出结果真实值计算出损失值,常见的损失函数有:nn.L1Loss,nn.MSELoss,nn.CrossEntropyLoss

以交叉熵损失函数为例,其使用方法举例如下:

# 先定义损失函数
loss = nn.CrossEntropyLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
# 将输出结果和真实值传入 此定义好的损失函数
output = loss(input, target)
output.backward()

3.3 优化器 torch.optim

此package可用来实现 多种类型的优化算法

**(1) 使用方法 **

a.先定义一个优化器对象,

b.然后进行优化处理

当在训练过程中需要进行优化处理时,其步骤如下:

for input, target in dataset:
    optimizer.zero_grad()
    output = model(input)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()

在测试过程中,需要进行如下处理:

# 保证在测试过程中,已经训练好的模型的参数不会改变
with torch.no_grad():
    for data in test_load:
        pass

在得到训练好的模型后,对其进行测试时,需要进行如下处理操作:

# 保证在测试过程中,已经训练好的模型的参数不会改变
with torch.no_grad():
    output = module(input)
pass

3.4 网络模型的保存和读取

对于网络模型的保存和读取,其一共包含两种方法

**(1) 方法1 **

import torch
import torchvision

vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1  .pth文件
torch.save(vgg16,"./module_save/module1.pth")

# 加载方式1
module1 = torch.load("./module_save/module1.pth")
print(module1)

**(2) 方法2 **

import torch
import torchvision

vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式2
torch.save(vgg16.state_dict(),"./module_save/module2.pth")
module2 = torch.load("./module_save/module2.pth")
# 以方式2导入的只是模型的参数,还需模型的结构
module3 = torchvision.models.vgg16(pretrained=False)
module3.load_state_dict("./module_save/module2.pth")

(3) 两种方法的比较

a.方法1保存的是网络结构模型参数;而方法2保存的仅是模型参数

b.方法1直接load便可以得到一个完整的神经网路模型;而方法2load的只是模型参数,因而需要重新定义网络(相当于重写一遍未训练之前网络定义的代码)

c.两种方法,官方推荐方法2

3.5 完整的模型训练套路

以cifar10数据预测为例,完整的模型训练套路如下:

**(0) 导入相关库 **

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import dataset, DataLoader
from torchvision.datasets import CIFAR10

**(1) 数据准备 **

# 数据准备
data_train = CIFAR10("./dataset/train", train= True, transform=torchvision.transforms.ToTensor(),download=True)
data_test = CIFAR10("./dataset/test", train= False, transform=torchvision.transforms.ToTensor(),download=True)
train_load = DataLoader(data_train,batch_size=64)
test_load = DataLoader(data_test, batch_size=64)

(2) 搭建神经网路

# 神经网路的搭建
class Mylayer(nn.Module):

    def __init__(self):
        super().__init__()
        self.module = Sequential(
            Conv2d(3, 32, kernel_size=5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, kernel_size=5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, kernel_size=5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )
    def forward(self,x):
        x = self.module(x)
        return x
# 网路模型的例化
mynet1 = Mylayer()    

(3) 定义损失函数和优化器

# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 学习率与优化器
learning_rate = 0.01
optimizer = torch.optim.SGD(mynet1.parameters(),lr=learning_rate)

(4) 模型训练、测试和保存

# 先定义一些参数
# 训练次数
total_train_step = 0
# 测试次数
total_test_step = 0
# 训练轮数
epoch = 1

# 开始训练 双重for循环
for i in range(epoch):
    print("-------第 {} 轮训练开始--------".format(i+1))
    # 一轮的训练过程
    mynet1.train()
    for data in train_load:
        imgs,targets = data
        outputs = mynet1(imgs)
        loss = loss_fn(outputs,targets)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            # 注:loss.item(),只输出数值大小
            print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
    # 一轮的测试过程
    total_test_loss = 0
    # 注:模型训练开始前,需加入如下这句语句:
    mynet1.eval()
    with torch.no_grad():
        for data in test_load:
            imgs,targets = data
            outputs = mynet1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
    print("第{}轮测试集结束,Loss:{}".format(i+1,total_test_loss))
    total_test_step = total_test_step + 1
    # 模型保存
    torch.save(mynet1, "./module_save/mynet1_{}.pth".format(i+1))

(5) GPU加速

以上4个步骤便可实现神经网路模型的训练,在此基础上,进行GPU加速处理。

pytorch提供了比较方便的GPU加速方法,具体步骤如下:

a. 找到程序中网络模型数据(输入、标注)以及损失函数这三个部分

b.在上述三个部分中加入.cuda()函数

便可实现GPU加速

a.对于网络模型部分,其原始代码为:

mynet1 = Mylayer()

将其改成:

mynet1 = Mylayer()
mynet1.cuda()

b.对于数据(输入、标注)部分,其原始代码如下:

# 在模型训练和测试部分,都出现了如下代码段:
imgs,targets = data

将其修改成:

imgs,targets = data
imgs = imgs.cuda()
targets = targets.cuda()

c.对于损失函数部分,其原始代码如下:

loss_fn = nn.CrossEntropyLoss()

将其修改成:

loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.cuda()

经过上述修改之后,程序训练和测试的速度得到了明显加快!

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