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倍。