神经网络:卷积层、池化层、非线性激活函数

本文详细介绍了卷积操作的基础,包括卷积层、池化层的原理,以及如何使用nn.Module进行模块化编程。通过实际代码演示了 stride 和 padding 的作用,并深入探讨了非线性激活函数在神经网络中的关键角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前置:卷积操作

在这里插入图片描述
在这里插入图片描述

stride = 1
输出一个3维矩阵
在这里插入图片描述
stride = 2
卷积后输出一个2维矩阵

#卷积操作
import torch
import torch.nn.functional as F
#二维张量的输入,开始有多少个中括号就是几维张量
#此处input和kernel是2维张量,因此torch.Size([5,5])括号里是一个长度为2的列表
#表示一个5*5的矩阵
input = torch.tensor([[1,2,0,3,1],
                     [0,1,2,3,1],
                     [1,2,1,0,0],
                     [5,2,3,1,1],
                     [2,1,0,1,1]])

#卷积核
#表示一个3*3的矩阵
kernel = torch.tensor([[1,2,1],
                       [0,1,0],
                       [2,1,0]])

#输入矩阵和卷积核的尺寸
print(input.shape)
print(kernel.shape)

#torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) → Tensor
#input – input tensor of shape(minibatch,in_channels,iH,iW)

input = torch.reshape(input,(1,1,5,5))
kernel = torch.reshape(kernel,(1,1,3,3))

print(input.shape)
print(kernel.shape)

output = F.conv2d(input,kernel,stride=1)
print(output)#输出3维矩阵

output2 = F.conv2d(input,kernel,stride=2)
print(output2)#输出2维矩阵

output3 = F.conv2d(input,kernel,stride=1,padding=1)
print(output3)#padding=1是在输入矩阵边缘补一圈0的操作,保证了输入输出维度一致。

一、基本骨架nn.Module的使用(对其继承)

import torch
from torch import nn

#一、基本骨架nn.Module的使用
#定义神经网络的模板(对nn.module类的继承)
class zhiyuan(nn.Module):
    def __init__(self) -> None:
        super().__init__()

    def forward(self,input):
        output = input + 1
        return output

#用zhiyuan模块创建出来的神经网络xuzhiyuan
xuzhiyuan = zhiyuan()#类的实例化
#定义输入x
x = torch.tensor(1.0)
#输出
output = xuzhiyuan(x)
print(output)

二、卷积层(Convolution Layers)

在这里插入图片描述
https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md

github上的这个动画很好地阐释了torch.nn.functional.conv2d函数的参数padding和stride的含义。

参数kernel_size的值取多少都无所谓,因为训练神经网络的过程中就是对卷积核的参数进行不断调整。

两个最重要的参数:

  • in_channels(输入图片的信道数)
  • out_channels(输出图片的信道数)

如果输出的channel数是2,就会生成两个卷积核,对应生成两个矩阵,最终这两个矩阵的叠加作为输出。
在这里插入图片描述

代码示例:

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor()
                                       ,download=True)

dataloader = DataLoader(dataset,batch_size=64)

class Verse(nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

    def forward(self,x):
        x = self.conv1(x)
        return x

verse = Verse()
# print(verse)

writer = SummaryWriter("logs")

step = 0
for data in dataloader:
    imgs,targets = data
    output = verse(imgs)
    print(imgs.shape)
    print(output.shape)
    #torch.Size([64, 3, 32, 32])
    writer.add_images("input",imgs,step)
    #torch.Size([64, 6, 30, 30])
    output = torch.reshape(output,(-1,3,30,30))#转3通道,只有3通道的RGB可以可视化输出
    writer.add_images("output",output,step)

    step = step + 1

writer.close()

三、池化层(Pooling Layers)

在这里插入图片描述
由多个输入平面构成的单个输入应该应用maxpool2d

在这里插入图片描述

ceil mode/floor mode

ceil:向上取整
floor:向下取整

最大池化:
在这里插入图片描述

是否保留右边不足一个池化核大小的数据取决于前面设定的参数ceil_mode
如果True,则向上取整,保留;
如果False,则向下取整,舍弃。

import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("../data",train=True,transform=torchvision.transforms.ToTensor())

dataloader = DataLoader(dataset,batch_size=64)
# input = torch.tensor([[1,2,0,3,1],
#                       [0,1,2,3,1],
#                       [1,2,1,0,0],
#                       [5,2,3,1,1],
#                       [2,1,0,1,1]],dtype=torch.float32)

# input = torch.reshape(input,(-1,1,5,5))#一个batch_size(后期会调整),一个channel,每个channel是一个5*5的矩阵
# print(input.shape)


#继承父类(nn.Module)
class Verse(nn.Module):

    def __init__(self) -> None:
        super(Verse,self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)

    def forward(self,input):
        output = self.maxpool1(input)
        return output

#实例化
verse = Verse()

writer = SummaryWriter("logs_maxpoold2")
step = 0
for data in dataloader:
    imgs,targets = data
    writer.add_images("input1",imgs,step)
    writer.add_images("output1",verse(imgs),step)
    step = step + 1


writer.close()

四、非线性激活函数

import torch
from torch import nn
from torch.nn import ReLU

input = torch.tensor([[1,0.5],
                      [-1,3]])

input = torch.reshape(input,(-1,1,2,2))
# print(input.shape)

class Verse(nn.Module):
    def __init__(self):
        super(Verse,self).__init__()
        self.relu1 = ReLU()

    def forward(self,input):
        output = self.relu1(input)
        return output

verse = Verse()

output = verse(input)
print(output)
#tensor([[[[1.0000, 0.5000],
#          [0.0000, 3.0000]]]])
<think>好的,我现在需要详细回答用户关于卷积神经网络(CNN)结构的问题,包括卷积层池化层、全连接层和激活函数的作用与关系,并且需要结合引用中的内容。首先,我要确保自己正确理解每个组件的功能以及它们之间的连接方式。 用户的问题明确要求结构详解,并且提到图解,虽然我无法直接生成图像,但需要用文字描述清楚各层的结构和数据流动。同时,用户引用的资料中有几点需要注意: 1. 引用[1]提到CNN的三大网络结构:卷积层池化层、全连接层,以及稀疏连接和权值共享的特点。这需要在解释各层时强调参数共享和局部连接的优势。 2. 引用[2]讨论了激活函数的作用,特别是非饱和激活函数如ReLU的优势,比如解决梯度消失和加速收敛。这部分需要结合到激活函数的作用部分,并说明为何在卷积层后使用。 3. 引用[3]中DCGAN的例子提到了删除全连接层、使用卷积层代替池化层,以及不同的激活函数应用(生成器用ReLU,判别器用LeakyReLU)。这可能需要在讨论结构变体或优化时提及,但用户主要问题在于基础结构,所以可能作为扩展内容。 4. 引用[4]指出卷积层参数量小但计算量大,全连接层相反,优化时需分别处理。这需要在各层的作用部分强调参数和计算量的特点。 接下来,我需要组织内容结构。通常,CNN的结构是按照输入层→卷积层激活函数池化层→(重复)→全连接层的顺序排列。每个部分需要详细说明: 1. 卷积层:局部感知、权值共享、特征提取。需要解释卷积操作,滤波器的作用,输出特征图的尺寸计算,以及参数量的计算(引用[4]提到的参数量小)。 2. 激活函数:引入非线性,如ReLU,防止梯度消失(引用[2])。说明为什么在卷积层后立即使用。 3. 池化层:降维、防止过拟合、保持平移不变性。说明最大池化和平均池化的区别。 4. 全连接层:整合特征,用于分类。参数量的对比(引用[4])。 5. 各层之间的关系:数据如何流动,特征如何从低级到高级抽象,最后分类。 需要注意用户可能对参数共享、局部连接等概念不熟悉,需要用简单例子说明,比如卷积核在输入上滑动,共享权重,减少参数。同时,结合引用中的内容,例如权值共享如何减少参数(引用[1]),激活函数的选择(引用[2]),全连接层的参数优化(引用[4])。 可能还需要提到典型的CNN结构,如LeNet-5、AlexNet等作为例子,但用户没有明确要求,所以可能简要带过。此外,可以提到现代网络中的变化,如使用步长代替池化(引用[3]中的DCGAN),但主要聚焦基础结构。 最后,生成相关问题时要基于用户可能的后续疑问,比如各层的参数计算、激活函数的选择原因、实际应用中的结构变体等。 现在,需要确保回答符合格式要求,使用正确的LaTeX,分点清晰,并在适当位置添加引用标识。例如,在解释激活函数时引用[2],在讨论参数优化时引用[4]。</think>### 卷积神经网络(CNN)结构详解 #### 1. **卷积层(Convolutional Layer)** **作用**:通过卷积核(滤波器)提取输入数据的局部特征(如边缘、纹理等),实现**稀疏连接**和**权值共享**,显著减少参数量[^1]。 **操作**: - 输入数据(如图像)与卷积核进行滑动点乘运算: $$ \text{输出特征图}(i,j) = \sum_{m}\sum_{n} \text{输入}(i+m,j+n) \cdot \text{卷积核}(m,n) + \text{偏置} $$ - **参数计算**:假设输入通道数为$C_{\text{in}}$,卷积核尺寸为$k \times k$,输出通道数为$C_{\text{out}}$,则参数量为: $$ C_{\text{out}} \times (C_{\text{in}} \times k \times k + 1) $$ **特点**: - 前几层卷积参数量占比小但计算量大[^4]; - 局部感知减少计算冗余,权值共享提升泛化能力[^1]。 --- #### 2. **激活函数(Activation Function)** **作用**:引入非线性,增强模型表达能力[^2]。 **常用类型**: - **ReLU**(修正线性单元):$f(x) = \max(0, x)$,解决梯度消失问题,加速收敛[^2]; - **LeakyReLU**:允许负区间微小梯度,防止神经元“死亡”; - **Sigmoid/Tanh**(饱和函数):多用于输出层,如二分类。 **位置**:通常紧接卷积层后,如: `输入 → 卷积层激活函数池化层` --- #### 3. **池化层(Pooling Layer)** **作用**:降维(减少计算量)、增强平移不变性、防止过拟合。 **操作**: - **最大池化**(Max Pooling):取窗口内最大值,突出显著特征; - **平均池化**(Average Pooling):取窗口内平均值,平滑特征。 **示例**:2×2池化窗口将特征图尺寸缩小为原1/4。 **特点**:无参数,仅保留关键信息。 --- #### 4. **全连接层(Fully Connected Layer)** **作用**:整合全局特征,输出分类结果(如类别概率)。 **结构**:每个神经元与前一层的所有神经元连接。 **参数计算**:假设输入维度$N$,输出维度$M$,则参数量为: $$ N \times M + M $$ **特点**: - 参数量大但计算量小(与卷积层相反); - 现代网络(如DCGAN)可能删除全连接层以提升效率[^3]。 --- #### 5. **层级关系与数据流动** 典型CNN结构示例: ``` 输入图像 → [卷积层 → ReLU → 池化层]×N → 全连接层 → Softmax → 分类结果 ``` - **低级特征**(边缘、颜色)→ **中级特征**(纹理、部件)→ **高级特征**(物体整体); - 池化层逐步压缩空间维度,全连接层综合特征进行分类。 --- #### 图解说明(文字描述) 1. **输入层**:原始图像(如224×224×3); 2. **卷积层1**:使用32个3×3卷积核 → 输出222×222×32; 3. **ReLU激活**:非线性变换; 4. **池化层1**:2×2最大池化 → 输出111×111×32; 5. **卷积层2**:64个3×3卷积核 → 输出109×109×64; 6. **全连接层**:将特征展平后连接至分类器。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

verse_armour

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值