PyTorch入门手册

torch — PyTorch 1.12 documentationhttps://pytorch.org/docs/stable/torch.html

PyTorch is an optimized tensor library for deep learning using GPUs and CPUs.

基于Pytorch的库:torchvision, torchaudio, pytorch-fast-transformer

一、Pytorch

1. 数据读取

使用Dataset类与DataLoader的组合来得到数据迭代器。在训练或预测时,数据迭代器能够输出每一批次所需的数据,并且对数据进行相应的预处理与数据增强操作。

Dataset类

通过集成Dataset类来自定义数据集的格式、大小和其他属性,后面就可以供DataLoader类直接使用,这就表示,无论使用自定义的数据集还是官方封装好的数据集,其本质都是继承了Dataset类,而在继承Dataset类时,至少要重写以下几个方式:

  • __init__(): 构造函数,可自定义数据读取方法以及进行数据预处理
  • __len__(): 返回数据集大小
  • __getitem()__: 索引数据集中的某一个数据
import torch
from torch.utils.data import Dataset
 
class MyDataset(Dataset):
    # 构造函数
    def __init__(self, data_tensor, target_tensor):
        self.data_tensor = data_tensor
        self.target_tensor = target_tensor
 
    # 返回数据集大小
    def __len__(self):
        return self.data_tensor.size(0)
 
    # 返回索引的数据与标签
    def __getitem__(self, index):
        return self.data_tensor[index], self.target_tensor[index]
 

Dataloader类

在训练过程中可能不能一次性将所有数据全部加载到内存中,也不能只用一个进程去加载,所以就需要多进程、迭代加载,而Dataloader就是基于这些被设计出来,Dataloader是一个迭代器,最基本的使用方法就是传入一个Dataset对象,它会根据参数batch_size的值生成一个batch的数据,节省内存的同时还可实现多进程、数据打乱等处理。传入参数:

  • dataset: Dataset类型,输入的数据集,必须参数
  • batch_size: int类型,每个batch有多少个样本
  • shuffle: bool类型,在每个epoch开始的时候,是否数据进行重新打乱
  • num_workers: int类型,加载数据的进程数,0意味着所有的数据都会被加载进主进程
def main():
    # 生成数据
    data_tensor = torch.randn(10, 3)
    target_tensor = torch.randint(2, (10,))  # 标签是0或1
 
    # 将数据封装成Dataset
    my_dataset = MyDataset(data_tensor, target_tensor)
    tensor_dataloader = DataLoader(dataset=my_dataset, batch_size=2, shuffle=True, num_workers=0)
    for data, target in tensor_dataloader:
        print(data, target)
    print('One batch tensor data: ', iter(tensor_dataloader).next())
 
main()

2. Layers 层 

  • torch.nn.Embedding (num_embeddings 嵌入字典大小embedding_dim 嵌入向量大小)
  • torch.nn.LSTM (input_size, hidden_size, num_layers=1, bias=True, batch_first=False, dropout=0): 输入x,(h0,c0),输出y,(h_n,c_n)
  • nn.CrossEntropyLoss (weight=Nonesize_average=Noneignore_index=- 100reduce=Nonereduction='mean'label_smoothing=0.0)

3. 工具函数

  • torch.nn.utils.clip_grad_norm_ 只解决梯度爆炸问题,不解决梯度消失问题

4. 常见问题

# loss.backward() 和 optimizer.step()

  • loss.backward(): 将损失loss向输入测进行反向传播;这一步会计算所有变量x的梯度值 \small \frac{d}{dx}loss,并将其累积为\small x*grad 进行备用,即 \small x*grad=(x*grad)_{pre}+\frac{d}{dx}loss ,公式中的 \small (x*grad)_{pre} 指的是上一个epoch累积的梯度。
  • optimizer.step()利用优化器对参数x进行更新,以随机梯度下降SGD为例,更新的公式为:\small x = x - lr*(x*grad),lr 表示学习率 learning rate,减号表示沿着梯度的反方向进行更新;
  • optimizer.zero_grad(): 清除优化器关于所有参数x的累计梯度值 \small x*grad,一般在loss.backward()前使用,即清除 \small (x*grad)_{pre}

# model.zero_grad() 与 optimizer.zero_grad()

  • model.zero_grad()的作用是将所有模型参数的梯度置为0
  • optimizer.zero_grad()的作用是清除所有优化的torch.Tensor的梯度
  • 当使用optimizer = optim.Optimizer(net.parameters())设置优化器时,此时优化器中的param_groups等于模型中的parameters(),此时,二者是等效的,从二者的源码中也可以看出来。
  • 当多个模型使用同一个优化器时,二者是不同的,此时需要根据实际情况选择梯度的清除方式。
  • 当一个模型使用多个优化器时,二者是不同的,此时需要根据实际情况选择梯度的清除方式。

# detach() 和 data()

detach()返回一个新的tensor,是从当前计算图中分离下来的,但是仍指向原变量的存放位置,其grad_fn=Nonerequires_grad=False,得到的这个tensor永远不需要计算其梯度,不具有梯度grad,即使之后重新将它的requires_grad置为true,它也不会具有梯度grad。

  • 注意:返回的tensor和原始的tensor共享同一内存数据。in-place函数修改会在两个tensor上同时体现(因为它们共享内存数据),此时当要对其调用backward()时可能会导致错误。
  • data()函数和 detach() 函数功能相同,但是其不能保证in-place的安全性。
  • In-place 正确性检查:所有的tensor都会记录用在他们身上的 in-place operations。如果pytorch检测到tensor在一个Function中已经被保存用来backward,但是之后它又被in-place operations修改。当这种情况发生时,在backward的时候,pytorch就会报错。这种机制保证了,如果你用了in-place operations,但是在backward过程中没有报错,那么梯度的计算就是正确的。

# .item()

返回的是tensor中的值,且只能返回单个值(标量),不能返回向量。将张量的值转换为标准的 Python 数值(float, int),只有当张量仅含一个元素时才能使用它

# torch.load(参数文件, map_location='cpu')

在gpu上训练保存的模型,而在cpu上加载,可能会报错,此时,需要使用map_location来将存储动态重新映射到可选设备上。

# @torch.no_grad() 和 model.eval()

  • model.eval(),会(disables dropout and has batch norm)但其模型参数还是会变化的,梯度的计算不受影响,计算流依然会存储和计算梯度,后仍然能够更新模型的对应的权重
  • torch.no_grad()的作用就是停止autograd模块的工作,即不会自动计算和存储梯度,因此能够起到加速计算过程和节省显存的作用

二、Torchvision

 torchvision是pytorch的一个图形库,它服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。以下是torchvision的构成:

  1.     torchvision.datasets: 一些加载数据的函数及常用的数据集接口;
  2.     torchvision.models: 包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
  3.     torchvision.transforms: 常用的图片变换,例如裁剪、旋转等;
  4.     torchvision.utils: 其他的一些有用的方法。
import torchvision
from PIL import Image
import torchvision.transforms as transforms

torchvision.datasets

torchvision的datasets包中提供了丰富的图像数据集的接口。这个包本身并不包含数据集文件本身,其工作方式是先从网络上把数据集下载到用户指定目录,然后用它的加载器加载到内存中。最后将这个加载后的数据集作为对象返回给用户

import torchvision
 
mnist_dataset = torchvision.datasets.MNIST(root='./data',
                                           train=True,
                                           transform=None,
                                           target_transform=None,
                                           download=True)

torchvision.transforms

# 图像预处理步骤
transform = transforms.Compose([
    transforms.Resize(96), # 缩放到 96 * 96 大小
    transforms.ToTensor(), # 转化为Tensor
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) # 归一化
])

torchvision.models

import torch
import torchvision.models as models

# 加载预训练模型
google_net = models.googlenet(pretrained=True)
resnet18 = models.resnet18()
alexnet = models.alexnet()
squeezenet = models.squeezenet1_0()
densenet = models.densenet_161()
 
# 提取分类层
fc_in_features = google_net.fc.in_features
print("fc_in_features:", fc_in_features)
 
# 查看分类层的输出参数
fc_out_features = google_net.fc.out_features
print("fc_out_features:", fc_out_features)
 
# 修改预训练模型的输出分类数
google_net.fc = torch.nn.Linear(fc_in_features, 10)

其他函数

# 将32张图片拼接在一个网格中
grid_tensor = torchvision.utils.make_grid(image_tensor, nrow=8, padding=2)
grid_image = transforms.ToPILImage()(grid_tensor)
display(grid_image)

三、Pytorch Fast Transformers

Fast Transformers for PyTorchNonehttps://fast-transformers.github.io/

1. Transformers layers

TransformerEncoderLayer(attention, d_model, n_heads, d_ff=None, dropout=0.1, activation='relu')

  • forward(x, attn_mask=None, length_mask=None)
  • x的形状(N,L,E)

TransformerDecoderLayer(self_attention, cross_attention, d_model, d_ff=None, dropout=0.1, activation='relu')

  • forward(x, memory, x_mask=None, x_length_mask=None, memory_mask=None, memory_length_mask=None)
  • x的形状(N,L,E),memory的形状(N,L',E),memory为编码器的矩阵

2. Recurrent Transformers

类似循环RNN,每次只处理一个元素

RecurrentTransformerEncoderLayer(attention, d_model, d_ff=None, dropout=0.1, activation='relu', event_dispatcher='')

  • forward(x, state=None)
  • The state is a python object that varies depending on the attention implementation (e.g., linear attention, full attention)
  • state使用了 feature maps而不是softmax 在self-attention的计算中。

RecurrentTransformerDecoderLayer(self_attention, cross_attention, d_model, d_ff=None, dropout=0.1, activation='relu', event_dispatcher='')

  • Attention to the previous inputs and a preprocessed memory.
  • forward(x, memory, memory_length_mask=None, state=None)
  • x的形状(N,E),memory的形状(N,S,E),memory为编码器的矩阵

3. Builders

        if is_training:
            # encoder (training)
            self.transformer_encoder = TransformerEncoderBuilder.from_kwargs(
                n_layers=self.n_layer,
                n_heads=self.n_head,
                query_dimensions=self.d_model//self.n_head,
                value_dimensions=self.d_model//self.n_head,
                feed_forward_dimensions=2048,
                activation='gelu',
                dropout=0.1,
                attention_type="causal-linear",
            ).get()
        else:
            # encoder (inference)
            print(' [o] using RNN backend.')
            self.transformer_encoder = RecurrentEncoderBuilder.from_kwargs(
                n_layers=self.n_layer,
                n_heads=self.n_head,
                query_dimensions=self.d_model//self.n_head,
                value_dimensions=self.d_model//self.n_head,
                feed_forward_dimensions=2048,
                activation='gelu',
                dropout=0.1,
                attention_type="causal-linear",
            ).get()

4. Masking

  • FullMask(mask=None, N=None, M=None, device='cpu')
  • LengthMask(lengths, max_len=None, device=None)
  • TriangularCausalMask(N, device="cpu")

5. Attention

References

PyTorch实践模型训练(Torchvision) - N3ptune - 博客园

猜你喜欢

转载自blog.csdn.net/m0_64768308/article/details/127010159