【pytorch框架】使用 PyTorch 进行深度学习
PyTorch 是由 Facebook 创建和发布的用于深度学习计算的 Python 库。它起源于早期的库 Torch 7,但完全重写。它是两个最受欢迎的深度学习库之一。PyTorch 是一个完整的库,能够训练深度学习模型以及在推理模式下运行模型,并支持使用 GPU 进行更快的训练和推理。这是一个我们不能忽视的平台。您可以使用pip安装 PyTorch。在撰写本文时,PyTorch 的最新版本是
1.Pytorch介绍
PyTorch 是由 Facebook 创建和发布的用于深度学习计算的 Python 库。它起源于早期的库 Torch 7,但完全重写。
它是两个最受欢迎的深度学习库之一。PyTorch 是一个完整的库,能够训练深度学习模型以及在推理模式下运行模型,并支持使用 GPU 进行更快的训练和推理。这是一个我们不能忽视的平台。
您可以使用 pip安装 PyTorch 。在撰写本文时,PyTorch 的最新版本是 2.0。每个平台(包括 Windows、Linux 和 macOS)都有预构建的 PyTorch。在有效的 Python 环境中,应该照顾好这一点, pip 以便在您的平台中为您提供最新版本。
除了 PyTorch 之外,还有通常与 PyTorch 一起使用的 torchvision 库。它提供了许多有用的功能来帮助计算机视觉项目。
sudo pip install torch torchvision
这样安装可能默认安装最新版本,也可以通过pip自定义进行安装 Previous PyTorch Versions | PyTorch
可选cuda版本或者使用cpu还有平台版本(windows、linux、mac)
使用示例
# Example of PyTorch library
import torch
# declare two symbolic floating-point scalars
a = torch.tensor(1.5)
b = torch.tensor(2.5)
# create a simple symbolic expression using the add function
c = torch.add(a, b)
print(c)
查看torch版本
import torch
print(torch.__version__)
2.构建第一个多层感知机模型
深度学习是关于构建大规模神经网络。神经网络最简单的形式称为多层感知器模型。神经网络的构建块是人工神经元或感知器。这些是简单的计算单元,具有加权输入信号并使用激活函数产生输出信号。
感知器被排列成网络。一排感知器称为一层,一个网络可以有多个层。网络中感知器的架构通常称为网络拓扑。配置完成后,需要在数据集上训练神经网络。神经网络的经典且仍然首选的训练算法称为随机梯度下降。

PyTorch 允许您在极少的代码行中开发和评估深度学习模型。
在下文中,您的目标是使用 PyTorch 开发您的第一个神经网络。使用 UCI 机器学习存储库中的标准二进制(两类)分类数据集,例如 Pima Indians 数据集。
为了简单起见,网络模型只是几层完全连接的感知器。在此特定模型中,数据集有 12 个输入或预测变量,输出是 0 或 1 的单个值。因此,网络模型应有 12 个输入(第一层)和 1 个输出(最后一层)。您的第一个模型将按如下方式构建:
import torch.nn as nn
model = nn.Sequential(
nn.Linear(8, 12),
nn.ReLU(),
nn.Linear(12, 8),
nn.ReLU(),
nn.Linear(8, 1),
nn.Sigmoid()
)
print(model)
这是一个具有 3 个全连接层的网络。每个层都是使用以下 nn.Linear(x, y) 语法在 PyTorch 中创建的,第一个参数是该层的输入数,第二个参数是输出数。在每层之间,使用整流线性激活,但在输出端,应用 Sigmoid 激活,使输出值介于 0 和 1 之间。这是一个典型的网络。深度学习模型就是在模型中有很多这样的层。
3.训练Pytorch模型
在 PyTorch 中构建神经网络并不能说明应该如何为特定作业训练模型。事实上,正如超参数所描述的那样,这方面有许多变化。在 PyTorch 或所有深度学习模型中,您需要决定以下有关如何训练模型:
- 什么是数据集,特别是输入和目标的外观
- 什么是损失函数来评估模型与数据的拟合优度
- 训练模型的优化算法是什么,优化算法的参数,如学习率和学习次数
使用了皮马印第安人数据集,所有输入都是数字。这将是最简单的情况,因为您不需要对数据进行任何预处理,因为神经网络可以轻松处理数字。
由于是二元分类问题,损失函数应为二元交叉熵。这意味着模型输出的目标值为分类结果的 0 或 1。但实际上,该模型可能会输出介于两者之间的任何内容。它越接近目标值越好(即损耗越低)。
梯度下降是优化神经网络的算法。梯度下降有许多变化,亚当是最常用的一种。
实现上述所有内容,以及上一课中构建的模型,以下是训练过程的代码:
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
dataset = np.loadtxt('pima-indians-diabetes.csv', delimiter=',')
X = dataset[:,0:8]
y = dataset[:,8]
X = torch.tensor(X, dtype=torch.float32)
y = torch.tensor(y, dtype=torch.float32).reshape(-1, 1)
loss_fn = nn.BCELoss() # binary cross-entropy
optimizer = optim.Adam(model.parameters(), lr=0.001)
n_epochs = 100
batch_size = 10
for epoch in range(n_epochs):
for i in range(0, len(X), batch_size):
Xbatch = X[i:i+batch_size]
y_pred = model(Xbatch)
ybatch = y[i:i+batch_size]
loss = loss_fn(y_pred, ybatch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f'Finished epoch {epoch}, latest loss {loss}')
上面的for循环是获取一批数据并馈入模型。然后观察模型的输出并计算损失函数。基于损失函数,优化器将对模型进行一步微调,使其能够更好地匹配训练数据。经过多个更新步骤后,模型应该足够接近训练数据,以便能够高精度地预测目标。
运行上面的训练循环,观察随着训练循环的进行,损失如何减少。
4.使用Pytorch模型推理
经过训练的神经网络模型是一种记住输入和目标如何相关的模型。然后,该模型可以在给定另一个输入的情况下预测目标。
在 PyTorch 中,经过训练的模型可以像函数一样运行。假设您在上一课中训练了模型,您可以按如下方式简单地使用它:
i = 5
X_sample = X[i:i+1]
y_pred = model(X_sample)
print(f"{X_sample[0]} -> {y_pred[0]}")
但实际上,运行推理的更好方法如下:
i = 5
X_sample = X[i:i+1]
model.eval()
with torch.no_grad():
y_pred = model(X_sample)
print(f"{X_sample[0]} -> {y_pred[0]}")
某些模型在训练和推理之间会有不同的行为。的 model.eval() 表示模型的目的是运行模型进行推理。该行 with torch.no_grad() 用于创建运行模型的上下文,以便 PyTorch 知道不需要计算梯度。这样可以消耗更少的资源。
这也是评估模型的方式。该模型输出一个介于 0 和 1 之间的 sigmoid 值。您可以通过将值四舍五入到最接近的整数(即布尔标签)来解释该值。比较舍入后的预测与目标匹配的频率,可以为模型分配准确率百分比,如下所示:
model.eval()
with torch.no_grad():
y_pred = model(X)
accuracy = (y_pred.round() == y).float().mean()
print(f"Accuracy {accuracy}")
运行上面的代码,看看你得到的准确性是多少。您应该达到大约 75%。
5.使用Torchvision加载数据
Torchvision 是 PyTorch 的姊妹库。在这个库中,有专门用于图像和计算机视觉的函数。如您所料,有一些功能可以帮助您读取图像或调整对比度。但可能最重要的是提供一个简单的接口来获取一些图像数据集。
您将构建一个深度学习模型来对小图像进行分类。这是一个模型,允许您的计算机查看图像上的内容。正如您在前面的课程中所看到的,拥有数据集来训练模型非常重要。您将使用的数据集是 CIFAR-10。它是 10 个不同对象的数据集。还有一个更大的数据集,称为CIFAR-100。
CIFAR-10数据集可以从互联网上下载。但是,如果您安装了torchvision,则只需执行以下操作:
import matplotlib.pyplot as plt
import torchvision
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True)
fig, ax = plt.subplots(4, 6, sharex=True, sharey=True, figsize=(12,8))
for i in range(0, 24):
row, col = i//6, i%6
ax[row][col].imshow(trainset.data[i])
plt.show()
该 torchvision.datasets.CIFAR10 函数可帮助您将 CIFAR-10 数据集下载到本地目录。数据集分为训练集和测试集。因此,上面的两行就是要得到它们。然后,从下载的数据集中绘制前 24 张图像。数据集中的每张图像都是以下之一的 32×32 像素图片:飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船或卡车。
6.使用Pytorch的DataLoader
上一课的 CIFAR-10 图像确实是 numpy 数组的格式。但对于 PyTorch 模型的使用,它需要位于 PyTorch 张量中。将 numpy 数组转换为 PyTorch 张量并不难,但在训练循环中,仍然需要将数据集分批划分。PyTorch DataLoader 可以帮助您使此过程更加顺畅。
回到上一课中加载的 CIFAR-10 数据集,您可以执行以下操作以获得相同的效果:
import matplotlib.pyplot as plt
import torchvision
import torch
from torchvision.datasets import CIFAR10
transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
trainset = CIFAR10(root='./data', train=True, download=True, transform=transform)
testset = CIFAR10(root='./data', train=False, download=True, transform=transform)
batch_size = 24
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=True)
fig, ax = plt.subplots(4, 6, sharex=True, sharey=True, figsize=(12,8))
for images, labels in trainloader:
for i in range(batch_size):
row, col = i//6, i%6
ax[row][col].imshow(images[i].numpy().transpose([1,2,0]))
break # take only the first batch
plt.show()
在此代码中,使用 transform 参数创建, trainset 以便在提取数据时将数据转换为 PyTorch 张量。这是在它后面的几行中 DataLoader 执行的。该 DataLoader 对象是一个 Python 可迭代对象,您可以提取输入(图像)和目标(整数类标签)。在本例中,将批处理大小设置为 24,并迭代第一个批处理。然后,显示批处理中的每个图像。
7.卷积神经网络
图像是 2D 结构。您可以通过扁平化它们轻松地将它们转换为一维向量,并构建神经网络模型来对它们进行分类。但众所周知,保留 2D 结构会更合适,因为分类是关于图像中的内容,即平移不变的。
图像处理神经网络的标准方法是使用卷积层。使用卷积层的神经网络称为卷积神经网络。示例如下:
import torch.nn as nn
model = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=(3,3), stride=1, padding=1),
nn.ReLU(),
nn.Dropout(0.3),
nn.Conv2d(32, 32, kernel_size=(3,3), stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=(2, 2)),
nn.Flatten(),
nn.Linear(8192, 512),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(512, 10)
)
print(model)
在上面,我们多次使用了 Conv2d 图层,以及 ReLU 激活。卷积层用于从图像中学习和提取特征。您添加的卷积层越多,网络可以学习更多高级特征。最终,您将使用池化层( MaxPool2d 如上图)对提取的特征进行分组,将它们展平为向量,然后将其传递到多层感知器网络进行最终分类。这是图像分类模型的通常结构。
8.训练图像分类器
结合为 CIFAR-10 数据集创建的 DataLoader,您可以使用以下训练循环来训练上一课中的卷积神经网络:
import torch.nn as nn
import torch.optim as optim
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
n_epochs = 20
for epoch in range(n_epochs):
model.train()
for inputs, labels in trainloader:
y_pred = model(inputs)
loss = loss_fn(y_pred, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
acc = 0
count = 0
model.eval()
with torch.no_grad():
for inputs, labels in testloader:
y_pred = model(inputs)
acc += (torch.argmax(y_pred, 1) == labels).float().sum()
count += len(labels)
acc /= count
print("Epoch %d: model accuracy %.2f%%" % (epoch, acc*100))
这将需要一段时间才能运行,您应该看到生成的模型可以达到不低于 70% 的准确率。
该模型是一个多分类网络。输出不是一个,而是许多分数,每个类一个。我们认为分数越高,模型认为图像属于某个类的置信度就越高。因此,使用的损失函数是交叉熵,即二元交叉熵的多类版本。
在上面的训练循环中,您应该会看到在前面的课程中学到的相当多的元素。包括在模型中的训练模式和推理模式之间切换、使用 torch.no_grad() 上下文以及计算准确性。
9.使用GPU训练
在 PyTorch 中使用 GPU 的方法是在执行之前将模型和数据发送到 GPU。然后,您可以选择从 GPU 发回结果,或直接在 GPU 中执行评估。
修改上一课中的代码以使用 GPU 并不难。以下是应该做的:
import torch.nn as nn
import torch.optim as optim
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
n_epochs = 20
for epoch in range(n_epochs):
model.train()
for inputs, labels in trainloader:
y_pred = model(inputs.to(device))
loss = loss_fn(y_pred, labels.to(device))
optimizer.zero_grad()
loss.backward()
optimizer.step()
acc = 0
count = 0
model.eval()
with torch.no_grad():
for inputs, labels in testloader:
y_pred = model(inputs.to(device))
acc += (torch.argmax(y_pred, 1) == labels.to(device)).float().sum()
count += len(labels)
acc /= count
print("Epoch %d: model accuracy %.2f%%" % (epoch, acc*100))
所做的更改如下: 您检查 GPU 是否可用并相应地设置。 device 然后将模型发送到设备。当输入(即一批图像)传递到模型时,应首先将其发送到相应的设备。由于模型输出也将在那里,因此损失计算或精度计算也应首先将目标发送到 GPU。
参考链接
Deep Learning with PyTorch (9-Day Mini-Course) - MachineLearningMastery.com
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)