加载中...

PyTorch常用操作


数据集加载

1. 网络数据集

加载数据集:https://pytorch.org/vision/stable/datasets.html

import torchvision.datasets as datasets
import torchvision.transforms as transforms

# 定义数据集变换(将图像转换为张量以及对图像进行归一化的操作)
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

# 加载MNIST数据集
train_set = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_set = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

2. 自己构造数据集

dataset.ImageFolder 是 PyTorch 中 torchvision.datasets 模块中的一个函数,用于从一个文件夹中加载图像数据集。该文件夹包含子文件夹,每个子文件夹对应一种类别,每个文件对应一个样本。

dataset.ImageFolder 函数的参数包括:

  • root: 数据集存放的根目录。
  • transform: 对数据集进行的变换。如果不指定,则返回原始数据集。
  • target_transform: 对标签进行的变换。如果不指定,则返回原始标签。
  • loader: 加载数据集的方式,默认为 PIL 的 Image.open() 函数。
  • is_valid_file: 一个可调用对象,用于过滤不合法的文件。如果不指定,则默认所有文件均为合法文件。

使用dataset.ImageFolder函数可以通过以下代码加载数据集:

import torchvision.datasets as datasets
import torchvision.transforms as transforms

# 定义数据集变换
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

# 加载数据集
dataset = datasets.ImageFolder(root='./data', transform=transform)

上述代码中,首先定义了一个数据集变换,其中包括将图像缩放到256×256大小、居中裁剪到224×224大小、将图像转换为张量以及对图像进行归一化的操作。然后使用 dataset.ImageFolder 函数加载 ./data目录下的数据集,并应用上述变换。

# 定义加载函数
def loader(path):
    with open(path, 'rb') as f:
        img = Image.open(f)
        return img.convert('RGB')

上述代码中,定义了一个加载函数loader,用于从文件路径中加载图像并返回一个PIL图像对象。该函数将图像转换为RGB格式,以便于应用数据集变换。

3. DataLoader

DataLoader 是 PyTorch 中用于加载数据的工具类。它可以将数据集封装成一个迭代器,用于在训练过程中按照指定的批次大小、随机打乱等方式加载数据。

  • dataset: Dataset类, 决定数据从哪读取以及如何读取
  • bathsize: 批大小
  • num_works: 是否多进程读取机制
  • shuffle: 每个epoch是否乱序
  • drop_last: 当样本数不能被batchsize整除时, 是否舍弃最后一批数据

以下是一个使用 DataLoader 类加载数据集的示例代码:

import torch.utils.data as data
import torchvision.transforms as transforms

# 定义数据集变换
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
])

# 加载图像数据集
train_set = data.ImageFolder(root='./data/train', transform=transform)
val_set = data.ImageFolder(root='./data/val', transform=transform)

# 定义数据加载器
train_loader = data.DataLoader(train_set, batch_size=32, shuffle=True)
val_loader = data.DataLoader(val_set, batch_size=32, shuffle=False)

上述代码中,首先定义了一个数据集变换transform,并使用dataset.ImageFolder()类加载图像数据集。然后,使用data.DataLoader()类定义了两个数据加载器,分别表示训练集和验证集。其中,train_loaderval_loader分别表示训练集和验证集的数据加载器。在数据加载器中,使用batch_size参数指定了每个批次的大小,使用shuffle参数指定了是否随机打乱数据集。

data/
├── train/
│   ├── class1/
│   │   ├── image1.jpg
│   │   ├── image2.png
│   │   └── ...
│   ├── class2/
│   │   ├── image1.jpg
│   │   ├── image2.png
│   │   └── ...
│   └── ...
├── val/
│   ├── class1/
│   │   ├── image1.jpg
│   │   ├── image2.png
│   │   └── ...
│   ├── class2/
│   │   ├── image1.jpg
│   │   ├── image2.png
│   │   └── ...
│   └── ...
└── ...

需要注意的是,DataLoader类是一个迭代器,可以使用for循环遍历数据集中的数据。例如:

for inputs, labels in train_loader:
    # 训练过程
    ...

在上述代码中,使用for循环遍历训练集中的数据。每次迭代返回一个批次的数据,其中inputs表示输入数据,labels表示对应的标签数据。

4. 数据集展示

import matplotlib.pyplot as plt
figure = plt.figure(figsize=(10, 10))
cols, rows = 4, 4
for i in range(1, cols * rows + 1):
    sample_idx = torch.randint(len(training_data), size=(1,)).item()
    img, label = training_data[sample_idx]
    figure.add_subplot(rows, cols, i)
    plt.title(label)
    plt.axis("off")
    plt.imshow(img.squeeze())
    #plt.imshow(img.squeeze(), cmap="gray")
plt.show()

数据集变换

PyTorch中提供了多种数据集变换(Transform),可以对图像、文本等不同类型的数据进行预处理。以下是常用的数据集变换:

1. 图像数据变换

  • transforms.Resize(size)

将图像的大小调整为指定的大小。size可以是一个整数,表示将图像的最短边调整为该大小,另一边按比例缩放;也可以是一个二元组,表示将图像的大小调整为指定的宽度和高度。

  • transforms.CenterCrop(size)

对图像进行中心裁剪,将图像裁剪为指定的大小。size可以是一个整数,表示将图像的宽度和高度都裁剪为该大小;也可以是一个二元组,表示将图像的宽度和高度分别裁剪为指定的宽度和高度。

  • transforms.RandomCrop(size)

对图像进行随机裁剪,将图像随机裁剪为指定的大小。size的含义与transforms.CenterCrop(size)相同。

  • transforms.RandomHorizontalFlip(p=0.5)

以指定的概率随机对图像进行水平翻转。p为翻转的概率,取值范围为[0, 1]

  • transforms.ToTensor()

将图像转换为Tensor格式。

  • transforms.Normalize(mean, std)

对图像进行标准化处理。meanstd分别为均值和标准差,可以是一个列表或元组,表示RGB三个通道的均值和标准差。

2. 文本数据变换

  • transforms.ToTensor()

将文本转换为Tensor格式。

  • transforms.Lambda(lambda)

自定义变换,使用lambda函数对文本进行处理。

Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))  #one-hot编码

3. 其他数据变换

  • transforms.Compose(transforms)

将多个变换组合起来使用。transforms为一个很多tansformes列表,表示需要组合使用的变换。

预训练模型与权重

https://pytorch.org/vision/stable/models.html

PyTorch中提供了很多预训练的模型,包括图像分类、目标检测、分割等领域的模型。这些预训练模型已经在大规模数据集上进行了训练,可以直接用于特定任务的微调或特征提取。

预训练模型通常包含两个部分:模型结构和权重。模型结构定义了模型的网络结构和参数,权重则包含了预训练模型的参数值。在PyTorch中,可以使用torchvision.models模块中的函数加载预训练模型及其权重。

以下是加载预训练模型及其权重的示例代码:

import torch.nn as nn
import torchvision.models as models

# 加载预训练模型
model = models.resnet18(pretrained=True)

# 将最后一层全连接层替换为自定义的层
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, num_classes)

# 加载预训练模型的权重
model.load_state_dict(torch.load('resnet18.pth'))

在上述代码中,使用models.resnet18(pretrained=True)函数加载预训练的ResNet18模型,其中pretrained=True表示加载预训练模型的权重。然后,将最后一层的全连接层替换为自定义的层。最后,使用torch.load()函数加载预训练模型的权重。

建立神经网络

https://pytorch.org/docs/stable/nn.html

1. 卷积层

nn.Conv2d()

2. 反卷积层

nn.ConvTranspose2d()

3. Pooling 层

nn.MaxPool2d()

nn.AvgPool2d()

nn.FractionalMaxPool2d()

nn.LPPool2d()

nn.AdaptiveMaxPool2d()

nn.AdaptiveAvgPool2d()

4. Padding 层

5. 激活层

nn.ReLU()

nn.Softmax()

nn.Tanh()

nn.Sigmoid()

nn.LeakyReLU()

6. 线性层

nn.Identity()

nn.Linear()

7. Sequential

model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

8. Block示例

构造块有助于编写重复复杂的网络

import torch
import torch.nn as nn


# 残差模块,将输入加到输出上
class Residual(nn.Module):
    def __init__(self, fn):
        super().__init__()
        self.fn = fn

    def forward(self, x, *args, **kwargs):
        return self.fn(x, *args, **kwargs) + x

# 上采样(反卷积)
def Upsample(dim):
    return nn.ConvTranspose2d(dim, dim, 4, 2, 1)

# 下采样
def Downsample(dim):
    return nn.Conv2d(dim, dim, 4, 2, 1)

class PreNorm(nn.Module):
    def __init__(self, dim, fn):
        super().__init__()
        self.fn = fn
        self.norm = nn.GroupNorm(1, dim)

    def forward(self, x):
        x = self.norm(x)
        return self.fn(x)

优化神经网络

1. 定义损失函数

https://pytorch.org/docs/stable/nn.html

在深度学习中,损失函数是评估模型性能的重要指标。PyTorch提供了多种常用的损失函数,可以根据具体情况选择合适的损失函数。

下面介绍几种常用的损失函数:

from torch import nn

# L1损失
nn.L1Loss()

# 均方误差损失函数(Mean Squared Error Loss)
nn.MSELoss()

# 交叉熵损失函数(Cross-Entropy Loss)
nn.CrossEntropyLoss()

# KL散度损失函数(Kullback-Leibler Divergence Loss)
nn.KLDivLoss(reduction='batchmean')

# 二元交叉熵损失函数
nn.BCELoss()

# Huber损失
nn.HuberLoss()

# Hinge损失
nn.HingeEmbeddingLoss()

2. 定义优化器

https://pytorch.org/docs/stable/optim.html

PyTorch中提供了许多优化器(Optimizer)用于优化神经网络的参数,使得损失函数最小化。以下是一些常用的优化器:

from torch import optim

# SGD(Stochastic Gradient Descent)
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# Adam(Adaptive Moment Estimation)
optimizer = optim.Adam([var1, var2], lr=0.0001)

# Adagrad(Adaptive Gradient)

# Adadelta

# RMSprop(Root Mean Square Propagation)

3. 使用示例

for input, target in dataset:
    optimizer.zero_grad()
    output = model(input)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step()

保存和加载模型

在PyTorch中,我们可以使用torch.save()torch.load()函数来保存和加载模型。

通常,我们将模型的参数保存到一个文件中,可以是.pt.pth格式的文件。

# 保存模型参数
torch.save(model.state_dict(), 'model_weights.pth')
model.load_state_dict(torch.load('model_weights.pth'))

# 保存整个模型
torch.save(model, 'model.pth')
model = torch.load('model.pth')

调用GPU

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

文章作者: JiJunhao
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 JiJunhao !
  目录