pytorch基础

pytorch基础

数据导入

数据增强

torchvision.transforms

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import torch
from torchvision import transforms
from PIL import Image

# 定义变换管道
transform = transforms.Compose([
transforms.RandomHorizontalFlip(), # 随机水平翻转
transforms.RandomVerticalFlip(), # 随机垂直翻转
transforms.RandomRotation(30), # 随机旋转,最大角度30度
transforms.RandomResizedCrop(224), # 随机裁剪并缩放为224x224
transforms.ColorJitter(brightness=0.5, contrast=0.5), # 调整亮度和对比度
transforms.ToTensor(), # 转为Tensor
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 归一化
])

# 读取图片并应用变换
image = Image.open('path_to_your_image.jpg')
transformed_image = transform(image)

# transformed_image 现在是一个Tensor,可以用于训练

常见操作

  • transforms.RandomHorizontalFlip(p=0.5):随机以概率p水平翻转

  • transforms.RandomVerticalFlip(p=0.5):随机以概率p垂直翻转

  • transforms.RandomRotation(degrees):随机旋转,角度范围是 -degrees 到 degrees

  • transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(3/4, 4/3),interpolation=PIL.Image.BILINEAR):随机裁剪并缩放图像到指定大小,scale表示裁剪区域相对于原始图像的比例,ratio表示裁剪区域的宽高比,interpolation表示插值方法。

  • transforms.RandomCrop(size,padding=None,pad_if_needed=False,fill=0,padding_mode='constant')

    • size:裁剪的大小
    • padding:设置填充大小。
      • 当为 a 时,上下左右均填充 a 个像素。
      • 当为 (a, b) 时, 上下填充 b 个像素, 左右填充 a 个像素。
      • 当为 (a, b, c, d) 时,左、上、右、下分别填充 a、b、c、d 个像素。
    • pad_if_needed:若图像小于设定 size,则填充,此时该项需要设置为 True。
    • padding_mode:填充模式,有 4 种模式:
      • constant:像素值由 fill 设定。
      • edge:像素值由图像边缘像素决定。
      • reflect:镜像填充,最后一个像素不镜像,例如 [1, 2, 3, 4]
        [3, 2, 1, 2, 3, 4, 3, 2]。
      • symmetric:镜像填充,最后一个像素镜像,例如 [1, 2, 3, 4]

[2, 1, 1, 2, 3, 4, 4, 3]。
- fill:padding_mode = ‘constant’ 时,设置填充的像素值。

  • transforms.Pad(padding,fill=0,padding_mode='constant')
    • padding:设置填充大小。
      • 当为 a 时,上下左右均填充 a 个像素。
      • 当为 (a, b) 时, 上下填充 b 个像素, 左右填充 a 个像素。
      • 当为 (a, b, c, d) 时,左、上、右、下分别填充 a、b、c、d 个像素。
    • fill:padding_mode = ‘constant’ 时,设置填充的像素值。
    • padding_mode:填充模式,有 4 种模式:
      • constant:像素值由 fill 设定。
      • edge:像素值由图像边缘像素决定。
      • reflect:镜像填充,最后一个像素不镜像,例如 [1, 2, 3, 4]
        [3, 2, 1, 2, 3, 4, 3, 2]。
      • symmetric:镜像填充,最后一个像素镜像,例如 [1, 2, 3, 4]

[2, 1, 1, 2, 3, 4, 4, 3]。

  • transforms.ColorJitter(brightness, contrast, saturation, hue):调整亮度、对比度、饱和度、色相
  • transforms.Grayscale(num_output_channels=1):将图像转换为灰度图像,num_output_channels=1 表示转换为单通道灰度图像,num_output_channels=3 表示转换为三通道灰度图像(每个像素的三个通道值相同)。
  • transforms.RandomGrayscale( num_output_channels,p=0.1):随机以概率p将图像转换为灰度图像
  • transforms.RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False):随机擦除,p表示以概率p执行擦除操作,scale表示擦除区域的面积占比,ratio表示擦除区域的宽高比,value表示擦除区域的填充值,inplace表示是否在原图像上进行操作。
  • transforms.ToTensor():转为Tensor
  • transforms.Normalize(mean, std):归一化,mean和std分别为每个通道的均值和标准差

应用

这些变换操作应用于数据集(如ImageFolder),然后在训练时使用DataLoader来加载图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from torchvision import datasets
from torch.utils.data import DataLoader

# 使用数据集,并应用转换
dataset = datasets.ImageFolder(root='path_to_dataset', transform=transform)

# 创建DataLoader
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# 迭代加载数据
for images, labels in dataloader:
# 在这里可以使用增强后的图像进行训练
pass

imgaug

相比于torchvision.transforms,它提供了更多的数据增强方法

官方例程

官方文档

github

安装

1
2
conda config --add channels conda-forge
conda install imgaug

简易使用

  1. 导入

imagaug不能进行图像的IO操作,建议使用imageio进行读入,如果使用的是opencv进行文件读取的时候,需要进行手动改变通道,将读取的BGR图像转换为RGB图像。除此以外,当我们用PIL.Image进行读取时,因为读取的图片没有shape的属性,所以我们需要将读取到的img转换为np.array()的形式再进行处理。

1
2
# 图片的读取
img = imageio.imread("./Lenna.jpg")
  1. 定义增强方法
  • imgaug包含了许多从Augmenter继承的数据增强的操作,需要利用imgaug.augmenters.Sequential()来构造我们数据增强的pipline
1
2
3
4
5
iaa.Sequential(children=None, # Augmenter集合
random_order=False, # 是否对每个batch使用不同顺序的Augmenter list
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
7
8
9
# 构建处理序列
aug_seq = iaa.Sequential([
iaa.Affine(rotate=(-25,25)),
iaa.AdditiveGaussianNoise(scale=(10,60)),
iaa.Crop(percent=(0,0.2))
])
# 对图片进行处理,image不可以省略,也不能写成images
image_aug = aug_seq(image=img)
ia.imshow(image_aug)
  • 针对一个batch的图片进行增强时,只需要将待处理的图片放在一个list中,并将函数的image改为images即可进行数据增强操作
1
2
3
4
5
6
7
8
9
10
aug_seq = iaa.Sequential([
iaa.Affine(rotate=(-25, 25)),
iaa.AdditiveGaussianNoise(scale=(10, 60)),
iaa.Crop(percent=(0, 0.2))
])

# 传入时需要指明是images参数
images_aug = aug_seq.augment_images(images = images)
#images_aug = aug_seq(images = images)
ia.imshow(np.hstack(images_aug))
  • 对批次的图片分部分处理,可以通过imgaug.augmenters.Sometimes()对batch中的一部分图片应用一部分Augmenters,剩下的图片应用另外的Augmenters。
1
2
3
4
5
6
7
iaa.Sometimes(p=0.5,  # 代表划分比例
then_list=None, # Augmenter集合。p概率的图片进行变换的Augmenters。
else_list=None, #1-p概率的图片会被进行变换的Augmenters。注意变换的图片应用的Augmenter只能是then_list或者else_list中的一个。
name=None,
deterministic=False,
random_state=None)

  • 对不同大小的图片进行处理

自定义块

1
2
3
4
5
6
7
8
9
10
11
12
13
import torch
from torch import nn
from torch.nn import functional as F

class MLP(nn.Module):
def __init__(self):
super().__init__()
self.hidden = nn.Linear(20, 256)
self.out = nn.Linear(256, 10)

def forward(self, X):
return self.out(F.relu(self.hidden(X)))

参数管理

将神经网络(nn.Module)看作是一个参数容器,它包含了所有的参数(权重和偏置),以及一些方法(如前向传播)。

  1. 参数访问
    • net.state_dict():返回一个字典,包含了模型的所有参数(权重和偏置),还可以利用net[n]来提取第n层的参数
    • net[n].weight:第n层的权重,net[n].weight.data:第n层的权重数据
    • net[n].bias:第n层的偏置,net[n].bias.data:第n层的偏置数据
    • net.parameters():返回一个迭代器,包含了模型的所有参数
  2. 参数初始化
    1
    2
    3
    4
    5
    6
    def init_normal(m):
    if type(m) == nn.Linear:
    nn.init.normal_(m.weight, mean=0, std=0.01)
    nn.init.zeros_(m.bias)

    net.apply(init_normal)#遍历所有层,对每个层应用init_normal函数
    1
    2
    3
    4
    5
    6
    def init_constant(m):
    if type(m) == nn.Linear:
    nn.init.constant_(m.weight, 1)
    nn.init.zeros_(m.bias)

    net.apply(init_constant)
    可以对不同层应用不同的初始化函数:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def init_xavier(m):
    if type(m) == nn.Linear:
    nn.init.xavier_uniform_(m.weight)
    nn.init.zeros_(m.bias)

    def init_42(m):
    if type(m) == nn.Linear:
    nn.init.constant_(m.weight, 42)
    nn.init.zeros_(m.bias)
    net[0].apply(init_xavier)
    net[1].apply(init_42)
  3. 参数绑定
    1
    2
    3
    4
    5
    shared = nn.Linear(8, 8)
    net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
    shared, nn.ReLU(),
    shared, nn.ReLU(),
    nn.Linear(8, 1))
    shared层的参数在不同层之间共享,即shared层的参数在不同层之间是指向同一个内存地址的

自定义层

可以把层作为组件嵌套进更复杂的模型

1
2
3
4
5
6
class MyLinear(nn.Module):
def __init__(self):
super().__init__()

def forward(self, X):
return X - X.mean()

带参数的层:

1
2
3
4
5
6
7
8
class MyLinear(nn.Module):
def __init__(self, in_features, out_features):
super().__init__()
self.weight = nn.Parameter(torch.randn(in_features, out_features))
self.bias = nn.Parameter(torch.zeros(out_features))

def forward(self, X):
return X @ self.weight + self.bias

自定义模型:

1
2
3
4
5
6
7
8
9
10
11
class MyMLP(nn.Module):
def __init__(self):
super().__init__()
self.linear = MyLinear(20, 256)
self.out = nn.Linear(256, 10)

def forward(self, X):
X = self.linear(X)
return self.out(F.relu(X))
# return self.out(X)
net = MyMLP()

保存与加载

  1. 加载和保存模型参数
    • torch.save(net.state_dict(), 'net.params'):保存模型参数
    • net.load_state_dict(torch.load('net.params')):加载模型参数
  2. 加载和保存整个模型
    • torch.save(net, 'net.pt'):保存整个模型
    • net = torch.load('net.pt'):加载整个模型
    • net.eval():将模型设置为评估模式,即关闭dropout和batch normalization等层的训练模式
    • net.train():将模型设置为训练模式,即开启dropout和batch normalization等层的训练模式

pytorch基础
http://example.com/2025/08/17/25_08_17pytorch基础/
作者
ZF ZHAO
发布于
2025年8月17日
许可协议