深度学习_卷积神经网络CNN

1. 引入

卷积神经网络(CNN)是一种专门用来处理具有网格结构数据的神经网络.它属于前馈神经网络,它被定义为:至少在某一层用卷积代替了矩阵乘法的神经网络.最常见的应用场景是图像识别.
前篇我们自己动手,用Python实现了一个BP神经网络,本篇我们在Keras框架之下实现卷积神经网络(Keras框架详见《深度学习_工具》篇).Keras几乎是搭建CNN最简单的工具了,然而原理并不简单:除了基本的神经网络中用的误差函数,激活函数等概念以外(具体详见《深度学习_BP神经网络》),CNN还用到了卷积,池化,DropOut等方法.将在本文中逐一介绍.

2. 原理

1) 图像识别

先来看看图形学中的图像识别是如何实现的.

图片.png

我们拿到了原图(图上左),一般先将其转换成灰度图(图上中).然后进行边缘检测,图像处理中常使用计算梯度方法(判断某像素与它相邻像素的差值)检测边缘.在CNN中我们用卷积来检测:先设计一个卷积核计算相邻像素的差值,然后用ReLU(f(x)=max(0,x))激活函数将那些差值小的置为0,即识别为非边缘(看到激活函数的厉害了吧,它把低于阈值的都扔掉了,这可是一般线性变换做不到的).于是得到了边缘图(图上右).处理后的图像是个稀疏的矩阵(多数点值都为0).
¬为了简化计算,我们希望将图片缩小,但在缩放的过程中,细的边缘线就会被弱化,甚至消失(图下左).在CNN中用池化解决这一问题,如果把3*3个点缩放到1点,”最大池化”会将这9个点中最大的值,作为新点的值,于是无论强边缘还是弱边缘都被保留了下来(图下右).
边缘检测只是图像识别的第一步,之后还将识别一些更上层的特征,比如拐角,车轮,汽车的轮廓等等,它们都可由卷积实现.越往后的层越抽象,最终一个神经网络模型建起来和图像处理中的"金字塔"有类似的结构,虽然下层的每个点都是局部的,但是上层的点具有全局性.

2) 卷积

下面来看看卷积到底是什么,它与之前学习的全连接神经网络有什么不同.
卷积定义是:通过两个函数f 和g 生成第三个函数的一种数学算子.呵呵,很抽象啊,形象地说,处理图像时,卷积就好像拿着一小块滤镜,把图像从左到右,从上到下,一格一格地扫一遍,如果在滤镜中看到想要的,就在下一层做个标记.看看下图就明白了.

(图片引自《深度学习》”花书”)

图中是一个二维平面上的卷积运算,输入是一个4x3的矩阵,卷积核(Kernel)是2x2的矩阵,输出是一个3x2的矩阵(卷积不都是2维的).这就是卷积——一种特殊的线性运算,考虑以下几种情况:
如果上图中的w,x,y,z都为0.25,则该卷积实现了均值运算(图片的模糊处理)
如果上图中w+x+y+z=1,则该卷积实现了实现了加权平均.
这个运算是不是有点眼熟,如果把Input中各点排着一列,把Kernel看成权值参数,则它是一个神经网络的连接.输入层有12个元素,隐藏层1有6个元素(先不管其它层)

卷积网络与全连接网络

如图所示,左则是卷积层,右则是全连接的神经网络,全连接时,共有126=72个连接(输入输出),72种权值;而卷积层只有24个连接(核大小*输出),4个权值w,x,y,z,分别用四种颜色标出.此处,引出了两个概念:
共享权值(参数共享):共享权值就是多个连接使用同一权值,卷积神经网络中共享的权值就是卷积核的内容,这样不但减小了学习难度.还带来的”平移等变”的性质,比如集体合影中每张脸都可以使用相同的卷积核(一组权值)识别出来,无论它在图中的什么位置,这样学习一张脸后,就能对每张脸应用相同的处理了.此技术多用于同一状态重复出现的情况下.(若图中只有一张脸,脸相关的卷积核共享作用就不大了)
全连接,局部连接与卷积:全连接就是上一层的每个点都与下一层的每个点连接,每个连接都有其自已的权值;局部连接是只有部分点相互连续;卷积是在局部连续的基础上又共享了权值.
卷积核可以是指定的,也可以是用梯度向前推出来的,可以是聚类算出来的(无监督学习),还可以先取一小块训练,然后用这小块训练的结果定义卷积的核.这取决于我们设计的不同算法.
由此可见,卷积层是两层之间的连接方法,与全连接相比,它大大简化了运算的复杂度,还节省了存储空间.之所以能这样简化是因为图像中距离越近的点关系越大(序列处理也同理:离得越近关系越大).

3) 池化

池化是使用某一位置的相邻输出的总体统计特征来代替网络在该位置的输出,和卷积差不多,它也是层到层之间的运算,经过池化处理,层中节点可能不变,也可能变小(常用它降采样,以减少计算量).
最大池化就是将相邻的N个点作为输入,将其中最大的值输出到下一层.除了最大池化,池化算法还有:取平均值,加权平均等等.
池化具有平移不变性:若对图片进行少量平移,经过池化函数后的大多数输出并不会发生改变,比如最大池化,移动一像素后,区域中最大的值可能仍在该区域内.
同理,在一个稀疏的矩阵中(不一定是图像),假设对n点做最大池化,那么只要其中有一点非0,则池化结果非0.如下图所示,只要手写数据5符合其中一个判断标准,则将其识别为数字5.

(图片引用自《深度学习》"花书")

池化还经常用于处理不同尺寸的图片:比如有800x600和200*150两张图,想对它们做同一处理,可通过设定池化的输出为100x75来实现保留特征的缩放,以至扩展到任意大小的图片.
基本上卷积网络都用使用池化操作.

4) DropOut

再举个例子,现在我们来识别老鼠,一般老鼠都有两只耳朵,两只眼睛,一个鼻子和一个嘴,它们有各自的形状且都是从上到下排列的.如果严格按照这个规则,那么"一只耳"就不会被识别成老鼠.
为提高鲁棒性,使用了DropOut方法.它随机地去掉神经网络中的一些点,用剩余的点训练,假设有一些训练集中的老鼠,被去掉的正是耳朵部分,那么"一只耳"最终也可能由于其它特征都对而被识别.
除了提高鲁棒性,DropOut还有其它一些优点,比如在卷积神经网络中,由于共享参数,我们训练一小部分的子网络(由DropOut剪出),参数共享会使得剩余的子网络也能有同样好的参数设定。保证学习效果的同时,也大大减少了计算量.
DropOut就如同在层与层之间故意加入了一些噪声,虽然避免了过拟合,但它是一个有损的算法,小的网络使用它可能会丢失一些有用的信息.一般在较大型的网络中使用DropOut.

5) 总结

卷积,池化,DropOut都是设计者根据数据的性质,采取的对全连接网络的优化和简化,虽然它们都是有损的,但是对计算和存储的优化也非常明显,使我们有机会将神经网络扩展到成百上千层.

3. 代码

1) 说明

代码的主要功能是根据Mnist库的图像数据训练手写数字识别.核心代码在后半部分,它使用了卷积层,池化层,Dropout层,Flatten层,和全连接层.

2) 代码

(为了让大家复制粘贴就能运行,还是附上了全部代码)

# -*- coding: utf-8 -*-
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

batch_size = 128 # 批尺寸
num_classes = 10 # 0-9十个数字对应10个分类
epochs = 12 # 训练12次

# input image dimensions
img_rows, img_cols = 28, 28 # 训练图片大小28x28

# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# 下面model相关的是关键部分
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), #加卷积层,核大小3x3,输出维度32
                 activation='relu', #激活函数为relu
                 input_shape=input_shape)) #传入数据
model.add(Conv2D(64, (3, 3), activation='relu')) #又加一个卷积层
model.add(MaxPooling2D(pool_size=(2, 2))) # 以2x2为一块池化
model.add(Dropout(0.25)) # 随机断开25%的连接
model.add(Flatten()) # 扁平化,例如将28x28x1变为784的格式
model.add(Dense(128, activation='relu')) # 加入全连接层
model.add(Dropout(0.5)) # 再加一层Dropout
model.add(Dense(num_classes, activation='softmax')) # 加入到输出层的全连接

model.compile(loss=keras.losses.categorical_crossentropy, # 设损失函数
              optimizer=keras.optimizers.Adadelta(), # 设学习率
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size, # 设批大小
          epochs=epochs, # 设学习次数
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0) # 用测试集评测
print('Test loss:', score[0])
print('Test accuracy:', score[1])

4. CNN的历史

看CNN的发展,从1998年LeCun的经典之作LeNet, 到将ImageNet图像识别率提高了10个百分点的AlexNet, VGG(加入更多卷积层), GoogleNet(使用了Inception一种网中网的结构), 再到RssNet(使用残差网络),ImageNet的Top-5错误率已经降到3.57%,低于人眼识别的错误率5.1%,并且仍在不断进步.这些不断提高的成绩以及在更多领域的应用让神经变得越来越热门.

从图中可见,从AlexNet的3层全连接神经网络,到ResNet的152层神经网络,全连接层越来越少,卷积层越来越多.除了算法的进步,人的知识也越来越多越来越细化地溶入了神经网络.

5. 参考

  1. CNN的发展史
    http://www.cnblogs.com/52machinelearning/p/5821591.html
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 本系列文章面向深度学习研发者,希望通过Image Caption Generation,一个有意思的具体任务,深入...
    imGeek阅读 2,659评论 1 33
  • 原文地址:http://www.jianshu.com/p/1c9daf19b0d9更多机器学习、深度学习笔记(含...
    Doit_行之阅读 2,293评论 0 18
  • 离自然和上帝最近的灵魂,美到极致,美到让人停下来欣赏,透过欣赏,流露出生命真实的状态,自然而来,自然而走,以赤子...
    郭相麟阅读 222评论 0 0
  • 普希金 透过一层轻纱似的薄雾 月亮洒下了它的幽光 它凄清的照着一片林木 照在林边荒凉的野地上 在枯索的科天的道上 ...
    Freesia阅读 247评论 0 0
  • 中午出去吃饭的时候,楼下面送外卖的大叔在打电话,带着哭腔,说你赶紧下来取一下,我送了三家都找错地方,快没有时间了,...
    骆驼小姐阅读 170评论 0 0