从此明白了卷积神经网络(CNN)

卷积神经网络是一种曾经让我无论如何也无法弄明白的东西,主要是名字就太“高级”了,网上的各种各样的文章来介绍“什么是卷积”尤为让人受不了。听了吴恩达的网课之后,豁然开朗,终于搞明白了这个东西是什么和为什么。我这里大概会用6~7篇文章来讲解CNN并实现一些有趣的应用。看完之后大家应该可以自己动手做一些自己喜欢的事儿了。

一、引子:边界检测

我们来看一个最简单的例子:“边界检测(edge detection)”,假设我们有这样的一张图片,大小8×8:

图片

图片中的数字代表该位置的像素值,我们知道,像素值越大,颜色越亮,所以为了示意,我们把右边小像素的地方画成深色。图的中间两个颜色的分界线就是我们要检测的边界。

怎么检测这个边界呢?我们可以设计这样的一个 滤波器(filter,也称为kernel),大小3×3:

图片

然后,我们用这个filter,往我们的图片上“盖”,覆盖一块跟filter一样大的区域之后,对应元素相乘,然后求和。计算一个区域之后,就向其他区域挪动,接着计算,直到把原图片的每一个角落都覆盖到了为止。这个过程就是 “卷积”
(我们不用管卷积在数学上到底是指什么运算,我们只用知道在CNN中是怎么计算的。)
这里的“挪动”,就涉及到一个步长了,假如我们的步长是1,那么覆盖了一个地方之后,就挪一格,容易知道,总共可以覆盖6×6个不同的区域。

那么,我们将这6×6个区域的卷积结果,拼成一个矩阵:

图片

诶?!发现了什么?
这个图片,中间颜色浅,两边颜色深,这说明咱们的原图片中间的边界,在这里被反映出来了!

从上面这个例子中,我们发现,我们可以通过设计特定的filter,让它去跟图片做卷积,就可以识别出图片中的某些特征,比如边界。
上面的例子是检测竖直边界,我们也可以设计出检测水平边界的,只用把刚刚的filter旋转90°即可。对于其他的特征,理论上只要我们经过精细的设计,总是可以设计出合适的filter的。

我们的CNN(convolutional neural network),主要就是通过一个个的filter,不断地提取特征,从局部的特征到总体的特征,从而进行图像识别等等功能。

那么问题来了,我们怎么可能去设计这么多各种各样的filter呀?首先,我们都不一定清楚对于一大推图片,我们需要识别哪些特征,其次,就算知道了有哪些特征,想真的去设计出对应的filter,恐怕也并非易事,要知道,特征的数量可能是成千上万的。

其实学过神经网络之后,我们就知道,这些filter,根本就不用我们去设计,每个filter中的各个数字,不就是参数吗,我们可以通过大量的数据,来 让机器自己去“学习”这些参数嘛。这,就是CNN的原理。

二、CNN的基本概念

1.padding 填白
从上面的引子中,我们可以知道,原图像在经过filter卷积之后,变小了,从(8,8)变成了(6,6)。假设我们再卷一次,那大小就变成了(4,4)了。

这样有啥问题呢?
主要有两个问题:

  • 每次卷积,图像都缩小,这样卷不了几次就没了;

  • 相比于图片中间的点,图片边缘的点在卷积中被计算的次数很少。这样的话,边缘的信息就易于丢失。

为了解决这个问题,我们可以采用padding的方法。我们每次卷积前,先给图片周围都补一圈空白,让卷积之后图片跟原来一样大,同时,原来的边缘也被计算了更多次。

图片

比如,我们把(8,8)的图片给补成(10,10),那么经过(3,3)的filter之后,就是(8,8),没有变。

我们把上面这种“让卷积之后的大小不变”的padding方式,称为 “Same”方式,
把不经过任何填白的,称为 “Valid”方式。这个是我们在使用一些框架的时候,需要设置的超参数。

2.stride 步长
前面我们所介绍的卷积,都是默认步长是1,但实际上,我们可以设置步长为其他的值。
比如,对于(8,8)的输入,我们用(3,3)的filter,
如果stride=1,则输出为(6,6);
如果stride=2,则输出为(3,3);(这里例子举得不大好,除不断就向下取整)

3.pooling 池化
这个pooling,是为了提取一定区域的主要特征,并减少参数数量,防止模型过拟合。
比如下面的MaxPooling,采用了一个2×2的窗口,并取stride=2:

图片

除了MaxPooling,还有AveragePooling,顾名思义就是取那个区域的平均值。

4.对多通道(channels)图片的卷(重要!)
这个需要单独提一下。彩色图像,一般都是RGB三个通道(channel)的,因此输入数据的维度一般有三个:(长,宽,通道)
比如一个28×28的RGB图片,维度就是(28,28,3)。

前面的引子中,输入图片是2维的(8,8),filter是(3,3),输出也是2维的(6,6)。

如果输入图片是三维的呢(即增多了一个channels),比如是(8,8,3),这个时候,我们的filter的维度就要变成(3,3,3)了,它的 最后一维要跟输入的channel维度一致。
这个时候的卷积,是三个channel的所有元素对应相乘后求和,也就是之前是9个乘积的和,现在是27个乘积的和。因此,输出的维度并不会变化。还是(6,6)。

但是,一般情况下,我们会 使用多了filters同时卷积,比如,如果我们同时使用4个filter的话,那么 输出的维度则会变为(6,6,4)

我特地画了下面这个图,来展示上面的过程:

图片

图中的输入图像是(8,8,3),filter有4个,大小均为(3,3,3),得到的输出为(6,6,4)。
我觉得这个图已经画的很清晰了,而且给出了3和4这个两个关键数字是怎么来的,所以我就不啰嗦了(这个图画了我起码40分钟)。

其实,如果套用我们前面学过的神经网络的符号来看待CNN的话,

  • 我们的输入图片就是X,shape=(8,8,3);

  • 4个filters其实就是第一层神金网络的参数W1,,shape=(3,3,3,4),这个4是指有4个filters;

  • 我们的输出,就是Z1,shape=(6,6,4);

  • 后面其实还应该有一个激活函数,比如relu,经过激活后,Z1变为A1,shape=(6,6,4);

所以,在前面的图中,我加一个激活函数,给对应的部分标上符号,就是这样的:

图片

【个人觉得,这么好的图不收藏,真的是可惜了】

三、CNN的结构组成

上面我们已经知道了卷积(convolution)、池化(pooling)以及填白(padding)是怎么进行的,接下来我们就来看看CNN的整体结构,它包含了3种层(layer):

1. Convolutional layer(卷积层—CONV)
由滤波器filters和激活函数构成。
一般要设置的超参数包括filters的数量、大小、步长,以及padding是“valid”还是“same”。当然,还包括选择什么激活函数。

2. Pooling layer (池化层—POOL)
这里里面没有参数需要我们学习,因为这里里面的参数都是我们设置好了,要么是Maxpooling,要么是Averagepooling。
需要指定的超参数,包括是Max还是average,窗口大小以及步长。
通常,我们使用的比较多的是Maxpooling,而且一般取大小为(2,2)步长为2的filter,这样,经过pooling之后,输入的长宽都会缩小2倍,channels不变。

3. Fully Connected layer(全连接层—FC)
这个前面没有讲,是因为这个就是我们最熟悉的家伙,就是我们之前学的神经网络中的那种最普通的层,就是一排神经元。因为这一层是每一个单元都和前一层的每一个单元相连接,所以称之为“全连接”。
这里要指定的超参数,无非就是神经元的数量,以及激活函数。

接下来,我们随便看一个CNN的模样,来获取对CNN的一些感性认识:

图片

上面这个CNN是我随便拍脑门想的一个。它的结构可以用:
X→CONV(relu)→MAXPOOL→CONV(relu)→FC(relu)→FC(softmax)→Y
来表示。

这里需要说明的是,在经过数次卷积和池化之后,我们 最后会先将多维的数据进行“扁平化”,也就是把 (height,width,channel)的数据压缩成长度为 height × width × channel 的一维数组,然后再与 FC层连接,这之后就跟普通的神经网络无异了

可以从图中看到,随着网络的深入,我们的图像(严格来说中间的那些不能叫图像了,但是为了方便,还是这样说吧)越来越小,但是channels却越来越大了。在图中的表示就是长方体面对我们的面积越来越小,但是长度却越来越长了。

四、卷积神经网络 VS. 传统神经网络

其实现在回过头来看,CNN跟我们之前学习的神经网络,也没有很大的差别。
传统的神经网络,其实就是多个FC层叠加起来
CNN,无非就是把FC改成了CONV和POOL,就是把传统的由一个个神经元组成的layer,变成了由filters组成的layer。

那么,为什么要这样变?有什么好处?
具体说来有两点:

1.参数共享机制(parameters sharing)
我们对比一下传统神经网络的层和由filters构成的CONV层:
假设我们的图像是8×8大小,也就是64个像素,假设我们用一个有9个单元的全连接层:

图片

那这一层我们需要多少个参数呢?需要 64×9 = 576个参数(先不考虑偏置项b)。因为每一个链接都需要一个权重w。

那我们看看 同样有9个单元的filter是怎么样的:

图片

其实不用看就知道,有几个单元就几个参数,所以总共就9个参数

因为,对于不同的区域,我们都共享同一个filter,因此就共享这同一组参数。
这也是有道理的,通过前面的讲解我们知道,filter是用来检测特征的,那一个特征一般情况下很可能在不止一个地方出现,比如“竖直边界”,就可能在一幅图中多出出现,那么 我们共享同一个filter不仅是合理的,而且是应该这么做的。

由此可见,参数共享机制,让我们的网络的参数数量大大地减少。这样,我们可以用较少的参数,训练出更加好的模型,典型的事半功倍,而且可以有效地 避免过拟合
同样,由于filter的参数共享,即使图片进行了一定的平移操作,我们照样可以识别出特征,这叫做 “平移不变性”。因此,模型就更加稳健了。

2.连接的稀疏性(sparsity of connections)
由卷积的操作可知,输出图像中的任何一个单元,只跟输入图像的一部分有关系:

图片

而传统神经网络中,由于都是全连接,所以输出的任何一个单元,都要受输入的所有的单元的影响。这样无形中会对图像的识别效果大打折扣。比较,每一个区域都有自己的专属特征,我们不希望它受到其他区域的影响。

正是由于上面这两大优势,使得CNN超越了传统的NN,开启了神经网络的新时代

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432021.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 输入子系统原理理解(原创)

linux 输入子系统原理理解(原创) 以前学了单独的按键设备驱动以及鼠标驱动,实际上,在linux中实现这些设备驱动,有一种更为推荐的方法,就是input输入子系统。平常我们的按键,触摸屏&#xff0…

Logistic Regression:最基础的神经网络

一、什么是logictic regression 下面的图是Andrew Ng提供的一个用logistic regression来识别主子的图片的算法结构示意图: 「左边」的「x0到x12287「是输入(input),我们称之为」特征(feather)」&#xff0…

Win7和Ubuntu14.10双系统

一、Wubi 本来是拿wubi安装的。步骤简单,装卸方便。就是失败了。。。 下载好镜像后解压一份,将wubi.exe复制出一份放在和镜像同目录下(目录要全英)。断网,运行wubi.exe按照提示安装。这里这篇教程挺好,之后…

LateX 笔记

y \frac{a}{b} y A_aA_{bb} y a\times{b} y \arctan{(x)} \pi y x^2

OpenDrive ARC绘制秘籍

加和减代表曲率的正负

mysql中char与varchar的区别分析

原文网址:http://www.jb51.net/article/23575.htm mysql中char与varchar的区别分析 作者: 字体:[增加 减小] 类型:转载在mysql教程中char与varchar的区别呢,都是用来存储字符串的,只是他们的保存方式不一样…

3W+字的设计模式手册

设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分别为创建型模式、结构型模式和行为型模式。…

datagridview 当前上下文中不存在bind_全面解析JavaScript中this指向问题

this指向参考文章:* thisJavaScript中this指向分为以下几种情况:普通函数或作为对象属性事件绑定构造函数箭头函数call/apply/bind指定下面我们来进行一一介绍普通函数或作为对象属性this取决于方法执行前面是否有“点”,有“点”的话&#x…

Unity Scene为每一个游戏物体进行扩展编辑

2个月前还在忙碌的找实习工作,看见招聘信息上面有一条熟悉扩展Unity编辑器,配合美工编程. 自己动手写完这个代码时候,发现写代码就像弹钢琴多么神奇. TestEdit类: using UnityEngine; using System.Collections; using UnityEditor;[CustomEditor(typeof(Test))] public class …

esmini LongSpeedAction修改

esmini的LongSpeedAction,如果shape设置为step的话,DynamicsDimension实际就无效了, 因为step的意思就是直接设置,在LongSpeedAction的Start过程中设置完就结束了,Step就不在 执行。 如果我们在step的情况下&#x…

cc2530i2c可同时接受两个传感器的数据吗_汽车方向及维修_玉树沃尔沃S40方向机,宝马531电子方向机进水可以维修吗...

产品品牌:徐州永诚汽车方向及维修公司产品单价:最小起订:23供货总量:2交货期限:13发货城市:徐州玉树沃尔沃S40方向机,宝马531电子方向机进水可以维修吗 [qadxfh3k]凭以往的经验,像这种多个控制模…

Android项目实战视频教程_快递轨迹查询应用开发

基于Android平台的快递轨迹查询应用开发全程实录(MenuDrawer、DbUtils、HttpUtils、讯飞语音识别)课程分类:Android适合人群:中级课时数量:10(17节)课时用到技术:MenuDrawer、DbUtils、HttpUtils、讯飞语音…

OpenXLSX 字段读取问题

在读取excel的时候发现有些字段无法读取,通过把excel文件解压后对比发现,正常读取和不 能正常读取的字段在sharedString.xml中存储的格式有差异,取其中一个字段,如下图: 正常读取的 不能读取的 对比可以看到其区别&a…

六西格玛dfss_六西格玛系列知识之二:六西格玛管理的基本原理

六西格玛管理是一系统,其系统性体现在它既提出了面向产品和服务设计开发的六西格玛设计,又提出了面向流程、产品制造、服务提供的六西格玛改进方法。从当前的情况来看,六西格玛设计(DFSS)项目推进尚未形成统一的或得到…

XCode5.1.1怎样实现代码块自己主动排版

1.问题描写叙述 在开发中常常遇到代码块须要排版的情况,假设一行一行缩进就太out了,但在xcode中怎样实现还真不知道2.解决方法 2.1选中须要排版的代码块 2.2单击"Editor | Structure | Re-Indent"菜单项 2.3看看是不是已经得到想要的结果了&am…

数据库监控[Z]

--查看表锁 select * from sys.v_$sqlarea where disk_reads>100--监控事例的等待 select event,sum(decode(wait_Time,0,0,1)) "Prev", sum(decode(wait_Time,0,1,0)) "Curr",count(*) "Tot"from v$session_Wait group by event order by 4 …

Could NOT find XXX (missing: XXX_LIBRARY XXX_DIR)

有时候从github上下载一些新的包编译时经常会缺少一些插件或库文件,比如 Could NOT find Bullet (missing: BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY BULLET_SOFTBODY_LIBRARY BULLET_INCLUDE_DIR) 或者 Could NOT find SDL (miss…

minheight能继承吗_民法典亮点盘点 | 侄子能继承叔叔的遗产吗?

2020年5月28日,十三届全国人大三次会议表决通过了《中华人民共和国民法典》,《民法典》将于2021年1月1日起施行。《民法典》共7编,依次为:总则编、物权编、合同编、人格权编、婚姻家庭编、继承编、侵权责任编,以及附则…

多C++标准版本指定

本文主要介绍 CMake 中 include 指令的相关知识。 1 概述 引用 CMake 官网对于 include 指令的介绍&#xff0c;如下&#xff1a; Load and run CMake code from a file or module. include 指令的用法如下&#xff1a; include(<file|module> [OPTIONAL] [RESULT_VA…

STL容器存储的内容动态分配情况下的内存管理

主要分两种情况&#xff1a;存储的内容是指针&#xff1b;存储的内容是实际对象。 看以下两段代码&#xff0c; typedef pair<VirObjTYPE, std::list<CheckID>*> VirObj_CheckID_pair;class LangChecker{public: LangChecker(); ~LangChecker(); voi…