简介

PyTorch 是一个开源的 Python 机器学习框架,由 Facebook 的人工智能研究团队开发并维护。它可以被用于深度学习任务,如图像识别、自然语言处理和语音识别等。PyTorch 提供了一种灵活的、动态的计算图系统,使得开发人员可以非常容易地创建和训练深度学习模型。PyTorch 还提供了丰富的工具和库,方便用户进行数据加载、数据处理和模型评估等操作。PyTorch 支持多种硬件,包括 CPU、GPU 和 TPU,使得用户可以轻松地在不同的硬件平台上训练和部署他们的深度学习模型。PyTorch 已经成为了深度学习领域中最受欢迎和广泛使用的框架之一。

PyTorch相对于TensorFlow具有以下优势:

  • 简单易用:PyTorch 的动态图机制使得用户可以更容易地定义、调试和修改模型,而不需要考虑 TensorFlow 静态图的复杂性。

  • 动态计算图:PyTorch 的计算图是动态的,它可以随着代码的运行而改变,这使得用户可以更加灵活地构建模型,尤其是在处理变长输入时更方便。

  • 更好的调试和可视化:PyTorch 的代码结构和调试工具使得用户可以更容易地进行模型调试和可视化。

  • 更好的支持 CUDA:PyTorch 的 CUDA 支持更好,使得用户可以更容易地在 GPU 上进行训练和推理。

  • 社区支持:PyTorch 在学术界和工业界都拥有广泛的用户和社区支持,可以得到更好的文档、教程和代码库支持。

CUDA

CUDA (Compute Unified Device Architecture) 是由 NVIDIA 开发的并行计算平台和编程模型。它允许程序员使用 NVIDIA 显卡进行高性能计算,加速各种计算密集型任务,如机器学习、深度学习、科学计算等。

CUDA 包含两个主要组件:CUDA Toolkit 和 CUDA Runtime。CUDA Toolkit 是一套用于开发和编译 CUDA 应用程序的工具和库,其中包括 NVIDIA 的 CUDA 编译器、CUDA 库、CUDA 程序调试器等。CUDA Runtime 则是一组用于在 NVIDIA GPU 上执行 CUDA 程序的库。

为了使用 CUDA 进行编程,你需要安装适用于你的 NVIDIA 显卡的 CUDA Toolkit。CUDA Toolkit 通常包括适用于不同操作系统和编程语言的版本,如 Linux、Windows、macOS、C/C++、Python 等。你还需要确保你的显卡支持 CUDA。NVIDIA 提供了一个支持 CUDA 的 GPU 列表,你可以在其中查找你的显卡型号以确定它是否支持 CUDA。

在深度学习中,CUDA 是加速神经网络训练和推断的主要工具之一。通过使用 CUDA,深度学习框架如 PyTorch、TensorFlow 等可以在 GPU 上加速张量运算和计算图执行,从而提高深度学习模型的训练和推断速度。

安装

链接:

首先查看电脑上的cuda版本,使用如下命令查看:

nvidia-smi

运行后,可在CUDA VERSION查看cuda版本,NVIDIA-SMI为当前显卡驱动的版本号。

进入pytorch安装地址,找到对应的CUDA版本进行pip的安装,假设CUDA的版本为11.7,那么根据官网可以执行如下命令安装pytorch:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117

若没有显卡(集显),可以使用CPU版本安装pytorch:

pip install torch torchvision torchaudio

张量(Tensor)

tensor是一个数学概念,可以翻译为张量。张量是基向量和分量的组合,可以用来表示在不同坐标系之间转换的多线性函数。在物理学和工程学中,张量被广泛应用于描述各种物理量和几何对象,如应力、应变、电磁场等。

tensor是PyTorch中的一个基础数据结构,用于存储多维数据。与NumPy的ndarray类似,但PyTorch的tensor可以在GPU上运行以加速计算。你可以直接使用torch.tensor()函数来创建一个张量。这个函数接受数据作为输入,并返回一个包含该数据的新张量。

首先引入tensor:

from torch import tensor

例如,创建一个张量:

from torch import tensor
x = tensor([1.0, 2.0, 3.0])

或者从NumPy数组创建张量:

import numpy as np  
from torch import tensor

numpy_array = np.array([1.0, 2.0, 3.0])  
tensor_from_numpy = tensor(numpy_array)

DataSet

在PyTorch中,Dataset是一个抽象类,用于表示数据集。它主要被用作一个包装类,可以将数据包装为Dataset类,然后传入DataLoader中。这使得在使用DataLoader时可以更加快捷地对数据进行操作。

自定义的数据集需要继承Dataset类并覆写相关方法,从而实现索引(index)到样本(sample)的映射。这一过程涉及到重载一些函数,如__init__()等。然而,Dataset类本身只相当于一个打包工具,包含了数据的地址,真正把数据读入内存的过程是由DataLoader进行的,它负责在训练过程中传递并获取一个batch的数据。

为了创建一个自定义DataSet类,我们需要继承Dataset抽象类

import torch  
from torch.utils.data import Dataset  
  
class MyCustomDataset(Dataset):  
    def __init__(self, data, targets):  
        self.data = data  
        self.targets = targets  
  
    def __len__(self):  
        # 返回数据集的大小  
        return len(self.data)  
  
    def __getitem__(self, idx):  
        # 根据索引返回一个数据样本和对应的目标值  
        return self.data[idx], self.targets[idx]

要使用这个自定义的Dataset类,你可以像下面这样创建一个数据集对象,并将其传递给一个数据加载器(DataLoader):

from torch.utils.data import DataLoader  
  
# 创建数据集对象  
my_dataset = MyCustomDataset(data, targets) 
  
# 创建数据加载器
data_loader = DataLoader(my_dataset, batch_size=4, shuffle=True)

同样的,下载pytorch官方的蚂蚁蜜蜂分类数据集后,你可以为它们创建自定义Dataset:

import os
from pathlib import Path
from PIL import Image
from torch.utils.data import Dataset

class MyPictureDataSet(Dataset):

    def __init__(self, root_dir, lable):
        self.image_path = Path(root_dir, lable).resolve()
        self.image_list = os.listdir(self.image_path)

    def __getitem__(self, index):
        item = self.image_list(index)
        return Image.open(item)
    
    def __len__(self):
        return len(self.image_list)

Tensorboard

TensorBoard 是 TensorFlow 的可视化工具,它用于展示你的 TensorFlow、Keras、PyTorch 等机器学习框架的运行过程。尽管 TensorBoard 最初是为 TensorFlow 设计的,但由于其灵活的接口和广泛的适用性,它也可以与 PyTorch 一起使用。TensorBoard 允许你可视化你的模型架构、绘制量化指标的图表、显示图片、文本等,这对于理解、调试和优化模型是非常有帮助的。

为了在PyTorch中使用TensorBoard,首先使用pip安装:

pip install tensorboard

在 PyTorch 中,torch.utils.tensorboard 提供了一个 SummaryWriter 类,用于写入 TensorBoard 可以读取的日志文件。你需要创建一个 SummaryWriter 实例,并指定日志文件的保存路径。

from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image

writer = SummaryWriter("logs") # 指定输出的log路径
# 读取数据
image_path = "data/train/ants/6240329_72c01e663e.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)
print(type(img_array))
print(img_array.shape)
# 添加数据
writer.add_image("train", img_array, 1, dataformats='HWC')
# 写入log中,y = 2x
for i in range(100):
    writer.add_scalar("y=2x", 2*i, i) # 2*i对应的是y轴,i对应的是x轴
# 关闭数据流
writer.close()

使用如下命令启动tensorboard:

tensorboard --logdir=runs # 默认6006端口
tensorboard --logdir=runs --port=8008 # 修改运行端口的位置

Torchvision

Torchvision是PyTorch生态系统中的一个重要组成部分,专注于机器视觉任务。它为研究者和开发者提供了一整套工具,用于构建、训练和部署图像和视频分析模型。

Transforms

在PyTorch中,torchvision.transforms是一个非常重要的模块,它提供了一系列图像预处理操作,这些操作可以组合成一个预处理流程,用于在训练和验证模型之前对图像数据进行增强和标准化。通过使用Transforms,我们可以确保模型在不同的图像条件下都能获得较好的性能,同时减少过拟合的风险。

transforms的主要作用和功能:

  • 数据增强:通过一系列随机变换(如随机裁剪、旋转等)来扩展数据集,使得模型能够更好地泛化到未见过的数据上。

  • 标准化:将数据转换成模型更容易处理的格式,如将图像数据标准化到特定的均值和标准差。

  • 转换到Tensor:将PIL图像或NumPy数组转换为PyTorch的Tensor格式,以便能够输入到神经网络中。

  • 其他预处理:如调整图像大小、更改图像通道顺序(例如从RGB到BGR)等。

ToTensor

ToTensor是PyTorch的torchvision.transforms模块中的一个函数,它的作用是将PIL图像或NumPy ndarray转换为torch.Tensor。这对于神经网络模型来说是非常重要的,因为神经网络通常接受tensor作为输入。

ToTensor函数接受PIL图像或NumPy ndarray作为输入。对于PIL图像,它应该是一个在0到255范围内的整数像素值的图像。对于NumPy ndarray,它应该是一个形状为(H x W x C)的数组,其中H是图像的高度,W是图像的宽度,C是图像的通道数,数据类型通常为uint8。以下是一个将PIL的图像转换成tensor的例子:

from PIL import Image
from torchvision.transforms import ToTensor

image = Image.open("hymenoptera_data/train/ants/0013035.jpg")
tensor_image = ToTensor()(image)
print(tensor_image)

Normalize

Normalize是PyTorch中torchvision.transforms模块提供的另一个重要的图像预处理操作。它的主要作用是对图像的像素值进行标准化处理,即对每个通道的像素值减去均值(mean)并除以标准差(std),从而使处理后的图像数据符合标准正态分布,这有助于提升模型的收敛速度和性能。

Normalize通常用在ToTensor之后,因为ToTensor已经将像素值从[0, 256]缩放到[0.0, 1.0]范围,而Normalize则进一步将像素值标准化到[-1, 1]或接近正态分布的范围。

from PIL import Image
from torchvision.transforms import ToTensor, Normalize

image = Image.open("hymenoptera_data/train/ants/0013035.jpg")
tensor_image = ToTensor()(image)
print(tensor_image)

# 假设mean和std是预先计算好的每个通道的均值和标准差  
# 对于RGB图像,通常mean和std都是长度为3的列表或元组  
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
normalize_image = Normalize(mean, std)(tensor_image)
print(normalize_image)

Resize

Resizetorchvision.transforms模块中提供的一个方法,它用于改变图像的尺寸。在处理图像数据时,经常需要调整图像的大小以适应不同的模型或输入要求。Resize方法可以将图像的宽度和高度调整为指定的尺寸,或者按照指定的比例进行缩放。

torchvision.transforms中,Resize可以接受以下几种形式的参数:

  • 一个整数:如果只提供一个整数,那么图像将被缩放到该尺寸的正方形。例如,Resize(256)会将图像缩放到256x256像素。

  • 一个元组(height, width):如果提供两个整数组成的元组,那么图像将被缩放到指定的宽度和高度。例如,Resize((224, 224))会将图像缩放到224x224像素。

下面是一个具体的例子,展示如何使用Resize方法来改变图像的大小:

from PIL import Image
from torchvision.transforms import ToTensor, Resize

image = Image.open("hymenoptera_data/train/ants/0013035.jpg")
print(image.size)
resize_image = Resize((512, 512))(image)
tensor_resize_image = ToTensor()(resize_image)
print(tensor_resize_image)

Compose

在PyTorch中,torchvision.transforms.Compose是一个非常有用的工具,它允许你将多个图像转换操作组合在一起,形成一个连续的转换流程。这对于数据预处理特别有用,因为通常我们需要对图像执行一系列操作,如裁剪、缩放、归一化等。通过将这些操作组合在一个Compose对象中,我们可以简化代码并提高数据加载的效率。

下面是一个使用Compose的例子:

from PIL import Image  
from torchvision.transforms import ToTensor, Normalize, Resize, Compose, CenterCrop
  
# 定义一系列图像转换操作  
transform = Compose([
    # 第一步:Resize,将图像缩放到指定尺寸,这里是256x256
    Resize(256),
    # 第二步:CenterCrop,从中心裁剪出224x224的区域,常用于保持长宽比的同时缩放图像
    CenterCrop(224),
    # 第三步:ToTensor,将PIL图像或NumPy ndarray转换为torch.Tensor,并缩放到[0.0, 1.0]
    ToTensor(),
    # 第四步:Normalize,标准化图像,减去均值并除以标准差,这里使用的是预训练模型常用的均值和标准差  
    Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
  
# 加载一张图像
image_path = "hymenoptera_data/train/ants/0013035.jpg"
pil_image = Image.open(image_path).convert('RGB')  # 确保图像是RGB格式
  
# 应用上面定义的转换流程
transformed_image = transform(pil_image)
  
# 此时,transformed_image是一个形状为(C, H, W)的torch.Tensor,且已经标准化
# C是通道数(对于RGB图像是3),H和W分别是图像的高度和宽度(在这里是224x224)
# 它的值已经被标准化到接近标准正态分布,这对于神经网络训练是非常有益的

预定义数据集

torchvision.datasets模块是PyTorch官方提供的计算机视觉数据集加载工具,它包含了许多预处理好的常用数据集,方便用户直接用于模型训练和测试。

若需要查看datasets中的数据集,可以进入官网:Datasets — Torchvision 0.16 documentation (pytorch.org)

以下是一些常用的数据集及其简要描述:

  1. CIFAR-10 和 CIFAR-100

    • CIFAR-10:包含10个类别的60,000张32x32彩色图像,每个类别有6,000张。其中有50,000张用于训练,10,000张用于测试。

    • CIFAR-100:与CIFAR-10类似,但包含100个类别,每个类别有600张图像。这些类别被分为20个超类。CIFAR-100对于多类别分类任务更具挑战性。

  2. ImageNet

    • ImageNet是一个大规模视觉识别挑战赛(ILSVRC)所使用的数据集,包含超过100万个图像,分为1,000个类别。常用的是ILSVRC 2012版本的数据集,它包含1,281,167张训练图像、50,000张验证图像和100,000张测试图像(测试图像的标签不公开)。

  3. COCO (Common Objects in Context)

    • COCO是一个用于图像识别、目标检测、语义分割和关键点检测的大型数据集。它提供了丰富的标注,包括图像中物体的精确分割、关键点位置和物体的三维形状等。COCO数据集有多个版本,常用的有COCO 2014和COCO 2017。

  4. Fashion-MNIST

    • Fashion-MNIST旨在作为MNIST数据集的直接替代品,用于更复杂的图像分类任务。它包含10个类别的70,000张28x28灰度图像,每个类别7,000张。Fashion-MNIST的类别包括T恤、裤子、套头衫、连衣裙、外套、凉鞋、衬衫、运动鞋、包和短靴。

  5. EMNIST (Extended MNIST)

    • EMNIST是MNIST的扩展版本,它包含了手写数字和字符的更大集合。除了数字0-9,EMNIST还包含了拉丁字母的大小写以及标点符号,总共分为62个类别。

  6. HMDB51

    • HMDB51是一个用于动作识别的大规模视频数据集,包含51个动作类别,总共有6,766个视频剪辑。

  7. Kinetics

    • Kinetics是一个大规模、高质量的视频动作分类数据集。它包含数百个动作类别,每个类别有数百个视频样本。Kinetics数据集有多个版本,如Kinetics-400、Kinetics-600和Kinetics-700,数字表示类别数。

  8. SVHN (Street View House Numbers)

    • SVHN是一个用于数字识别的数据集,包含从谷歌街景视图中收集的大量图像。数据集中的图像包含门牌号码,目标是识别这些数字。

  9. VOC (PASCAL Visual Object Classes)

    • VOC是一个用于目标检测和图像分割的标准数据集。它包含20个常见物体类别,如人、自行车、汽车、狗等。VOC数据集有多个年份的版本,如VOC2007、VOC2012等。

如果你想加载 MNIST 数据集(一个手写数字分类的数据集),你可以这样做:

from torchvision import datasets

# 下载并加载训练数据集
train_dataset = datasets.MNIST(root='./dataset', train=True, download=True, transform=None)

# 下载并加载测试数据集
test_dataset = datasets.MNIST(root='./dataset', train=False, download=True, transform=None)

DataLoader

PyTorch的DataLoader设计主要是为了实现以下几个目标:

  • 批量处理:神经网络训练时,通常需要将数据分成多个小批量进行处理。DataLoader可以自动为我们完成这一任务。

  • 数据打乱:在每个训练周期开始时,DataLoader可以重新打乱数据,这有助于提高模型的泛化能力。

  • 并行加载:利用Python的多进程功能,DataLoader可以支持数据的并行加载,从而在训练过程中不会因数据加载而造成瓶颈。

DataLoader主要用于以下场景:

  • 训练神经网络:在训练神经网络时,我们需要不断地从数据集中抽取小批量的数据来进行训练。DataLoader可以很好地完成这一任务。

  • 验证和测试:除了训练外,我们还需要在验证集和测试集上评估模型的性能。DataLoader也可以用于这些场景。

为了使用DataLoader,我们需要根据以下步骤编写脚本:

  1. 定义数据集:首先,我们需要定义一个数据集。这可以通过继承torch.utils.data.Dataset类并实现__len____getitem__方法来完成。

  2. 实例化DataLoader:然后,我们可以使用定义的数据集来实例化一个DataLoader对象。在实例化时,我们可以设置各种参数,如批量大小、是否打乱数据、并行加载的进程数等。

  3. 迭代DataLoader:最后,在训练和验证过程中,我们可以迭代DataLoader对象来获取小批量的数据。

首先我们新建一个自定义数据集:

from torch.utils.data import Dataset
  
class MyDataset(Dataset):
    def __init__(self, data):
        self.data = data
  
    def __len__(self):
        return len(self.data)
  
    def __getitem__(self, idx):
        return self.data[idx]

接下来我们将数据输入在dataset中,然后使用dataloader加载dataset

data = torch.randn(100, 3, 224, 224)  # 随机生成100张3通道的224x224图像
dataset = MyDataset(data)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4)

DataLoader中,batch_sizeshufflenum_workers是三个非常常用的参数,它们的作用如下:

  1. batch_size

    • 作用:指定每个批次(batch)中样本的数量。

    • 解释:在训练神经网络时,通常不会一次性将所有数据送入网络,而是分批送入。batch_size就定义了每个批次中包含的数据样本数。例如,如果batch_size=32,那么DataLoader每次会取出32个样本组成一个批次返回。

  2. shuffle

    • 作用:指定是否在每个训练周期(epoch)开始时打乱数据集。

    • 解释:当shuffle=True时,DataLoader会在每个epoch开始时重新随机排列数据集中的样本顺序,这有助于增加模型的泛化能力,因为每次训练时数据的顺序都不同。如果shuffle=False,则数据集的顺序保持不变。

  3. num_workers

    • 作用:指定用于数据加载的子进程数量。

    • 解释:数据加载可能会成为训练过程中的瓶颈,尤其是在处理大量数据或复杂的数据预处理时。num_workers允许你并行地加载数据,从而加快数据加载速度。例如,如果num_workers=4,那么会有4个子进程同时工作,从数据集中预取数据,这样主进程(通常是训练循环)就可以更高效地利用计算资源。需要注意的是,增加num_workers会增加内存消耗,并且当num_workers>0时,数据加载会在子进程中异步进行,这有时会导致一些难以调试的问题。

接下来就可以使用该Dataloader进行机器训练了:

for batch in dataloader:  
    # 使用batch进行训练或验证  
    pass

文章作者: Vsoapmac
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 soap的会员制餐厅
人工智能 人工智能 深度学习
喜欢就支持一下吧