CNN模型手写数字识别及其相关概念

        

CNN相关概念
卷积神经网络(Convolutional Neural Network,CNN)是一种专门为处理具有网格结构数据的深度学习模型,例如图像、声音和文本。
卷积核

特征提取:识别和提取输入数据中的局部特征。通过在不同位置应用卷积核,网络能够捕捉到图像中的边缘、纹理、形状等特征。

降维:卷积核在应用过程中,会减少特征图(feature map)的尺寸。

参数共享:在卷积层中,同一卷积核会在整个输入数据上滑动,这意味着卷积核中的权重参数是共享的。

局部响应归一化(LRN):有助于提高特征图中的对比度,使得模型能够更好地识别图像中的关键特征。

平移不变性:卷积核的滑动窗口特性使得网络对输入数据的平移具有不变性,即网络不会因为输入数据的位置变化而改变其识别特征的能力。

卷积层使用卷积核对输入数据进行滑动窗口处理,提取局部特征。
池化层池化层位于卷积层之后,用于减小特征图的尺寸,减少参数数量,并减少过拟合的风险。
全连接层其中每个神经元都与前一层中的所有神经元相连。全连接层通常位于网络的输出层,用于将前一层的特征映射到具体的输出类别或预测。在全连接层之后,通常会使用一个或多个激活函数来产生概率分布或类别预测。

CNN一般实现步骤:
  1. 数据加载与预处理。
  2. 模型搭建。
  3. 定义损失函数、优化器。
  4. 模型训练。
  5. 模型测试。

 基于Pytorch框架实现CNN神经网络手写数字识别。
流程步骤:
  1. 导入相关库。
  2. 使用MNIST数据集,进行数据预处理。
  3. CNN模型搭建。
  4. 参数设置。
  5. 模型训练。
 步骤1代码:
import numpy as np
import torch 
from torch import nn
from torchvision import datasets, transforms,utils
from PIL import Image
import matplotlib.pyplot as plt
 步骤2代码:
# 定义超参数
batch_size = 128  # 设置每个批次(batch)的样本数为128

# 对输入的数据进行标准化处理
# transforms.ToTensor() 将图像数据转换为 PyTorch 中的张量(tensor)格式,并将像素值缩放到 0-1 的范围内。
# 这是因为神经网络需要的输入数据必须是张量格式,并且需要进行归一化处理,以提高模型的训练效果。
transform = transforms.Compose([transforms.ToTensor(),
                               transforms.Normalize(mean=[0.5],std=[0.5])])

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

# 创建数据加载器(用于将数据分次放进模型进行训练)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True,  # 装载过程中随机乱序
                                           num_workers=2)  # 表示2个子进程加载数据
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False,
                                          num_workers=2)
  • batch_size = 128: 设置每次迭代中从数据集中取样的样本数量。

  • transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean=[0.5], std=[0.5])]): 定义一个转换器,它包含两个子转换器:transforms.ToTensor()用于将图像数据转换为PyTorch的张量格式,并归一化像素值到0-1范围内;transforms.Normalize(mean=[0.5], std=[0.5])用于进一步标准化像素值,使其均值为0.5,标准差为0.5。

  • train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True): 创建一个MNIST数据集实例,用于训练。root='./data'指定数据集下载和存储的路径;train=True指定加载训练数据;transform=transform指定之前定义的转换器;download=True表示如果数据集不在指定路径下,则自动下载。

  • test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=transform, download=True): 创建一个MNIST数据集实例,用于测试。train=False指定加载测试数据。

  • train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True, num_workers=2): 创建一个数据加载器,用于训练模型。dataset=train_dataset指定要加载的数据集;batch_size=batch_size指定每个批次的大小;shuffle=True指定是否在装载过程中随机乱序;num_workers=2指定使用2个子进程来并行加载数据。

  • test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False, num_workers=2): 创建一个数据加载器,用于测试模型。shuffle=False指定在装载过程中不进行随机乱序。其他参数与训练数据加载器相同。

 步骤3代码:
class CNN(nn.Module):
    # 定义网络结构
    def __init__(self):
        super(CNN, self).__init__()  # 调用父类的初始化方法
        # 定义第一个卷积层
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=16,  # 输入通道数为1,输出通道数为16
                               kernel_size=5, stride=1, padding=2)  # 卷积核大小为5x5,步长为1,填充为2
        # 定义第一个ReLU激活函数
        self.relu1 = nn.ReLU()
        # 定义第一个池化层
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)  # 池化核大小为2x2,步长为2
        # 定义第二个卷积层
        self.conv2 = nn.Conv2d(in_channels=16, out_channels=32,  # 输入通道数为16,输出通道数为32
                               kernel_size=5, stride=1, padding=2)  # 卷积核大小为5x5,步长为1,填充为2
        # 定义第二个ReLU激活函数
        self.relu2 = nn.ReLU()
        # 定义第二个池化层
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)  # 池化核大小为2x2,步长为2
        # 定义第一个全连接层
        self.fc1 = nn.Linear(in_features=7*7*32, out_features=256)  # 输入特征数为7x7x32,输出特征数为256
        # 定义第一个全连接层的ReLU激活函数
        self.relu3 = nn.ReLU()
        # 定义第二个全连接层
        self.fc2 = nn.Linear(in_features=256, out_features=10)  # 输入特征数为256,输出特征数为10

    # 定义前向传播过程的计算函数
    def forward(self, x):
        # 第一层卷积、激活函数和池化
        x = self.conv1(x)
        x = self.relu1(x)
        x = self.pool1(x)
        # 第二层卷积、激活函数和池化
        x = self.conv2(x)
        x = self.relu2(x)
        x = self.pool2(x)
        # 将数据平展成一维
        x = x.view(-1, 7*7*32)
        # 第一层全连接层
        x = self.fc1(x)
        x = self.relu3(x)
        # 第二层全连接层
        x = self.fc2(x)
        return x

 步骤4代码:
import torch.optim as optim

learning_rate = 0.001 # 学习率

# 定义损失函数,计算模型的输出与目标标签之间的交叉熵损失
criterion = nn.CrossEntropyLoss()
# 训练过程通常采用反向传播来更新模型参数,这里使用的是SDG(随机梯度下降)优化器
# momentum 表示动量因子,可以加速优化过程并提高模型的泛化性能。
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
#也可以选择Adam优化方法
# optimizer = torch.optim.Adam(net.parameters(),lr=1e-2)
步骤5代码:
# 实例化CNN模型
model = CNN()
num_epochs = 10  # 定义迭代次数为10

# 如果可用的话使用 GPU 进行训练,否则使用 CPU 进行训练。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 将神经网络模型 model 移动到指定的设备上。
model = model.to(device)
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # 将输入数据 images 和标签数据 labels 移动到指定的设备上。
        images = images.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()  # 清空上一个batch的梯度信息
        # 将输入数据 images 喂入神经网络模型 model 中进行前向计算,得到模型的输出结果 outputs。
        outputs = model(images)
        # 使用交叉熵损失函数 criterion 计算模型输出 outputs 与标签数据 labels 之间的损失值 loss。
        loss = criterion(outputs, labels)
        # 使用反向传播算法计算模型参数的梯度信息,并使用优化器 optimizer 对模型参数进行更新。
        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()))

print('Finished Training')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值