介绍
猫狗分类来源于Kaggle上的一个入门竞赛。

https://www.kaggle.com/competitions/dogs-vs-cats-redux-kernels-edition/overview
代码及解释
首先,导入一系列的库。
import numpy as np
from PIL import Image
from pathlib import Path
import torch
from torch import nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader, random_split
from torchvision import transforms
import matplotlib.pyplot as plt
这段代码主要是导入了一些Python库,包括:
- numpy:Python中常用的科学计算库,用于处理数组、矩阵等数值数据。
- PIL(Python Imaging Library):Python图像处理库,用于处理各种图像格式。
- pathlib:Python处理文件和目录路径的标准库,支持多平台。
- torch:PyTorch深度学习框架的核心库。
- nn:PyTorch中用于构建神经网络的模块。
- F(functional):PyTorch中用于创建自定义卷积层、激活函数等的函数。
- DataLoader:PyTorch中用于加载和批量处理数据的工具。
- transforms:PyTorch中对图像和数据进行预处理的工具。
- matplotlib:Python绘图库,用于绘制数据和图像。
这些库的导入是PyTorch实践项目中经常用到的基础操作,其中PIL、numpy和matplotlib主要用于读取和展示图像、transforms用于对图像进行数据增强,torch和nn则是构建和训练深度神经网络的核心。
而后,启用GPU加速。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("device: ", device)
get_label = lambda x: x.name.split('.')[0]
class get_dataset(Dataset):
def __init__(self, root, transform=None):
self.images = list(Path(root).glob('*.jpg'))
self.transform = transform
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
img = self.images[idx]
label = get_label(img)
label = 1 if label == 'dog' else 0
if self.transform:
img = self.transform(Image.open(img))
return img, torch.tensor(label, dtype=torch.int64)
这段代码定义了一个类get_dataset,用于加载和预处理数据集。
在类的初始化函数中,root为数据集路径,transform为数据预处理函数。通过list和glob函数获取符合条件的文件名,即所有后缀为jpg的图片文件名,并将其转为列表self.images。同时记录transform函数,即数据预处理函数。
__len__函数返回数据集中的图片数量,__getitem__函数根据索引idx获取对应图片和标签。首先获取索引对应的图片img,并通过get_label函数获取该图片对应的标签。该函数将图片文件名以’.‘分割,并将第一个分割出来的字符串作为标签。如果标签等于’dog’,则将其转为数字1,否则转为数字0。
接着如果有定义transform函数,就将img通过transform函数进行数据预处理。最后返回处理后的图片和标签,其中标签用torch.tensor转为整型。
🤚注意:glob 是 Python 标准库中 pathlib 模块下的一个函数,用于查找指定路径下符合特定规则的文件或文件夹路径,返回一个生成器(generator)。
在这个实现中,glob(‘*.jpg’) 表示查找 root 目录下所有后缀为 .jpg 的文件。通配符 * 表示匹配任意字符,因此 *.jpg 表示匹配任意字符开头、.jpg 结尾的文件名。
举个例子,如果 root 目录下有这些文件:
- cat.1.jpg
- cat.2.jpg
- dog.1.jpg
- dog.2.jpg
- rabbit.1.jpg
那么 list(Path(root).glob(‘*.jpg’)) 将返回这些文件的路径:
Copy Code[
'root/cat.1.jpg',
'root/cat.2.jpg',
'root/dog.1.jpg',
'root/dog.2.jpg',
'root/rabbit.1.jpg'
]
这里需要注意,glob 函数返回的是一个生成器,需要通过 list() 转换成列表才能进行遍历或其他操作。
transforms = transforms.Compose([
transforms.Resize([224, 224]), # resize the input image to a uniform size
transforms.ToTensor(), # convert PIL Image or numpy.ndarray to tensor and normalize to somewhere between [0,1]
transforms.Normalize( # standardized processing
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
这段代码定义了一个数据预处理过程,用于将读入的图像进行标准化处理,从而方便模型训练。
数据预处理使用了 transforms 模块中的 Compose 函数,它可以将多种图像变换串联起来,形成一个可复用的数据处理流程。这里串联了三个变换:
- Resize 变换:将图像调整为指定的大小,这里将图像大小调整为 224×224224×224 像素。这一步是为了将所有图像都调整到同样的大小,方便后续数据输入模型。
- ToTensor 变换:将 PIL Image 类型或者 numpy.ndarray 类型的图像数据转换成 PyTorch 中的 Tensor 类型。从而使图像可以被输入到神经网络中进行计算。
- Normalize 变换:通过对数据进行归一化处理,将每一个像素在 RGB 颜色通道上的取值压缩到 [0,1][0,1] 区间内。这里使用 imagenet 数据集的平均值和标准差作为归一化的标准,将每个像素减去平均值再除以标准差,达到对数据进行标准化的目的。
最终 transforms 变量定义了一个复合的预处理过程,可以方便地应用于训练集和测试集中的图像数据。
注意:transforms.Normalize() 是一个数据标准化操作,通过对每个像素在 RGB 颜色通道上的取值进行归一化,将图像的统计性质进行规范化,从而方便模型的使用和训练。
具体地,该函数接受两个参数:mean 和 std,分别表示要减去的均值和要除以的标准差。在这里,mean 和 std 的取值是根据 Imagenet 数据集的统计特征来计算的,这些统计特征对于大多数视觉任务都是通用的:
- mean:表示在 Imagenet 训练集上所有图片在 RGB 颜色通道上的平均取值。对于彩色图像,mean 是一个长度为 3 的列表,分别表示 RGB 三个颜色通道上的平均值。在这里,mean 的取值为 [0.485, 0.456, 0.406]。
- std:表示在 Imagenet 训练集上所有图片在 RGB 颜色通道上的标准差。同样地,std 也是一个长度为 3 的列表,在这里,std 的取值为 [0.229, 0.224, 0.225]。
假设输入图像为 x,则 Normalize 操作的具体计算为:(x−mean)/std,即将输入图像减去均值再除以标准差。最终得到的图像每个像素在每个颜色通道上的取值都在 [0,1][0,1] 区间内。
这样的标准化操作可以帮助模型更好地训练和收敛,提高了模型的鲁棒性,同时加快了模型训练的速度。
train_data, valid_data = random_split(dataset,
lengths=[int(len(dataset)*0.8),int(len(dataset)*0.2)],
generator=torch.Generator().manual_seed(7))
# print("train: ", len(train_data))
# print("valid: ", len(valid_data))
train_loader = DataLoader(train_data, batch_size=64, shuffle=True)
valid_loader = DataLoader(valid_data, batch_size=64)
这段代码定义了数据集的划分方式以及相应的数据加载器。
首先,数据集(即 dataset)被随机划分为训练集和验证集,划分的方式是使用 PyTorch 中的 random_split() 函数。其中,lengths 参数指定了划分后训练集和验证集的长度比例,即训练集长度为总数据集的 80%,验证集长度为总数据集的 20%。同时,这里也设置了随机数生成器的种子为 7,保证每次划分结果的一致性。
接着,使用 PyTorch 中的 DataLoader() 函数对训练集和验证集进行批量数据的加载,具体来说:
- train_loader:表示训练集的数据加载器,它从 train_data 中按照指定大小(batch_size=64)将数据读取到内存中,并将数据打乱(shuffle=True)以提高模型鲁棒性。这样,每次训练时可以从 train_data 中随机取出一个大小为 64 的批次进行训练。
- valid_loader:表示验证集的数据加载器,它从 valid_data 中按照指定大小(batch_size=64)将数据读取到内存中。与训练集不同的是,验证集一般不需要 shuffle 操作,因为在模型训练时是无法使用验证集进行反向传播和梯度更新的。
最终,train_loader 和 valid_loader 可以作为模型的输入数据来源,在模型的训练和验证过程中起到很重要的作用。
class CNN(nn.Module):
def __init__

该代码示例展示了如何使用PyTorch处理Kaggle上的狗猫分类问题,包括数据预处理、定义卷积神经网络模型、训练和验证过程,以及在测试集上的评估。模型采用CNN架构,通过数据增强、标准化处理提高模型性能。

4535

被折叠的 条评论
为什么被折叠?



