欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 深入理解卷积神经网络(CNN):从原理到实践

深入理解卷积神经网络(CNN):从原理到实践

2025/4/19 11:44:44 来源:https://blog.csdn.net/weixin_68114439/article/details/147285807  浏览:    关键词:深入理解卷积神经网络(CNN):从原理到实践

引言

       卷积神经网络(Convolutional Neural Networks, CNN)是深度学习领域最具影响力的架构之一,尤其在计算机视觉任务中表现出色。自2012年AlexNet在ImageNet竞赛中一战成名以来,CNN不断演进,推动着图像识别、医疗影像分析、自动驾驶等领域的快速发展。本文将系统介绍CNN的核心原理、关键组件和实际应用,并通过PyTorch代码示例展示如何构建一个CNN模型。

 一、CNN的基本原理

1.1 传统神经网络的问题

在处理图像数据时,传统全连接神经网络(FCN)存在明显缺陷:
- 参数爆炸:一张28×28的灰度图像展开后就有784个输入节点,若第一隐藏层有1000个神经元,                       仅这一层就需要784,000个参数!
- 忽略局部相关性:图像中相邻像素间存在强相关性,但全连接网络无法有效利用这种空间信息
- 缺乏平移不变性:物体在图像中的位置变化会导致网络需要重新学习

1.2 CNN的三大核心思想

CNN通过以下设计巧妙解决了上述问题:

1. 局部感受野(Local Receptive Fields)  
   每个神经元只连接输入区域的局部区域,而非全部输入

2. 权值共享(Shared Weights)  
   同一特征图使用相同的卷积核,大幅减少参数数量

3. 空间下采样(Spatial Subsampling) 
   通过池化层逐步降低空间分辨率,增加高层特征的感受野

> 参数数量对比:  
> 对于28×28图像,全连接层(隐藏层1000神经元)需要784,000参数  
> 而5×5卷积核(32个通道)仅需5×5×32=800参数

 二、CNN的核心组件详解

2.1 卷积层(Convolutional Layer)

import torch.nn as nn# 定义一个卷积层
conv_layer = nn.Conv2d(in_channels=3,    # 输入通道数(RGB图像为3)out_channels=16,  # 输出通道数/卷积核数量kernel_size=3,    # 卷积核尺寸stride=1,         # 步长padding=1         # 边缘填充
)

2.2 池化层(Pooling Layer)

# 最大池化示例
max_pool = nn.MaxPool2d(kernel_size=2, stride=2)# 平均池化示例
avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)

  作用:
- 降低空间维度,减少计算量
- 增强平移不变性
- 扩大感受野

2.3 激活函数


# ReLU激活函数
activation = nn.ReLU()# LeakyReLU示例
leaky_relu = nn.LeakyReLU(negative_slope=0.01)

三、经典CNN架构演进

class CNN(nn.Module):def __init__(self):   #python基础关于类,self类自已本身super(CNN,self).__init__()   #继承的父类初始化self.conv1=nn.Sequential(nn.Conv2d(in_channels=1,out_channels=16,kernel_size=5,stride=1,padding=2,),nn.ReLU(),nn.MaxPool2d(kernel_size=2),)self.conv2=nn.Sequential(nn.Conv2d(16,32,5,1,2),nn.ReLU(),nn.Conv2d(32, 32, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(2),)self.conv3=nn.Sequential(nn.Conv2d(32,64,5,1,2),nn.ReLU(),)self.out=nn.Linear(64*7*7,10)def forward(self,x):x=self.conv1(x)x=self.conv2(x)x=self.conv3(x)x=x.view(x.size(0),-1)output=self.out(x)return output

四、PyTorch实现CNN实战

4.1手写数字识别:

import torchprint(torch.__version__)'''
MNIST包含70,000张手写数字图像:60,000张用于训练,10,000张用于测试。
图像是灰度的,28x28像素的,并且居中的,以减少预处理和加快运行。
'''
import torch
from torch import nn   #导入神经网络模块,
from torch.utils.data import DataLoader   #数据包管理工具,打包数据,
from torchvision import datasets    #封装了很多与图像相关的模型,数据集
from torchvision.transforms import ToTensor    #数据转换,张量,将其他类型的数据转换为tensor张量'''下载训练数据集(包含训练图片+标签)'''
training_data=datasets.MNIST(root='data',           #表示下载的手写数字 到哪个路径。60000train=True,            #读取下载后的数据 中的 训练集download=True,         #如果你之前已经下载过了,就不用再下载transform=ToTensor(),  #张量,图片是不能直接传入神经网络模型
)    #对于pytorch库能够识别的数据一般是tensor张量。'''下载测试数据集(包含训练图片+标签)'''
test_data=datasets.MNIST(root='data',           #表示下载的手写数字 到哪个路径。60000train=False,           #读取下载后的数据 中的 训练集download=True,         #如果你之前已经下载过了,就不用再下载transform=ToTensor(),  #Tensor是在深度学习中提出并广泛应用的数据类型
)    #NumPy数组只能在CPU上运行。Tensor可以在GPU上运行,这在深度学习应用中可以显著提高计算速度
print(len(training_data))'''展示手写字图片,把训练数据集中的前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)#图像窗口中创建多个小窗口,小窗口用于显示图片plt.title(label)plt.axis("off") #  plt.show(I)#是示矢量,plt.imshow(img.squeeze(),cmap="gray") #plt.imshow()将Numpy数组data中的数据显示为图像,并在图形窗口中显贡a = img.squeeze()# img.squeeze()从张量img中去掉维度为1的。如果该维度的大小不为1则张量不会改变。#cmap="gray
plt.show()# 创建数据DataLoader(数据加载器)
# batch_size:将数据集分成多份,每一份为batch_size个数据
# 优点:可以减少内存的使用,提高训练速度。train_dataloader=DataLoader(training_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)'''断当前设备是否支持GPU,其中mps是苹果m系列芯片的GPU。'''
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")  #字符串的格式化'''定义神经网络 类的继承'''
class CNN(nn.Module):def __init__(self):   #python基础关于类,self类自已本身super(CNN,self).__init__()   #继承的父类初始化self.conv1=nn.Sequential(nn.Conv2d(in_channels=1,out_channels=16,kernel_size=5,stride=1,padding=2,),nn.ReLU(),nn.MaxPool2d(kernel_size=2),)self.conv2=nn.Sequential(nn.Conv2d(16,32,5,1,2),nn.ReLU(),nn.Conv2d(32, 32, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(2),)self.conv3=nn.Sequential(nn.Conv2d(32,64,5,1,2),nn.ReLU(),)self.out=nn.Linear(64*7*7,10)def forward(self,x):x=self.conv1(x)x=self.conv2(x)x=self.conv3(x)x=x.view(x.size(0),-1)output=self.out(x)return outputmodel = CNN().to(device)
print(model)def train(dataloader,model,loss_fn,optimizer):model.train()   #告诉模型,我要开始训练,模型中w进行随机化操作,已经更新w。在训练过程中,w会被修改的
#pytorch提供2种方式来切换训练和测试的模式,分别是:model.train()和 model.eval()。
#一般用法是:在训练开始之前写上model.trian(),在测试时写上 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可以被省略,父类中已经对次功能进行了设置。自动初始化loss=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)num_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_batchescorrect /=sizeprint(f'Test result: \n Accuracy: {(100*correct)}%, Avg loss: {test_loss}')loss_fn=nn.CrossEntropyLoss()   #创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
optimizer=torch.optim.Adam(model.parameters(),lr=0.01)   #创建一个优化器,SGD为随机梯度下降算法
# #params:要训练的参数,一般我们传入的都是model.parameters()#
# lr:learning_rate学习率,也就是步长#loss表示模型训练后的输出结果与,样本标签的差距。如果差距越小,就表示模型训练越好,越逼近干真实的模型。# train(train_dataloader,model,loss_fn,optimizer)
# test(test_dataloader,model,loss_fn)epoch=9
for i in range(epoch):print(i+1)train(train_dataloader, model, loss_fn, optimizer)test(test_dataloader,model,loss_fn)

运行结果:

 结语

        CNN作为深度学习的基石架构,不仅在计算机视觉领域大放异彩,其核心思想也被广泛应用于语音识别、自然语言处理等领域。通过本文的系统介绍,希望读者能够建立起对CNN的全面认识,并能够动手实现自己的CNN模型。记住,理解原理只是第一步,持续的实践和创新才是掌握CNN的关键!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词