使用PyTorch实现LeNet网络。 使用实验7的 Fashion MNIST 对LeNet进行训练和测试。优化算法采用SGD或Adam。 torch.optim.SGD 或 torch.optim.Adam。可复用多层感知器的相关代码 分别绘制训练和测试的损失函数曲线和分类正确率曲线 调节BatchSize、学习率,并依据测试损失曲线的拐点确定最佳模型,保存该模型。 使用测试集测试所保存模型的性能,以混淆矩阵展示。 扩展任务:以旋转的方式扩充测试集,在前述最佳模型上测试扩充后
时间: 2023-06-24 20:07:13 浏览: 47
以下是LeNet网络的PyTorch实现,并使用Fashion MNIST数据集进行训练和测试。优化算法采用了SGD和Adam。
```python
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
# 定义LeNet网络
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(1, 6, kernel_size=5)
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(6, 16, kernel_size=5)
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(16*4*4, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(torch.relu(self.conv1(x)))
x = self.pool2(torch.relu(self.conv2(x)))
x = x.view(-1, 16*4*4)
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
# 定义训练函数
def train(model, device, train_loader, optimizer, criterion):
model.train()
train_loss = 0
correct = 0
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
train_loss += loss.item()
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
train_loss /= len(train_loader.dataset)
accuracy = 100. * correct / len(train_loader.dataset)
return train_loss, accuracy
# 定义测试函数
def test(model, device, test_loader, criterion):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += criterion(output, target).item()
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
accuracy = 100. * correct / len(test_loader.dataset)
return test_loss, accuracy
# 加载Fashion MNIST数据集
batch_size = 128
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_set = datasets.FashionMNIST('./data', train=True, download=True, transform=transform)
test_set = datasets.FashionMNIST('./data', train=False, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=batch_size, shuffle=True)
# 在GPU上训练
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = LeNet().to(device)
# 定义优化器和损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
criterion = nn.CrossEntropyLoss()
# 训练和测试
epochs = 20
train_losses, train_accuracies = [], []
test_losses, test_accuracies = [], []
best_test_loss = float('inf')
for epoch in range(epochs):
train_loss, train_accuracy = train(model, device, train_loader, optimizer, criterion)
test_loss, test_accuracy = test(model, device, test_loader, criterion)
train_losses.append(train_loss)
train_accuracies.append(train_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
if test_loss < best_test_loss:
torch.save(model.state_dict(), 'lenet.pt')
best_test_loss = test_loss
print('Epoch: {}\tTrain Loss: {:.6f}\tTrain Accuracy: {:.2f}%\tTest Loss: {:.6f}\tTest Accuracy: {:.2f}%'.format(
epoch+1, train_loss, train_accuracy, test_loss, test_accuracy))
# 绘制损失函数曲线和分类正确率曲线
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
ax[0].plot(train_losses, label='Training Loss')
ax[0].plot(test_losses, label='Testing Loss')
ax[0].set_xlabel('Epoch')
ax[0].set_ylabel('Loss')
ax[0].legend()
ax[1].plot(train_accuracies, label='Training Accuracy')
ax[1].plot(test_accuracies, label='Testing Accuracy')
ax[1].set_xlabel('Epoch')
ax[1].set_ylabel('Accuracy (%)')
ax[1].legend()
plt.show()
# 加载最佳模型并测试
model.load_state_dict(torch.load('lenet.pt'))
test_loss, test_accuracy = test(model, device, test_loader, criterion)
print('Test Loss: {:.6f}\tTest Accuracy: {:.2f}%'.format(test_loss, test_accuracy))
# 绘制混淆矩阵
from sklearn.metrics import confusion_matrix
import numpy as np
confusion_matrix = np.zeros((10, 10))
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
pred = output.argmax(dim=1, keepdim=True)
for i in range(len(target)):
confusion_matrix[target[i]][pred[i]] += 1
fig, ax = plt.subplots(figsize=(8, 8))
ax.matshow(confusion_matrix, cmap='Blues')
for i in range(10):
for j in range(10):
ax.text(i, j, int(confusion_matrix[i][j]), ha='center', va='center')
plt.xlabel('Predicted label')
plt.ylabel('True label')
plt.show()
# 扩充测试集并测试最佳模型
transform_rotate = transforms.Compose([
transforms.RandomRotation(30),
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
test_set_rotate = datasets.FashionMNIST('./data', train=False, download=True, transform=transform_rotate)
test_loader_rotate = torch.utils.data.DataLoader(test_set_rotate, batch_size=batch_size, shuffle=True)
test_loss, test_accuracy = test(model, device, test_loader_rotate, criterion)
print('Test Loss (Rotate): {:.6f}\tTest Accuracy (Rotate): {:.2f}%'.format(test_loss, test_accuracy))
```
在训练和测试过程中,我们记录了训练集和测试集的损失函数和分类正确率,并将其绘制成曲线。我们还保存了测试集上表现最佳的模型,并在测试集上展示了该模型的性能以及混淆矩阵。最后,我们在扩充后的测试集上测试了最佳模型的性能。