神经网络(neual networks)是人工智能研究领域的一部分,当前最流行的神经网络是深度卷积神经网络(deep convolutional neural networks, CNNs),虽然卷积网络也存在浅层结构,但是因为准确度和表现力等原因很少使用。目前提到CNNs和卷积神经网络,学术界和工业界不再进行特意区分,一般都指深层结构的卷积神经网络,层数从”几层“到”几十上百“不定。
CNNs目前在很多很多研究领域取得了巨大的成功,例如: 语音识别,图像识别,图像分割,自然语言处理等。虽然这些领域中解决的问题并不相同,但是这些应用方法都可以被归纳为:
CNNs可以自动从(通常是大规模)数据中学习特征,并把结果向同类型未知数据泛化。
基础的CNN由 卷积(convolution), 激活(activation), and 池化(pooling)三种结构组成。CNN输出的结果是每幅图像的特定特征空间。当处理图像分类任务时,我们会把CNN输出的特征空间作为全连接层或全连接神经网络(fully connected neural network, FCN)的输入,用全连接层来完成从输入图像到标签集的映射,即分类。当然,整个过程最重要的工作就是如何通过训练数据迭代调整网络权重,也就是后向传播算法。
CNN网络一共有5个层级结构:
1.输入层
常见的输入层中预处理方式有:
2.卷积层
3.激活层
所谓激励,实际上是对卷积层的输出结果做一次非线性映射。 如果不用激励函数(其实就相当于激励函数是f(x)=x),这种情况下,每一层的输出都是上一层输入的线性函数。容易得出,无论有多少神经网络层,输出都是输入的线性组合,与没有隐层的效果是一样的,这就是最原始的感知机了。
常用的激励函数有:
激励层建议: 首先ReLU,因为迭代速度快,但是有可能效果不佳。如果ReLU失效的情况下,考虑使用Leaky ReLU或者 Maxout,此时一般情况都可以解决。Tanh函数在文本和音频处理有比较好的效果。深度学习最常用的10个激活函数
4.池化层
池化(Pooling):也称为欠采样或下采样。主要用于特征降维,压缩数据和参数的数量,减小过拟合,同时提高模型的容错性。主要有:
5.全连接FC层
经过前面若干次卷积+激励+池化后,终于来到了输出层,模型会将学到的一个高质量的特征图片全连接层。其实在全连接层之前,如果神经元数目过大,学习能力强,有可能出现过拟合。因此,可以引入dropout操作(随机删除神经网络中的部分神经元)来解决此问题。还可以进行局部归一化(LRN)、数据增强等操作,来增加鲁棒性。 当来到了全连接层之后,可以理解为一个简单的多分类神经网络(如:BP神经网络),通过softmax函数得到最终的输出。整个模型训练完毕。
光栅化: 图像经过池化-下采样后,得到的是一系列的特征图,而多层感知器接受的输入是一个向量。因此需要将这些特征图中的像素一次取出,排列成一个向量。
下面将分别对这几层做介绍:
数据输入层:Input Layer,主要用来作为网络的输入,在这一层我们主要对数据进行预处理,并且根据输入数据的特性决定好输入的shape。如果要进行2D的卷积,以keras为例,数据需要处理成:(samples, channels, rows, cols)
其中:
在讲解卷积之前,我们需要知道以下名词及其含义:
以下图为例
绿色圆圈代表的是输入的矩阵,显然,它有3层,所以channel是3
蓝色圆圈代表的就是一个卷积核,它的宽和高就是对应的kernel_width和kernel_height
红色圆圈代表的就是filters,有几个filters就有几个卷积核
其中需要搞明白filter和channel的关系:
channels
,取决于图片类型,比如RGB;out_channels
,取决于卷积核的数量。此时的 out_channels
也会作为下一次卷积时的卷积核的 in_channels
;in_channels
,刚刚2中已经说了,就是上一次卷积的 out_channels
,如果是第一次做卷积,就是1中样本图片的 channels
。卷积就是输入图像和filter的对应位置元素相乘再求和,然后按照规定步长进行移动,再进行相同的操作,如下图
首先第一个filter是一个3* 3的matrix,把这个filter放在image的左上角,把filter的9个值和image的9个值做内积,两边都是1,1,1(斜对角),内积的结果就得到3。然后规定的步长(stride)是1,所以向右移动1个距离,然后再次计算得到-1。将原图上下滑动结束之后,就得到了新的一张特征图。如果还没看明白,可以看到下面的图
其中padding就是在输入的特征图周围进行填充。
红色部分就是进行的填充,可以通过设置padding=?规定外围填充多少层。
为什么要进行填充? 如果没有填充,每一次卷积之后会有以下问题:
所以加入了padding,这样就解决了feature map尺寸越来越小的问题。同时卷积核对边缘信息的处理不止处理了一次,对边缘信息的提取更加充分了。
根据输入数据的大小和卷积核大小可以确定输出特征图大小计算方法:
通过输入原特征图的宽和高,就可以计算下一次输出特征图的宽和高,下一层输入的通道数就是这次卷积的filter数。
卷积层对原图运算多个卷积产生一组线性激活响应,而非线性激活层是对之前的结果进行一个非线性的激活响应。
在神经网络中用到最多的非线性激活函数是Relu函数,它的公式定义如下:
f(x)=max(0,x)
即,保留大于等于0的值,其余所有小于0的数值直接改写为0。
为什么要这么做呢?上面说到,卷积后产生的特征图中的值,越靠近1表示与该特征越关联,越靠近-1表示越不关联,而我们进行特征提取时,为了使得数据更少,操作更方便,就直接舍弃掉那些不相关联的数据。
relu的函数表达式,relu(x)=max(x,0),或者写成分段函数的表达式:
x>0的时候,函数的导数直接就是1,不存在梯度衰减的问题。虽然ReLU函数缓解了梯度消失的问题,但是同时也带来另外一个问题,就是梯度死亡问题。可以看到在x<0的时候,函数是硬饱和的,这个时候导数直接为0了,一旦输入落进这个区域,那么神经元就不会更新权重了,这个现象称为神经元死亡。
Relu优点:
卷积操作后,我们得到了一张张有着不同值的feature map,尽管数据量比原图少了很多,但还是过于庞大(比较深度学习动不动就几十万张训练图片),因此接下来的池化操作就可以发挥作用了,它最大的目标就是减少数据量。
池化分为两种,Max Pooling 最大池化、Average Pooling平均池化。顾名思义,最大池化就是取最大值,平均池化就是取平均值。
以最大池化层为例,池化层和卷积层的运作模式是相同的,但是唯一的区别就是在相应位置上进行的不是卷积操作,而是在filter的大小范围内找到一个最大值(平均池化就是在filter的大小范围内所有数取平均)。
池化层根据卷积后的输出图像大小以及池化窗口大小,Padding确定输出特征图大小:
经过前面若干次卷积+激励+池化后,终于来到了输出层,模型会将学到的一个高质量的特征图片全连接层。
flatten就是feature map拉直,拉直之后就可以丢到fully connected feedforward netwwork,然后就结束了。
很多人不知道该如何计算每一层的parameter数量。 在卷积中,训练的参数主要是filter中的参数。 训练意义:
h(x)=f(wx+b)上式子就是神经元所表示的函数,x表示输i入,w表示权重,b表示偏置,f表示激活函数,h(x)表示输出。
训练卷积神经网络的过程就是不断调整权重w与偏置b的过程,以使其输出h(x)达到预期值。
权重w与偏置b就相当于神经元的记忆。
加偏置原因:
不加偏置b的话,函数就必定经过原点,进行分类的适用范围就少了
参考神经网络中w,b参数的作用(为何需要偏置b的解释)
所以可以用以下方法计算:
每一层的parameter=(kernel_width*kernel_height+1)*in_channel
(+1是要加上偏置b)
下面给一个网络结构以及对应的每层的信息表
输入设计:
x_train = x_train.reshape(x_train.shape[0], img_x, img_y, 1) #(samples, rows, cols, channels)
模型设计:
model = Sequential() #初始化模型
#卷积层,stride默认是1
model.add(Conv2D(32, kernel_size=(5, 5), activation='relu', input_shape=(img_x, img_y, 1)))
model.add(MaxPool2D(pool_size=(2, 2), strides=(2, 2))) #池化层
model.add(Conv2D(64, kernel_size=(5, 5), activation='relu')) #卷积层
model.add(MaxPool2D(pool_size=(2, 2), strides=(2, 2))) #池化层
model.add(Flatten()) #全连接层
model.add(Dense(1000, activation='relu')) #全连接层
model.add(Dense(10, activation='softmax')) #softmax分类输出
下面是模型代码对应的网络结构图
阅读量:1022
点赞量:0
收藏量:0