【炼丹侠】如何用GPU服务器实现VGGNet训练

VGGNet是一种深度卷积神经网络,由牛津大学计算机视觉组的研究团队开发。VGGNet的设计思想简单而有效,以深度堆叠的卷积层为主要特点。

VGGNet的核心思想是通过多个小尺寸的卷积核和池化层来构建深度网络,具有比较小的感受野。相比于其他网络结构,如AlexNet,VGGNet采用了更深的网络结构,有更多的卷积层和池化层,从而提高了网络的表达能力。

VGGNet的基本组成单元是由连续的卷积层和池化层构成的块,通常有两到三个卷积层,后面跟随一个池化层。整个网络由多个这样的块组成,最后是几个全连接层和一个输出层。VGGNet的卷积核尺寸都是3x3,步长为1,并且在每个卷积层后都使用了ReLU激活函数进行非线性映射。

VGGNet的一个重要贡献是证明了增加网络深度可以提高性能,同时还提出了一种通用的网络结构设计原则。VGGNet在2014年的ImageNet图像识别挑战赛中取得了很好的成绩,成为了当时最具影响力的深度学习模型之一。其简单而有效的设计思想对后来的深度卷积神经网络的发展产生了重要影响。

本次选取经典的VGGNet对MNIST数据集进行训练操作,得到一个可用的模型文件,本次训练使用的服务器为炼丹侠平台A100服务器,其中GPU型号为A100 80GB,CPU使用了AMD EPYC 7542 32-Core Processor,训练分为了GPU训练测试和CPU训练测试。

下面是GPU版本和CPU版本VGGNet训练MNIST数据集的完整代码。

GPU版本:

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

# Check if GPU is available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# Define a simplified VGG-like model
class VGGNet(nn.Module):
    def __init__(self):
        super(VGGNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(32, 32, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.classifier = nn.Sequential(
            nn.Linear(64 * 7 * 7, 128),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(128, 10)
        )
    
    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x

# Load and preprocess MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True)

# Create the network, loss function, and optimizer
net = VGGNet().to(device)  # Move the model to GPU
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)

# Train the model
for epoch in range(10):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)  # Move inputs and labels to GPU
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {running_loss / len(trainloader)}")

print("Finished Training")

# Save the trained model
torch.save(net.state_dict(), 'mnist_vggnet.pth')

CPU版本:

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

# Define a simplified VGG-like model
class VGGNet(nn.Module):
    def __init__(self):
        super(VGGNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(32, 32, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.classifier = nn.Sequential(
            nn.Linear(64 * 7 * 7, 128),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(128, 10)
        )
    
    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x

# Load and preprocess MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True)

# Create the network, loss function, and optimizer
net = VGGNet()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)

# Train the model
for epoch in range(10):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {running_loss / len(trainloader)}")

print("Finished Training")

# Save the trained model
torch.save(net.state_dict(), 'mnist_vggnet.pth')

其训练过程如下:
https://www.bilibili.com/video/BV1Fu4y1X76f/?spm_id_from=333....

通过训练可观察到如下区别

  1. 训练速度差异: GPU版本的训练代码在训练过程中会明显快于CPU版本。相比于CPU训练,使用A100训练的VGGNet时间性能提升了23倍,因为GPU在并行计算方面表现出色,特别适用于深度学习模型的训练。相比之下,CPU的通用计算能力较弱,处理图像数据的卷积运算等任务相对较慢。
  2. 硬件加速效果: GPU版本的训练代码利用了GPU的并行计算能力,从而能够在更短的时间内处理更多的计算任务。这种硬件加速效果在处理大规模数据集或复杂模型时特别显著。

你可能感兴趣的:(深度学习神经网络人工智能服务器)