Press "Enter" to skip to content

深度学习库介绍:PyTorch和Lightning AI

深度学习库介绍:PyTorch和Lightning AI 四海 第1张  

深度学习是基于神经网络的机器学习模型的一种分支。在其他机器模型中,通过手动或依靠领域专业知识进行数据处理以找到有意义的特征;然而,深度学习可以模仿人脑来发现重要特征,提高模型性能。

深度学习模型有许多应用,包括人脸识别、欺诈检测、语音转文本、文本生成等等。深度学习已成为许多高级机器学习应用的标准方法,学习它们不会有任何损失。

为了开发这个深度学习模型,我们可以依靠各种库框架,而不是从零开始。在本文中,我们将讨论两个不同的库,即PyTorch和Lightning AI,用于开发深度学习模型。让我们开始吧。

 

PyTorch

 

PyTorch是一个用于训练深度学习神经网络的开源库框架。PyTorch由Meta group在2016年开发,并逐渐流行起来。其流行的原因在于PyTorch将Torch的GPU后端库与Python语言结合起来。这种组合使得该包易于用户理解,但在开发深度学习模型方面仍然强大。

PyTorch具有一些突出的特点,包括良好的前端界面、分布式训练和快速灵活的实验过程。由于PyTorch用户众多,社区开发和投资也非常庞大。因此,学习PyTorch从长远来看会非常有益。

PyTorch的构建块是张量,即用于编码所有输入、输出和模型参数的多维数组。你可以把张量想象成NumPy数组,但具有在GPU上运行的能力。

让我们试用一下PyTorch库。如果你没有GPU系统(尽管它也可以在CPU上工作),建议在云端进行教程,比如Google Colab。但是,如果你想在本地开始,我们需要通过这个页面安装库。选择适合你的系统和规格。

例如,如果你有一个支持CUDA的系统,下面的代码是用于pip安装的。

pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

 

安装完成后,让我们尝试一些PyTorch的功能来开发深度学习模型。在本教程中,我们将基于PyTorch的网络教程,使用PyTorch制作一个简单的图像分类模型。我们将浏览代码并解释代码中发生的事情。

首先,我们需要使用PyTorch下载数据集。在本例中,我们将使用MNIST数据集,这是一个手写数字分类数据集。

from torchvision import datasets

train = datasets.MNIST(
    root="image_data",
    train=True,
    download=True
)

test = datasets.MNIST(
    root="image_data",
    train=False,
    download=True,
)

 

我们将下载MNIST的训练集和测试集到我们的根文件夹中。让我们看看我们的数据集是什么样子。

import matplotlib.pyplot as plt
 
for i, (img, label) in enumerate(list(train)[:10]):
    plt.subplot(2, 5, i+1)
    plt.imshow(img, cmap="gray")
    plt.title(f'Label: {label}')
    plt.axis('off')
 
plt.show()

 

深度学习库介绍:PyTorch和Lightning AI 四海 第2张  

每个图像都是一个介于零和九之间的单个数字,意味着我们有十个标签。接下来,让我们基于这个数据集开发一个图像分类器。

我们需要将图像数据集转换为张量,以便使用PyTorch开发深度学习模型。由于图像是PIL对象,我们可以使用PyTorch的ToTensor函数进行转换。此外,我们还可以使用datasets函数自动转换图像。

from torchvision.transforms import ToTensor
train = datasets.MNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)

test = datasets.MNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

 

通过将转换函数传递给transform参数,我们可以控制数据的形式。接下来,我们将数据包装到DataLoader对象中,以便PyTorch模型可以访问我们的图像数据。

from torch.utils.data import DataLoader
size = 64

train_dl = DataLoader(train, batch_size=size)
test_dl = DataLoader(test, batch_size=size)

for X, y in test_dl:
    print(f"X的形状[N, C, H, W]: {X.shape}")
    print(f"y的形状: {y.shape} {y.dtype}")
    break

 

X的形状[N, C, H, W]: torch.Size([64, 1, 28, 28])
y的形状: torch.Size([64]) torch.int64

 

在上面的代码中,我们为训练和测试数据创建了DataLoader对象。每个数据批次迭代将返回64个特征和标签。此外,我们的图像形状为28 * 28(高度 * 宽度)。

接下来,我们将开发神经网络模型对象。

from torch import nn

#如果有GPU访问权限,请更改为'cuda'
device = 'cpu'

class NNModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.lr_stack = nn.Sequential(
            nn.Linear(28*28, 128),
            nn.ReLU(),
            nn.Linear(128, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.lr_stack(x)
        return logits

model = NNModel().to(device)
print(model)

 

NNModel(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (lr_stack): Sequential(
    (0): Linear(in_features=784, out_features=128, bias=True)
    (1): ReLU()
    (2): Linear(in_features=128, out_features=128, bias=True)
    (3): ReLU()
    (4): Linear(in_features=128, out_features=10, bias=True)
  )
)

 

在上面的对象中,我们创建了一个带有少量层结构的神经模型。为了开发神经模型对象,我们使用nn.module函数的子类化方法,在__init__中创建神经网络层。

我们首先使用flatten函数将2D图像数据转换为像素值。然后,我们使用sequential函数将我们的层包装成一系列层。在sequential函数内部,我们有我们的模型层:

nn.Linear(28*28, 128),
nn.ReLU(),
nn.Linear(128, 128),
nn.ReLU(),
nn.Linear(128, 10)

 

按顺序,上面发生的是:

  1. 首先,通过线性层中的线性函数将28 * 28个特征的输入数据转换为128个特征的输出。
  2. ReLU是一个非线性激活函数,介于模型输入和输出之间,引入非线性。
  3. 128个特征输入到线性层,并有128个特征输出。
  4. 另一个ReLU激活函数。
  5. 128个特征作为线性层的输入,10个特征作为输出(我们的数据集标签只有10个标签)。

最后,forward函数用于模型的实际输入过程。接下来,模型将需要损失函数和优化函数。

from torch.optim import SGD

loss_fn = nn.CrossEntropyLoss()
optimizer = SGD(model.parameters(), lr=1e-3)

 

在下面的代码中,我们只是在运行建模活动之前准备训练和测试。

import torch
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device)
        pred = model(X)
        loss = loss_fn(pred, y)

        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

        if batch % 100 == 0:
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"损失: {loss:>2f}  [{current:>5d}/{size:>5d}]")

def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"测试错误:\n准确率:{(100*correct):>0.1f}%,平均损失:{test_loss:>2f} \n")

 

现在我们准备运行模型训练。我们需要决定我们想要使用模型进行多少个epoch(迭代)。对于这个例子,假设我们想要运行5次。

epoch = 5
for i in range(epoch):
    print(f"Epoch {i+1}\n-------------------------------")
    train(train_dl, model, loss_fn, optimizer)
    test(test_dl, model, loss_fn)
print("完成!")

 

深度学习库介绍:PyTorch和Lightning AI 四海 第3张  

该模型现在已经完成训练,可以用于任何图像预测活动。结果可能会有所不同,所以请期待与上述图像不同的结果。

这只是PyTorch可以做的一些事情,但你可以看到使用PyTorch构建模型很容易。如果你对预训练模型感兴趣,PyTorch有一个可以访问的Hub。

 

Lighting AI

 

Lighting AI是一家提供各种产品的公司,用于减少训练PyTorch深度学习模型的时间并简化模型。他们的一个开源产品是PyTorch Lightning,它是一个提供训练和部署PyTorch模型框架的库。

Lighting提供了一些功能,包括代码灵活性、无样板文件、最小API和改进的团队协作。Lighting还提供了多GPU利用和快速、低精度训练等功能。这使Lighting成为开发PyTorch模型的良好选择。

让我们尝试使用Lighting进行模型开发。首先,我们需要安装这个包。

pip install lightning

 

安装Lighting后,我们还需要安装Lighting AI的另一个产品TorchMetrics,以简化度量选择。

pip install torchmetrics

 

安装所有库后,我们将尝试使用Lighting包装器开发与之前示例相同的模型。下面是开发模型的完整代码。

import torch
import torchmetrics
import pytorch_lightning as pl
from torch import nn
from torch.optim import SGD

# 如果你有GPU,将其更改为'cuda'
device = 'cpu'

class NNModel(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.lr_stack = nn.Sequential(
            nn.Linear(28 * 28, 128),
            nn.ReLU(),
            nn.Linear(128, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )
        self.train_acc = torchmetrics.Accuracy(task="multiclass", num_classes=10)
        self.valid_acc = torchmetrics.Accuracy(task="multiclass", num_classes=10)

    def forward(self, x):
        x = self.flatten(x)
        logits = self.lr_stack(x)
        return logits

    def training_step(self, batch, batch_idx):
        x, y = batch
        x, y = x.to(device), y.to(device)
        pred = self(x)
        loss = nn.CrossEntropyLoss()(pred, y)
        self.log('train_loss', loss)
       
        # 计算训练准确率
        acc = self.train_acc(pred.softmax(dim=-1), y)
        self.log('train_acc', acc, on_step=True, on_epoch=True, prog_bar=True)
        return loss

    def configure_optimizers(self):
        return SGD(self.parameters(), lr=1e-3)

    def test_step(self, batch, batch_idx):
        x, y = batch
        x, y = x.to(device), y.to(device)
        pred = self(x)
        loss = nn.CrossEntropyLoss()(pred, y)
        self.log('test_loss', loss)
       
        # 计算测试准确率
        acc = self.valid_acc(pred.softmax(dim=-1), y)
        self.log('test_acc', acc, on_step=True, on_epoch=True, prog_bar=True)
        return loss

 

让我们分解一下上面的代码发生了什么。与我们之前开发的PyTorch模型不同的是,NNModel类现在使用LightingModule的子类化。此外,我们使用TorchMetrics分配了用于评估的准确率指标。然后,我们在类内部添加了训练和测试步骤,并设置了优化函数。

有了所有设置好的模型,我们将使用转换后的DataLoader对象来运行模型训练。

# 创建一个PyTorch Lightning训练器
trainer = pl.Trainer(max_epochs=5)

# 创建模型
model = NNModel()

# 拟合模型
trainer.fit(model, train_dl)

# 测试模型
trainer.test(model, test_dl)

print("训练完成")

 

深度学习库介绍:PyTorch和Lightning AI 四海 第4张  

使用Lightning库,我们可以轻松调整所需的结构。要进一步阅读,请查阅他们的文档。

 

结论

 

PyTorch是一个用于开发深度学习模型的库,它提供了一个简单的框架,可以访问许多高级API。Lightning AI也支持该库,它提供了一个简化模型开发和增强开发灵活性的框架。本文介绍了库的特点和简单的代码实现。Cornellius Yudha Wijaya是一名数据科学助理经理和数据作者。在全职工作于Allianz Indonesia的同时,他喜欢通过社交媒体和写作媒体分享Python和数据技巧。

Leave a Reply

Your email address will not be published. Required fields are marked *