李宏毅《深度学习》(六)

人工智能的浪潮正在席卷全球,诸多词汇时刻萦绕在我们耳边:人工智能(Artificial Intelligence)、机器学习(Machine Learning)、深度学习(Deep Learning)。本文主要是对李宏毅课程内容进行笔记梳理,参考链接在文末已经给出。

10-卷积神经网络(CNN)

概述

神经网络(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.输入层

常见的输入层中预处理方式有:

  • 去均值
  • 归一化
  • PCA/SVD降维等

2.卷积层

3.激活层

所谓激励,实际上是对卷积层的输出结果做一次非线性映射。 如果不用激励函数(其实就相当于激励函数是f(x)=x),这种情况下,每一层的输出都是上一层输入的线性函数。容易得出,无论有多少神经网络层,输出都是输入的线性组合,与没有隐层的效果是一样的,这就是最原始的感知机了。

常用的激励函数有:

  • Sigmoid函数
  • Tanh函数
  • ReLU
  • Leaky ReLU
  • ELU
  • Maxout

激励层建议: 首先ReLU,因为迭代速度快,但是有可能效果不佳。如果ReLU失效的情况下,考虑使用Leaky ReLU或者 Maxout,此时一般情况都可以解决。Tanh函数在文本和音频处理有比较好的效果。有机会单独做一期介绍激活函数

4.池化层

池化(Pooling):也称为欠采样或下采样。主要用于特征降维,压缩数据和参数的数量,减小过拟合,同时提高模型的容错性。主要有:

  • Max Pooling:最大池化(池化窗口的最大值)——较常用
  • Average Pooling:平均池化 (池化窗口的平均值)

5.全连接FC层

经过前面若干次卷积+激励+池化后,终于来到了输出层,模型会将学到的一个高质量的特征图片全连接层。其实在全连接层之前,如果神经元数目过大,学习能力强,有可能出现过拟合。因此,可以引入dropout操作(随机删除神经网络中的部分神经元)来解决此问题。还可以进行局部归一化(LRN)数据增强等操作,来增加鲁棒性。 当来到了全连接层之后,可以理解为一个简单的多分类神经网络(如:BP神经网络),通过softmax函数得到最终的输出。整个模型训练完毕。

光栅化: 图像经过池化-下采样后,得到的是一系列的特征图,而多层感知器接受的输入是一个向量。因此需要将这些特征图中的像素一次取出,排列成一个向量。

下面将分别对这几层做介绍:


输入层

数据输入层:Input Layer,主要用来作为网络的输入,在这一层我们主要对数据进行预处理,并且根据输入数据的特性决定好输入的shape。如果要进行2D的卷积,以keras为例,数据需要处理成:(samples, channels, rows, cols)其中:

  • sample:样本数量
  • channels:通道数,这个主要是输入数据的深度,如果图像是一个灰度图像,那么深度就是1,如果是彩色图像,那么就是由RGB的3个通道组成。
  • rows:可以想象成输入矩阵的行数
  • cols:可以想象成输入矩阵的列数
    具体如何规定输入的shape,还需要看对应框架下API的源码,源码内会有相应的解释,告诉你输入的shape应该是什么样子,例如keras的Conv2D的源码。

image.png


卷积层

在讲解卷积之前,我们需要知道以下名词及其含义:

  • filters:过滤器数量
  • padding:填充
  • stride:步长
  • kernel_width:卷积核宽
  • kernel_height:卷积核长

以下图为例

image.png

绿色圆圈代表的是输入的矩阵,显然,它有3层,所以channel是3

蓝色圆圈代表的就是一个卷积核,它的宽和高就是对应的kernel_width和kernel_height

红色圆圈代表的就是filters,有几个filters就有几个卷积核

其中需要搞明白filter和channel的关系:

  1. 最初输入的图片样本的 channels ,取决于图片类型,比如RGB;
  2. 卷积操作完成后输出的 out_channels ,取决于卷积核的数量。此时的 out_channels 也会作为下一次卷积时的卷积核的 in_channels
  3. 卷积核中的 in_channels ,刚刚2中已经说了,就是上一次卷积的 out_channels ,如果是第一次做卷积,就是1中样本图片的 channels 。
基本操作

卷积就是输入图像和filter的对应位置元素相乘再求和,然后按照规定步长进行移动,再进行相同的操作,如下图

image.png
首先第一个filter是一个3* 3的matrix,把这个filter放在image的左上角,把filter的9个值和image的9个值做内积,两边都是1,1,1(斜对角),内积的结果就得到3。然后规定的步长(stride)是1,所以向右移动1个距离,然后再次计算得到-1。将原图上下滑动结束之后,就得到了新的一张特征图。如果还没看明白,可以看到下面的图

image.png

padding

其中padding就是在输入的特征图周围进行填充。

image.png
红色部分就是进行的填充,可以通过设置padding=?规定外围填充多少层。

为什么要进行填充?
如果没有填充,每一次卷积之后会有以下问题:

  1. 卷积后的矩阵越变越小(如果卷积层100层,每一层都缩小最终得到的将是很小的图片)
  2. 输入矩阵(左)边缘像素(绿阴影)只被计算过一次,而中间像素(红阴影)被卷积计算多次,意味着丢失图像角落信息

所以加入了padding,这样就解决了feature map尺寸越来越小的问题。同时卷积核对边缘信息的处理不止处理了一次,对边缘信息的提取更加充分了。

最终计算

根据输入数据的大小和卷积核大小可以确定输出特征图大小计算方法:

截屏2020-07-19 下午9.32.25.png

通过输入原特征图的宽和高,就可以计算下一次输出特征图的宽和高,下一层输入的通道数就是这次卷积的filter数。


激活层

卷积层对原图运算多个卷积产生一组线性激活响应,而非线性激活层是对之前的结果进行一个非线性的激活响应。

在神经网络中用到最多的非线性激活函数是Relu函数,它的公式定义如下:

f(x)=max(0,x)

即,保留大于等于0的值,其余所有小于0的数值直接改写为0。

为什么要这么做呢?上面说到,卷积后产生的特征图中的值,越靠近1表示与该特征越关联,越靠近-1表示越不关联,而我们进行特征提取时,为了使得数据更少,操作更方便,就直接舍弃掉那些不相关联的数据。

relu的函数表达式,relu(x)=max(x,0),或者写成分段函数的表达式:

截屏2020-07-20 上午11.56.58.png

x>0的时候,函数的导数直接就是1,不存在梯度衰减的问题。虽然ReLU函数缓解了梯度消失的问题,但是同时也带来另外一个问题,就是梯度死亡问题。可以看到在x<0的时候,函数是硬饱和的,这个时候导数直接为0了,一旦输入落进这个区域,那么神经元就不会更新权重了,这个现象称为神经元死亡。

20200318140644754.png

Relu优点:

  1. 缓解了梯度消失的问题(x>0的时候,函数的导数直接就是1,不存在梯度衰减的问题)
  2. 计算非常简单(只需要使用阈值判断即可,导数也是几乎不用计算)
  3. 可以产生稀疏性(小于0的部分直接设置为0,这就使得神经网络的中间输出是稀疏的,有一定的Droupout的作用,也就能够在一定程度上防止过拟合)

池化层

卷积操作后,我们得到了一张张有着不同值的feature map,尽管数据量比原图少了很多,但还是过于庞大(比较深度学习动不动就几十万张训练图片),因此接下来的池化操作就可以发挥作用了,它最大的目标就是减少数据量

池化分为两种,Max Pooling 最大池化、Average Pooling平均池化。顾名思义,最大池化就是取最大值,平均池化就是取平均值。

image.png

以最大池化层为例,池化层和卷积层的运作模式是相同的,但是唯一的区别就是在相应位置上进行的不是卷积操作,而是在filter的大小范围内找到一个最大值(平均池化就是在filter的大小范围内所有数取平均)。

池化层根据卷积后的输出图像大小以及池化窗口大小,Padding确定输出特征图大小:

截屏2020-07-19 下午9.35.17.png


全连接层

经过前面若干次卷积+激励+池化后,终于来到了输出层,模型会将学到的一个高质量的特征图片全连接层。

flatten就是feature map拉直,拉直之后就可以丢到fully connected feedforward netwwork,然后就结束了。

image.png


parameters的计算

很多人不知道该如何计算每一层的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)

下面给一个网络结构以及对应的每层的信息表

流量识别卷积神经网络结构.png

image.png

keras的CNN例子

输入设计:

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分类输出

下面是模型代码对应的网络结构图

手写体识别网络结构.png
参考链接:

  • 链接:https://www.zhihu.com/topic/20043586/intro
  • 链接:https://zhuanlan.zhihu.com/p/27908027
  • 链接:https://blog.csdn.net/yjl9122/article/details/70198357
  • 链接:https://www.cnblogs.com/alexanderkun/p/9295004.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值