当前位置: 首页 > news >正文

《卷积神经网络(CNN):深度学习中的图像识别利器》

在当今数字化时代,图像数据无处不在,而卷积神经网络(Convolutional Neural Network,简称 CNN)作为一种强大的深度学习模型,已经成为图像识别领域的核心工具。CNN 以其卓越的性能和广泛的应用,改变了我们处理和理解图像的方式。它能够自动提取图像中的特征,通过卷积层、池化层和激活函数等组件,捕捉图像的局部特征和空间层次结构。CNN 不仅在手写数字识别、图像分类等任务中表现出色,还在目标检测、语义分割等领域展现了强大的能力。
在这里插入图片描述
CNN 的基本原理
CNN 的核心思想是利用卷积运算来提取图像的特征。与传统的全连接神经网络不同,CNN 通过卷积层、池化层和激活函数等组件,能够自动学习图像中的局部特征和空间层次结构,从而更有效地处理图像数据。
在这里插入图片描述
卷积层
卷积层是 CNN 的关键部分,它通过卷积核(也称为滤波器)在输入图像上滑动并进行卷积运算,从而提取图像的局部特征。卷积核是一个小的二维矩阵,它与输入图像的局部区域进行逐元素相乘并求和,生成一个新的特征图(Feature Map)。通过使用多个不同的卷积核,可以提取图像中的多种特征,如边缘、纹理、形状等。例如,在一个简单的图像边缘检测任务中,一个卷积核可以被设计为突出图像中的水平边缘,而另一个卷积核可以检测垂直边缘。随着网络层数的增加,卷积层可以逐步提取更复杂的特征,从低层次的简单特征(如边缘和纹理)到高层次的语义特征(如物体的轮廓和形状)。

在这里插入图片描述

一、环境准备与数据加载

在开始之前,我们需要安装 PyTorch 和 torchvision。PyTorch 是一个强大的深度学习框架,而 torchvision 提供了许多与图像相关的数据集和工具。

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

接下来,我们加载手写数字数据集 MNIST。MNIST 数据集包含 60,000 张训练图像和 10,000 张测试图像,每张图像都是 28×28 的灰度图像,对应一个数字标签(0-9)。

'''下载训练数据集(包含训练图片+标签)'''
training_data = datasets.MNIST(root="data",train=True,download=True,transform=ToTensor()#Tensor是在深度学习中提出并广泛运用的数据类型,它与深度学习框架(如PyTorch,TensorFlow)
) #Numpy 数组只能在cpu上运行。Tensor可以在GPU上运行,这在深度学习中可以显著提高计算速度。
print(len(training_data))'''下载测试数据集(包含训练图片+标签)'''
test_data = datasets.MNIST(root="data",train=False,download=True,transform=ToTensor()
)
print(len(test_data))

这里,我们使用 ToTensor 将图像数据转换为 PyTorch 张量(Tensor)。张量是 PyTorch 中的基本数据类型,类似于 NumPy 的数组,但它可以在 GPU 上运行,从而加速计算。

二、数据可视化

为了更好地理解数据,我们可视化一些训练图像。

'''展示手写字图片,把训练数据集中的前59000张图片展示一下'''
from matplotlib import pyplot as plt
figure = plt.figure()
for i in range(9):img, label = training_data[i+59000] #提取第59000张图片figure.add_subplot(3,3,i+1) #图片窗口中创建多个小窗口 ,小窗口用于显示图片 3*3plt.title(label)plt.axis("off") # plt.show(I) #显示矢量,plt.imshow(img.squeeze(),cmap="gray")# 将numpy数组data的数据转化为图像a = img.squeeze()#从张量img中去掉维度最高的也就是1,如果改维度的大小不为1 则张量不会改变
plt.show()train_dataloader = DataLoader(training_data,batch_size=64)#64张图片为一个包
test_dataloader = DataLoader(test_data,batch_size=64)

这段代码从训练数据集中提取了 9 张图像,并将它们显示在一个 3×3 的网格中。img.squeeze() 是将图像张量从形状 (1, 28, 28) 转换为 (28, 28),以便正确显示。

三、构建卷积神经网络模型

接下来,我们构建一个卷积神经网络(CNN)模型。CNN 是处理图像数据的常用模型,因为它能够自动提取图像的特征。

class CNN(nn.Module):def __init__(self):  # 输入大小(1,28,28)super(CNN, self).__init__()  # 初始化父类self.conv1 = nn.Sequential(  # 将多个层组合到一起,创建了一个容器nn.Conv2d(  #2d一般用于图像,3d用于视频数据(多一个时间维度),1d一般用于结构化的序列数据in_channels=1,  #、图像通道个数,1表示灰度图(确定了卷积核 组中的个数)out_channels=8, # 要得到几多少个特征图,卷积核的个数kernel_size=3,  # 卷积核大小,3*3stride=1,       # 步长padding=1,),nn.ReLU(),  # (8,28,28)nn.MaxPool2d(kernel_size=2)  # (8,14,14))self.conv2 = nn.Sequential(nn.Conv2d(8, 16, 3, 1, 1),  # (16,14,14)nn.ReLU(),  # (16,14,14)nn.MaxPool2d(2)  # (16,7,7))self.conv3 = nn.Sequential(nn.Conv2d(16, 32, 3, 1, 1),  # (32,7,7)nn.ReLU(),)self.out = nn.Linear(32 * 7 * 7, 10)def forward(self, x):  # 前向传播 数据的流向 就是神经网络层连接起来,函数名称不能改。x = self.conv1(x)  # 将图像进行展开x = self.conv2(x)x = self.conv3(x)  # (32,7,7)x = x.view(x.size(0), -1)x = self.out(x)return xmodel = CNN().to(device)#把刚刚创建的模型传入到GPU
print(model)

这个模型包含三个卷积层(conv1conv2conv3)和一个全连接层(out)。每个卷积层后面都接了一个 ReLU 激活函数和一个最大池化层(MaxPool2d),用于提取特征和降低维度。最后,我们将卷积层的输出展平为一维张量,输入到全连接层进行分类。

四、模型训练与测试

在训练模型之前,我们需要定义损失函数和优化器。

loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写数字识别中一共有10个数字,输出会有10个结果optimizer = torch.optim.Adam(model.parameters(),lr=0.01)#创建一个优化器,SGD为随机梯度下降算法
##params:要训练的参数,一般我们传入的都是model.parameters()。
##lr: learning_rate 学习率,也就是步长。

这里,我们使用交叉熵损失函数(CrossEntropyLoss)和 Adam 优化器。交叉熵损失函数适用于多分类问题,而 Adam 优化器是一种常用的优化算法,它结合了多种优化方法的优点。

接下来,我们定义训练和测试函数。

def train(dataloader,model,loss_fn,optimizer):model.train()# 告诉模型,我要开始训练,模型中w进行随机化操作,已经更新w,在训练过程中,w会被修改的
#pytorch提供2种方式来切换训练和测试的模式,分别是:model.train() 和 model.eval().
# 一般用法是:在训练开始之前写model.train() 在测试时写上model.eval()。batch_size_num = 1for X,y in dataloader:                  #其中batch为每一个数据的编号X,y = X.to(device),y.to(device)     #把训练数据集和标签传入cpu或GPUpred = model.forward(X)             #.forward可以被省略,父类中已经对次功能进行了设置。自动初始化wloss = loss_fn(pred,y)              #通过交叉熵损失函数计算损失值loss#Backpropagation 进来一个batch的数据,计算一次梯度,更新一次网络optimizer.zero_grad()               #梯度值清零loss.backward()                     #反向传播计算得到每个参数的梯度值woptimizer.step()                    #根据梯度更新网络w参数loss_value = loss.item()            #从tensor数据中提取数据出来,tensor获取损失值if batch_size_num % 100 == 0:print(f"loss:{loss_value:>7f} [number:{batch_size_num}]")batch_size_num += 1def test(dataloader,model,loss_fn):size = len(dataloader.dataset)#10000num_batches = len(dataloader)#打包的数量model.eval() #测试,w就不能再更新。test_loss,correct = 0,0with torch.no_grad(): #一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。for X,y in dataloader:X, y = X.to(device),y.to(device)pred = model.forward(X)test_loss += loss_fn(pred,y).item()#test_loss是会自动累加每一个批次的损失值correct += (pred.argmax(1) == y).type(torch.float).sum().item()a = (pred.argmax(1) == y)   #dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值b = (pred.argmax(1) == y).type(torch.float)test_loss /= num_batches #能来衡量模型测试的好坏correct /= size #平均的正确率print(f"Test result: \n Accuracy:{(100*correct)}%,Avg loss:{test_loss}")

在训练函数中,我们对每个批次的数据进行前向传播、计算损失、反向传播和参数更新。在测试函数中,我们计算模型在测试数据集上的准确率和平均损失。

最后,我们运行训练和测试代码。

for j in range(10):train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader,model,loss_fn)

这里,我们将模型移动到 GPU(如果可用),并训练 10 个 epoch。每个 epoch 都会遍历一次训练数据集。

运行结果

在这里插入图片描述

五、总结

通过这个简单的例子,我们实现了基于 PyTorch 的手写数字识别模型。我们学习了如何加载数据、构建模型、训练和测试模型。虽然这个模型比较简单,但它为我们深入学习深度学习和 PyTorch 提供了一个很好的起点。

相关文章:

  • 解决fastJson JSON.parseArray方法 非法字符问题
  • e实例性能测评:Intel Xeon Platinum处理器,经济型入门级服务器
  • 基于爱—特的未来的时空奇点压缩爆炸
  • 【限流算法】计数器、漏桶、令牌桶算法
  • 高精度--
  • ArcPy工具箱制作(上)
  • Vue王炸打包工具新作品 Tsdown上线
  • Java Collection(8)——Map的遍历方式
  • LLM做逻辑推理题 - 拥有古物的是谁?
  • C语言数据结构---二叉树---堆的应用
  • FreeRTOS事件标志组
  • LeetCode算法题(Go语言实现)_52
  • OpenCV 图形API(42)颜色空间转换-----将 BGR图像转换为 I420(YUV 4:2:0)格式函数BGR2I420()
  • 考研数据结构之图的应用:最小生成树、最短路径、拓扑排序与关键路径
  • 邮件自动回复助手(Rasa/SMTP)实现教程
  • 【HDFS入门】HDFS核心配置与优化指南概述
  • 【Pytorch之一】--torch.stack()方法详解
  • C#学习第15天:泛型
  • list.
  • 【工具变量】各地级市人口集聚及多中心程度数据集(2000-2023年)
  • 牛市早报|国家发改委:将推出做好稳就业稳经济推动高质量发展若干举措
  • 专访丨青年作家杜梨:以动物的视角去观察这个世界
  • 吕国范任河南省人民政府副省长
  • 安阳一村支书微信群骂村民被警方行拘,辩称对方先“污蔑造谣”
  • “中国游”带火“中国购”,“即买即退”让外国游客购物更丝滑
  • 持续更新丨伊朗内政部长:港口爆炸已致14人死亡