CNN(卷积神经网络)从0-1数字识别

CNN原理:

卷积神经网络(Convolutional Neural Network,CNN)是一种深度学习模型,主要用于处理和分析具有网格结构数据的任务,尤其是图像数据。CNN在图像处理领域取得了巨大成功,广泛应用于图像分类、目标检测、图像分割等任务。

CNN的主要特点:

  • 卷积层(Convolutional Layer):
    卷积层是CNN的核心组成部分,它通过在输入数据上滑动的一系列滤波器(也称为卷积核)来提取特征。每个滤波器都可以检测输入数据中的某种特定模式或特征,如边缘、纹理等。
  • 池化层(Pooling Layer):
    池化层用于降低特征图的空间维度,减少计算量并提高模型的鲁棒性。常用的池化操作包括最大池化(Max Pooling)和平均池化(Average Pooling)。
    非线性激活函数:CNN中通常在卷积层之后使用非线性激活函数,如ReLU(Rectified Linear Unit),以引入非线性特性并增强模型的表达能力。
  • 全连接层(Fully Connected Layer):
    在CNN的末端通常包含一个或多个全连接层,用于将卷积层提取的特征映射转换为最终的预测结果。全连接层可以捕捉不同特征之间的复杂关系,并输出最终的分类或回归结果。

CNN的优势:

  • 参数共享:在卷积层中,每个滤波器的参数都是共享的,这样可以大大减少模型的参数数量,降低过拟合的风险。
  • 局部感受野:卷积操作只考虑输入数据的局部区域,从而使模型对平移、旋转和缩放等变换具有一定的不变性。
  • 层级结构:CNN通常采用多层次的结构,逐渐提取更加抽象和高级的特征,使模型能够有效地理解和处理复杂的数据。

实现过程:

导入第三方库
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
import torchvision

定义超参数

# 定义超参数
batch_size = 128 # 每个批次(batch)的样本数

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

显示训练样本图片

for i in range(0,5):
    oneimg,label = train_dataset[i]
    grid = utils.make_grid(oneimg)
    grid = grid.numpy().transpose(1,2,0) 
    std = [0.5]
    mean = [0.5]
    grid = grid * std + mean
    # 可视化图像
    plt.subplot(1, 5, i+1)
    plt.imshow(grid)
    plt.axis('off')

plt.show()

在这里插入图片描述

定义CNN结构

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms, utils
class CNN(nn.Module):
    # 定义网络结构
    def __init__(self):
        super(CNN, self).__init__()
        # 图片是灰度图片,只有一个通道
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, 
                               kernel_size=5, stride=1, padding=2)
        self.relu1 = nn.ReLU()
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, 
                               kernel_size=5, stride=1, padding=2)
        self.relu2 = nn.ReLU()
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.fc1 = nn.Linear(in_features=7*7*32, out_features=128)
        self.relu3 = nn.ReLU()
        self.fc2 = nn.Linear(in_features=128, out_features=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  
    
# 实例化CNN模型
model = CNN()
learning_rate = 0.001 # 学习率
num_epochs = 10 # 定义迭代次数
# 定义损失函数,计算模型的输出与目标标签之间的交叉熵损失
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)
optimizer = optim.Adam(model.parameters(), lr=1e-3)



# 如果可用的话使用 GPU 进行训练,否则使用 CPU 进行训练。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 将神经网络模型 net 移动到指定的设备上。
model = model.to(device)
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)
        optimizer.zero_grad() # 清空上一个batch的梯度信息
        # 将输入数据 inputs 喂入神经网络模型 net 中进行前向计算,得到模型的输出结果 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')


在这里插入图片描述

保存训练的模型

# 模型保存
PATH = './mnist_net.pth'
torch.save(model.state_dict(), PATH)

测试训练模型的结果

# 测试CNN模型
with torch.no_grad(): # 进行评测的时候网络不更新梯度
    correct = 0
    total = 0
    for images, labels in test_loader:
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
    print('Accuracy of the network on the 10000 test images: {} %'.format(100 * correct / total))

在这里插入图片描述

训练结果

# 将 test_loader 转换为一个可迭代对象 dataiter
dataiter = iter(test_loader)
# 使用 next(dataiter) 获取 test_loader 中的下一个 batch 的图像数据和标签数据
images, labels = next(dataiter)

# print images
test_img = utils.make_grid(images)
test_img = test_img.numpy().transpose(1,2,0)
std = [0.5]
mean =  [0.5]
test_img = test_img*std+0.5
plt.imshow(test_img)
plt.show()
plt.savefig('./mnist_net.png')
print('GroundTruth: ', ' '.join('%d' % labels[j] for j in range(128)))

在这里插入图片描述

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值