Pytorch
一、训练模型
1.导入工具包
torch:
这是PyTorch框架的基础库,提供了自动求导机制和丰富的张量运算支持,是构建和训练神经网络的基础。
torch.nn:
PyTorch的神经网络库,包含多种构建神经网络所需的层结构(如卷积层、全连接层)和激活函数等
torch.utils.data:
提供了数据加载和处理的工具,是加载数据集并进行批处理的重要模块
torchvision.transforms:
PyTorch的视觉库中的一个模块,提供了一系列图像处理的变换操作,用于数据增强和预处理
torchvision.datasets:
提供了常见的数据集和相关的数据加载方法,如MNIST、CIFAR-10、ImageNet等
DataLoader:
torch.utils.data中的一个类,用于构建可迭代的数据加载器,可以方便地在训练循环中按批次加载数据
torch.optim.lr_schedule
r: 提供了学习率调整策略,如学习率衰减,有助于训练过程中改善模型性能和减少过拟合
os:
Python的标准库之一,提供了与操作系统交互的功能,如文件创建、路径操作等
import torch.optim as optim
import torch
import torch.nn as nn
import torch.utils.data
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torch.optim.lr_scheduler as lr_scheduler
import os
2.判断环境是CPU运行还是GPU
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
3.数据预处理
transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)):
随机裁剪图像,裁剪后的图像大小为256x256像素。裁剪区域的大小是原始图像尺寸的0.8到1.0倍之间随机选择
transforms.RandomRotation(degrees=15):
随机旋转图像,旋转角度在-15度到15度之间随机选择
transforms.RandomHorizontalFlip():
随机水平翻转图像,即有一半的概率会翻转,一半的概率不翻
transforms.CenterCrop(size=224):
从图像中心裁剪出224x224像素的区域
transforms.ToTensor():
将图像转换为PyTorch张量,并且将像素值从[0, 255]范围缩放到[0, 1]范围
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]):
对图像进行标准化处理。这里使用的是ImageNet数据集的均值和标准差,这些值分别用于每个颜色通道的减均值和除以标准差操作
验证数据预处理 (transform[‘val’])
transforms.Resize(size=256):
将图像大小调整为256x256像素,这里没有使用随机裁剪,而是直接调整大小
transforms.CenterCrop(size=224):
从图像中心裁剪出224x224像素的区域
transforms.ToTensor():
将图像转换为PyTorch张量,并且将像素值从[0, 255]范围缩放到[0, 1]范围
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]):
对图像进行标准化处理,使用的是ImageNet数据集的均值和标准差
# 定义数据预处理
transform = {
'train': transforms.Compose([
transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),
transforms.RandomRotation(degrees=15),
transforms.RandomHorizontalFlip(),
transforms.CenterCrop(size=224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(size=256),
transforms.CenterCrop(size=224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
}
4.读取数据
dataset = './dataset':
这行代码设置了数据集的根目录。这里的./表示当前工作目录,所以dataset变量指向的是当前工作目录下的dataset文件夹
train_directory = os.path.join(dataset, 'train'):
这行代码将dataset目录和train子目录连接起来,创建训练数据集的完整路径。如果当前工作目录是/home/user/project,那么train_directory将是/home/user/project/dataset/train
valid_directory = os.path.join(dataset, 'val'):
这行代码将dataset目录和val子目录连接起来,创建验证数据集的完整路径。同样,如果当前工作目录是/home/user/project,那么valid_directory将是/home/user/project/dataset/val
dataset = './dataset'
train_directory = os.path.join(dataset, 'train')
valid_directory = os.path.join(dataset, 'val')
5.设置超参数
batch_size = 32
num_classes = 2 # 修改为您的分类数
6.创建训练(train)和验证(val)数据集的数据加载器
data = { ... }:
这个字典定义了两个键:‘train’和’val’,它们分别对应于训练和验证数据集。对于每个键,都使用torchvision.datasets.ImageFolder类来创建一个数据集。ImageFolder假设每个类别的图像都存储在一个单独的文件夹中,并且文件夹的名称是类别的名称。root参数指定了数据集的根目录,transform参数指定了应用于每个图像的预处理操作
train_loader = DataLoader(data['train'], batch_size=batch_size, shuffle=True, num_workers=8):
这行代码创建了训练数据加载器。DataLoader类接受一个数据集作为输入,并提供一个可迭代的数据加载器。batch_size参数指定了每个批次中图像的数量。shuffle=True表示在每次遍历数据集时都会随机打乱数据的顺序,这对于训练是有益的,因为它可以减少模型的过拟合。num_workers=8表示在加载数据时使用8个子进程。这可以加快数据加载速度,尤其是在使用GPU进行训练时
test_loader = DataLoader(data['val'], batch_size=batch_size, shuffle=False, num_workers=8):
这行代码创建了验证数据加载器。与训练数据加载器类似,但它设置了shuffle=False,因为在验证阶段,我们不希望数据顺序被打乱,以便于评估模型的性能
data = {
'train': datasets.ImageFolder(root=train_directory, transform=transform['train']),
'val': datasets.ImageFolder(root=valid_directory, transform=transform['val'])
}
train_loader = DataLoader(data['train'], batch_size=batch_size, shuffle=True, num_workers=8)
test_loader = DataLoader(data['val'], batch_size=batch_size, shuffle=False, num_workers=8)
二、定义VGG16模型
1. 定义VGG16模型
class VGG16(nn.Module):
这行代码定义了一个新的类VGG16,它继承自nn.Module。nn.Module是所有神经网络模块的基类
def __init__(self, num_classes=1000):
构造函数接收一个参数num_classes,表示模型输出的类别数。默认值为1000,这是ImageNet数据集的类别数
super(VGG16, self).__init__():
这行代码调用了基类的构造函数
self.features = nn.Sequential(...):
这部分定义了VGG-16的特征提取部分,包括5个卷积块,每个卷积块包含多个卷积层和一个池化层。每个卷积层后面都跟着一个ReLU激活函数
self.classifier = nn.Sequential(...):
这部分定义了VGG-16的分类器部分,包括3个全连接层,每个全连接层后面都跟着一个ReLU激活函数和一个Dropout层。最后一个全连接层的输出节点数与num_classes参数相同
def forward(self, x):
前向传播函数接收输入x,首先通过特征提取部分self.features,然后将特征图展开为一维向量,最后通过分类器部分self.classifier得到最终的分类结果
class VGG16(nn.Module):
def __init__(self, num_classes