pytorch个人学习笔记

pytorch学习笔记

来自datawhale的深入浅出pytorch教程的笔记。主要对第二章和第三章的常用函数和方法进行梳理,方便要用的时候查找和复习,同时巩固对pytorch实现深度学习基本流程的认识。
教程链接:深入浅出pytorch

文章目录

  • pytorch学习笔记
      • 第二章:pytorch基础知识
        • 2.1张量
        • 2.2自动求导
      • 第三章:pytorch主要组成模块
        • 3.2基本配置
        • 3.3数据读入
        • 3.4模型构建
        • 3.5模型初始化
        • 3.6损失函数
        • 3.7 训练与评估
        • 3.9 pytorch优化器
      • 其他
        • 模型定义与修改
        • 模型保存与读取
        • torchvision

第二章:pytorch基础知识

2.1张量

  1. 生成tensor
函数 功能
Tensor(sizes) 基础构造函数
tensor(data) 类似于np.array
ones(sizes) 全1
zeros(sizes) 全0
eye(sizes) 对角为1,其余为0
arange(s,e,step) 从s到e,步长为step
linspace(s,e,steps) 从s到e,均匀分成step份
rand/randn(sizes) rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布
normal(mean,std) 正态分布(均值为mean,标准差是std)
randperm(m) 随机排列
  1. 加法
    1. x+y
    2. x.add_(y)
    3. torch.add(x,y)
  2. 索引:类似numpy,如x[3:5,:]
  3. x.view(-1,3):改变形状,填-1表示由其他维度决定,view只改变观察角度不改tensor本身
  4. y=x.clone():复制x,二者内存独立
  5. x.item():x 的数值,不涉及其他性质
  6. 广播机制:两个形状不同的tensor按元素计算(如加法)时会先适当复制元素使这两个 Tensor 形状相同后再按元素运算。

2.2自动求导

  • requires_grad:布尔值,在创建张量时设置,表示是否计算梯度,若训练需要用到梯度为true,某些情况例如评估时为false。
  • grad_fn:布尔值。将y看作x的函数。这样创建的张量的grad_fn为true,如果是赋值给自身则为false。
  • out.backward():对out反向传播,对于标量out.backward()和 out.backward(torch.tensor(1.)) 等价,对于张量必须在括号内传入一个张量。每次传播梯度都会叠加
  • x.grad:x的梯度,返回的也是一个tensor对象
  • x.data:x的值,对x.data的操作会影响x的值但不影响梯度计算
  • x.grad.data.zero_():令梯度为0,防止梯度的累加
  • with torch.no_grad()::其后面的代码不会跟踪梯度的变化
    一个例子
import torch
x = torch.ones(2, 2, requires_grad=True)
print(x)
y = x**2
print(y)
print(y.grad_fn)
z = y * y * 3
out = z.mean()
print(z, out)
out.backward()
print(x.grad)

最后一项输出为tensor([[3., 3.], [3., 3.]])


第三章:pytorch主要组成模块

3.2基本配置

必须导入的包

import os
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import torch.optim as optimizer

一些基础配置

  • batch size
  • 初始学习率(初始)
  • 训练次数(max_epochs)
  • GPU配置
batch_size = 16
# 批次的大小
lr = 1e-4
# 优化器的学习率
max_epochs = 100

GPU的设置有两种常见的方式:

# 方案一:使用os.environ,这种情况如果使用GPU不需要设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'

# 方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")

我们可以定义自己的Dataset类来实现灵活的数据读取,定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数:

  • init: 用于向类中传入外部参数,同时定义样本集
  • getitem: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
  • len: 用于返回数据集的样本数
class MyDataset(Dataset):
    def __init__(self, data_dir, info_csv, image_list, transform=None):
        """
        Args:
            data_dir: path to image directory.
            info_csv: path to the csv file containing image indexes
                with corresponding labels.
            image_list: path to the txt file contains image names to training/validation set
            transform: optional transform to be applied on a sample.
        """
        label_info = pd.read_csv(info_csv)
        image_file = open(image_list).readlines()
        self.data_dir = data_dir
        self.image_file = image_file
        self.label_info = label_info
        self.transform = transform

    def __getitem__(self, index):
        """
        Args:
            index: the index of item
        Returns:
            image and its labels
        """
        image_name = self.image_file[index].strip('\n')
        raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name]
        label = raw_label.iloc[:,0]
        image_name = os.path.join(self.data_dir, image_name)
        image = Image.open(image_name).convert('RGB')
        if self.transform is not None:
            image = self.transform(image)
        return image, label

    def __len__(self):
        return len(self.image_file)

3.3数据读入

构建好Dataset后,就可以使用DataLoader来按批次读入数据了,实现代码如下:

from torch.utils.data import DataLoader
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True)
val_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size, num_workers=4, shuffle=False)

其中:

  • batch_size:样本是按“批”读入的,batch_size就是每次读入的样本数
  • num_workers:有多少个进程用于读取数据
  • shuffle:是否将读入的数据打乱
  • drop_last:对于样本最后一部分没有达到批次数的样本,使其不再参与训练

3.4模型构建

定义MLP类:init:用于初始化和定义前向计算的基础函数(如全连接层,relu);forward:调用_init_中的函数形成前向计算函数,无需定义backward,系统会自动计算。类的输入可以是模型的任意一个组件。
神经网络的层可分为有参数与无参数两种,无参数例如标准化,有参数的有多种,包括:

  • 二维卷积层:Conv2D,参数有输入通道数in_channels,输出通道数out_channels,卷积核宽度kernel_size,卷积核长宽不一致的填充数字padding
  • 池化层:pool2d,参数有池化层边长pool_size,和池化方式mode
    一个神经网络的典型训练过程如下:
  1. 定义包含一些可学习参数(或者叫权重)的神经网络
  2. 在输入数据集上迭代
  3. 通过网络处理输入
  4. 计算 loss (输出和正确答案的距离)
  5. 将梯度反向传播给网络的参数
  6. 更新网络的权重,一般使用一个简单的规则:weight = weight - learning_rate * gradient(梯度下降)

使用torch.nn包来构建神经网络,nn包则依赖于autograd包来定义模型并对它们求导。一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。

  • torch.Tensor - 一个多维数组,支持诸如backward()等的自动求导操作,同时也保存了张量的梯度。
  • nn.Module - 神经网络模块。是一种方便封装参数的方式,具有将参数移动到GPU、导出、加载等功能。
  • nn.Parameter - 张量的一种,当它作为一个属性分配给一个Module时,它会被自动注册为一个参数。
  • autograd.Function - 实现了自动求导前向和反向传播的定义,每个Tensor至少创建一个Function节点,该节点连接到创建Tensor的函数并对其历史进行编码。
  • net.parameters() -网络的可学习参数

3.5模型初始化

使用torch初始化conv和linear

torch.nn.init.kaiming_normal_(conv.weight.data)
torch.nn.init.constant_(linear.weight.data,0.3)

3.6损失函数

常用损失函数:

  1. 二分类交叉熵损失函数
    torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction=‘mean’)
  • weight:每个类别的loss设置权值
  • size_average:数据为bool,为True时,返回的loss为平均值;为False时,返回的各样本的loss之和。
  • reduce:数据类型为bool,为True时,loss的返回是标量。
  1. 交叉熵损失函数
    torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction=‘mean’)
    ignore_index:忽略某个类的损失函数。
  2. L1损失函数
    torch.nn.L1Loss(size_average=None, reduce=None, reduction=‘mean’)
    reduction参数决定了计算模式。有三种计算模式可选:none:逐个元素计算。 sum:所有元素求和,返回标量。 mean:加权平均,返回标量。 如果选择none,那么返回的结果是和输入元素相同尺寸的。默认计算方式是求平均。
  3. MSE损失函数
    torch.nn.MSELoss(size_average=None, reduce=None, reduction=‘mean’)
  4. 平滑L1 (Smooth L1)损失函数
    torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction=‘mean’, beta=1.0)
  5. 二分类logistic损失函数
    torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction=‘mean’)

3.7 训练与评估

切换模型的状态:

model.train()   # 训练状态
model.eval()   # 验证/测试状态

一个完整的训练过程:
用for循环读取DataLoader中的全部数据。
for data, label in train_loader:

之后将数据放到GPU上用于后续计算,此处以.cuda()为例
data, label = data.cuda(), label.cuda()

开始用当前批次数据做训练时,应当先将优化器的梯度置零:
optimizer.zero_grad()

之后将data送入模型中训练:
output = model(data)

根据预先定义的criterion计算损失函数:
loss = criterion(output, label)

将loss反向传播回网络:
loss.backward()

使用优化器更新模型参数:
optimizer.step()

3.9 pytorch优化器

共十种,均来自pytorch.optim。先实例化再step一下即可更新参数。

optimizer = torch.optim.SGD([weight], lr=0.1, momentum=0.9)
optimizer.step()

其他

模型定义与修改

有三种方式定义模型:Sequential,ModuleList和ModuleDict,他们的方法大致相同。以Sequential为例:

import torch.nn as nn
net = nn.Sequential(
        nn.Linear(784, 256),
        nn.ReLU(),
        nn.Linear(256, 10), 
        )
print(net)

通过net.fc(某一模型层)=classifier(替换层)可以修改模型的某一层。

在forward函数里可以给模型增加输入输出

    def forward(self, x, add_variable):
        x1000 = self.net(x)
        x10 = self.dropout(self.relu(x1000))
        x10 = self.fc1(x10)
        x10 = self.output(x10)
        return x10, x1000

模型保存与读取

# 保存+读取整个模型
torch.save(model, save_dir)
loaded_model = torch.load(save_dir)
loaded_model.cuda()

torchvision

torchvision包含了在计算机视觉中常常用到的数据集,模型和图像处理的方式。常用模块:

  • torchvision.datasets 常见数据集
  • torchvision.models 预训练模型
  • torchvision.tramsforms 图像处理方法

你可能感兴趣的:(pytorch,学习,深度学习)