CNN学习和遇到的问题与keras简介

CNN学习及遇到的问题与keras简介

CNN学习

从神经网络到卷积神经网络(CNN)**

我们知道神经网络的结构是这样的:

这里写图片描述

那卷积神经网络跟它是什么关系呢?

其实卷积神经网络依旧是层级网络,只是层的功能和形式做了变化,可以说是传统神经网络的一个改进。比如下图中就多了许多传统神经网络没有的层次。

这里写图片描述

卷积神经网络的层级结构

  • 数据输入层/ Input layer

  • 卷积计算层/ CONV layer

  • ReLU激励层 / ReLU layer

  • 池化层 / Pooling layer

  • 全连接层 / FC layer

    1.数据输入层

    该层要做的处理主要是对原始图像数据进行预处理,其中包括:
      • 去均值:把输入数据各个维度都中心化为0,如下图所示,其目的就是把样本的中心拉回到坐标系原点上。
      • 归一化:幅度归一化到同样的范围,如下所示,即减少各维度数据取值范围的差异而带来的干扰,比如,我们有两个维度的特征A和B,A范围是0到10,而B范围是0到10000,如果直接使用这两个特征是有问题的,好的做法就是归一化,即A和B的数据都变为0到1的范围。
      • PCA/白化:用PCA降维;白化是对数据各个特征轴上的幅度归一化

    去均值与归一化效果图:

这里写图片描述

去相关与白化效果图:

这里写图片描述

2.卷积计算层

这一层就是卷积神经网络最重要的一个层次,也是“卷积神经网络”的名字来源。

在这个卷积层,有两个关键操作:

  • 局部关联。每个神经元看做一个滤波器(filter)
  • 窗口(receptive field)滑动, filter对局部数据计算

先介绍卷积层遇到的几个名词:

  • 深度/depth(解释见下图)
  • 步长/stride (窗口一次滑动的长度)
  • 填充值/zero-padding

这里写图片描述

填充值是什么呢?以下图为例子,比如有这么一个5*5的图片(一个格子一个像素),我们滑动窗口取2*2,步长取2,那么我们发现还剩下1个像素没法滑完,那怎么办呢?
这里写图片描述

那我们在原先的矩阵加了一层填充值,使得变成6*6的矩阵,那么窗口就可以刚好把所有像素遍历完。这就是填充值的作用。

这里写图片描述

卷积的计算(注意,下面蓝色矩阵周围有一圈灰色的框,那些就是上面所说到的填充值)

这里写图片描述

这里的蓝色矩阵就是输入的图像,粉色矩阵就是卷积层的神经元,这里表示了有两个神经元(w0,w1)。绿色矩阵就是经过卷积运算后的输出矩阵,这里的步长设置为2这里写图片描述
蓝色的矩阵(输入图像)对粉色的矩阵(filter)进行矩阵内积计算并将三个内积运算的结果与偏置值b相加(比如上面图的计算:2+(-2+1-2)+(1-2-2) + 1= 2 - 3 - 3 + 1 = -3),计算后的值就是绿框矩阵的一个元素。

这里写图片描述

下面的动态图形象地展示了卷积层的计算过程:这里写图片描述

参数共享机制
  • 在卷积层中每个神经元连接数据窗的权重是固定的,每个神经元只关注一个特性。神经元就是图像处理中的滤波器,比如边缘检测专用的Sobel滤波器,即卷积层的每个滤波器都会有自己所关注一个图像特征,比如垂直边缘,水平边缘,颜色,纹理等等,这些所有神经元加起来就好比就是整张图像的特征提取器集合。
  • 需要估算的权重个数减少: AlexNet 1亿 => 3.5w
  • 一组固定的权重和不同窗口内数据做内积: 卷积

这里写图片描述

3.激励层

把卷积层输出结果做非线性映射。这里写图片描述

CNN采用的激励函数一般为ReLU(The Rectified Linear Unit/修正线性单元),它的特点是收敛快,求梯度简单,但较脆弱,图像如下。这里写图片描述

激励层的实践经验:
  ①不要用sigmoid!不要用sigmoid!不要用sigmoid!
  ② 首先试RELU,因为快,但要小心点
  ③ 如果2失效,请用Leaky ReLU或者Maxout
  ④ 某些情况下tanh倒是有不错的结果,但是很少

4.池化层

池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。
简而言之,如果输入是图像的话,那么池化层的最主要作用就是压缩图像。

这里再展开叙述池化层的具体作用。

  1. 特征不变性,也就是我们在图像处理中经常提到的特征的尺度不变性,池化操作就是图像的resize,平时一张狗的图像被缩小了一倍我们还能认出这是一张狗的照片,这说明这张图像中仍保留着狗最重要的特征,我们一看就能判断图像中画的是一只狗,图像压缩时去掉的信息只是一些无关紧要的信息,而留下的信息则是具有尺度不变性的特征,是最能表达图像的特征。
  2. 特征降维,我们知道一幅图像含有的信息是很大的,特征也很多,但是有些信息对于我们做图像任务时没有太多用途或者有重复,我们可以把这类冗余信息去除,把最重要的特征抽取出来,这也是池化操作的一大作用。
  3. 在一定程度上防止过拟合,更方便优化。这里写图片描述

池化层用的方法有Max pooling 和 average pooling,而实际用的较多的是Max pooling。

这里就说一下Max pooling,其实思想非常简单。这里写图片描述

对于每个2*2的窗口选出最大的数作为输出矩阵的相应元素的值,比如输入矩阵第一个2*2窗口中最大的数是6,那么输出矩阵的第一个元素就是6,如此类推。

5.全连接层

两层之间所有神经元都有权重连接,通常全连接层在卷积神经网络尾部。也就是跟传统的神经网络神经元的连接方式是一样的:

这里写图片描述

一般CNN结构依次为

  1. INPUT
  2. [[CONV -> RELU]*N -> POOL?]*M
  3. [FC -> RELU]*K
  4. FC

卷积神经网络之训练算法

  1. 同一般机器学习算法,先定义Loss function,衡量和实际结果之间差距。
  2. 找到最小化损失函数的W和b, CNN中用的算法是SGD(随机梯度下降)。

卷积神经网络之优缺点

​ 优点

  • 共享卷积核,对高维数据处理无压力

  • 无需手动选取特征,训练好权重,即得特征分类效果好

    缺点

  • 需要调参,需要大样本量,训练最好要GPU

  • 物理含义不明确(也就说,我们并不知道没个卷积层到底提取到的是什么特征,而且神经网络本身就是一种难以解释的“黑箱模型”)

卷积神经网络之典型CNN
  • LeNet,这是最早用于数字识别的CNN
  • AlexNet, 2012 ILSVRC比赛远超第2名的CNN,比
  • LeNet更深,用多层小卷积层叠加替换单大卷积层。
  • ZF Net, 2013 ILSVRC比赛冠军
  • GoogLeNet, 2014 ILSVRC比赛冠军
  • VGGNet, 2014 ILSVRC比赛中的模型,图像识别略差于GoogLeNet,但是在很多图像转化学习问题(比如object detection)上效果奇好
卷积神经网络之 fine-tuning

何谓fine-tuning?
fine-tuning就是使用已用于其他目标、预训练好模型的权重或者部分权重,作为初始值开始训练。

那为什么我们不用随机选取选几个数作为权重初始值?原因很简单,第一,自己从头训练卷积神经网络容易出现问题;第二,fine-tuning能很快收敛到一个较理想的状态,省时又省心。

那fine-tuning的具体做法是?

  • 复用相同层的权重,新定义层取随机权重初始值
  • 调大新定义层的的学习率,调小复用层学习率

卷积神经网络的常用框架

Caffe
  • 源于Berkeley的主流CV工具包,支持C++,python,matlab
  • Model Zoo中有大量预训练好的模型供使用
Torch
  • Facebook用的卷积神经网络工具包
  • 通过时域卷积的本地接口,使用非常直观
  • 定义新网络层简单
TensorFlow
  • Google的深度学习框架
  • TensorBoard可视化很方便
  • 数据和模型并行化好,速度快
总结

卷积网络在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间的精确的数学表达式,只要用已知的模式对卷积网络加以训练,网络就具有输入输出对之间的映射能力。

CNN一个非常重要的特点就是头重脚轻(越往输入权值越小,越往输出权值越多),呈现出一个倒三角的形态,这就很好地避免了BP神经网络中反向传播的时候梯度损失得太快。

卷积神经网络CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于CNN的特征检测层通过训练数据进行学习,所以在使用CNN时,避免了显式的特征抽取,而隐式地从训练数据中进行学习;再者由于同一特征映射面上的神经元权值相同,所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的一大优势。卷积神经网络以其局部权值共享的特殊结构在语音识别和图像处理方面有着独特的优越性,其布局更接近于实际的生物神经网络,权值共享降低了网络的复杂性,特别是多维输入向量的图像可以直接输入网络这一特点避免了特征提取和分类过程中数据重建的复杂度。

以下是我自己在学习CNN的时候遇到的一些困惑,以及查阅一些资料后得到的一些答案。
第一个问题:为什么不用BP神经网络去做呢?

1.全连接,权值太多,需要很多样本去训练,计算困难
  • 应对之道:减少权值的尝试,局部连接,权值共享

  卷积神经网络有两种神器可以降低参数数目。
  第一种神器叫做局部感知野,一般认为人对外界的认知是从局部到全局的,而图像的空间联系也是局部的像素联系较为紧密,而距离较远的像素相关性则较弱。因而,每个神经元其实没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。
  第二级神器,即权值共享。

这里写图片描述

2.边缘过渡不平滑
  • 应对之道:采样窗口彼此重叠这里写图片描述

第二个问题:LeNet里的隐层的神经元个数怎么确定呢?

它和原图像,也就是输入的大小(神经元个数)、滤波器的大小和滤波器在图像中的滑动步长都有关!

LeNet-5共有7层,不包含输入,每层都包含可训练参数(连接权重)。输入图像为32*32大小。这里写图片描述

例如,我的图像是1000x1000像素,而滤波器大小是10x10,假设滤波器没有重叠,也就是步长为10,这样隐层的神经元个数就是(1000x1000 )/ (10x10)=100x100个神经元了。

那重叠了怎么算?比如上面图的C2中28*28是如何得来的?这里的步长就是1,窗口大小是5*5,所以窗口滑动肯定发生了重叠。下图解释了28的由来。这里写图片描述

第三个问题:S2层是一个下采样层是干嘛用的?为什么是下采样?

也就是上面所说的池化层,只是叫法不同而已。这层利用图像局部相关性的原理,对图像进行子抽样,可以减少数据处理量同时保留有用信息,相当于图像压缩。

Keras简介

Keras是一个高层神经网络API,Keras由纯Python编写而成并基TensorflowTheano以及CNTK后端。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果,如果你有如下需求,请选择Keras:

  • 简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)

  • 支持CNN和RNN,或二者的结合

  • 无缝CPU和GPU切换

    一些基本概念:

    符号计算

    Keras的底层库使用Theano或TensorFlow,这两个库也称为Keras的后端。无论是Theano还是TensorFlow,都是一个“符号式”的库。

    因此,这也使得Keras的编程与传统的Python代码有所差别。笼统的说,符号主义的计算首先定义各种变量,然后建立一个“计算图”,计算图规定了各个变量之间的计算关系。建立好的计算图需要编译以确定其内部细节,然而,此时的计算图还是一个“空壳子”,里面没有任何实际的数据,只有当你把需要运算的输入放进去后,才能在整个模型中形成数据流,从而形成输出值。

    就像用管道搭建供水系统,当你在拼水管的时候,里面是没有水的。只有所有的管子都接完了,才能送水。

    Keras的模型搭建形式就是这种方法,在你搭建Keras模型完毕后,你的模型就是一个空壳子,只有实际生成可调用的函数后(K.function),输入数据,才会形成真正的数据流。

    使用计算图的语言,如Theano,以难以调试而闻名,当Keras的Debug进入Theano这个层次时,往往也令人头痛。没有经验的开发者很难直观的感受到计算图到底在干些什么。尽管很让人头痛,但大多数的深度学习框架使用的都是符号计算这一套方法,因为符号计算能够提供关键的计算优化、自动求导等功能。

    我们建议你在使用前稍微了解一下Theano或TensorFlow,Bing/Google一下即可。

    张量

    张量,或tensor,是本文档会经常出现的一个词汇,在此稍作解释。

    使用这个词汇的目的是为了表述统一,张量可以看作是向量、矩阵的自然推广,我们用张量来表示广泛的数据类型。

    规模最小的张量是0阶张量,即标量,也就是一个数。

    当我们把一些数有序的排列起来,就形成了1阶张量,也就是一个向量

    如果我们继续把一组向量有序的排列起来,就形成了2阶张量,也就是一个矩阵

    把矩阵摞起来,就是3阶张量,我们可以称为一个立方体,具有3个颜色通道的彩色图片就是一个这样的立方体

    把立方体摞起来,好吧这次我们真的没有给它起别名了,就叫4阶张量了,不要去试图想像4阶张量是什么样子,它就是个数学上的概念。

    张量的阶数有时候也称为维度,或者轴,轴这个词翻译自英文axis。譬如一个矩阵[[1,2],[3,4]],是一个2阶张量,有两个维度或轴,沿着第0个轴(为了与python的计数方式一致,本文档维度和轴从0算起)你看到的是[1,2],[3,4]两个向量,沿着第1个轴你看到的是[1,3],[2,4]两个向量。

    要理解“沿着某个轴”是什么意思,不妨试着运行一下下面的代码:

    import numpy as np
    
    a = np.array([[1,2],[3,4]])
    sum0 = np.sum(a, axis=0)
    sum1 = np.sum(a, axis=1)
    
    print sum0
    print sum1

    关于张量,目前知道这么多就足够了。事实上我也就知道这么多

    data_format

    这是一个无可奈何的问题,在如何表示一组彩色图片的问题上,Theano和TensorFlow发生了分歧,’th’模式,也即Theano模式会把100张RGB三通道的16×32(高为16宽为32)彩色图表示为下面这种形式(100,3,16,32),Caffe采取的也是这种方式。第0个维度是样本维,代表样本的数目,第1个维度是通道维,代表颜色通道数。后面两个就是高和宽了。这种theano风格的数据组织方法,称为“channels_first”,即通道维靠前。

    而TensorFlow,的表达形式是(100,16,32,3),即把通道维放在了最后,这种数据组织方式称为“channels_last”。

    Keras默认的数据组织形式在~/.keras/keras.json中规定,可查看该文件的image_data_format一项查看,也可在代码中通过K.image_data_format()函数返回,请在网络的训练和测试中保持维度顺序一致。

    唉,真是蛋疼,你们商量好不行吗?

    函数式模型

    函数式模型算是本文档比较原创的词汇了,所以这里要说一下

    在Keras 0.x中,模型其实有两种,一种叫Sequential,称为序贯模型,也就是单输入单输出,一条路通到底,层与层之间只有相邻关系,跨层连接统统没有。这种模型编译速度快,操作上也比较简单。第二种模型称为Graph,即图模型,这个模型支持多输入多输出,层与层之间想怎么连怎么连,但是编译速度慢。可以看到,Sequential其实是Graph的一个特殊情况。

    在Keras1和Keras2中,图模型被移除,而增加了了“functional model API”,这个东西,更加强调了Sequential是特殊情况这一点。一般的模型就称为Model,然后如果你要用简单的Sequential,OK,那还有一个快捷方式Sequential。

    由于functional model API在使用时利用的是“函数式编程”的风格,我们这里将其译为函数式模型。总而言之,只要这个东西接收一个或一些张量作为输入,然后输出的也是一个或一些张量,那不管它是什么鬼,统统都称作“模型”。

    batch

    这个概念与Keras无关,老实讲不应该出现在这里的,但是因为它频繁出现,而且不了解这个技术的话看函数说明会很头痛,这里还是简单说一下。

    深度学习的优化算法,说白了就是梯度下降。每次的参数更新有两种方式。

    第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这种方法每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习,这称为Batch gradient descent,批梯度下降。

    另一种,每看一个数据就算一下损失函数,然后求梯度更新参数,这个称为随机梯度下降,stochastic gradient descent。这个方法速度比较快,但是收敛性能不太好,可能在最优点附近晃来晃去,hit不到最优点。两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。

    为了克服两种方法的缺点,现在一般采用的是一种折中手段,mini-batch gradient decent,小批的梯度下降,这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,计算量也不是很大。

    基本上现在的梯度下降都是基于mini-batch的,所以Keras的模块中经常会出现batch_size,就是指这个。

    顺便说一句,Keras中用的优化器SGD是stochastic gradient descent的缩写,但不代表是一个样本就更新一回,还是基于mini-batch的。

    epochs

    真的不是很想解释这个词,但是新手问的还挺多的…… 简单说,epochs指的就是训练过程中数据将被“轮”多少次,就这样。

    对新手友好的小说明

    虽然这不是我们应该做的工作,但为了体现本教程对新手的友好,我们在这里简单列一下使用keras需要的先行知识。稍有经验的研究者或开发者请忽略本节,对于新手,我们建议在开始之前,确保你了解下面提到的术语的基本概念。如果你确实对某项内容不了解,请首先查阅相关资料,以免在未来使用中带来困惑。

    关于Python

    • 显然你应对Python有一定的熟悉,包括其基本语法,数据类型,语言特点等,如果你还不能使用Python进行程序设计,或不能避免Python中常见的一些小陷阱,或许你应该先去找个教程补充一下。这里推一个快速学习Python的教程廖雪峰的Python教程
    • 你应该有面向对象的概念,知道类、对象、封装、多态、继承、作用域等术语的含义。
    • 你应该对Python的科学计算包和深度学习包有一定了解,这些包包含但不限于numpy, scipy, scikit-learn, pandas…
    • 特别地,你需要了解什么是生成器函数(generator),以及如何编写生成器函数。什么是匿名函数(lambda)

    关于深度学习

    由于Keras是为深度学习设计的工具,我们这里只列举深度学习中的一些基本概念。请确保你对下面的概念有一定理解。

    • 有监督学习,无监督学习,分类,聚类,回归
    • 神经元模型,多层感知器,BP算法
    • 目标函数(损失函数),激活函数,梯度下降法
    • 全连接网络、卷积神经网络、递归神经网络
    • 训练集,测试集,交叉验证,欠拟合,过拟合
    • 数据规范化
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值