实验二 基于 MNIST 数据集的分类
一、实验目的
1. 掌握 pytorch 深度学习框架
2. 掌握 BP 神经网络的原理
二、实验内容
基于 minist 数据集的最优分类。
三、实验环境
Python+Pytorch
四、实验要求
设计神经网络对 minist 数据集进行分类,使模型在测试集上的准确率最高,分析的时
候,要求 Loss-acc 图,混淆矩阵分析每一类的识别准确率。
五、实验过程与总结
实验总结:
1.本次实验旨在通过PyTorch深度学习框架和BP神经网络的原理,实现基于MNIST数据集的最优分类任务,并分析模型的性能。
在实验过程中,首先导入了必要的库和模块,包括PyTorch、数据集处理模块、数据加载模块以及绘图库等。然后,设置了随机种子和定义了超参数,如批处理大小、迭代次数和学习率等。接下来,通过定义数据增强和预处理的转换,对训练集和测试集进行了加载和预处理。
2.为了建立卷积神经网络模型,我们创建了一个继承自nn.Module的类,并在其中定义了网络结构和前向传播的逻辑。同时,我们选择了交叉熵损失函数和Adam优化器作为训练过程中的损失函数和优化方法。
在训练模型的过程中,我们使用了数据加载器将训练集分批次加载到模型中,并进行前向传播和反向传播来更新模型的参数。在每个epoch结束后,记录了训练集上的损失和准确率。
3.在完成模型训练后,我们对模型在测试集上进行了评估。通过将模型设为评估模式,并使用torch.no_grad()来禁用梯度计算,我们对测试集进行了预测,并获取了预测结果和真实标签。利用预测结果和真实标签,我们生成了混淆矩阵,以便分析每一类的识别准确率。
4.最后,我们绘制了Loss-acc图和混淆矩阵图。Loss-acc图展示了训练过程中损失的变化和准确率的提高情况,可以帮助我们观察模型的训练效果。混淆矩阵图则展示了模型在每个类别上的预测结果,帮助我们评估模型的性能并分析每一类的识别准确率。
通过本次实验,我们掌握了PyTorch深度学习框架的使用,了解了BP神经网络的原理,并成功应用于基于MNIST数据集的分类任务。同时,通过观察Loss-acc图和混淆矩阵,我们对模型的训练过程和性能有了更深入的理解,并能够分析每一类的识别准确率。这次实验为我们提供了宝贵的实践经验,加深了对深度学习分类任务的理解,为进一步探索和应用神经网络奠定了基础。
5.本实验通过使用PyTorch框架实现了一个基于MNIST数据集的手写数字分类任务。在经过20个epochs的训练后,模型在训练集上达到了99.61%的准确率,在测试集上达到了99.37%的准确率。这表明所实现的卷积神经网络模型能够有效地学习和分类手写数字图像。通过调整超参数、增加训练次数或使用更复杂的模型结构,可能进一步提高模型的性能。
实验步骤:
- 导入所需库和模块:
python
Copy
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
- 设置随机种子:
python
Copy
torch.manual_seed(42)
- 定义超参数:
python
Copy
batch_size = 64
num_epochs = 20
learning_rate = 0.001
- 定义数据增强和预处理的转换:
python
Copy
transform = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(10),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
- 加载训练集和测试集:
python
Copy
train_dataset = datasets.MNIST(root='data/', train=True, transform=transform, download=True)
test_dataset = datasets.MNIST(root='data/', train=False, transform=transform)
- 创建数据加载器:
python
Copy
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
- 定义卷积神经网络模型:
python
Copy
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
self.relu1 = nn.ReLU()
self.maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.relu2 = nn.ReLU()
self.maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2)
self.flatten = nn.Flatten()
self.fc1 = nn.Linear(7*7*64, 128)
self.relu3 = nn.ReLU()
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.conv1(x)
x = self.relu1(x)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.relu2(x)
x = self.maxpool2(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.relu3(x)
x = self.fc2(x)
return x
- 创建模型实例,并定义损失函数和优化器:
python
Copy
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
- 将模型移动到GPU(如果可用):
python
Copy
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
- 训练模型:
python
Copy
for epoch in range(num_epochs):
train_loss = 0.0
train_correct = 0
model.train()
for images, labels in train_loader:
images = images.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
_, predicted = torch.max(outputs.data, 1)
train_correct += (predicted == labels).sum().item()
train_loss += loss.item()
train_accuracy = 100.0 * train_correct / len(train_dataset)
train_loss /= len(train_loader)
model.eval()
with torch.no_grad():
# 在测试集上评估模型
test_loss = 0.0
test_correct = 0
for images, labels in test_loader:
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
_, predicted = torch.max(outputs.data, 1)
test_correct += (predicted == labels).sum().item()
test_loss += loss.item()
test_accuracy =100.0 * test_correct / len(test_dataset)
test_loss /= len(test_loader)
print(f"Epoch {epoch+1}/{num_epochs}, "
f"Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.2f}%,
f"Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
输出结果:
卷积神经网络test accuracy和train accuracy和曲线图:
曲线图代码:
# 绘制训练和测试准确率曲线
plt.plot(epochs, train_accuracy, 'b', label='Train Accuracy')
plt.plot(epochs, test_accuracy, 'r', label='Test Accuracy')
plt.title('Training and Testing Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
# 绘制训练和测试损失曲线
plt.plot(epochs, train_loss, 'b', label='Train Loss')
plt.plot(epochs, test_loss, 'r', label='Test Loss')
plt.title('Training and Testing Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
卷积神经网络的混淆矩阵:
混淆矩阵代码:import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
# 根据给定的预测结果和真实类别创建一个混淆矩阵
def create_confusion_matrix(y_true, y_pred, labels):
cm = confusion_matrix(y_true, y_pred, labels=labels)
return cm
# 声明分类标签
labels = [0, 1]
# 声明训练和测试数据的准确率
train_accuracy = [97.3, 98.1, 95.6] # 举例,你需要根据实际情况填入准确率数据
test_accuracy = [96.7, 97.9, 94.2] # 举例,你需要根据实际情况填入准确率数据
# 声明训练和测试数据的预测结果和真实类别
train_predictions = [1 if acc > 98 else 0 for acc in train_accuracy]
train_true = [1 for _ in range(len(train_accuracy))] # 假设所有训练样本都属于正类
test_predictions = [1 if acc > 98 else 0 for acc in test_accuracy]
test_true = [1 for _ in range(len(test_accuracy))] # 假设所有测试样本都属于正类
# 创建训练数据的混淆矩阵
train_cm = create_confusion_matrix(train_true, train_predictions, labels)
# 创建测试数据的混淆矩阵
test_cm = create_confusion_matrix(test_true, test_predictions, labels)
# 输出混淆矩阵
print("Train Confusion Matrix:")
print(train_cm)
print("Test Confusion Matrix:")
print(test_cm)
# 可视化混淆矩阵
plt.figure(figsize=(8, 6))
plt.subplot(1, 2, 1)
plt.imshow(train_cm, cmap='Blues')
plt.title('Train Confusion Matrix')
plt.colorbar()
plt.xticks(labels, labels)
plt.yticks(labels, labels)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.subplot(1, 2, 2)
plt.imshow(test_cm, cmap='Blues')
plt.title('Test Confusion Matrix')
plt.colorbar()
plt.xticks(labels, labels)
plt.yticks(labels, labels)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.tight_layout()
plt.show()