说明:这篇文章需要有一些相关的基础知识,否则看起来可能比较吃力。

1.卷积与神经元

1.1 什么是卷积?

简单来说,卷积(或内积)就是一种先把对应位置相乘然后再把结果相加的运算。(具体含义或者数学公式可以查阅相关资料)

如下图就表示卷积的运算过程:

(图1)

卷积运算一个重要的特点就是,通过卷积运算,可以使原信号特征增强,并且降低噪音.

1.2 激活函数

这里以常用的激活函数sigmoid为例:

把上述的计算结果269带入此公式,得出f(x)=1

1.3 神经元

如图是一个人工神经元的模型:

(图2)

对于每一个神经元,都包含以下几部分:

x:表示输入

w:表示权重

θ:表示偏置

∑wx:表示卷积(内积)

f :表示激活函数

o:表示输出

1.4 图像的滤波操作

对于一个灰度图片(图3) 用sobel算子(图4)进行过滤,将得到如图5所示的图片。

1.5小结

上面的内容主要是为了统一一下概念上的认识:

图1的蓝色部分、图2中的xn、图3的图像都是神经元的输入部分;图1的红色部分数值值、图2的wn值、图4的矩阵值都可以叫做权重(或者滤波器或者卷积核,下文统称权重)。而权重(或卷积核)的大小(如图4的3×3)叫做接受域(也叫感知野或者数据窗口,下文统称接受域)

2.卷积神经网络

在介绍卷积神经网络定义之前,先说几种比较流行的卷积神经网络的结构图。

2.1 常见的几种卷积神经网络结构图

(图6)

(图7)

(图8)

(图9)

图8中的C-层、S-层是6中的Convolutions层和subsampling层的简写,C-层是卷积层,S-层是子抽样和局部平均层。在图6和图7中C-层、S-层不是指具体的某 一个层,而是指输入层和特征映射层、特征映射层和特征映射层之间的计算过程,而特征映射层则保持的是卷积、子抽样(或下采样)和局部平均的输出结果。而图 6和图7的区别在于最终结果输出之前是否有全连接层,而有没有全连接层会影响到是否还需要一个扁平层(扁平层在卷积层和全连接层之间,作用是多维数据一维化)。

图9中CONV层是卷积层(即C-层),但是新出现的RELU层和POOL层是什么呢?RELU层其实是激活层(relu只是激活函数的一种,sigmoid/tanh比较常见于全连接层,relu常见于卷积层),为什么会多出来一个激活层呢?请看下图:

    

(图10)                                           (图2,方便对比复制了过来)

神经元的完整的数学建模应该是图10所示,与图2相比,把原来在一起的操作拆成了两个独立的操作:∑wx(卷积)和f(激活),因此多出了一个激活层。所以,在Keras中组建卷积神经网络的话,即可以采用如图2的方式(激活函数作为卷积函数的一个参数)也可采用图10所示的方式(卷积层和激活层分开)。激活层不需要参数。

Pool层,即池化层,其作用和S-层一样:进行子抽样然后再进行局部平均。它没有参数,起到降维的作用。将输入切分成不重叠的一些 n×n 区域。每一个区域就包含个值。从这个值计算出一个值。计算方法可以是求平均、取最大 max 等等。假设 n=2,那么4个输入变成一个输出。输出图像就是输入图像的1/4大小。若把2维的层展平成一维向量,后面可再连接一个全连接前向神经网络。

从图7可以看出,无论是卷积层还是池化层都可以叫做特征映射层,而两层之间的计算过程叫做卷积或者池化,但是这么表述容易在概念上产生混淆,所以本文不采用这种表述方式,只是拿来作为对比理解使用。

下面对上面的内容做一下总结:

卷积层(C-层或Convolutions层或CONV层或特征提取层,下文统称卷积层):主要作用就是进行特征提取。

池化层(S-层或子抽样局部平均层或下采样局部平均层或POOL层,下文统称池化层):主要作用是减小特征图,起到降维的作用。常用的方法是选取局部区域的最大值或者平均值。如下图所示:

(图11)

对于第一个卷积层来说(图6的C1-层),一个特征对应一个通道(或叫feature map或特征映射或者叫滤波器,下文统称特征映射),例如三原色(RGB)的图像就需要三个特征映射层。但是经过第一个池化层(图6的S2-层,PS:图中错标成了S1-层)之后,下一个特征提取层 (图6的C3-层)的特征映射 (feature map)个数并不一定与开始的相同了(图6中从8特征变成了20特征),一般情况下会比初始的特征映射个数多,因为根据视觉系统原理----底层的结构构成上层更抽象的结构,所以当前层的特征映射是上一层的特征映射的组合,也就是一个特征映射会对应上一层的一个或多个特征映射。

2.2 接受域和步长

2.2.1 接受域

(图12)

如图所示,中间的正方形都表示接受域,其大小为5*5。这里再重复一下:权重(卷积核)指的是数字,接受域指的是权重(卷积核)的大小。

2.2.2 步长

(图13)

接受域的对应范围从输入的区域1移到区域2的过程,或者从区域3移动到区域4都涉及到一个参数:步长,即每次移动的幅度。在此例中的步长可以表示成3或 者(3,3),单个3表示横纵坐标方向都移动3个坐标点,如果(3,2)则表示横向移动3个坐标点,纵向移动2个坐标点。每次移动是按一个方向移动,不是两个方向都移 动(图13中,从区域1移动到区域2、区域3,然后才移动到区域4,如果两个方向都移动三个坐标点则从区域1到了区域5,是不对的)。

2.3卷积神经网络

 2.3.1卷积神经网络定义

卷积神经网络是一个多层的神经网络,每层由多个二维平面(特征映射)组成,而每个平面由多个独立神经元组成。

2.3.2卷积神经网络特点

卷积神经网络是为识别二维形状而特殊设计的一个多层感知器,这种网络结构对二维形状的平移、比例缩放、倾斜或者共他形式的变形具有高度不变性。

卷积神经网络是前馈型网络。

 2.3.3 卷积神经网络的形式的约束

2.3.3.1 特征提取

每一个神经元从上一层的局部接受域得到突触输人,因而迫使它提取局部特征。一旦一个特征被提取出来,只要它相对于其他特征的位置被近似地保留下来,它的精确位置就变得没有那么重要了。

下图两个X虽然有点稍微变形,但是还是可以识别出来都是X。

(图14)

2.3.3.2 特征映射

网络的每一个计算层都是由多个特征映射组成的,每个特征映射都是平面形式的。平面中单独的神经元在约束下共享相同的突触权值集(权重),这种结构形式具有如下的有益效果:

a.平移不变性(图14的两个X)

b.自由参数数量的缩减(通过权值共享实现)

这里重点说下共享权值,以及卷积层神经单元个数的确定问题。

以图12的结构为基础,做以下假设:

假设一:输入范围在横纵方向与接受域正好是倍数关系

(图15)

先说没有接受域的情况,如果特征映射有9个神经元,这9个神经元与9*9的输入做全连接,那么需要的权重个数为9*9*9=729个。添加了接受域后,9个神经元 分别与接受域做链接,这种情况下如果一个神经元对应一组权重,则有9*9=81个权重值,再假如这一组权重的值是固定的(可参考图12的接受域值,这组值不变,而不是每个值相等),那么就只剩下了9个权重值。从729个权重值减少到9个权重值,这个过程就是权值共享的过程。也许从729减少到9个,差别不是特别大,如果输入是1000*1000,神经元个数是1000万呢?这样的话由权值共享导致的减少的计算量就很客观了。

假设二:输入范围在横纵方向与接受域不是是倍数关系

    

(图16 )                                                 (图17)

以图15为参考,只是把输入域变成图16所示的8*8的情况,若步长还是(3,3),那么横纵向各移动一次后就无法移动了,即接受域的可视范围为粉色边框内的6*6的区域(图16的粉红框A区域和B区域),外侧的2行2列的数据是读不到的。这种情况有两种处理方式,一是直接放弃,但是这种方式几乎不用,另外一种方式在周围补0(图17所示),使输入域变成(3,3)的倍数。

通过上述内容,可以知道每个特征映射的神经元的个数是由输入域大小、接受域、步长共同决定的。如图15,9*9的输入域、3*3的接受域、(3,3)的步长,可 以计算出特征映射的神经元个数为9个。

2.3.3.3 子抽样

每个卷积层后面跟着一个实现局部平均和子抽样的计算层(池化层),由此特征映射的分辨率降低。这种操作具有使特征映射的输出对平移和其他形式的变形 的敏感度下降的作用。

3.用Keras构建一个卷积神经网络

  3.1 卷积神经网络结构图

(图18)

3.2 Keras中的输入及权重

3.2.1 示例代码(小数字方便打印验证)

PS:Convolution2D 前最好加ZeroPadding2D,否则需要自己计算输入、kernel_size、strides三者之间的关系,如果不是倍数关系,会直接报错。

model = Sequential()

model.add(ZeroPadding2D((1, 1), batch_input_shape=(1, 4, 4, 1)))
model.add(Convolution2D(filters=1,kernel_size=(3,3),strides=(3,3), activation='relu', name='conv1_1'))
model.layers[1].get_weights() model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(filters=1,kernel_size=(2,3),strides=(2,3), activation='relu', name='conv1_2'))
model.layers[3].get_weights()

3.2.2 代码解释

1) batch_input_shape=(1, 4, 4, 1)

表示:输入1张1通道(或特征映射)的4*4的数据.因为我采用的是用Tensorflow做后端,所以采用“channels_last”数据格式。

2) filters = 1

表示:有1个通道(或特征映射)

3) kernel_size = (2,3)

表示:权重是2*3的矩阵

4) striders = (2,3)

表示:步长是(2,3)

3.2.3 权重(默认会初始化权重)

3.2.3.1 第一个model.layers[1].get_weights()输出(格式整理后)

(图19)

3.2.3.2 第二个model.layers[1].get_weights()输出

(图20)

3.2.3.3 另外两个输出(没有写的参数值同上)

1)batch_input_shape=(1, 4, 4, 3),filters = 1, kernel_size = (3,3)

(图21)

2) batch_input_shape=(1, 4, 4, 3),filters = 3, kernel_size = (2,3)

(图22)

3.2.4 小结

图19到图22的内容是为了说明在Keras中权重的表示方式,为下面的实验做准备。

通过以上参数得出的权重对比,当权重是二维矩阵(n*n)时:

1) [[[…]]]:表示横轴数目

2) [[…]]:表示纵轴数目

3) […]:表示通道的个数。图21和图22的区别:因为图22是3通道3filter,所以每个通道对应一个filter(图20),而图22相当于把3个图20合一起了。

4) […]内逗号隔开的数:filter的个数

5) [[[[…]]]]:这个可能代表层数(前面几个参数是平面的,这个参数是立体的。在下面的实验中没有得到具体验证,只是根据最外层是5个方括号推测的)

 3.3 sobel算子转化成权重

由3.2.4的结论,可以把图4的sobel算子转换成Keras中的权重:

weights = [[[[[-1]],[[0]],[[1]]],[[[-2]],[[0]],[[2]]],[[[-1]],[[0]],[[1]]]]]

weights =np.array(weights)

PS:注意最外围是5个方括号

 3.4 实验代码 

from PIL import Image
import numpy as np
from keras.models import Sequential
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.optimizers import SGD '''
第一步:读取图片数据
说明:这个过程需要安装pillow模块:pip install pillow
'''
##1张1通道的256*256的灰度图片
##data[0,0,0,0]:表示第一张图片的第一个通道的坐标为(0,0)的像素值
img_width, img_height = 256, 256
data = np.empty((1,1,img_width,img_height),dtype="float32")
##打开图片
img = Image.open("D:\\keras\\lena.jpg")
##把图片转换成数组形式
arr = np.asarray(img,dtype="float32")
data[0,:,:,:] = arr '''
第二步:设置权重
说明:注意最外围是5个方括号
'''
weights = [[[[[-1]],[[0]],[[1]]],[[[-2]],[[0]],[[2]]],[[[-1]],[[0]],[[1]]]]]
weights =np.array(weights) '''
第三步:组织卷积神经网络
说明:
1.因为实验采用的是默认的tensorflow后端,而输入图像是channels_first模式,所以注意data_format参数的设置
2.为了实验的效果,所以strides、pool_size等参数设置成了1
''' ##第一次卷积
model = Sequential()
model.add(ZeroPadding2D(padding=(2, 2), data_format='channels_first', batch_input_shape=(1, 1,img_width, img_height)))
model.add(Convolution2D(filters=1,kernel_size=(3,3),strides=(1,1), activation='relu', name='conv1_1', data_format='channels_first'))
model.set_weights(weights) ##第二次卷积
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(filters=1,kernel_size=(3,3),strides=(1,1), activation='relu', name='conv1_2',data_format='channels_first'))
model.set_weights(weights) ##池化操作
model.add(ZeroPadding2D((0, 0)))
model.add(MaxPooling2D(pool_size=1, strides=None,data_format='channels_first')) '''
第四步: 设置优化参数并编译网络
''' # 优化函数,设定学习率(lr)等参数
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
# 使用mse作为loss函数
model.compile(loss='mse', optimizer=sgd, class_mode='categorical') '''
第五步:预测结果
'''
result = model.predict(data,batch_size=1,verbose=0) '''
第六步:保存结果到图片
'''
img_new=Image.fromarray(result[0][0]).convert('L')
img_new.save("D:\\keras\\tt123.jpg")

3.5 实验效果

   

(图23)                                                               (图24)

图24是池化层参数改为pool_size=2时的效果。

深度学习:Keras入门(二)之卷积神经网络(CNN)的更多相关文章

  1. 深度学习:Keras入门(二)之卷积神经网络(CNN)【转】

    本文转载自:https://www.cnblogs.com/lc1217/p/7324935.html 说明:这篇文章需要有一些相关的基础知识,否则看起来可能比较吃力. 1.卷积与神经元 1.1 什么 ...

  2. 深度学习:Keras入门(二)之卷积神经网络(CNN)(转)

    转自http://www.cnblogs.com/lc1217/p/7324935.html 1.卷积与神经元 1.1 什么是卷积? 简单来说,卷积(或内积)就是一种先把对应位置相乘然后再把结果相加的 ...

  3. UFLDL深度学习笔记 (六)卷积神经网络

    UFLDL深度学习笔记 (六)卷积神经网络 1. 主要思路 "UFLDL 卷积神经网络"主要讲解了对大尺寸图像应用前面所讨论神经网络学习的方法,其中的变化有两条,第一,对大尺寸图像 ...

  4. 神经网络与深度学习笔记 Chapter 6之卷积神经网络

    深度学习 Introducing convolutional networks:卷积神经网络介绍 卷积神经网络中有三个基本的概念:局部感受野(local receptive fields), 共享权重 ...

  5. 深度学习方法(五):卷积神经网络CNN经典模型整理Lenet,Alexnet,Googlenet,VGG,Deep Residual Learning

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. 关于卷积神经网络CNN,网络和文献中 ...

  6. 深度学习基础-基于Numpy的卷积神经网络(CNN)实现

    本文是深度学习入门: 基于Python的实现.神经网络与深度学习(NNDL)以及动手学深度学习的读书笔记.本文将介绍基于Numpy的卷积神经网络(Convolutional Networks,CNN) ...

  7. 深度学习原理与框架-Tensorflow卷积神经网络-cifar10图片分类(代码) 1.tf.nn.lrn(局部响应归一化操作) 2.random.sample(在列表中随机选值) 3.tf.one_hot(对标签进行one_hot编码)

    1.tf.nn.lrn(pool_h1, 4, bias=1.0, alpha=0.001/9.0, beta=0.75) # 局部响应归一化,使用相同位置的前后的filter进行响应归一化操作 参数 ...

  8. 深度学习原理与框架-Tensorflow卷积神经网络-卷积神经网络mnist分类 1.tf.nn.conv2d(卷积操作) 2.tf.nn.max_pool(最大池化操作) 3.tf.nn.dropout(执行dropout操作) 4.tf.nn.softmax_cross_entropy_with_logits(交叉熵损失) 5.tf.truncated_normal(两个标准差内的正态分布)

    1. tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')  # 对数据进行卷积操作 参数说明:x表示输入数据,w表示卷积核, stride ...

  9. 深度学习原理与框架-Tensorflow卷积神经网络-神经网络mnist分类

    使用tensorflow构造神经网络用来进行mnist数据集的分类 相比与上一节讲到的逻辑回归,神经网络比逻辑回归多了隐藏层,同时在每一个线性变化后添加了relu作为激活函数, 神经网络使用的损失值为 ...

随机推荐

  1. ASP.NET MVC 重写RazorViewEngine实现多主题切换

    在ASP.NET MVC中来实现主题的切换一般有两种方式,一种是通过切换皮肤的css和js引用,一种就是通过重写试图引擎.通过重写试图引擎的方式更加灵活,因为我不仅可以在不同主题下面布局和样式不一样, ...

  2. JQuery——banner旋转木马效果

    博主在浏览网页时无意间发现了一种banner图的轮播方式--像旋转木马一样的轮播方式,博主感觉非常新颖独特,经过查阅资料,观看某课网教程总算搞了出来的,其原理主要利用了JQuery代码实现,好了不多说 ...

  3. 【操作教程】利用YCSB测试巨杉数据库性能

    一.前言 巨杉数据库(SequoiaDB)是国内第一款新一代文档型分布式数据库,巨杉数据库由巨杉软件完全自主研发,拥有完全自主知识产权,不基于任何其它的开源项目.SequoiaDB数据库是为分布式存储 ...

  4. maven(一) maven到底是个啥玩意~

    我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是自己悟性太低还是怎么滴,就是搞不清楚,现在弄清楚了,基本上入门了.写该篇博文,就是为了帮助那些和我一样对于maven迷迷糊糊的人. ...

  5. 简单总结几种常见web攻击手段及其防御方式

    web攻击手段有几种,本文简单介绍几种常见的攻击手段及其防御方式 XSS(跨站脚本攻击) CSRF(跨站请求伪造) SQL注入 DDOS XSS 概念 全称是跨站脚本攻击(Cross Site Scr ...

  6. Makefile学习总结

    Makefile用法分析     在linux开发中,应用程序的编译基本都采用GNU的make工具,而make搭配Makefile来实现工程代码的编译,在越是大型复杂的项目中,make的强悍之处越是明 ...

  7. sql相关

    case 函数 编写查询,按条件合并两列为一列(eg:我想从FullName或FirstName的列中找出不为空的雇员的名字) SELECT Name = CASE WHEN EMPLOYEE.Ful ...

  8. 是否使用安全模式启动word

          打开word,出现了一个提示,显示着“word遇到问题需要关闭.我们对此引起的不便表示抱歉.”下面有选项“恢复我的工作并重启word”,选中它.点下面的“不发送”.      在出现的提示 ...

  9. 一颗简单的hibernate栗子

    Hibernate是一个开源的ORM框架,顾名思义,它的核心思想即ORM(Object Relational Mapping,对象关系映射),可以通过对象来操作数据库中的信息,据说开发者一开始是不太熟 ...

  10. Java的基本数据类型和运算

    编码 ASCII--0~127  65-A  97-a 西欧码表---ISO-8859-1---0-255---1个字节 gb2312----0-65535---gbk---2个字节 Unicode编 ...