共计 4251 个字符,预计需要花费 11 分钟才能阅读完成。
VGGNet 是一种深度卷积神经网络,由牛津大学计算机视觉组的钻研团队开发。VGGNet 的设计思维简略而无效,以深度重叠的卷积层为次要特点。
VGGNet 的核心思想是通过多个小尺寸的卷积核和池化层来构建深度网络,具备比拟小的感触野。相比于其余网络结构,如 AlexNet,VGGNet 采纳了更深的网络结构,有更多的卷积层和池化层,从而进步了网络的表达能力。
VGGNet 的根本组成单元是由间断的卷积层和池化层形成的块,通常有两到三个卷积层,前面追随一个池化层。整个网络由多个这样的块组成,最初是几个全连贯层和一个输入层。VGGNet 的卷积核尺寸都是 3 ×3,步长为 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….
通过训练可察看到如下区别
- 训练速度差别:GPU 版本的训练代码在训练过程中会显著快于 CPU 版本。相比于 CPU 训练,应用 A100 训练的 VGGNet 工夫性能晋升了 23 倍,因为 GPU 在并行计算方面表现出色,特地实用于深度学习模型的训练。相比之下,CPU 的通用计算能力较弱,解决图像数据的卷积运算等工作绝对较慢。
- 硬件加速成果:GPU 版本的训练代码利用了 GPU 的并行计算能力,从而可能在更短的工夫内解决更多的计算工作。这种硬件加速成果在解决大规模数据集或简单模型时特地显著。