CNN、LeNet、AlexNet基于MNIST数据集进行训练和测试,并可视化对比结果

完成内容:

  1. 构建CNN并基于MNIST数据集进行训练和测试
  2. 构建LeNet并基于MNIST数据集进行训练和测试
  3. 构建AlexNet并基于MNIST数据集进行训练和测试
  4. 对比了不同网络在MNIST数据集上训练的效果

准备工作

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
from tqdm import tqdm
from matplotlib import pyplot as plt
import pandas as pd
from math import pi

下载数据,加载data_loader

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f'device:{device}')
batch_size = 256

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])

# 加载数据(本步建议挂梯子)
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)

# 加载data_loader
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

results = []

定义CNN和LeNet通用的训练函数和测试函数

def train(model, train_loader, criterion, optimizer, device):
    model.train()
    running_loss = 0.0
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    return running_loss / len(train_loader)


def test(model, test_loader, criterion, device):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for inputs, labels in test_loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            _, predicted = torch.max(outputs, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    accuracy = correct / total
    return accuracy

构建CNN并基于MNIST数据集进行训练和测试

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=5, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        self.classifier = nn.Linear(16 * 14 * 14, 10)

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x


# 展示网络内部结构
X = torch.rand(size=(1, 1, 28, 28), dtype=torch.float32)
for layer in CNN().features:
    X = layer(X)
    print(layer.__class__.__name__,'output shape: \t',X.shape)
网络结构:
Conv2d output shape: 	 torch.Size([1, 16, 28, 28])
ReLU output shape: 	 torch.Size([1, 16, 28, 28])
MaxPool2d output shape: 	 torch.Size([1, 16, 14, 14])
# 初始化CNN,优化器,损失函数
model = CNN().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
result = []
# 训练网络
num_epochs = 5
for epoch in tqdm(range(num_epochs), desc="training", unit="epoch"):
    train_loss = train(model, train_loader, criterion, optimizer, device)
    test_acc = test(model, test_loader, criterion, device)
    result.append(test_acc)
    print(f'Epoch {epoch+1}/{num_epochs}, Loss: {train_loss:.4f}, Test Accuracy: {test_acc:.4f}')
results.append(result)
results    

LeNet-MNIST

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.ReLU(),  # (1, 6, 28, 28)
            nn.AvgPool2d(kernel_size=2, stride=2),  # (1, 6, 14, 14)
            nn.Conv2d(6, 16, kernel_size=5), nn.ReLU(),  # (1, 16, 10, 10)
            nn.AvgPool2d(kernel_size=2, stride=2),  # (1, 16, 5, 5)
            nn.Flatten(),  # (1, 400)
            nn.Linear(16 * 5 * 5, 120), nn.ReLU(),  # (1, 120)
            nn.Linear(120, 84), nn.ReLU(),  # (1, 84)
            nn.Linear(84, 10)  # (1, 10)
        )

    def forward(self, x):
        x = self.features(x)
        return x
# 展示LeNet网络内部结构
X = torch.rand(size=(1, 1, 28, 28), dtype=torch.float32)
for layer in LeNet().features:
    X = layer(X)
    print(layer.__class__.__name__,'output shape: \t',X.shape)
# 网络结构:
Conv2d output shape: 	 torch.Size([1, 6, 28, 28])
ReLU output shape: 	 torch.Size([1, 6, 28, 28])
AvgPool2d output shape: 	 torch.Size([1, 6, 14, 14])
Conv2d output shape: 	 torch.Size([1, 16, 10, 10])
ReLU output shape: 	 torch.Size([1, 16, 10, 10])
AvgPool2d output shape: 	 torch.Size([1, 16, 5, 5])
Flatten output shape: 	 torch.Size([1, 400])
Linear output shape: 	 torch.Size([1, 120])
ReLU output shape: 	 torch.Size([1, 120])
Linear output shape: 	 torch.Size([1, 84])
ReLU output shape: 	 torch.Size([1, 84])
Linear output shape: 	 torch.Size([1, 10])
# 初始化CNN,优化器,损失函数
model = LeNet().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
result = []
# 训练模型
num_epochs = 5
for epoch in tqdm(range(num_epochs), desc="training", unit="epoch"):
    train_loss = train(model, train_loader, criterion, optimizer, device)
    test_acc = test(model, test_loader, criterion, device)
    result.append(test_acc)
    print(f'Epoch {epoch+1}/{num_epochs}, Loss: {train_loss:.4f}, Test Accuracy: {test_acc:.4f}')
results.append(result)
results

AlexNet-MNIST

# 定义AlexNet
class AlexNet(nn.Module):
    def __init__(self, num_classes=10):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 64, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64, 192, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes),
        )

    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x
# 重新加载数据
transform = transforms.Compose([
    transforms.Resize((227, 227)),
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# 初始化AlexNet、优化器、损失函数
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
alexnet = AlexNet(num_classes=10).to(device)
optimizer = optim.Adam(alexnet.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
result = []

# 训练
num_epochs = 5
for epoch in tqdm(range(num_epochs), desc="training", unit="epoch"):
    alexnet.train()
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad()
        outputs = alexnet(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    #  测试
    alexnet.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for inputs, labels in test_loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = alexnet(inputs)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    accuracy = correct / total
    result.append(accuracy)
    print(f"Accuracy on test set: {accuracy * 100:.2f}%")
results.append(result)

结果分析

# Set data
df = pd.DataFrame(results)
columns = ['epoch1', 'epoch2', 'epoch3', 'epoch4', 'epoch5']
df.columns = columns
df['Network'] = ['CNN','LeNet', 'AlexNet']
print(df)
# ------- PART 1: Create background

# number of variable
categories=list(df)[:-1]
N = len(categories)

# What will be the angle of each axis in the plot? (we divide the plot / number of variable)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

# Initialise the spider plot
ax = plt.subplot(111, polar=True)

# If you want the first axis to be on top:
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)

# Draw one axe per variable + add labels
plt.xticks(angles[:-1], categories)

# Draw ylabels
ax.set_rlabel_position(0)
plt.yticks([0.925,0.95,0.975], ["0.925","0.95","0.975"], color="grey", size=7)
plt.ylim(0.9,1)


# ------- PART 2: Add plots

# Plot each individual = each line of the data


# Ind1
values=df.loc[0].drop('Network').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid', label="CNN")
ax.fill(angles, values, 'b', alpha=0.1)

# Ind2
values=df.loc[1].drop('Network').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid', label="LeNet")
ax.fill(angles, values, 'r', alpha=0.1)

# Ind3
values=df.loc[2].drop('Network').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, linewidth=1, linestyle='solid', label="AlexNet")
ax.fill(angles, values, 'g', alpha=0.1)

# Add legend
plt.legend(loc='upper right', bbox_to_anchor=(0.1, 0.1))

# Show the graph
plt.show()


   epoch1  epoch2  epoch3  epoch4  epoch5  Network
0  0.9629  0.9764  0.9818  0.9823  0.9826      CNN
1  0.9461  0.9706  0.9781  0.9810  0.9869    LeNet
2  0.9844  0.9865  0.9887  0.9855  0.9900  AlexNet

在这里插入图片描述

总体而言:
AlexNet效果更好,但Alex网络更复杂,计算开销更大;
CNN网络最简单,计算开销最小,效果也较好;
LeNet效果不如预期,按理来说LeNet网络更复杂,相较于CNN拟合效果应更好,但实际效果有偏差,怀疑是epoch较少,5个epoch不足以收敛

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/239115.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Canvas】记录一次从0到1绘制风场空间分布图的过程

前言 📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步! 🍅 个人主页:南木元元 目录 背景 前置知识 风场数据 绘制风场 准备工作 生成二维网格 获取…

vxe-table 右键菜单+权限控制(v3)

1.menu-config 是用于配置右键菜单的属性。通过 menu-config 属性,定义右键菜单的内容、显示方式和样式。 通过 menu-config 属性配置了右键菜单,其中的 options 属性定义了右键菜单的选项。用户在表格中右键点击时,将会弹出包含这些选项的自…

md笔记使用加自动备份整理

1、安装使用 TyporaGiteePicGo搭建图床(解决使用Typora写的笔记上传csdn图片无法正常显示问题) 2、修改主题 文件-》偏好设置-》外观-》打开主题文件夹 将css文件放到里面然后重启typora(css文件可以参考参考链接) 3、设置自动备份…

数据结构二维数组计算题,以行为主?以列为主?

1.假设以行序为主序存储二维数组Aarray[1..100,1..100],设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]( )。 A.808 B.818 C.1010 D&…

包装效果图渲染技巧:怎么用云渲染省钱、省时间

在今天这个市场竞争白热化的时代,一个产品的包装设计往往决定了它在架上是否能够脱颖而出。因此,品牌在推向市场前精心设计的包装效果图显得尤为重要。在这里,我们将探究包装效果图渲染的关键性、渲染技巧及云渲染技术如何在提升渲染品质与降…

Matlab 点云收缩L1中值(Weiszfeld算法)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 对于之前的加权均值收缩方式,它存在一个很大的缺点,即容易受到噪声的影响,因此这里我们采用另一种统计学方案:L1中值。其形式如下所示: 其中 x i x_i

DICOM 文件中,VR,VL,Sequence,图像二进制的几个注意点

DICOM 文件中,VR,VL,Sequence,图像二进制的几个注意点 1. 传输语法 DICOM 文件的结构,在网上有很多的学习资料,这里只介绍些容易混淆的概念,作为回看笔记。 每个传输语法,起都是表…

openGauss学习笔记-154 openGauss 数据库运维-备份与恢复-闪回恢复

文章目录 openGauss学习笔记-154 openGauss 数据库运维-备份与恢复-闪回恢复154.1 闪回查询154.1.1 背景信息154.1.2 前提条件154.1.3 语法154.1.4 参数说明154.1.5 使用示例 154.2 闪回表154.2.1 背景信息154.2.2 前提条件154.2.3 语法154.2.4 使用示例 154.3 闪回DROP/TRUNCA…

【清晰明了】Jenkins邮件发送配置

自带邮件插件 首先要知道的是jenkins是自带邮件插件的,且不支持卸载。 下面开始配置自带邮件插件。 配置默认邮件管理员 系统管理 --> 系统配置,进行如下配置: 不配置管理员邮件地址报错如下 jakarta.mail.internet.AddressException:…

网络编程----select 模型总结

为什么要使用select模型? 答:解决基本C/S模型中,accept()、recv()、send()阻塞的问题 select模型与C/S模型的不同点 C/S模型中accept()会阻塞一直傻等socket来链接select模型只解决accept()傻等的问题,不解决recv(),send()执行…

大厂大数据面试题收录(1)

目录 1.java 中 object 类有哪些方法? 2.说一下和equals的区别? 3.为什么要重写 equals 和 hashcode()方法? 4.机器学习中,监督学习 和 无监督学习的区别是啥?? 5.kafka 组件熟悉吗,kafka 如何实现消息的有序的&a…

css 表示具有特定类或者其他属性的某种标签类型的元素

需求 通过 css 选择器获取某种标签&#xff08;如&#xff1a;div、input 等&#xff09;具有某个属性&#xff08;如&#xff1a;class、id 等&#xff09;的元素&#xff0c;从而修改其样式。 代码 通过 [标签].[属性] 的方式来获取 <div class"test">&l…

C++相关闲碎记录(8)

1、预定义的Function adapter 和 binder #include <iostream> #include <functional>int main() {auto plus10 std::bind(std::plus<int>(), std::placeholders::_1, 10);std::cout << "10: " << plus10(6) << std::endl…

基于FPGA的视频接口之高速IO(PCIE)

简介 相对于其他高速IO接口应用&#xff0c;PCIE协议有专门的的IP来进行操作&#xff0c;通过8对输入高速IO&#xff0c;以及输出高速IO&#xff0c;来实现PCIEX8功能。 原理框图 原理图 软件调用

Nginx首页修改及使用Nginx实现端口转发

按照我之前博客给的方法搭建好这样一个CTF靶场 但是呢它默认是在8000端口 如何直接访问IP地址或者域名就可以实现直接访问到靶场呢 我们需要将80端口的内容转发到8000&#xff0c;使用nginx实现端口转发功能 首先我们安装nginx&#xff1a; 安装工具和库 yum -y install gc…

《地理信息系统原理》笔记/期末复习资料(9. 网络地理信息系统)

目录 9. 网络地理信息系统 9.1. 概述 9.1.1. 网络GIS概念 9.1.2. 网络GIS体系结构 9.1.3. 网络GIS内容体系 9.2. 分布式网络GIS 9.2.1. 分布式网络GIS概念 9.2.2. 分布式主要技术 9.3. WebGIS 9.3.1. WebGIS概念 9.3.2. WebGIS分类与特点 9.3.3. WebGIS技术框架 9…

IDEA中的Postman!这款插件:免费,好用!

Postman是大家最常用的API调试工具&#xff0c;那么有没有一种方法可以不用手动写入接口到Postman&#xff0c;即可进行接口调试操作&#xff1f;今天给大家推荐一款IDEA插件&#xff1a;Apipost Helper&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还…

电商早报 | 12月12日| 淘宝公布2023年度商品初选名单入围

淘宝公布2023年度商品初选名单&#xff1a;军大衣、酱香拿铁、熊猫周边入围 又一年临近收官&#xff0c;淘宝如期启动了“2023年度十大商品”评选。 12月11日&#xff0c;淘宝官方发布了初选入围名单&#xff0c;30件最具代表性的商品脱颖而出。据淘宝路边社介绍&#xff0c;…

系统架构设计师教程(三)信息系统基础知识

信息系统基础知识 3.1 信息系统概述3.1.1 信息系统的定义3.1.2 信息系统的发展3.1.3 信息系统的分类3.1.4 信息系统的生命周期3.1.5 信息系统建设原则3.1.6 信息系统开发方法 3.2 业务处理系统 (TPS)3.2.1 业务处理系统的概念3.2.2 业务处理系统的功能3.2.3 业务处理系统的特点…

互联网加竞赛 opencv 图像识别 指纹识别 - python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器视觉的指纹识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c;适…