Pytorch速通笔记
总之这是第二次速通,只写了基本的一些东西,可能够用了
官网地址:https://pytorch.org/
Dateset类(包括构建Transform)
# 所有自己的 Dataset 需要继承自这个类
# 需要覆写3个method
from torch.utils.data import Dataset
class MyDataset(Dataset):
# 初始化自己的数据集,传入自己预处理好的数据集,可以先处理数据路径更方便
def __init__(self, data, transform, myloader):
self.data = data
self.transform = transform
self.loader = loader
def __len__(self):
return len(self.data)
# 获取每一个数据的具体值的方法
def __getitem__(self, idx):
# data的数据格式为 [imgpath,lable]对应
imgpath, label = self.data[idx]
# 如果 label 比较复杂的时候,可以写一个 label_loder 的方法
image = self.transform(self.myloader(imgpath))
return image, label
# Dataset 类具有如下聚合方式
TrainDataset = MyDataset_1 + MyDataset_2
Transform的使用
from torchvision import transforms
# 自定义 transform
transform = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize(256),
# transforms.RandomResizedCrop(224,scale=(0.5,1.0)),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
裁剪 | |
---|---|
中心裁剪 | transforms.CenterCrop |
随机裁剪 | transforms.RandomCrop |
随机长宽比裁剪 | transforms.RandomResizedCrop |
上下左右中心裁剪 | transforms.FiveCrop |
上下左右中心裁剪后翻转 | transforms.TenCrop |
翻转和旋转——Flip and Rotation | |
---|---|
依概率p水平翻转 | transforms.RandomHorizontalFlip(p=0.5) |
依概率p垂直翻转 | transforms.RandomVerticalFlip(p=0.5) |
随机旋转 | transforms.RandomRotation |
图像变换 | |
---|---|
重置大小 | transforms.Resize |
标准化 | transforms.Normalize |
转为tensor,并归一化至[0-1] | transforms.ToTensor |
填充 | transforms.Pad |
修改亮度、对比度和饱和度 | transforms.ColorJitter |
转灰度图 | transforms.Grayscale |
线性变换 | transforms.LinearTransformation() |
仿射变换 | transforms.RandomAffine |
依概率p转为灰度图 | transforms.RandomGrayscale |
将数据转换为PILImage | ransforms.ToPILImage |
Apply a user-defined lambda as a transform | transforms.Lambda |
对transforms操作,使数据增强更灵活 | |
---|---|
transforms.RandomChoice(transforms) | 从给定的一系列transforms中选一个进行操作 |
transforms.RandomApply(transforms, p=0.5) | 给一个transform加上概率,依概率进行操作 |
transforms.RandomOrder | 将transforms中的操作随机打乱 |
TensorBoard的使用
from torch.utils.tensorboard import SummaryWeiter
# 写入tensorboard日志
# 很方便的数据图表
writer = SummaryWriter(logdir)
writer.add_image(tag , img_tensor_or_numpy , step, dataformats="HWC") #添加图片
writer.add_scalar(tag , scalar_value , global_step) # 添加图表
writer.close()
# cmd 指令:tensorboard --logdir=logdir --port=6006
torchvision使用
在pytorch的官方文档中看,可以直接下载一些比较简单的数据集
DataLoader初始化数据集
from torch.utils.data import Dataset, DataLoader
Dtr = DataLoader(
dataset=train_data,
batch_size=50,
shuffle=True, # 是否打乱顺序
num_workers=0, # 读取进程数量,0为默认主进程
drop_last=True # 最后一个batch除不尽的时候是否丢弃
)
# DataLoader 本质是一个迭代器
nn.Module 神经网络搭建
官方文档 https://pytorch.org/docs/stable/nn.html#
基本所有的神经网络结构都在里面了,要什么自己找,torch的结构搭建非常简单
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super().__init__()
# 自定义网络 - 卷积层
# in_channels (int), out_channels (int), kernel_size (int or tuple)
# With square kernels and equal stride
self.conv1 = nn.Conv2d(3, 20, 3, stride=2)
# non-square kernels and unequal stride and with padding
self.conv2= nn.Conv2d(20, 15, (3, 5), stride=(2, 1), padding=(4, 2))
# non-square kernels and unequal stride and with padding and dilation
self.cov3 = nn.Conv2d(15, 1, (5, 5), stride=(1, 1), padding=(2, 2), dilation=(3, 1))
# 自定义网路 - 池化层
# pool of square window of size=3, stride=2
self.pool1 = nn.MaxPool2d(3, stride=2,)
# pool of non-square window
self.pool2 = nn.MaxPool2d((3, 2), stride=(2, 1))
# 前馈路径示例
def forward(self, x):
x = F.relu(self.conv1(x))
x = self.pool1(x)
x = F.sigmod(self.conv2(x))
x = self.pool2(X)
x = F.relu(self.conv3(x))
return x
# 小孩子不懂,网络瞎搭的,很抽象但看到的人先别急
nn.Sequential 更方便的小型网络生成器
# Using Sequential to create a small model. When `model` is run,
# input will first be passed to `Conv2d(1,20,5)`. The output of
# `Conv2d(1,20,5)` will be used as the input to the first
# `ReLU`; the output of the first `ReLU` will become the input
# for `Conv2d(20,64,5)`. Finally, the output of
# `Conv2d(20,64,5)` will be used as input to the second `ReLU`
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
# Using Sequential with OrderedDict. This is functionally the
# same as the above code
model = nn.Sequential(
OrderedDict([
('conv1', nn.Conv2d(1,20,5)),
('relu1', nn.ReLU()),
('conv2', nn.Conv2d(20,64,5)),
('relu2', nn.ReLU())
]))
torch.optim 优化器构造
官方文档https://pytorch.org/docs/stable/optim.html
# 构造优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr=0.0001)
# 使用优化器(简单示例)
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
# 一些优化算法,如共轭梯度和LBFGS,需要多次重新评估函数,因此您必须传递一个closure,允许它们重新计算您的模型。closure 应该清除梯度,计算损失并返回。
for input, target in dataset:
def closure():
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
return loss
optimizer.step(closure)
网路运行示例
for epoch in range(epoch_num): # epoch 表示训练代数
train_loss = []
for batch_idx, minibatch in enumerate(Dtr, 0):
# Dtr = Dataloader(XXXX)
# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标
# 表示模型迭代,次数太少模型没效果,次数太对容易没有免费的午餐定理
data, target = Mygetdata(minibatch)
optimizer.zero_grad() # 每个 batch 计算前梯度清空,因为前面的 batch 的 grid 对本次无用
output = my_module(data) # 前馈传播
loss = my_loss(output, target) # 计算损失函数
loss.backward() # 反向传播
optimizer.step() # 更新参数
train_loss.append(loss.cpu().item())
torch.save(model.state_dict(), 'model_weights.pth')
# 可以用 tqdm 插件显示进度条,但是在进度需要写入log文件时就算了
# 过程中的数据可以利用 tensorboard 进行可视化