一、CNN卷积神经网络原理
卷积神经网络(Convolutional Neural Networks / CNNs / ConvNets)与普通神经网络非常相似,它们都由具有可学习的权重和偏置常量(biases)的神经元组成。每个神经元都接收一些输入,并做一些点积计算,输出是每个分类的分数。
一个卷积神经网络由很多层组成,它们的输入是三维的,输出也是三维的,有的层有参数,有的层不需要参数。
** CNN主要特点**:减少权值,局部连接,权值共享
1. CNN的一般结构
- 输入层:用于数据的输入
- 卷积层:卷积神经网路中每层卷积层由若干卷积单元组成,每个卷积单元的参数都是通过反向传播算法优化得到的。卷积运算的目的是提取输入的不同特征,第一层卷积层可能只能提取一些低级的特征如边缘、线条和角等层级,更多层的网络能从低级特征中迭代提取更复杂的特征。
- 激励层:由于卷积也是一种线性运算,因此需要增加非线性映射
- 池化层:压缩数据和参数的量,减少过拟合
- 全连接层:通常在CNN的尾部进行重新拟合,减少特征信息的损失
- 输出层:用于输出结果
(1)输入层
CNN输入层的输入格式保留了图片本身的结构。
卷积神经网络利用输入是图片的特点,把神经元设计成三个维度 : width, height, depth(注意这个depth不是神经网络的深度,而是用来描述神经元的) 。比如输入的图片大小是 32 × 32 × 3 (rgb),那么输入神经元就也具有 32×32×3 的维度。
(2)卷积层
用它来进行特征提取。这里需要特殊说明的是,对于卷积层而言,有一个重要的概念就是深度(depth),即为图像的通道数,如RGB的深度就是三层的。而卷积层的感受野(receptive,又称过滤器(filter),神经元(neuron),卷积核(kernel))的深度必须与输入图像的深度相同。但filter的个数是可以根据需要让程序员自己定义。
基本概念
- 感受视野:
即感受上一层的部分特征。在卷积神经网络中,隐藏层中的神经元的感受视野比较小,只能看到上一次的部分特征,上一层的其他特征可以通过平移感受视野来得到同一层的其他神经元。 - 卷积核
感受视野中的权重矩阵 w w w - 步长
感受视野对输入的扫描间隔称为步长(stride) - 边界扩充
当步长比较大时(stride>1),为了扫描到边缘的一些特征,感受视野可能会“出界”,这时需要对边界扩充(pad) - 特征映射图(feature map)
通过一个带有卷积核的感受视野 扫描生成的下一层神经元矩阵
(3)激励层
激励函数:使用relu作为激活函数
f ( x ) = m a x ( 0 , μ ) f(x)=max(0, μ) f(x)=max(0,μ)
函数图像
为什么不用sigmoid函数?
因为sigmoid的函数具有饱和性,当输入的x过大或过小时,函数的输出会非常接近+1与-1,在这里斜率会非常小,那么在训练时引用梯度下降时,其饱和性会使梯度非常小,严重降低了网络的训练速度。
进行卷积操作后,会产生一个特征图(Feature Map),设其尺寸为O,filter尺寸为K,图像宽度为W,高度为H(图中的W用H替换即为计算后的高度,这里为了方便,简写为W),步幅为S,补零填充(Zero Padding)为P,(这里补零填充的意思为在原图像周围补几圈0,这是为了尽可能多地保留原始输入内容的信息。),则有:
(4)池化层
池化(pool)即下采样(downsamples),目的是为了减少特征图。池化操作对每个深度切片独立,规模一般为 2*2,相对于卷积层进行卷积运算,池化层进行的运算一般有以下几种:
- 最大池化(Max Pooling)。取4个点的最大值。这是最常用的池化方法。
- 均值池化(Mean Pooling)。取4个点的均值。
- 高斯池化。借鉴高斯模糊的方法。不常用。
- 可训练池化。训练函数 ff ,接受4个点为输入,出入1个点。不常用。
最常见的池化层是规模为2*2, 步幅为2,对输入的每个深度切片进行下采样。每个MAX操作对四个数进行,如下图所示:
池化操作将保存深度大小不变。
如果池化层的输入单元大小不是二的整数倍,一般采取边缘补零(zero-padding)的方式补成2的倍数,然后再池化。
(5)全连接层
连接所有的特征,将输出值送给分类器。
全连接层和卷积层可以相互转换:
- 对于任意一个卷积层,要把它变成全连接层只需要把权重变成一个巨大的矩阵,其中大部分都是0 除了一些特定区块(因为局部感知),而且好多区块的权值还相同(由于权重共享)。
- 相反地,对于任何一个全连接层也可以变为卷积层。我们把 filter size 正好设置为整个输入层大小即可
(6)输出层
输出目标结果
二、使用CNN模型对MINIST手写字符数据集进行分类
环境
Win10,python3.6,spyder,pytorch
代码结构
- 导入包
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
- 设备配置
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
- 定义设置超参数
其中num_epochs为训练迭代次数;batch_size为每次训练的批数目;learning_rating为学习率
num_epochs = 5
num_classes = 10
batch_size = 100
learning_rate = 0.001
- 加载MNIST数据集
调用pytorch的torchversion.datasets,通过datasets.MNIST方式来下载调用这些数据集 - 定义两层卷积神经网络模型
Conv2d为二维卷积层,因为输入的图片是单通道,所以第一个卷积层的输入通道为1,输出通道为16,滤波器为5x5;第二个卷积层的输入通道为16,输出通道为32,滤波器同样是5x5。
# 定义两层卷积神经网络模型
class ConvNet(nn.Module):
def __init__(self, num_classes=10):
super(ConvNet, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2), #1表示通道数,16表示卷积个数
nn.BatchNorm2d(16), #归一化
nn.ReLU(), #