MNIST数据集_CNN

news2025/1/10 3:03:32

前言

提醒:
文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。
其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展及意见建议,欢迎评论区讨论交流。

文章目录

  • 前言
  • 数据集MNIST
      • 数据集概述
      • 数据集的结构
      • 数据集的格式
      • 使用 MNIST 数据集
      • 例子:如何加载 MNIST 数据集
      • 数据集的应用
      • 数据集的挑战
    • 数据集介绍
      • 1. 导入必要的库
      • 2. 加载MNIST数据集
      • 3. 加载测试集
      • 4. 创建数据加载器
    • 数据集实例
  • CNN
      • 1. 卷积层(Convolutional Layer)
        • 数学公式:
        • 卷积的步骤:
      • 2. 激活函数(Activation Function)
      • 3. 池化层(Pooling Layer)
        • 最大池化:
      • 4. 全连接层(Fully Connected Layer)
      • 5. 卷积神经网络的典型结构
      • 6. 卷积神经网络的训练
      • 7. CNN 训练的优化:梯度下降法
  • 代码分析
    • def __init__(self,hidden_channel_size_1,hidden_channel_size_2,num_classes=10):
        • 1 第一层卷积
        • 2 第二层卷积
        • 3 全连接层
    • def forward(self, x):
        • 前向传播
    • criterion = nn.CrossEntropyLoss()
        • 损失函数
    • optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
        • 优化器
    • 训练过程
    • 测试模型
      • 总结


数据集MNIST

MNIST(Modified National Institute of Standards and Technology)数据集是一个广泛使用的图像数据集,主要用于训练和测试图像处理系统,尤其是机器学习和计算机视觉领域的算法。MNIST 是手写数字的一个标准化数据集,常用作分类任务的基准数据集。

数据集概述

***MNIST 数据集包含了 28x28 像素的手写数字图像,且图像是灰度图(即每个像素值在 0 到 255 之间)***数据集包含两部分:

  1. 训练集(Training set):

    • 包含 60,000 张图像。
    • 每张图像对应一个标签,表示该图像所表示的数字(0 到 9)。
  2. 测试集(Test set):

    • 包含 10,000 张图像。
    • 用于测试模型的泛化能力。

每张图像的标签为 0 到 9 的一个数字,表示图像中手写数字的类别。
在这里插入图片描述

数据集的结构

  • 图像大小: 每张图像的尺寸为 28x28 像素。
  • 灰度级: 每个像素的灰度值介于 0(黑色)到 255(白色)之间。
  • 数据类型: 图像数据通常会被转换为浮点数(归一化为 0 到 1 之间),以便输入到神经网络中进行训练。

数据集的格式

MNIST 数据集的每张图像都由 28x28 的灰度值构成,并且对应一个标签。数据通常以以下格式存储:

  • 每张图像是一个 28x28 的矩阵。
  • 每个标签是一个数字(0 到 9),表示图像中的数字。

使用 MNIST 数据集

MNIST 数据集是机器学习和深度学习初学者常用的入门数据集,适用于各种分类算法的实验和研究。因为它的任务相对简单,所以它常常作为测试新算法的基准。常见的算法包括:

  • 传统的机器学习算法(如支持向量机 SVM、k近邻 KNN 等)。
  • 深度学习模型(如卷积神经网络 CNN)。

例子:如何加载 MNIST 数据集

使用 PyTorch,可以通过 torchvision.datasets.MNIST 来直接加载 MNIST 数据集。

数据集的应用

  • 机器学习: 因为 MNIST 是一个简单且具有代表性的分类问题,它非常适合用来评估和比较不同的机器学习算法。许多研究者和开发者使用它来验证新提出的算法的有效性。
  • 深度学习: 在深度学习领域,MNIST 数据集常常用来作为卷积神经网络(CNN)和其他深度学习模型的初步测试集,帮助开发者快速验证他们的模型效果。

数据集的挑战

尽管 MNIST 数据集非常经典,但它也逐渐暴露出了一些局限性。随着计算机视觉技术的进步,MNIST 的问题变得相对简单,许多现代模型可以达到接近 100% 的准确率。因此,很多研究者现在更倾向于使用更复杂的图像数据集,如 CIFAR-10、CIFAR-100、ImageNet 等。

数据集介绍

使用 PyTorch,可以通过 torchvision.datasets.MNIST 来直接加载 MNIST 数据集:

# MNIST dataset 
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
train_dataset = torchvision.datasets.MNIST(root='data', 
                                           train=True, 
                                           download=True,
                                           transform=transforms.ToTensor())

test_dataset = torchvision.datasets.MNIST(root='data', 
                                          train=False, 
                                          transform=transforms.ToTensor(),
                                          download=True)

# Data loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)

1. 导入必要的库

import torch
import torchvision
import torchvision.transforms as transforms
  • torch:PyTorch的核心库,提供了多维数组(Tensor)等基础设施。
  • torchvision:一个专门用于计算机视觉任务的库,提供了常用的数据集、模型和图像处理工具。
  • torchvision.transforms:用于数据预处理和数据增强的模块。

2. 加载MNIST数据集

train_dataset = torchvision.datasets.MNIST(root='data', 
                                           train=True, 
                                           download=True,
                                           transform=transforms.ToTensor())
  • torchvision.datasets.MNIST:这是一个用于加载MNIST数据集的类。MNIST数据集包含手写数字的图像,通常用于图像分类任务。

  • 参数说明

    • root='data':指定数据集存储的根目录。如果该目录不存在,数据集将下载到此位置。
    • train=True:加载训练集。如果设置为False,则加载测试集。
    • download=True:如果在指定的root路径下找不到数据集,将自动下载数据集。
    • transform=transforms.ToTensor():应用于数据集的转换操作。这里使用了transforms.ToTensor(),它将加载的PIL图像转换为PyTorch的Tensor格式,同时将像素值从[0, 255]范围归一化到[0, 1]范围。

3. 加载测试集

test_dataset = torchvision.datasets.MNIST(root='data', 
                                          train=False, 
                                          transform=transforms.ToTensor(),
                                          download=True)
  • 这段代码与加载训练集的代码类似,但train=False表示加载的是测试集。其他参数相同。测试集用于模型评估,而训练集用于模型训练。

4. 创建数据加载器

train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)
  • torch.utils.data.DataLoader:这是PyTorch提供的一个工具,用于批量加载数据集,便于在训练和测试模型时使用。

  • 参数说明

    • dataset=train_dataset:指定要加载的数据集,这里是训练集。
    • batch_size=batch_size:每个批次加载的数据样本数量。batch_size是一个变量,通常在代码的其他地方定义。合理的批量大小可以提高训练效率,并有助于模型的收敛。
    • shuffle=True:在每个epoch开始前打乱数据集的顺序,增加训练的随机性,有助于提升模型的泛化能力。
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)
  • 这段代码用于加载测试集,参数与训练集加载器相似。这里的shuffle=False表示在测试时不打乱数据集。测试集的顺序通常是重要的,以便在评估模型性能时保持一致。

数据集实例

# MNIST dataset 
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
train_dataset = torchvision.datasets.MNIST(root='data', 
                                           train=True, 
                                           download=True,
                                           transform=transforms.ToTensor())

test_dataset = torchvision.datasets.MNIST(root='data', 
                                          train=False, 
                                          transform=transforms.ToTensor(),
                                          download=True)

# Data loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=100, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=100, 
                                          shuffle=False)
                                          
images, labels = zip(*[(train_dataset[i][0], train_dataset[i][1]) for i in range(10)])

# 设置绘图
fig, axes = plt.subplots(2, 5, figsize=(10, 5))

# 展示图像
for i, ax in enumerate(axes.flat):
    # 获取图像数据和标签
    img = images[i].numpy().squeeze()  # 移除多余的维度
    label = labels[i]
    
    # 显示图像
    ax.imshow(img, cmap='gray')
    ax.set_title(f'Label: {label}')
    ax.axis('off')  # 不显示坐标轴

plt.tight_layout()
plt.show()

运行结果为:
在这里插入图片描述

CNN

卷积神经网络(Convolutional Neural Networks,CNN)是一种深度学习模型,广泛应用于计算机视觉、语音识别等任务。CNN 通过利用局部连接和权重共享,显著降低了模型参数的数量,从而提高了训练效率并防止过拟合。CNN 的核心是卷积操作,并结合了池化层和全连接层等其他组件。

1. 卷积层(Convolutional Layer)

卷积层是 CNN 的核心,它负责从输入数据中提取特征。其基本操作是 卷积(convolution),通过卷积核(或滤波器)对输入数据进行滑动和局部特征提取。

数学公式:

设输入图像为一个二维矩阵 I I I,卷积核(滤波器)为 K K K,卷积操作输出为特征图 O O O。对于一个输入图像 I I I 和一个卷积核 K K K,卷积的计算公式为:

O ( i , j ) = ( I ∗ K ) ( i , j ) = ∑ m ∑ n I ( i + m , j + n ) K ( m , n ) O(i, j) = (I * K)(i, j) = \sum_m \sum_n I(i+m, j+n) K(m, n) O(i,j)=(IK)(i,j)=mnI(i+m,j+n)K(m,n)

引用自:
【卷积】直观形象的实例,10分钟彻底搞懂
【卷积神经网络】8分钟搞懂CNN,动画讲解喜闻乐见在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

其中:

  • I ( i , j ) I(i, j) I(i,j) 是输入图像 I I I 在位置 ( i , j ) (i, j) (i,j) 的像素值;
  • K ( m , n ) K(m, n) K(m,n) 是卷积核 K K K 在位置 ( m , n ) (m, n) (m,n) 的权重;
  • O ( i , j ) O(i, j) O(i,j) 是输出特征图在位置 ( i , j ) (i, j) (i,j) 的值。

这里的操作是卷积核在输入图像上滑动并计算加权和。通过卷积层,CNN 能够提取局部特征(例如边缘、纹理、颜色等),并保留空间层次信息。

卷积的步骤:
  1. 卷积核从图像的左上角开始,逐步向右滑动(水平),然后向下滑动(垂直)。
  2. 在每个位置,卷积核与输入图像的局部区域进行加权求和,输出一个新的像素值,生成新的特征图。
  3. 通过多个卷积核,CNN 可以从不同的角度提取不同类型的特征。

2. 激活函数(Activation Function)

卷积操作后的输出通常会经过非线性激活函数,常用的激活函数包括 ReLU(Rectified Linear Unit)。ReLU 的数学公式如下:

ReLU ( x ) = max ⁡ ( 0 , x ) \text{ReLU}(x) = \max(0, x) ReLU(x)=max(0,x)

ReLU 激活函数帮助网络引入非线性,使其能够学习复杂的特征。它的优点是计算简单且收敛速度较快。

在这里插入图片描述

3. 池化层(Pooling Layer)

池化层用于降低特征图的空间维度(宽度和高度),同时保持重要特征。池化层通常有两种操作:最大池化(Max Pooling)和 平均池化(Average Pooling)。在最大池化中,取池化窗口内的最大值;在平均池化中,取池化窗口内的平均值。

最大池化:

给定池化窗口大小为 2 × 2 2 \times 2 2×2,池化操作可以表示为:

O ( i , j ) = max ⁡ m , n ∈ P ( i , j ) I ( m , n ) O(i, j) = \max_{m, n \in P(i,j)} I(m, n) O(i,j)=m,nP(i,j)maxI(m,n)

其中, P ( i , j ) P(i,j) P(i,j) 是以 ( i , j ) (i, j) (i,j) 为中心的池化窗口。

池化操作的作用是减小特征图的尺寸,从而降低计算量并减少模型的参数量。

在这里插入图片描述

4. 全连接层(Fully Connected Layer)

在卷积和池化层后,CNN 通常包含一个或多个全连接层(FC),其作用是将高层次的特征组合成最终的分类结果。全连接层的每个神经元与前一层的所有神经元都有连接。

全连接层的计算公式为:

y = f ( W x + b ) y = f(Wx + b) y=f(Wx+b)

其中:

  • x x x 是上一层的输出(例如,经过卷积层和池化层后的特征图展平后形成的向量);
  • W W W 是权重矩阵;
  • b b b 是偏置项;
  • f f f 是激活函数(通常使用 ReLU 或 Sigmoid)。

在这里插入图片描述

全连接层的作用是进行分类或回归任务。对于分类任务,通常会在全连接层后使用 Softmax 激活函数,得到每个类别的概率分布。

5. 卷积神经网络的典型结构

一个典型的 CNN 网络结构包括以下几部分:

  1. 卷积层(Convolutional Layer):提取局部特征。
  2. 激活函数(ReLU):引入非线性。
  3. 池化层(Pooling Layer):降维,减少计算量。
  4. 全连接层(Fully Connected Layer):将高层特征映射到最终的输出(如分类标签)。
  5. Softmax 层:将输出转换为概率分布(用于分类任务)。

6. 卷积神经网络的训练

CNN 的训练过程类似于其他神经网络。主要包括以下几个步骤:

  1. 前向传播:输入图像通过卷积层、激活函数、池化层、全连接层,最终输出预测结果。
  2. 计算损失:通过比较预测结果与实际标签,计算损失函数(如交叉熵损失)。
  3. 反向传播:通过反向传播算法计算梯度,并利用梯度下降算法更新网络权重。

损失函数 L L L 通常是交叉熵损失(用于分类任务):

L = − ∑ i = 1 N y i log ⁡ ( y ^ i ) L = - \sum_{i=1}^{N} y_i \log(\hat{y}_i) L=i=1Nyilog(y^i)

其中:

  • y i y_i yi 是实际标签的 one-hot 编码;
  • y ^ i \hat{y}_i y^i 是网络的预测输出。

7. CNN 训练的优化:梯度下降法

在训练过程中,通常使用 梯度下降(Gradient Descent)及其变种(如 Adam、SGD 等)来优化网络的参数。通过计算损失函数对权重的梯度,更新网络中的参数。梯度下降的更新公式为:

W = W − η ∂ L ∂ W W = W - \eta \frac{\partial L}{\partial W} W=WηWL

其中:

  • W W W 是权重;
  • η \eta η 是学习率;
  • ∂ L ∂ W \frac{\partial L}{\partial W} WL 是损失函数对权重的梯度。

代码分析

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
# try running the following code, if you see errors on Windows OS

# import os
# os.environ['KMP_DUPLICATE_LIB_OK']='TRUE'
# Device configuration
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Hyper-parameters 
hidden_channel_size_1 = 16
hidden_channel_size_2 = 32
num_epochs = 5
batch_size = 100
learning_rate = 0.001
# MNIST dataset 
train_dataset = torchvision.datasets.MNIST(root='data', 
                                           train=True, 
                                           download=True,
                                           transform=transforms.ToTensor())

test_dataset = torchvision.datasets.MNIST(root='data', 
                                          train=False, 
                                          transform=transforms.ToTensor(),
                                          download=True)

# Data loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)
len(train_dataset),len(test_dataset)
# CNN
class CNeuralNet(nn.Module):
    def __init__(self,hidden_channel_size_1,hidden_channel_size_2,num_classes=10):
        super(CNeuralNet, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, hidden_channel_size_1, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(hidden_channel_size_1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(hidden_channel_size_1, hidden_channel_size_2, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(hidden_channel_size_2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.fc = nn.Linear(7*7*hidden_channel_size_2, num_classes) # originally 28*28, after two MaxPool2d(2), becomes 7*7
        
    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.reshape(out.size(0), -1)
        out = self.fc(out)
        return out
    
model = CNeuralNet(hidden_channel_size_1,hidden_channel_size_2).to(device)
# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)  
# Train the model
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        
        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # Backward and optimize
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if (i+1) % 100 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))

# Test the model
model.eval()  # eval mode (batchnorm uses moving mean/variance instead of mini-batch mean/variance)
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

    print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

运行结果:
在这里插入图片描述

def init(self,hidden_channel_size_1,hidden_channel_size_2,num_classes=10):

def __init__(self,hidden_channel_size_1,hidden_channel_size_2,num_classes=10):
        super(CNeuralNet, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, hidden_channel_size_1, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(hidden_channel_size_1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(hidden_channel_size_1, hidden_channel_size_2, kernel_size=5, stride=1, padding=2),
            nn.BatchNorm2d(hidden_channel_size_2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.fc = nn.Linear(7*7*hidden_channel_size_2, num_classes) # originally 28*28, after two MaxPool2d(2), becomes 7*7
1 第一层卷积
self.layer1 = nn.Sequential(
    nn.Conv2d(1, hidden_channel_size_1, kernel_size=5, stride=1, padding=2),
    nn.BatchNorm2d(hidden_channel_size_1),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=2, stride=2))
  • 卷积层nn.Conv2d(1, hidden_channel_size_1, kernel_size=5, stride=1, padding=2)
    输入通道数为 1(灰度图像),输出通道数为 hidden_channel_size_1(即 16),卷积核大小为 5x5,步幅为 1,填充为 2。这意味着卷积后的输出维度保持为 28x28。

    卷积操作的数学公式为:

    O i , j = ∑ m , n I i + m , j + n ⋅ K m , n O_{i,j} = \sum_{m,n} I_{i+m, j+n} \cdot K_{m,n} Oi,j=m,nIi+m,j+nKm,n

    其中:

    • I I I 是输入图像矩阵, K K K 是卷积核, O O O 是输出特征图。
  • 批量归一化nn.BatchNorm2d(hidden_channel_size_1)
    用于规范化输出,保持均值接近 0,方差接近 1,帮助加速训练并防止梯度消失。

  • ReLU 激活函数nn.ReLU()
    引入非线性,ReLU 的公式为:

    ReLU ( x ) = max ⁡ ( 0 , x ) \text{ReLU}(x) = \max(0, x) ReLU(x)=max(0,x)

  • 最大池化nn.MaxPool2d(kernel_size=2, stride=2)
    对特征图进行池化操作,使用 2x2 的池化窗口,步幅为 2,这将特征图尺寸减半。即,28x28 的特征图变为 14x14。

2 第二层卷积
self.layer2 = nn.Sequential(
    nn.Conv2d(hidden_channel_size_1, hidden_channel_size_2, kernel_size=5, stride=1, padding=2),
    nn.BatchNorm2d(hidden_channel_size_2),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=2, stride=2))
  • 输入特征图大小为 14x14,卷积核大小为 5x5,步幅为 1,填充为 2,因此输出特征图的大小仍然是 14x14。
  • 执行最大池化后,特征图尺寸将减半,变为 7x7。
3 全连接层
self.fc = nn.Linear(7*7*hidden_channel_size_2, num_classes) 
  • 在经过两次池化后,特征图的尺寸为 7x7,每个卷积层有 hidden_channel_size_2 个通道(即 32)。因此,全连接层的输入大小是 7 × 7 × 32 = 1568 7 \times 7 \times 32 = 1568 7×7×32=1568
  • 最终输出为 num_classes,即 10(代表数字 0-9 的分类)。

在这里插入图片描述

def forward(self, x):

前向传播
def forward(self, x):
    out = self.layer1(x)
    out = self.layer2(out)
    out = out.reshape(out.size(0), -1)  # Flatten the output from convolution layers
    out = self.fc(out)
    return out
  • out.reshape(out.size(0), -1):将卷积层的输出展平为一维向量,准备进入全连接层。
  • 最终输出是一个大小为 (batch_size, num_classes) 的张量,表示每个输入图像属于每个类别的得分。

criterion = nn.CrossEntropyLoss()

损失函数
criterion = nn.CrossEntropyLoss()
  • 交叉熵损失:用于分类任务,特别是多类别分类问题。公式为:

L = − ∑ i = 1 C y i log ⁡ ( y ^ i ) L = -\sum_{i=1}^{C} y_i \log(\hat{y}_i) L=i=1Cyilog(y^i)

其中:

  • C C C 是类别数(这里是 10)。
  • y i y_i yi 是实际类别的标签,通常是 one-hot 编码。
  • y ^ i \hat{y}_i y^i 是模型预测的类别概率,通常通过 softmax 激活函数得到。

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

优化器
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
  • Adam 优化器:一种自适应的优化算法,结合了 梯度下降自适应学习率

    更新公式如下:

θ t = θ t − 1 − η m t v t + ϵ \theta_t = \theta_{t-1} - \eta \frac{m_t}{\sqrt{v_t} + \epsilon} θt=θt1ηvt +ϵmt

其中:

  • θ \theta θ 是网络参数(权重)。
  • m t m_t mt v t v_t vt 分别是梯度的均值和方差估计。
  • η \eta η 是学习率, ϵ \epsilon ϵ 是为了避免除零的常数。

训练过程

for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)  # 前向传播
        loss = criterion(outputs, labels)  # 计算损失

        optimizer.zero_grad()  # 清除之前的梯度
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
  • 前向传播:输入图像通过卷积层和全连接层,生成输出。
  • 计算损失:使用交叉熵损失函数计算预测值与真实标签之间的误差。
  • 反向传播:计算梯度并更新网络的参数。

测试模型

model.eval()  # 设定为评估模式,关闭 dropout 和 batchnorm
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
  • 评估模式:在评估阶段,model.eval() 会让 BatchNorm 使用训练过程中累计的均值和方差。
  • 计算准确率:通过 torch.max() 获取模型预测的类别索引,然后与实际标签进行比较,计算正确预测的数量,最终计算模型的准确率。

总结

这段代码实现了一个典型的卷积神经网络,包含两个卷积层和一个全连接层,通过训练数据不断优化网络参数,最终在测试数据上进行评估。主要数学公式包括:

  1. 卷积操作:通过卷积核提取局部特征。
  2. ReLU 激活函数:引入非线性变换。
  3. 交叉熵损失:用于多类别分类问题。
  4. 梯度下降优化:通过 Adam 优化器更新模型参数。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Flink】Flink Checkpoint 流程解析

Flink Checkpoint 流程解析 Checkpoint 流程解析 Flink Checkpoint 流程解析Checkpint 流程概括Checkpoint 触发流程解析 (Flink 1.20)任务启动后 JobManager 开始定期对任务执行 CheckpointJobManager 使用 CheckpointCoordinator 触发 CheckpointCheckpointCoordinator 初始化…

MIT工具课第六课任务 Git基础练习题

如果您之前从来没有用过 Git,推荐您阅读 Pro Git 的前几章,或者完成像 Learn Git Branching 这样的教程。重点关注 Git 命令和数据模型相关内容; 相关内容整理链接:Linux Git新手入门 git常用命令 Git全面指南:基础概念…

Sui 主网升级至 V1.38.3

Sui 主网现已升级至 V1.38.3 版本,同时协议升级至 69 版本。请开发者及时关注并调整! 其他升级要点如下所示: 协议 #20199 在共识快速路径投票中设置允许的轮次数量。 节点(验证节点与全节点) #20238 为验证节点…

【AI系统】低比特量化原理

低比特量化原理 计算机里面数值有很多种表示方式,如浮点表示的 FP32、FP16,整数表示的 INT32、INT16、INT8,量化一般是将 FP32、FP16 降低为 INT8 甚至 INT4 等低比特表示。 模型量化则是一种将浮点值映射到低比特离散值的技术,可…

项目文章 | RNA-seq+WES-seq+机器学习,揭示DNAH5是结直肠癌的预后标志物

肿瘤突变负荷(TMB)已成为预测结直肠癌(CRC)患者预后和对免疫治疗反应的关键生物标志物。然而,全外显子测序(WES-seq)作为TMB评估的金标准,成本高且耗时。此外,高TMB患者之…

【NLP修炼系列之Bert】Bert多分类多标签文本分类实战(附源码下载)

引言 今天我们就要用Bert做项目实战,实现文本多分类任务和我在实际公司业务中的多标签文本分类任务。通过本篇文章,可以让想实际入手Bert的NLP学习者迅速上手Bert实战项目。 1 项目介绍 本文是Bert文本多分类和多标签文本分类实战,其中多分…

【CSS in Depth 2 精译_069】11.3 利用 OKLCH 颜色值来处理 CSS 中的颜色问题(上)

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 11 章 颜色与对比】 ✔️ 11.1 通过对比进行交流 11.1.1 模式的建立11.1.2 还原设计稿 11.2 颜色的定义 11.2.1 色域与色彩空间11.2.2 CSS 颜色表示法 11.2.2.1 RGB…

基础算法——搜索与图论

搜索与图论 图的存储方式2、最短路问题2.1、Dijkstra算法(朴素版)2.2、Dijkstra算法(堆优化版)2.3、Bellman-Ford算法2.4、SPFA求最短路2.5、SPFA判负环2.6、Floyd算法 图的存储方式 2、最短路问题 最短路问题可以分为单源最短路…

IDEA创建Spring Boot项目配置阿里云Spring Initializr Server URL【详细教程-轻松学会】

1.首先打开idea选择新建项目 2.选择Spring Boot框架(就是选择Spring Initializr这个) 3.点击中间界面Server URL后面的三个点更换为阿里云的Server URL Idea中默认的Server URL地址:https://start.spring.io/ 修改为阿里云Server URL地址:https://star…

Git_如何更改默认路径

网上搜了一堆都不好使,其实可以直接使用git bash输入命令来解决 打开 Git Bash:首先打开 Git Bash 终端,这是一个类似于命令提示符的窗口,可在其中执行 Git 命令。设置 Git 默认存储路径:使用 git config 命令来修改 …

计算机毕业设计Python房价预测 房屋推荐 房价可视化 链家爬虫 房源爬虫 房源可视化 卷积神经网络 大数据毕业设计 机器学习 人工智能 AI

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

AndroidAutoSize实战教程:今日头条屏幕适配方案详解

如何在项目中结合 AndroidAutoSize 来进行今日头条屏幕适配,我会具体讲解如何用 AndroidAutoSize 实现屏幕适配,并结合 Kotlin 代码举例分析。 通过 AndroidAutoSize 库来实现屏幕适配,确保在不同的屏幕尺寸、分辨率、密度下,应用…

【HarmonyOS】层级轮播卡片效果

【HarmonyOS】层级轮播卡片效果 一、功能效果: 1.上下堆叠由大到小的卡片层叠效果。 2.上层卡片可手势左右滑动,自动左滑动。 3.三层卡片随滑动,内容进行依次切换。 二、开发思路 【完整代码见章节三】 1.最上层使用swiper进行轮播效果…

Postman自定义脚本Pre-request-script以及Test

这两个都是我们进行自定义script脚本的地方,分别是在请求执行的前后运行。 我们举两个可能经常运用到的场景。 (一)请求A先执行,请求B使用请求A响应结果作为参数。如果我们不用自定义脚本,可能得先执行请求A,然后手动复制响应结果…

一些引入依赖,提示引入方式报错的问题

背景 当我们使用gulp自动化处理文件的时候,难免会遇到需要按照一定条件过滤的需求,这里博主所遇到问题是,通过文件内容中是否包含 某一串字符串 决定过滤当前的文件 比如: 碰到文件中包含注释 * replace-note 此文件未被引用 ,那…

R语言 | 峰峦图 / 山脊图

目的:为展示不同数据分布的差异。 1. ggplot2 实现 # 准备数据 datmtcars[, c("mpg", "cyl")] colnames(dat)c("value", "type") head(dat) # value type #Mazda RX4 21.0 6 #Mazda RX4 Wag …

6月份stable diffusion animatediff等插件使用指南,又来更新了

插件一直会更新,包含了基本市面上流行的90%插件,好用的插件更是不会错过,往期插件请看往期文章,如果你没有时间一直关注sd更新的进展,请关注我,一个月用几个小时看一下我的文章,最短时间跟进sd。…

jmeter配置

单接口运行没问题,但是批量执行100个线程数发现总是提示请求不合法 最后发现 需要将配置改成 正好回归一下这个配置: Ramp-Up时间(秒)的定义: Ramp-Up时间是指在JMeter测试中,所有指定的线程&#xff08…

WPF中的VisualState(视觉状态)

以前在设置控件样式或自定义控件时&#xff0c;都是使用触发器来进行样式更改。触发器可以在属性值发生更改时启动操作。 像这样&#xff1a; <Style TargetType"ListBoxItem"><Setter Property"Opacity" Value"0.5" /><Setter …

如何利用Java爬虫获得商品类目

在当今数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。获取和分析数据的能力对于任何希望在市场上保持竞争力的企业来说都是至关重要的。对于电子商务平台和市场研究公司而言&#xff0c;获取商品类目数据尤为重要&#xff0c;因为这些数据可以帮助他们更好地理解市场…