1.实验目的
- 掌握卷积层、池化层的作用。
- 掌握AlexNet网络模型的结构。
- 掌握卷积神经网络的设计、训练和测试。
2.实验要求
编程实现AlexNet网络模型,用于对给定的数据进行分类。要求代码格式规范,注释齐全,程序可正常运行。
3.模型设计
AlexNet包含8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。
4.模型实现
代码如下:
import time
import torch
from torch import nn,optim
import torchvision
from torchvision.datasets import FashionMNIST
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import sys
sys.path.append("..")
# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 下载数据集
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))#均值标准差 标准化处理 加速训练过程
])
train_dataset = FashionMNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = FashionMNIST(root='./data', train=False, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
# 定义模型
import torch.nn as nn
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 96, 5, 1, 2),#输入通道数,输出通道数,卷积核大小,步长,填充
nn.ReLU(),
nn.MaxPool2d(3, 2),
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2),
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU(),
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU(),
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)
# 计算全连接层输入大小
self.fc_input_size = self._get_fc_input_size()
self.fc = nn.Sequential(
nn.Linear(self.fc_input_size, 4096),
nn.ReLU(),
nn.Dropout(0.5),#随机丢弃
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 10)
)
def forward(self, img):
feature = self.conv(img)
feature = feature.view(img.size(0), -1)#展平
output = self.fc(feature)
return output
def _get_fc_input_size(self):
x = torch.randn(1, 1, 28, 28)
x = self.conv(x)
return x.view(-1).size(0)
# 实例化模型和定义损失函数、优化器
net = AlexNet().to(device)
criterion = nn.CrossEntropyLoss()#交叉熵损失函数
optimizer = optim.Adam(net.parameters(), lr=0.001)
# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
net.train()
running_loss = 0.0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad() # 梯度清零
outputs = net(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"轮次 {epoch+1}, 平均损失: {running_loss/len(train_loader)}")#平均损失
# 测试模型
net.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = net(images)
_, predicted = torch.max(outputs, 1)#返回最大值和最大值索引,不看最大值
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"在测试集上的准确率: {(correct/total)*100:.2f}%")
结果如下: