CNN常见问题总结

前言

在初次学习深度学习的时候,必不可少的接触卷积神经网络(CNN),本篇文章就记录一下通过应用CNN来做分类时,自己遇到的一些问题和踩到的一些坑。

  • 本文使用的时Pytorch 1.1.0版本,更多关于pytorch的资料可到pytorch官网和pytorch中文网查找资料,有CUDA 10.1版本来进行GPU加速(搞深度学习没GPU基本完蛋)。

CNN原理

CNN网络是一种用来处理局部和整体相关性的计算网络结构,被应用在图像识别(CV)、自然语言处理(NLP)甚至是语音识别领域,因为图像数据具有显著的局部与整体关系,其在图像识别领域的应用获得了巨大的成功。

其实说白了CNN能在CV领域取得巨大成功最重要的就两个点:

  • 局部连接
    局部连接的思想,是受启发于生物学里的视觉系统结构,视觉皮层的神经元就是仅用局部接受信息。对于二维图像,局部像素关联性较强。这种局部连接保证了训练后的滤波器能够对局部特征有最强的响应,使神经网络可以提取数据的局部特征; 下图是一个很经典的图示,左边是全连接,右边是局部连接。
    在这里插入图片描述

  • 权值共享
    权值共享,即计算同一深度的神经元时采用的卷积核参数是共享的。

在这里插入图片描述

  • 总结:这里就体现了卷积神经网络的奇妙之处,使用少量的参数,却依然能有非常出色的性能。上述仅仅是提取图像一种特征的过程。如果要多提取出一些特征,可以增加多个卷积核,不同的卷积核能够得到图像不同尺度下的特征,称之为特征图(feature map)。

CNN的结构

以图像分类任务为例,CNN一般包含5种类型的网络层次结构:

  1. 输入层(input)。一般输入层都是对原始图像经过数据的预处理之后的像素矩阵,往往数据预处理的越好,结果就越好。
  2. 卷积层(conv2d)。局部连接,权值共享,说白了就是做特征提取,卷积层越深提取到的特征就越丰富,分类也就越准确。
  3. 批归一化层(Batch Normalization)。虽然我们对输入数据进行了归一化处理,但是输入数据经过 σ(WX+b) 这样的矩阵乘法以及非线性运算之后,其数据分布很可能被改变,而随着深度网络的多层运算之后,数据分布的变化将越来越大。如果我们能在网络的中间也进行归一化处理,是否对网络的训练起到改进作用呢?答案是肯定的。
  4. 激活层(ReLU)。激活层(Activation Layer)负责对卷积层抽取的特征进行激活,由于卷积操作是由输入矩阵与卷积核矩阵进行相差的线性变化关系,需要激活层对其进行非线性的映射。激活层主要由激活函数组成,即在卷积层输出结果的基础上嵌套一个非线性函数,让输出的特征图具有非线性关系。
  5. 池化层(Pooling)。作用是对感受域内的特征进行筛选,提取区域内最具代表性的特征,能够有效地降低输出特征尺度,进而减少模型所需要的参数量。
  6. 全连接(FC)。负责对卷积神经网络学习提取到的特征进行汇总,将多维的特征输入映射为二维的特征输出通常低维度特征对应任务的学习目标。

CNN卷积层的基本参数

卷积层中需要用到卷积核(滤波器或特征检测器)与图像特征矩阵进行点乘运算,利用卷积核与对应的特征感受域进行划窗式运算时,需要设定卷积核对应的大小、步长、个数以及填充的方式。以最简单的例子进行说明:输入信号的形式为 ( N , C i n , H , W ) (N,C_in ,H,W) (N,Cin,H,W) N N N表示batch size, C i n C_in Cin表示channel个数, H , W H,W HW分别表示特征图的高和宽。

  1. in_channels(int) – 输入信号的通道
  2. out_channels(int) – 卷积产生的通道
  3. kerner_size(int or tuple) - 卷积核的尺寸
  4. stride(int or tuple, optional) - 卷积步长
  5. padding(int or tuple, optional) - 输入的每一条边补充0的层数
  6. dilation(int or tuple, optional) – 卷积核元素之间的间距
  7. groups(int, optional) – 从输入通道到输出通道的阻塞连接数
  8. bias(bool, optional) - 如果bias=True,添加偏置

参数存在如下关系:

input: ( N , C i n , H i n , W i n ) (N,C_in,H_in,W_in)

### 卷积神经网络中的常见填充方法 在卷积神经网络CNN)中,填充是一种重要的技术,它通过扩展输入数据的边界来控制特征图的空间尺寸。以下是几种常见的填充方法及其特点: #### 零填充 (Zero Padding) 零填充是最常用的填充方式之一,在输入张量周围添加额外的零值像素[^3]。这种填充的主要目的是防止因卷积操作而导致的特征图缩小,并允许网络学习更丰富的空间信息。 - **优点**: - 维持输入和输出大小一致(当步幅为1时),有助于保留原始图像的信息。 - 提高模型的感受野,使深层网络能够捕捉更大范围内的上下文关系。 - **应用场景**: 常见于许多经典架构如ResNet、VGG等中,特别是在需要保持分辨率不变的情况下使用。 ```python import torch.nn as nn conv_layer_with_padding = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1) ``` --- #### 边缘复制填充 (Edge Replication Padding) 边缘复制填充会将输入矩阵的边界值重复到新增加的位置上[^4]。这种方法可以减少由于引入固定数值而产生的不自然效果。 - **适用情况**: 当希望避免人工设定的常数干扰实际数据分布时采用此法。 ```python from torchvision.transforms import functional as F image_padded_by_edge = F.pad(image_tensor, pad=(1, 1), mode='edge') ``` --- #### 反射填充 (Reflection Padding) 反射填充通过对称镜像的方式处理新加入的数据点[^5]。具体而言,它是基于现有数据沿边界的翻转模式构建出来的补充部分。 - **特性描述**: 更贴近原图结构变化规律,适用于某些特定领域比如风格迁移任务里平滑过渡区域的设计需求。 ```python reflection_pad = nn.ReflectionPad2d(padding=1) output = reflection_pad(input_tensor) ``` --- #### 循环填充 (Circular Padding) 循环填充则把整个数组看作周期函数的一部分来进行延展[^6]。这意味着最后一列之后紧接着的是第一列的内容;同样地,最上面一行之上紧跟着底部那一行。 - **特殊用途**: 主要应用于频域分析或者那些天然具备周期性质的任务之中。 ```python circular_padded_image = torch.roll(torch.cat([input[-1:], input], dim=0)) ``` --- ### 总结 不同的填充策略各有千秋,选择哪种取决于具体的业务背景以及预期达到的效果目标。例如,在医疗影像分割任务中可能更加倾向于利用zero-padding维持清晰度的同时扩大感受视野[^7];而在艺术创作方面,则或许偏好reflection-padding以获得柔和连贯的画面质感。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值