【Python · PyTorch】卷积神经网络 CNN(LeNet-5网络)

【Python · PyTorch】卷积神经网络 CNN(LeNet-5网络)

  • 1. LeNet-5网络
    • ※ LeNet-5网络结构
  • 2. 读取数据
    • 2.1 Torchvision读取数据
    • 2.2 MNIST & FashionMNIST 下载解包读取数据
  • 2. Mnist
    • ※ 训练 LeNet5 预测分类
  • 3. EMnist
    • ※ 训练 LeNet5 预测分类
  • 4. FashionMnist
    • ※ 训练 LeNet5 预测分类
  • 5. CIFAR-10
    • ※ 训练 LeNet5 预测分类

1. LeNet-5网络

标志:经典的卷积神经网络

LeNet-5由Yann Lecun 提出,是一种经典的卷积神经网络,是现代卷积神经网络的起源之一。

Yann将该网络用于邮局的邮政的邮政编码识别,有着良好的学习和识别能力。

※ LeNet-5网络结构

LeNet-5具有一个输入层,两个卷积层,两个池化层,3个全连接层(其中最后一个全连接层为输出层)。
LeNet5

下面我们以灰度值黑白图像为例,描述LeNet网络结构,其中:”接纳“表示”中间层输入“,”传递“表示”中间层输出“。

层次结构:

  • 输入层 (Input Layer)
    • 输入尺寸:32 × 32 数据图
    • 灰度值:0 ~ 255(一般进行预处理)
    • 传递通道数:1
  • 卷积层 C1 (Convolutional Layer c1)
    • 卷积核尺寸:5 × 5
    • 卷积核数量:6
    • 步长:1
    • 填充:0
    • 传递尺寸:28 × 28 特征图
    • 传递通道数:6
  • 子采样/池化层 S2 (Subsampling Layer S2)
    • 类型:MaxPooling
    • 窗口尺寸:2 × 2
    • 步长:2
    • 传递尺寸:14 × 14 特征图
    • 传递通道数:6
  • 卷积层 C3 (Convolutional Layer c3)
    • 卷积核尺寸:5 × 5
    • 卷积核数量:16
    • 步长:1
    • 填充:0
    • 传递尺寸:10 × 10 特征图
    • 传递通道数:16
  • 子采样/池化层 S4 (Subsampling Layer S4)
    • 类型:MaxPooling
    • 窗口尺寸:2 × 2
    • 步长:2
    • 传递尺寸:5 × 5 特征图
    • 传递通道数:6
  • 全连接层 C5 (Fully Connected Layer C5)
    • 展平尺寸:400 ( 25 * 16 )
    • 传递尺寸:120
  • 全连接层 C6 (Fully Connected Layer C6)
    • 接纳尺寸:120
    • 传递尺寸:84
  • 输出层 (Output Layer)
    • 接纳尺寸:84
    • 输出尺寸:10

Same卷积 & Full卷积 & Valid卷积

  • Same卷积:根据卷积核大小对输入特征图自适应 零填充 (以k定p),确保输出的特征图大小与输入的特征图尺寸相同。
  • Full卷积:允许卷积核超出特征图范围,但须确保卷积核边缘与特征图边缘相交。Same卷积是特殊的Full卷积。
  • Valid卷积:卷积过程中不使用填充,输出特征图的尺寸小于输入特征图的尺寸。

本文 Torch & Torchvision版本

Torch版本

2. 读取数据

2.1 Torchvision读取数据

Datasets 使用

torchvision.datasets模块包含多种预定义类型的数据集,例如MNISTEMNISTFashionMNISTCIFAR-10ImageNet等。它封装了这些数据集的下载、加载和预处理步骤。

torchvision.datasets 4个参数

  • root:字符串类型,指定存放路径
  • train:布尔类型,区分训练集与测试集
  • download:布尔类型,开启下载,若本地存在则不进行下载
  • transform:用于对数据预先处理的转换

2.2 MNIST & FashionMNIST 下载解包读取数据

定义读取函数

""" 定义读取函数 """
def load_mnist(path, kind='train'):
    import os
    import gzip
    import numpy as np
    
    """ Load MNIST data for `path` """
    labels_path = os.path.join(path, '{}-labels-idx1-ubyte.gz'.format(kind))
    images_path = os.path.join(path, '{}-images-idx3-ubyte.gz'.format(kind))
    
    with gzip.open(labels_path, 'rb') as lbpath:
        labels = np.frombuffer(lbpath.read(), dtype=np.uint8, offset=8)
    with gzip.open(images_path, 'rb') as lbpath:
        images = np.frombuffer(lbpath.read(), dtype=np.uint8, offset=16).reshape(len(labels), 28*28)
        
    return images, labels

抽取:训练集测+ 试集

X_train, y_train = load_mnist(path="./data/mnist")
X_test, y_test = load_mnist(path="./data/mnist", kind='t10k')

自定义 Pytorch Dataset 类

""" 自定义 Pytorch Dataset 类 """
class MnistDataset(Dataset):
    def __init__(self, data_path, kind=None, transform=None):
        self.transform = transform
        images, labels = load_mnist(path="./data/mnist", kind=kind)
        

2. Mnist

Mnist数据集:手写数字识别数据集,数据集分为训练集和测试集,用以训练和评估机器学习模型。

该数据集在深度学习领域具有重要地位,尤其适合初学者学习和实践图像识别技术。

  • 该数据集含有10种类别,共70000张灰度图像。包含 60000个训练集样本 和 10000个测试集样本。
  • 每张图像以 28×28 像素的分辨率提供。

MNIST是一个手写数字数据集,该数据集由美国国家标准与技术研究所(National Institute of Standards and Technology, NIST)发起整理。该数据集的收集目的是希望通过算法,实现对手写数字的识别。

1998年,Yan LeCun 等人首次提出了LeNet-5 网络,利用上述数据集实现了手写字体的识别。

MNIST数据集由4个部分组成,分别为训练集图像、训练集标签、测试集图像和测试集标签。其中训练集图像为 60,000 张图像,测试集图像为 10,000 张。每张图像即为一个28*28的像素数组,每个像素的值为0或255(黑白图像)。

每个标签则为长度为10的一维数组,代表其为0-9数字的概率。

卷积神经网络 - 手写数字 - 可视化

手写数字示意

手写数字示意

代码

利用torchvision.datasets.MNIST()读取

""" 导入三方库 """
import torch
import torchvision
from torch.utils.data import DataSet, DataLoader
import torchvision.transforms as transforms

# 定义转换实例
data_transform = transforms.Compose(
	[transforms.ToTensor(),											# transforms.ToTensor() 将给定图像转为Tensor
    transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5])]	# transforms.Normalize() 归一化处理
)

# 加载MNIST数据集
trainset = torchvision.datasets.MNIST(root='./data/',train=True, download=True, transform=data_transform)
testset = torchvision.datasets.MNIST(root='./data/',train=False, download=True, transform=data_transform)

# 加载数据加载器,便于小批量优化
trainloader = torch.utils.data.DataLoader(trainset, batch_size=100, shuffle=True)
testloader = troch.utils.data.DataLoader(testset, batch_size=100, shuffle=False)

※ 训练 LeNet5 预测分类

① 导入三方库

导入三方库

import os
import numpy as np
import cv2
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
import seaborn as sns
import matplotlib.pyplot as plt

确定运行设备:判断cuda是否可用

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

② 读取数据集

利用torchvision.datasets.MNIST()读取

# 定义转换实例
data_transform = transforms.Compose(
	[transforms.ToTensor(),											# transforms.ToTensor() 将给定图像转为Tensor
    transforms.Normalize(mean=[0.5], std=[0.5])]					# transforms.Normalize() 归一化处理
)

# 加载FashionMNIST数据集
train_set = torchvision.datasets.FashionMNIST(root='./data/',train=True, download=True, transform=data_transform)
test_set = torchvision.datasets.FashionMNIST(root='./data/',train=False, download=True, transform=data_transform)

# 加载数据加载器,便于小批量优化
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=100, shuffle=False)

③ 创建神经网络

创建神经网络

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()

        self.layer1 = nn.Sequential( 
            # 为匹配 LeNet 32*32 输入,故对 28*28 图像作 p=2 padding。
            nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(6),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer3 = nn.Sequential(
            nn.Flatten(),
            nn.Linear(in_features=16*5*5, out_features=120),
            nn.ReLU(),
            nn.Linear(in_features=120, out_features=84),
            nn.ReLU(),
            nn.Linear(in_features=84, out_features=10),
            nn.LogSoftmax()
        )
    def forward(self, x):
        output = self.layer1(x)
        output = self.layer2(output)
        output = self.layer3(output)
        return output

④ 训练神经网络

预定义超参数

# 随机种子
torch.manual_seed(20)
# 创建神经网络对象
model = LeNet()
# 确定神经网络运行设备
model.to(device)
# 损失函数
loss_function = nn.CrossEntropyLoss()
# 优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练轮次
epochs = 5
# 小批量训练次数
batch_size = 100
# 训练损失记录
final_losses = []

定义神经网络训练函数

def train_model():
    count = 0
    for epoch in range(epochs):
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            train = images.view(100, 1, 28, 28)
            # 1. 正向传播
            preds = model(train)

            # 2. 计算误差
            loss = loss_function(preds, labels)
            final_losses.append(loss)
            # 3. 反向传播
            optimizer.zero_grad()
            loss.backward()
            # 4. 优化参数
            optimizer.step()

            count += 1
            if count % 100 == 0:
                print("Epoch: {}, Iteration: {}, Loss: {} ".format(epoch, count, loss.data))

调用训练函数 + 保存模型

train_model()
torch.save(model.state_dict(), "mlenet.pth")
print("Saved PyTorch Model State to mlenet.pth")

绘制训练损失图像

for i in range(len(final_losses)):
    final_losses[i] = final_losses[i].item()
plt.plot(final_losses)
plt.show()

训练损失

⑤ 测试神经网络

定义混淆矩阵

confusion_matrix = np.zeros((10,10))

定义神经网络测试函数

def test_model():
    model = LeNet()
    model.to(device)
    model.load_state_dict(torch.load('mlenet.pth'))
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)

            preds = model(images)
            preds = torch.max(preds, 1)[1]
            labels = torch.max(labels, 1)[1]

            correct += (preds == labels).sum()
            total += len(images)
        print(f"accuracy: {correct/total}")

调用训练函数 + 输出混淆矩阵

# 调用训练函数
test_model()
# 输出混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix, annot=True, cmap='Oranges', linecolor='black', linewidth=0.5, fmt='.20g')

准确率

混淆矩阵

3. EMnist

EMnist数据集:手写字符识别数据集,Mnist数据集进阶版本,数据集分为训练集和测试集,用以训练和评估机器学习模型。

该数据集在深度学习领域具有重要地位,尤其适合初学者学习和实践图像识别技术。

  • 该数据集含有10种类别,共70000张灰度图像。包含 60000个训练集样本 和 10000个测试集样本。
  • 每张图像以 28×28 像素的分辨率提供。

EMNIST 分为以下 6 类:

By_Class : 共 814255 张,62 类,与 NIST 相比重新划分类训练集与测试集的图片数。

By_Merge: 共 814255 张,47 类, 与 NIST 相比重新划分类训练集与测试集的图片数。

Balanced : 共 131600 张,47 类, 每一类都包含了相同的数据,每一类训练集 2400 张,测试集 400 张。

Digits :共 28000 张,10 类,每一类包含相同数量数据,每一类训练集 24000 张,测试集 4000 张。

Letters : 共 103600 张,37 类,每一类包含相同数据,每一类训练集 2400 张,测试集 400 张。

MNIST : 共 70000 张,10 类,每一类包含相同数量数据(注:这里虽然数目和分类都一样,但是图片的处理方式不一样,EMNIST 的 MNIST 子集数字占的比重更大)


Letter中相似的字母 (例如c或o) 被整合为1个字符,则共有37个字母可被识别,但因 未区分大小写&手写印刷体 最终被统一归为 26 类别,又因为包含未分类类别 [N/A] 故归为 27 类别

本小节利用 EMNIST-Letters 数据集训练LeNet5模型,进行字符识别。

数据集排列:

[N/A]abcd……

※ 训练 LeNet5 预测分类

① 导入三方库

导入三方库

import os
import numpy as np
import cv2
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
import seaborn as sns
import matplotlib.pyplot as plt

确定运行设备:判断cuda是否可用

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

② 读取数据集

利用torchvision.datasets.EMNIST()读取

# 定义转换实例
data_transform = transforms.Compose(
	[transforms.ToTensor(),											# transforms.ToTensor() 将给定图像转为Tensor
    transforms.Normalize(mean=[0.5], std=[0.5])]					# transforms.Normalize() 归一化处理
)

# 加载FashionMNIST数据集
train_set = torchvision.datasets.FashionMNIST(root='./data/',train=True, download=True, transform=data_transform)
test_set = torchvision.datasets.FashionMNIST(root='./data/',train=False, download=True, transform=data_transform)

# 加载数据加载器,便于小批量优化
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=100, shuffle=False)

③ 创建神经网络

创建神经网络

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()

        self.layer1 = nn.Sequential( 
            # 为匹配 LeNet 32*32 输入,故对 28*28 图像作 p=2 padding。
            nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(6),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer3 = nn.Sequential(
            nn.Flatten(),
            nn.Linear(in_features=16*5*5, out_features=120),
            nn.ReLU(),
            nn.Linear(in_features=120, out_features=84),
            nn.ReLU(),
            nn.Linear(in_features=84, out_features=27),
            nn.LogSoftmax()
        )
    def forward(self, x):
        output = self.layer1(x)
        output = self.layer2(output)
        output = self.layer3(output)
        return output

④ 训练神经网络

预定义超参数

# 随机种子
torch.manual_seed(20)
# 创建神经网络对象
model = LeNet()
# 确定神经网络运行设备
model.to(device)
# 损失函数
loss_function = nn.CrossEntropyLoss()
# 优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练轮次
epochs = 5
# 小批量训练次数
batch_size = 100
# 训练损失记录
final_losses = []

定义神经网络训练函数

def train_model():
    count = 0
    for epoch in range(epochs):
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            # 1. 正向传播
            preds = model(train)

            # 2. 计算误差
            loss = loss_function(preds, labels)
            final_losses.append(loss)
            # 3. 反向传播
            optimizer.zero_grad()
            loss.backward()
            # 4. 优化参数
            optimizer.step()

            count += 1
            if count % 100 == 0:
                print("Epoch: {}, Iteration: {}, Loss: {} ".format(epoch, count, loss.data))

调用训练函数 + 保存模型

train_model()
torch.save(model.state_dict(), "elenet.pth")
print("Saved PyTorch Model State to mlenet.pth")

绘制训练损失图像

for i in range(len(final_losses)):
    final_losses[i] = final_losses[i].item()
plt.plot(final_losses)
plt.show()

训练损失

⑤ 测试神经网络

定义混淆矩阵

confusion_matrix = np.zeros((27,27))

定义神经网络测试函数

def test_model():
    model = LeNet()
    model.to(device)
    model.load_state_dict(torch.load('elenet.pth'))
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)

            preds = model(images)
            preds = torch.max(preds, 1)[1]

            correct += (preds == labels).sum()
            total += len(images)
            for i in range(len(preds)):
                confusion_matrix[preds[i]][labels[i]] += 1
        print(f"accuracy: {correct/total}")

调用训练函数 + 输出混淆矩阵

# 调用训练函数
test_model()
# 输出混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix, annot=True, cmap='Oranges', linecolor='black', linewidth=0.5, fmt='.20g')

准确率

混淆矩阵

4. FashionMnist

FashionMnist:衣物图标识别数据集,Mnist数据集进阶版本,数据集分为训练集和测试集,用以训练和评估机器学习模型。

该数据集在深度学习领域具有重要地位,尤其适合初学者学习和实践图像识别技术。

  • 该数据集含有10种类别,共70000张灰度图像。包含 60000个训练集样本 和 10000个测试集样本。
  • 每张图像以 28×28 像素的分辨率提供。
标注编号类别
0T恤 T-shirt
1裤子 Trousers
2套衫 Pullover
3裙子 Dress
4外套 Coat
5凉鞋 Sandal
6汗衫 Shirt
7运动鞋 Sneaker
8包 Bag
9踝靴 Ankle boot

※ 训练 LeNet5 预测分类

① 导入三方库

导入三方库

import os
import numpy as np
import cv2
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
import seaborn as sns
import matplotlib.pyplot as plt

确定运行设备:判断cuda是否可用

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

② 读取数据集

利用torchvision.datasets.FashionMNIST()读取

# 定义转换实例
data_transform = transforms.Compose(
	[transforms.ToTensor(),											# transforms.ToTensor() 将给定图像转为Tensor
    transforms.Normalize(mean=[0.5], std=[0.5])]					# transforms.Normalize() 归一化处理
)

# 加载FashionMNIST数据集
train_set = torchvision.datasets.FashionMNIST(root='./data/',train=True, download=True, transform=data_transform)
test_set = torchvision.datasets.FashionMNIST(root='./data/',train=False, download=True, transform=data_transform)

# 加载数据加载器,便于小批量优化
train_loader = torch.utils.data.DataLoader(train_set, batch_size=100, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=100, shuffle=False)

③ 创建神经网络

创建神经网络

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()

        self.layer1 = nn.Sequential( 
            # 为匹配 LeNet 32*32 输入,故对 28*28 图像作 p=2 padding。
            nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(6),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer3 = nn.Sequential(
            nn.Flatten(),
            nn.Linear(in_features=16*5*5, out_features=120),
            nn.ReLU(),
            nn.Linear(in_features=120, out_features=84),
            nn.ReLU(),
            nn.Linear(in_features=84, out_features=10),
            nn.LogSoftmax()
        )
    def forward(self, x):
        output = self.layer1(x)
        output = self.layer2(output)
        output = self.layer3(output)
        return output

④ 训练神经网络

预定义超参数

# 随机种子
torch.manual_seed(20)
# 创建神经网络对象
model = LeNet()
# 确定神经网络运行设备
model.to(device)
# 损失函数
loss_function = nn.CrossEntropyLoss()
# 优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练轮次
epochs = 5
# 小批量训练次数
batch_size = 100
# 训练损失记录
final_losses = []

定义神经网络训练函数

def train_model():
    count = 0
    for epoch in range(epochs):
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            train = images.view(100, 1, 28, 28)
            # 1. 正向传播
            preds = model(train)

            # 2. 计算误差
            loss = loss_function(preds, labels)
            final_losses.append(loss)
            # 3. 反向传播
            optimizer.zero_grad()
            loss.backward()
            # 4. 优化参数
            optimizer.step()

            count += 1
            if count % 100 == 0:
                print("Epoch: {}, Iteration: {}, Loss: {} ".format(epoch, count, loss.data))

调用训练函数 + 保存模型

train_model()
torch.save(model.state_dict(), "fmlenet.pth")
print("Saved PyTorch Model State to fmlenet.pth")

绘制训练损失图像

for i in range(len(final_losses)):
    final_losses[i] = final_losses[i].item()
plt.plot(final_losses)
plt.show()

训练损失

⑤ 测试神经网络

定义混淆矩阵

confusion_matrix = np.zeros((10,10))

定义神经网络测试函数

def test_model():
    model = LeNet()
    model.to(device)
    model.load_state_dict(torch.load('fmlenet.pth'))
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)

            preds = model(images)
            preds = torch.max(preds, 1)[1]

            correct += (preds == labels).sum()
            total += len(images)
            for i in range(len(preds)):
                confusion_matrix[preds[i]][labels[i]] += 1
        print(f"accuracy: {correct/total}")

调用训练函数 + 输出混淆矩阵

# 调用训练函数
test_model()
# 输出混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix, annot=True, cmap='Oranges', linecolor='black', linewidth=0.5, fmt='.20g')

准确率

混淆矩阵
由此得出,标准LeNet5网络拟合Fashion效果良好。

5. CIFAR-10

CIFAR10数据集共有60000个样本(32*32像素的RGB彩色图像),每个RGB图像包含3个通道(R通道、G通道、B通道)。

  • 该数据集含有10种类别,共60000张彩色图像。包含 50000个训练集样本 和 10000个测试集样本。
标注编号类别
0飞机 Airplane
1汽车 Automobile
2鸟 Bird
3猫 Cat
4鹿 Deer
5狗 Dog
6青蛙 Frog
7马 Horse
8船 Ship
9卡车 Truck

CIFAR10数据集的内容,如图所示。

CIFAR10

※ 训练 LeNet5 预测分类

① 导入三方库

导入三方库

import os
import numpy as np
import cv2
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
import seaborn as sns
import matplotlib.pyplot as plt

确定运行设备:判断cuda是否可用

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

② 读取数据集

利用torchvision.datasets.CIFAR10()读取

# 定义一个转换参数的实例
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]
)

# 加载CIFAR10数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=data_transform)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=data_transform)
 
# 创建数据加载器
train_loader = torch.utils.data.DataLoader(trainset, batch_size=600, shuffle=True)
test_loader = torch.utils.data.DataLoader(testset, batch_size=600, shuffle=False)

③ 创建神经网络

创建神经网络

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()

        self.layer1 = nn.Sequential( 
            nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5),
            nn.BatchNorm2d(6),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.layer3 = nn.Sequential(
            nn.Flatten(),
            nn.Linear(in_features=16*5*5, out_features=120),
            nn.ReLU(),
            nn.Linear(in_features=120, out_features=84),
            nn.ReLU(),
            nn.Linear(in_features=84, out_features=10),
            nn.LogSoftmax()
        )
    def forward(self, x):
        output = self.layer1(x)
        output = self.layer2(output)
        output = self.layer3(output)
        return output

④ 训练神经网络

预定义超参数

# 随机种子
torch.manual_seed(20)
# 创建神经网络对象
model = LeNet()
# 确定神经网络运行设备
model.to(device)
# 损失函数
loss_function = nn.CrossEntropyLoss()
# 优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练轮次
epochs = 50
# 小批量训练次数
batch_size = 600
# 训练损失记录
final_losses = []

定义神经网络训练函数

def train_model():
    for epoch in range(epochs):
        count = 0
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            train = images
            
            # 1. 正向传播
            preds = model(train)
            # 2. 计算误差
            loss = loss_function(preds, labels)
            final_losses.append(loss)
            # 3. 反向传播
            optimizer.zero_grad()
            loss.backward()
            # 4. 优化参数
            optimizer.step()

            count += 1
            if count % 100 == 0:
                print("Epoch: {}, Iteration: {}, Loss: {} ".format(epoch, count, loss.data))

调用训练函数 + 保存模型

train_model()
torch.save(model.state_dict(), "clenet.pth")
print("Saved PyTorch Model State to clenet.pth")

绘制训练损失图像

for i in range(len(final_losses)):
    final_losses[i] = final_losses[i].item()
plt.plot(final_losses)
plt.show()

训练损失

⑤ 测试神经网络

定义混淆矩阵

confusion_matrix = np.zeros((10,10))

定义神经网络测试函数

def test_model():
    model = LeNet()
    model.to(device)
    model.load_state_dict(torch.load('fmlenet.pth'))
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)

            preds = model(images)
            preds = torch.max(preds, 1)[1]

            correct += (preds == labels).sum()
            total += len(images)
            for i in range(len(preds)):
                confusion_matrix[preds[i]][labels[i]] += 1
        print(f"accuracy: {correct/total}")

调用训练函数 + 输出混淆矩阵

# 调用训练函数
test_model()
# 输出混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix, annot=True, cmap='Oranges', linecolor='black', linewidth=0.5, fmt='.20g')

准确率

混淆矩阵

由此得出,未经修饰/改进的标准LeNet5网络对CIFAR10数据集的拟合效果不佳。

可改进的方向:

  • 本文对CIFAR10数据集的拟合效果不佳,后续可对此问题再作探究。
  • 本文所有网络的输出层采用了LogSoftmax函数,而非Softmax函数,后续可在此问题上继续探讨。

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

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

相关文章

Live2D嵌入前端页面

废话不多说,直接看效果,给页面中嵌入的一个动态的二次元人物,美化页面,实际效果自行查看。 教程开始 一. 把项目拉取到本地 项目地址 自行下载到本地,下载方式自行选择。 二.把项目文件夹放到前端页面目录内 三.把下…

openlayer 将 GeoJSON 格式的 geometry 转换为 feature

openlayer 将 GeoJSON 格式的 geometry 转换为 feature geometry格式如图: 代码: /*** 将 GeoJSON 格式的 geometry 转换为 feature* param geometry* returns*/geoJsonToWkt(geometry) {const { coordinates, type } geometry;let olGeometry;swit…

web应用安全和信息泄露预防

文章目录 1:spring actuator导致的信息泄露1.1、Endpoint配置启用检测1.2、信息泄露复现1.3、防御 2:服务端口的合理使用3:弱口令(密码)管理4:服务端攻击4.1、短信业务,文件上传等资源型接口1、…

基于LSTM的新闻中文文本分类——基于textCNN与textRNN

构建词语字典 def build_vocab(file_path, tokenizer, max_size, min_freq):# 定义词汇表字典:使用 vocab_dic {} 初始化一个空字典,用于存储每个词及其出现频率vocab_dic {}with open(file_path, r, encodingUTF-8) as f:for line in tqdm(f):lin l…

MySQL 的 Change Buffer 是什么?它有什么作用?

MySQL 的 Change Buffer 是什么?它有什么作用? MySQL 是目前广泛使用的开源数据库管理系统,其中的 InnoDB 存储引擎凭借其高性能、高可靠性以及强大的事务支持,成为了默认的存储引擎。在 InnoDB 的众多优化机制中,Cha…

Spark 之 Aggregate

Aggregate 参考链接: https://github.com/PZXWHU/SparkSQL-Kernel-Profiling 完整的聚合查询的关键字包括 group by、 cube、 grouping sets 和 rollup 4 种 。 分组语句 group by 后面可以是一个或多个分组表达式( groupingExpressions )…

C#高级:Winform中的自定义窗体输入

目录 一、多样式输入(无封装) 1.代码 2.效果 二、单输入框封装 1.使用 2.封装 3.效果 三、组合框批量输入封装 1.使用 2.封装 3.效果 一、多样式输入(无封装) 1.代码 private async void button1_Click(object send…

使用GDB或Delve对已经运行起来的Go程序进行远程调试

同步发布在我的博客,欢迎来点赞。 使用 GDB 或 Delve 对已经运行起来的 Go 程序进行远程调试 使用 GDB 或 Delve 对已经运行起来的 Go 程序进行远程调试 背景 Java 程序可以很方便地通过 jdwp 参数指定一个对外端口进行远程调试,如 java \ -agentlib…

简单实现QT对象的[json]序列化与反序列化

简单实现QT对象的[json]序列化与反序列化 简介应用场景qt元对象系统思路实现使用方式题外话 简介 众所周知json作为一种轻量级的数据交换格式,在开发中被广泛应用。因此如何方便的将对象数据转为json格式和从json格式中加载数据到对象中就变得尤为重要。 在python类…

Java开发经验——开发常用工具类

摘要 本文介绍了Java开发中常用的工具类,包括Apache Commons Collections的SetUtils、Google Guava的Sets、Apache Commons Lang的ArrayUtils等,以及它们在集合操作、数组操作、字符串处理、JSON处理等方面的应用。文章还涉及了Optional类、Money工具类…

esp32c3开发板通过micropython的mqtt库连MQTT物联网消息服务器

MQTT介绍 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息协议,旨在设备之间进行通信,尤其是在网络条件较差的情况下。MQTT v3.1.1 和 MQTT v5 是该协议的两个主要版本。 MQTT v3.1.1: 优点&#xff…

【IDE】使用指南

定期更新实用技能,建议关注收藏点赞。 友情链接: 点击跳转常见代码编辑器的报错解决方案 目录 常用快捷键pycharm右下角边栏脚本头安装IDE的插件git配置TODO 代码编辑器里有许多小技巧,便于办公。本篇主要以pycharm,vscode等主流常用IDE为…

OpenGL入门009——漫反射在片段着色器中的应用

本节将在片段着色器中应用漫反射 文章目录 一些概念漫反射 实战简介dependenciesshadervsshader.fs utilsCube.cpp main.cppCMakeLists.txt最终效果 一些概念 漫反射 概述: 描述的是粗糙表面对光的反射,反射的光线相关各个方向均匀分布,与视…

删库跑路,启动!

起因:这是一个悲伤的故事,在抓logcat时 device待机自动回根目录了,而题主对当前路径的印象还停留在文件夹下,不小心在根目录执行了rm -rf * … 所以,这是个悲伤的故事,东西全没了…device也黑屏了&#xff…

Ubuntu下的Eigen库的安装及基本使用教程

一、Eigen库介绍 简介 Eigen [1]目前最新的版本是3.4,除了C标准库以外,不需要任何其他的依赖包。Eigen使用的CMake建立配置文件和单元测试,并自动安装。如果使用Eigen库,只需包特定模块的的头文件即可。 基本功能 Eigen适用范…

OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)

本文来源公众号“OpenCV与AI深度学习”,仅用于学术分享,侵权删,干货满满。 原文链接:分享|16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括: 1. 人…

MySQL win安装 和 pymysql使用示例

目录 一、MySQL安装 下载压缩包: 编写配置文件: 配置环境变量: 初始化服务和账户 关闭mysql开机自启(可选) 建议找一个数据库可视化软件 二、使用pymysql操作数据库 安装pymysql 示例代码 报错处理 一、My…

springboot基于微信小程序的停车场管理系统

摘 要 停车场管理系统是一种基于移动端的应用程序,旨在方便车主停车的事务办理。该小程序提供了便捷的停车和功能,使车主能够快速完成各项必要的手续和信息填写。旨在提供一种便捷、高效的预约停车方式,减少停车手续的时间和精力成本。通过该…

js:数组转换为字符串

1、使用join 通过join,将数组拼接,使用,进行分割 let array [a, b, c] let str array.join(,); console.log(str) 2、使用toString() const array [a, b, c] const string array.toString() console.log(string) 3、使用扩展运算符和…

npm上传自己封装的插件(vue+vite)

一、npm账号及发包删包等命令 若没有账号,可在npm官网:https://www.npmjs.com/login 进行注册。 在当前项目根目录下打开终端命令窗口,常见命令如下: 1、登录命令:npm login(不用每次都重新登录&#xff0…