PyTorch入门手册
这个包本身并不包含数据集文件本身,其工作方式是先从网络上把数据集下载到用户指定目录,然后用它的加载器加载到内存中。在训练过程中可能不能一次性将所有数据全部加载到内存中,也不能只用一个进程去加载,所以就需要多进程、迭代加载,而Dataloader就是基于这些被设计出来,Dataloader。在训练或预测时,数据迭代器能够输出每一批次所需的数据,并且对数据进行相应的预处理与数据增强操作。的值生成一个b
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=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean', label_smoothing=0.0)
3. 工具函数
- torch.nn.utils.clip_grad_norm_ :只解决梯度爆炸问题,不解决梯度消失问题
4. 损失函数
5. 常见问题
# loss.backward() 和 optimizer.step()
- loss.backward(): 将损失loss向输入测进行反向传播;这一步会计算所有变量x的梯度值 ,并将其累积为 进行备用,即 ,公式中的 指的是上一个epoch累积的梯度。
- optimizer.step(): 利用优化器对参数x进行更新,以随机梯度下降SGD为例,更新的公式为:,lr 表示学习率 learning rate,减号表示沿着梯度的反方向进行更新;
- optimizer.zero_grad(): 清除优化器关于所有参数x的累计梯度值 ,一般在loss.backward()前使用,即清除 。
# 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=None且requires_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的构成:
- torchvision.datasets: 一些加载数据的函数及常用的数据集接口;
- torchvision.models: 包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
- torchvision.transforms: 常用的图片变换,例如裁剪、旋转等;
- 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
- FullAttention
- LinearAttention
- CausalLinearAttention
- ImprovedClusteredAttention
- ClusteredAttention
- ReformerAttention
- LocalAttention
- ConditionalFullAttention
References
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)