作文网站源码,wordpress slider使用,网商网,长沙网站制作哪家AlexNet 是一种经典的深度学习模型#xff0c;它在 2012 年的 ImageNet 图像分类比赛中大放异彩#xff0c;彻底改变了计算机视觉领域的格局。AlexNet 的核心创新包括使用深度卷积神经网络#xff08;CNN#xff09;来处理图像#xff0c;并采用了多个先进的技术如 ReLU 激…AlexNet 是一种经典的深度学习模型它在 2012 年的 ImageNet 图像分类比赛中大放异彩彻底改变了计算机视觉领域的格局。AlexNet 的核心创新包括使用深度卷积神经网络CNN来处理图像并采用了多个先进的技术如 ReLU 激活函数、Dropout 正则化等。
本文将介绍如何使用 PyTorch 框架实现 AlexNet并在 MNIST 数据集上进行训练。MNIST 是一个简单但经典的数据集常用于初学者测试机器学习算法。
文末附完整项目。
一、AlexNet 网络结构
AlexNet 的结构大致可以分为两部分特征提取部分卷积层和分类部分全连接层。下面是 AlexNet 的简要结构
卷积层五个卷积层用于提取特征。每个卷积层后面都有一个激活函数ReLU和一个池化层。全连接层三个全连接层第一个和第二个全连接层后有 Dropout 层防止过拟合。输出层使用 Softmax 激活函数输出 1000 个类别的概率。
二、使用 PyTorch 实现 AlexNet
训练部分
1. 导入必要的库
首先我们需要导入一些必要的库包括 PyTorch 和一些数据处理工具。
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
from torchvision import datasets
from torch.cuda.amp import GradScaler, autocast # 导入混合精度训练
from tqdm import tqdm
import multiprocessing
import matplotlib.pyplot as plt
2. 定义 AlexNet 模型
接下来我们定义一个类 AlexNet继承自 nn.Module并在其中实现 AlexNet 的结构。
class AlexNet(nn.Module):def __init__(self):super(AlexNet, self).__init__()# 定义卷积层和池化层self.features nn.Sequential(nn.Conv2d(1, 64, kernel_size11, stride4, padding2), # 第一个卷积层nn.ReLU(inplaceTrue), # 激活函数nn.MaxPool2d(kernel_size3, stride2), # 池化层nn.Conv2d(64, 192, kernel_size5, padding2), # 第二个卷积层nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3, stride2),nn.Conv2d(192, 384, kernel_size3, padding1), # 第三个卷积层nn.ReLU(inplaceTrue),nn.Conv2d(384, 256, kernel_size3, padding1), # 第四个卷积层nn.ReLU(inplaceTrue),nn.Conv2d(256, 256, kernel_size3, padding1), # 第五个卷积层nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3, stride2) # 池化层)# 定义全连接层self.classifier nn.Sequential(nn.Dropout(), # Dropout 层防止过拟合nn.Linear(256 * 6 * 6, 4096), # 第一个全连接层nn.ReLU(inplaceTrue),nn.Dropout(),nn.Linear(4096, 4096), # 第二个全连接层nn.ReLU(inplaceTrue),nn.Linear(4096, 10) # 输出层10 个类别)def forward(self, x):# 前向传播x self.features(x) # 卷积层x x.view(x.size(0), -1) # 展平数据x self.classifier(x) # 全连接层return x 3. 数据预处理和加载
在进行训练之前我们需要对 MNIST 数据集进行预处理。AlexNet 要求输入的图像大小为 227x227因此我们需要调整图像的大小。
# 使用 torchvision.transforms 对图像进行一系列的预处理操作
transform transforms.Compose([transforms.Resize((227, 227)), # 调整输入图像的大小为 227x227 (符合 AlexNet 的要求)transforms.ToTensor(), # 将图像转换为 Tensor 格式transforms.Normalize((0.5,), (0.5,)) # 标准化操作均值0.5标准差0.5
])# 下载并加载 MNIST 数据集数据集已经被预处理
trainset datasets.MNIST(root./data, trainTrue, downloadTrue, transformtransform)
testset datasets.MNIST(root./data, trainFalse, downloadTrue, transformtransform)# 使用 DataLoader 加载训练集和测试集设置 batch size 和多线程加载
trainloader DataLoader(trainset, batch_size128, num_workers2, pin_memoryTrue)
testloader DataLoader(testset, batch_size128, num_workers2, pin_memoryTrue) 4. 定义损失函数和优化器
使用交叉熵损失函数和 Adam 优化器来训练模型。
#创建模型实例并将其移动到 GPU 上
model AlexNet().to(device)
#定义损失函数和优化器
criterion nn.CrossEntropyLoss() # 分类问题常用的损失函数
optimizer optim.AdamW(model.parameters(), lr0.001) # 使用 AdamW 优化器# 用于保存训练过程中的损失和准确率
train_losses []
train_accuracies [] 5. 训练模型
现在我们可以开始训练模型了。我们会对训练集进行多轮训练并每轮输出损失和准确率。
def train_model():epochs 5 # 训练周期数accumulation_steps 4 # 梯度累积的步骤数当前未使用scaler GradScaler() # 初始化混合精度训练的 GradScalerfor epoch in range(epochs):model.train() # 设置模型为训练模式running_loss 0.0 # 初始化当前 epoch 的损失correct 0 # 记录正确的预测个数total 0 # 记录总的样本数print(fEpoch [{epoch 1}/{epochs}] started.)# 使用 tqdm 包装 trainloader 以显示进度条for i, (inputs, labels) in enumerate(tqdm(trainloader, descfEpoch {epoch 1}/{epochs}, ncols100), 1):inputs, labels inputs.to(device), labels.to(device) # 将数据和标签移动到 GPU 上optimizer.zero_grad() # 清空优化器中的梯度信息with autocast(): # 启用混合精度训练outputs model(inputs) # 获取模型输出loss criterion(outputs, labels) # 计算损失scaler.scale(loss).backward() # 反向传播计算梯度if (i 1) % accumulation_steps 0: # 每 accumulation_steps 次更新一次梯度目前无效scaler.step(optimizer)scaler.update()optimizer.zero_grad()running_loss loss.item() # 累加当前 batch 的损失_, predicted torch.max(outputs, 1) # 获取模型的预测结果total labels.size(0) # 更新总样本数correct (predicted labels).sum().item() # 更新正确的预测个数# 计算本轮训练的平均损失和准确率epoch_loss running_loss / len(trainloader)epoch_accuracy correct / total * 100train_losses.append(epoch_loss) # 保存当前 epoch 的损失train_accuracies.append(epoch_accuracy) # 保存当前 epoch 的准确率print(fEpoch [{epoch 1}/{epochs}] finished. Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%\n)# 6. 保存模型torch.save(model.state_dict(), alexnet_mnist.pth) # 保存模型权重print(Model saved successfully!)
测试部分
6. 数据预处理和加载
首先我们需要对 MNIST 数据集进行预处理确保图像的尺寸符合 AlexNet 的输入要求。AlexNet 的标准输入尺寸为 227x227因此我们需要调整 MNIST 图像的尺寸并将其转换为张量格式进行处理。
# 定义对图像的转换操作调整大小、转换为Tensor、标准化
transform transforms.Compose([transforms.Resize((227, 227)), # 调整输入图像的大小为 227x227 (符合 AlexNet 的要求)transforms.ToTensor(), # 将图像转换为 Tensor 格式transforms.Normalize((0.5,), (0.5,)) # 标准化操作均值0.5标准差0.5
])# 加载 MNIST 数据集训练集并应用定义的图像转换
trainset datasets.MNIST(root./data, trainTrue, downloadTrue, transformtransform)
trainloader DataLoader(trainset, batch_size64, shuffleFalse) # 使用 DataLoader 批量加载数据 数据预处理我们使用 transforms.Compose 来组合多个数据转换操作。首先将图像调整为 227x227 像素以符合 AlexNet 的输入要求然后将图像转换为 Tensor 格式并进行标准化处理。 加载数据通过 DataLoader 加载训练数据设定批处理大小为 64并禁用数据打乱因为我们并不进行训练仅展示前几个图像。
7. 定义 AlexNet 模型结构
接下来我们实现 AlexNet 的卷积层和全连接层。这里我们将使用灰度图像作为输入因此输入通道数为 1而非 3。
# 这个模型是基于经典的 AlexNet 结构只不过输入是灰度图像1通道而非 RGB 图像3通道
class AlexNet(nn.Module):def __init__(self):super(AlexNet, self).__init__()# 特征提取部分卷积层 激活函数 池化层self.features nn.Sequential(nn.Conv2d(1, 64, kernel_size11, stride4, padding2), # 输入1通道灰度图输出64通道nn.ReLU(inplaceTrue), # 激活函数 ReLUnn.MaxPool2d(kernel_size3, stride2), # 池化层nn.Conv2d(64, 192, kernel_size5, padding2), # 第二个卷积层nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3, stride2), # 池化层nn.Conv2d(192, 384, kernel_size3, padding1), # 第三个卷积层nn.ReLU(inplaceTrue),nn.Conv2d(384, 256, kernel_size3, padding1), # 第四个卷积层nn.ReLU(inplaceTrue),nn.Conv2d(256, 256, kernel_size3, padding1), # 第五个卷积层nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3, stride2) # 池化层)# 分类器部分全连接层self.classifier nn.Sequential(nn.Dropout(), # Dropout 层防止过拟合nn.Linear(256 * 6 * 6, 4096), # 全连接层1输入大小 256*6*6输出 4096nn.ReLU(inplaceTrue),nn.Dropout(),nn.Linear(4096, 4096), # 全连接层2输出 4096nn.ReLU(inplaceTrue),nn.Linear(4096, 10) # 输出层10个类别MNIST 0-9)def forward(self, x):# 前向传播过程x self.features(x) # 通过卷积层提取特征x x.view(x.size(0), -1) # 展平数据展平成一维x self.classifier(x) # 通过全连接层进行分类return x 3. 加载预训练模型
在实际使用中我们通常会保存训练好的模型权重并进行加载。这里我们假设已经训练好模型并将其保存为 alexnet_mnist.pth。
# 此函数用于加载保存的模型权重
def load_model(model_pathalexnet_mnist.pth):model AlexNet().to(device) # 创建模型实例并移动到设备GPU/CPUmodel.load_state_dict(torch.load(model_path)) # 加载模型权重model.eval() # 设置模型为评估模式print(Model loaded successfully!)return model 4. 批量进行图片预测
接下来我们将编写一个函数用于批量预测图像并返回其对应的预测结果。
# 该函数从 dataloader 中获取指定数量的图像并进行预测
def batch_predict_images(model, dataloader, num_images6):predictions [] # 用于保存预测结果images [] # 用于保存输入图像labels [] # 用于保存实际标签# 不计算梯度以提高效率with torch.no_grad():for i, (input_images, input_labels) in enumerate(dataloader):if i * 64 num_images: # 控制处理的图像数量breakinput_images input_images.to(device) # 将图像数据转移到 GPU 上input_labels input_labels.to(device) # 将标签数据转移到 GPU 上# 通过模型进行预测outputs model(input_images)_, predicted torch.max(outputs, 1) # 获取预测的类别predictions.extend(predicted.cpu().numpy()) # 保存预测结果到 CPU 上images.extend(input_images.cpu().numpy()) # 保存输入图像到 CPU 上labels.extend(input_labels.cpu().numpy()) # 保存真实标签到 CPU 上return images[:num_images], labels[:num_images], predictions[:num_images] 三、可视化
为了更好地了解模型的训练情况我们可以通过绘制图表来展示训练过程中的损失和准确率。
def plot_training_progress():plt.figure(figsize(12, 6)) # 创建一个宽12英寸、高6英寸的图形窗口# 绘制训练损失的子图plt.subplot(1, 2, 1) # 1行2列的第一个子图plt.plot(range(1, 6), train_losses, markero, labelTrain Loss)plt.title(Train Loss per Epoch)plt.xlabel(Epoch)plt.ylabel(Loss)plt.grid(True)# 绘制训练准确率的子图plt.subplot(1, 2, 2) # 1行2列的第二个子图plt.plot(range(1, 6), train_accuracies, markero, labelTrain Accuracy)plt.title(Train Accuracy per Epoch)plt.xlabel(Epoch)plt.ylabel(Accuracy (%))plt.grid(True)# 调整布局避免子图重叠plt.tight_layout()# 显示图形窗口plt.show()我们编写一个函数来可视化批量图像及其对应的预测结果。我们将使用 matplotlib 来绘制图像。
# 该函数显示图像和预测结果
def visualize_images(images, labels, predictions):fig, axes plt.subplots(2, 3, figsize(10, 7)) # 创建 2x3 的图像子图axes axes.ravel() # 将子图展平成一维数组for i in range(6):image images[i].squeeze() # 去掉多余的维度例如[1, 227, 227] - [227, 227]ax axes[i]ax.imshow(image, cmapgray) # 显示图像使用灰度图ax.set_title(fPred: {predictions[i]} | Actual: {labels[i]}) # 显示预测标签和实际标签ax.axis(off) # 关闭坐标轴显示plt.tight_layout() # 调整子图之间的间距plt.show() # 显示图像四、启动
#训练
if __name__ __main__:# 设置 multiprocessing 的启动方法为 spawnWindows 需要multiprocessing.set_start_method(spawn)# 开始训练模型train_model()# 绘制训练过程图plot_training_progress()#测试
if __name__ __main__:# 设置 multiprocessing 的启动方法为 spawn用于兼容不同操作系统Windows需要multiprocessing.set_start_method(spawn)# 加载训练好的模型model load_model()# 获取前6张图像及其预测结果images, labels, predictions batch_predict_images(model, trainloader, num_images6)# 可视化这些图像及其预测结果visualize_images(images, labels, predictions)五、总结
在本文中我们介绍了如何使用 PyTorch 实现 AlexNet 并在 MNIST 数据集上进行训练。通过这个过程你可以了解如何构建卷积神经网络、加载数据集、训练模型并进行评估。AlexNet 的结构在计算机视觉任务中仍然具有重要意义尤其是在图像分类任务中。
PyTorch 使得实现和训练深度学习模型变得更加简便和灵活你可以通过对本文代码的修改来尝试不同的模型或数据集从而加深对深度学习的理解。
五、参考资料
PyTorch 官方文档AlexNet 论文AlexNet: 使用 PyTorch 实现 AlexNet 进行 MNIST 图像分类https://gitee.com/qxdlll/alex-netGitHub - qxd-ljy/AlexNet: 使用 PyTorch 实现 AlexNet 进行 MNIST 图像分类使用 PyTorch 实现 AlexNet 进行 MNIST 图像分类. Contribute to qxd-ljy/AlexNet development by creating an account on GitHub.https://github.com/qxd-ljy/AlexNet