关于机器学习:炼丹侠如何用GPU服务器实现ResNet50训练

53次阅读

共计 3850 个字符,预计需要花费 10 分钟才能阅读完成。

ResNet-50 是一种深度卷积神经网络,由 Microsoft Research 提出,用于解决深层神经网络中的梯度隐没和信息流动问题。它是 ResNet 系列中的一员,是绝对较小的一种架构。ResNet-50 在 2015 年的 ImageNet Large Scale Visual Recognition Challenge 中取得了第一名。

ResNet-50 的次要翻新点是引入了“残差块”。传统的深层神经网络越深,梯度隐没和信息传递艰难会变得更重大,导致训练艰难。残差块通过引入跨层的“残差连贯”来解决这个问题。在传统的卷积层前面,残差块通过将输出间接加到输入中,从而容许网络在必要时跳过某些层,使信息得以更轻松地传递。这种残差连贯容许训练更深、更简单的网络,而不会呈现梯度隐没问题。

ResNet-50 的架构蕴含 50 个卷积层,次要分为多个残差块。每个残差块由一系列卷积层、批归一化层和激活函数(通常是 ReLU)组成。架构中还包含了全局均匀池化层和一个全连贯层用于分类工作。

ResNet-50 在计算机视觉畛域被宽泛用于图像分类、指标检测、图像宰割等工作,因为其弱小的性能和能力。它的胜利引发了许多后续网络架构的启发,成为了深度学习畛域的重要里程碑之一。

ResNet-50 在泛滥计算机视觉工作中都表现出色,特地实用于须要解决简单特色和大规模数据集的场景。其深度架构和独特的残差连贯设计使得它在图像分类、指标检测、图像宰割等工作中体现优越。在图像分类工作中,ResNet-50 可能高效地辨认物体和场景,在指标检测工作中可能精确地定位和辨认指标物体,而在图像宰割工作中,它可能将图像宰割为不同的区域并辨认每个区域的对象或特色。此外,ResNet-50 还在特征提取工作中有着杰出体现,将图像转化为高级语义特色,可用于图像生成和迁徙学习。尤其对于大规模数据集,其深度和残差连贯使得其可能更好地泛化和适应数据的复杂性,从而在大规模数据训练集上展现出卓越性能。

本次采纳炼丹侠平台的 A100 服务器对 ResNet-50 模型进行训练,设置了应用 A100 训练和应用 CPU 训练两种形式,采纳的数据集为公开的 cifar10 数据集,残缺代码如下:

GPU 版本

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

# 设置随机种子以便复现性
torch.manual_seed(42)

# 查看 GPU 是否可用,如果可用则应用
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# 超参数
batch_size = 64
learning_rate = 0.001
num_epochs = 10

# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

# 下载 MNIST 数据集并创立数据加载器
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)

# 定义简略的 ResNet-50 模型(仅作示例,实际上 ResNet-50 不适用于 MNIST)class ResNet50(nn.Module):
    def __init__(self):
        super(ResNet50, self).__init__()
        self.model = torchvision.models.resnet50(pretrained=False)
        self.model.fc = nn.Linear(2048, 10)  # 批改全连贯层输入类别数为 10(MNIST 有 10 个类别)def forward(self, x):
        return self.model(x)

# 实例化模型并挪动到 GPU
model = ResNet50().to(device)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images, labels = images.to(device), labels.to(device)

        # 前向流传
        outputs = model(images)
        loss = criterion(outputs, labels)

        # 反向流传和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (i+1) % 100 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}')

print('Training finished.')

# 保留模型
torch.save(model.state_dict(), 'resnet50_mnist.pth')

CPU 版本

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

# 设置随机种子以便复现性
torch.manual_seed(42)

# 超参数
batch_size = 64
learning_rate = 0.001
num_epochs = 10

# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

# 下载 MNIST 数据集并创立数据加载器
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)

# 定义简略的 ResNet-50 模型(仅作示例,实际上 ResNet-50 不适用于 MNIST)class ResNet50(nn.Module):
    def __init__(self):
        super(ResNet50, self).__init__()
        self.model = torchvision.models.resnet50(pretrained=False)
        self.model.fc = nn.Linear(2048, 10)  # 批改全连贯层输入类别数为 10(MNIST 有 10 个类别)def forward(self, x):
        return self.model(x)

# 实例化模型并挪动到 CPU
device = torch.device("cpu")
model = ResNet50().to(device)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images, labels = images.to(device), labels.to(device)

        # 前向流传
        outputs = model(images)
        loss = criterion(outputs, labels)

        # 反向流传和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (i+1) % 100 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4

训练过程如下:

https://www.bilibili.com/video/BV16N411n7S6/?vd_source=64fad5…

ResNet-50 在解决深层网络的梯度隐没和信息流动问题上性能优越。它引入了“残差块”和“残差连贯”,容许网络在必要时跳过层级,防止训练艰难。在本次训练过程中,通过对 cifar10 数据集的训练,应用 A100 进行减速的训练时长为 72s,应用 CPU 进行训练的时长为 2200s,工夫性能晋升 30 倍。

正文完
 0