fre1228 2024-04-25 22:34 采纳率: 83.3%
浏览 5
已结题

深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集

根据CNN网络模型,搭建BP模型并训练MNIST数据集,并计算精确度

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清图
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作数据集

# 设定下载参数
transform = transforms.Compose([
    transforms.ToTensor(), 
    transforms.Normalize(0.1307, 0.3081)
])

# 下载训练集与测试集
train_Data = datasets.MNIST(
    root = 'D:/Jupyter/dataset/mnist/', 
    train = True, 
    download = True, 
    transform = transform
)
test_Data = datasets.MNIST(
    root = 'D:/Jupyter/dataset/mnist/', 
    train = False, 
    download = True, 
    transform = transform
)
# 批次加载器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=256)
test_loader  = DataLoader(test_Data, shuffle=False, batch_size=256)


class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Tanh(),
            nn.AvgPool2d(kernel_size=2, stride=2),
            nn.Conv2d(6, 16, kernel_size=5), nn.Tanh(),
            nn.AvgPool2d(kernel_size=2, stride=2),
            nn.Conv2d(16, 120, kernel_size=5), nn.Tanh(),
            nn.Flatten(),
            nn.Linear(120, 84), nn.Tanh(),
            nn.Linear(84, 10)
        )

    def forward(self, x):
        y = self.net(x)
        return y
# 查看网络结构
X = torch.rand(size= (1, 1, 28, 28))
for layer in CNN().net:
    X = layer(X)
print( layer.__class__.__name__, 'output shape: \t', X.shape )
# 创建子类的实例,并搬到GPU上
model = CNN().to('cuda:0')
# 损失函数的选择
loss_fn = nn.CrossEntropyLoss()    # 自带softmax激活函数
# 优化算法的选择
learning_rate = 0.9    # 设置学习率
optimizer = torch.optim.SGD(
    model.parameters(), 
    lr = learning_rate, 
)
# 训练网络
epochs = 5
losses = []        # 记录损失函数变化的列表

for epoch in range(epochs):
    for (x, y) in train_loader:                  # 获取小批次的x与y
        x, y = x.to('cuda:0'), y.to('cuda:0')    # 把小批次搬到GPU上
        Pred = model(x)                          # 一次前向传播(小批量)
        loss = loss_fn(Pred, y)                  # 计算损失函数
        losses.append(loss.item())               # 记录损失函数的变化
        optimizer.zero_grad()                    # 清理上一轮滞留的梯度
        loss.backward()                          # 一次反向传播
        optimizer.step()                         # 优化内部参数

Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()
# 测试网络
correct = 0
total = 0

with torch.no_grad():                                   # 该局部关闭梯度计算功能
    for (x, y) in test_loader:                          # 获取小批次的x与y
        x, y = x.to('cuda:0'), y.to('cuda:0')           # 把小批次搬到GPU上
        Pred = model(x)                                 # 一次前向传播(小批量)
        _, predicted = torch.max(Pred.data, dim=1)
        correct += torch.sum( (predicted == y) )
        total += y.size(0) 
        
print(f'测试集精准度: {100*correct/total} %')


  • 写回答

20条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-25 22:34
    关注
    获得0.45元问题酬金

    引自免费微信小程序:皆我百晓生

    在您提供的代码中,您已经成功地基于卷积神经网络(CNN)模型搭建了一个深度学习框架,并对MNIST数据集进行了训练。以下是您代码的简要分析和一些可能的改进点:

    代码分析:

    1. 数据预处理

      • 使用torchvision.transforms定义了数据转换,包括将图像转换为张量、进行归一化。
    2. 数据集加载

      • 使用torchvision.datasets.MNIST加载MNIST数据集,分别设置了训练集和测试集的路径。
      • 使用DataLoader创建批次加载器,对训练集和测试集进行批量化处理。
    3. CNN模型定义

      • 定义了一个名为CNNnn.Module子类,包含了一系列卷积层、激活函数(Tanh)、池化层、全连接层。
      • forward方法中,通过self.net(x)实现了输入数据x经过整个网络的前向传播。
    4. 模型初始化及设备设置

      • 实例化CNN模型,并将其移动到GPU(cuda:0)上。
    5. 损失函数与优化器

      • 选择交叉熵损失函数(nn.CrossEntropyLoss)作为损失指标,它自带softmax激活函数。
      • 使用随机梯度下降(SGD)作为优化器,设定学习率为0.9。
    6. 模型训练

      • 进行5个epoch的训练循环,每个循环内遍历训练集的小批次数据。
      • 对每个小批次,执行前向传播、计算损失、清理梯度、反向传播和参数更新。
    7. 损失曲线绘制

      • 记录每次迭代的损失值,绘制训练过程中损失函数的变化曲线。
    8. 模型测试与精度计算

      • 在测试阶段,关闭梯度计算,遍历测试集的小批次数据。
      • 对每个小批次,执行前向传播并计算预测结果,统计正确预测的数量,最终计算测试集精度。

    改进建议:

    1. 学习率调整

      • 目前设定的学习率为0.9,对于大多数CNN模型来说,这个值可能过大,可能导致训练过程不收敛。建议尝试更常见的学习率,如0.01或0.001,并考虑使用学习率衰减策略(如torch.optim.lr_scheduler.StepLR)来动态调整学习率。
    2. 激活函数选择

      • Tanh激活函数在现代深度学习实践中较少使用,通常推荐使用ReLU及其变种(如ReLU、Leaky ReLU、ELU等)。这些激活函数在训练深层网络时能有效缓解梯度消失问题。您可以将nn.Tanh()替换为nn.ReLU(inplace=True)
    3. 优化器参数

      • 考虑添加动量(momentum)和权重衰减(weight_decay),这有助于加速训练过程并防止过拟合。例如,可以使用torch.optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9, weight_decay=5e-4)
    4. 模型性能评估

      • 除了计算测试集精度外,还可以考虑计算训练集精度以及训练集和测试集上的混淆矩阵,以便更全面地评估模型性能。

    综上所述,您的代码已经实现了基于CNN模型对MNIST数据集的训练和测试。为了进一步提升模型性能,您可以参考上述改进建议进行调整。以下为您提供了修改后的代码:

    import torch
    import torch.nn as nn
    from torch.utils.data import DataLoader
    from torchvision import transforms
    from torchvision import datasets
    import matplotlib.pyplot as plt
    
    transform = transforms.Compose([
        transforms.ToTensor(), 
        transforms.Normalize((0.1307,), (0.3081,))
    ])
    
    train_Data = datasets.MNIST(
        root='D:/Jupyter/dataset/mnist/', 
        train=True, 
        download=True, 
        transform=transform
    )
    test_Data = datasets.MNIST(
        root='D:/Jupyter/dataset/mnist/', 
        train=False, 
        download=True, 
        transform=transform
    )
    
    class CNN(nn.Module):
        def __init__(self):
            super(CNN, self).__init__()
            self.net = nn.Sequential(
                nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.ReLU(inplace=True),
                nn.AvgPool2d(kernel_size=2, stride=2),
                nn.Conv2d(6, 16, kernel_size=5), nn.ReLU(inplace=True),
                nn.AvgPool2d(kernel_size=2, stride=2),
                nn.Conv2d(16, 120, kernel_size=5), nn.ReLU(inplace=True),
                nn.Flatten(),
                nn.Linear(120, 84), nn.ReLU(inplace=True),
                nn.Linear(84, 10)
            )
    
        def forward(self, x):
            y = self.net(x)
            return y
    
    model = CNN().to('cuda:0')
    loss_fn = nn.CrossEntropyLoss()
    learning_rate = 0.001
    optimizer = torch.optim.SGD(
        model.parameters(), 
        lr=learning_rate, 
        momentum=0.9, 
        weight_decay=5e-4
    )
    
    epochs = 5
    losses = []
    
    for epoch in range(epochs):
        for (x, y) in train_loader:
            x, y = x.to('cuda:0'), y.to('cuda:0')
            Pred = model(x)
            loss = loss_fn(Pred, y)
            losses.append(loss.item())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    
    plt.plot(range(len(losses)), losses)
    plt.xlabel('Iterations')
    plt.ylabel('Training Loss')
    plt.title('Training Loss vs. Iterations')
    plt.show()
    
    correct = 0
    total = 0
    
    with torch.no_grad():
        for (x, y) in test_loader:
            x, y = x.to('cuda:0'), y.to('cuda:0')
            Pred = model(x)
            _, predicted = torch.max(Pred.data, dim=1)
            correct += torch.sum(predicted == y)
            total += y.size(0)
    
    print(f'Test set accuracy: {100 * correct / total}%')
    

    这段代码已根据改进建议进行了相应调整。如果您在实际运行中遇到问题或需要进一步优化,欢迎继续提问。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 5月3日
  • 赞助了问题酬金15元 4月25日
  • 创建了问题 4月25日

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题