卷积神经网络组件之卷积&池化层

来源:互联网 发布:手机照度计算软件 编辑:程序博客网 时间:2024/06/05 19:28

前言

其实之前使用的bp前馈神经网络就是一个全连接神经网络,现在就是要把它封装成一个层。在卷积神经网络中会使用到。

卷积神经网路(CNN)

卷积神经网络也是一种前馈神经网络,相对于传统的神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现(摘自维基百科)。
怎么去解释和理解这句话呢?
之前实现的是一个全连接神经网络,也就是说每个神经元对应一个输入,当前层的输出就是下一层的输入。
之前的识别手写的代码也可以看到28*28维的小型图片输入层的神经元就要784个神经元,这一层就有784个w和b需要更新。假设我们的图片很大,1000*1000的,这图片也不是很少见。那么输入层的神经元多大上百万个。怎么办呢。针对上述这种情况这时候就有卷积神经网络。卷积神经网络有很多策略提高模型的准确性和和速度。

卷积层

在卷积神经网中必须有一个卷积层

问题引出

那么卷积层是用来干什么的呢?

回到我们之前我们的输入层每一个神经元对应一个像素点,那么像素点多了之后网络计算会爆炸。我们要思考一下难道我们每一像素点都是有用的么?这是否定的。因为一个像素点 实在是太小了。可以想象一下,你少一根头发丝你父母也还认识你的。甚至你脸上打了马赛克,你父母也是可以认识你的。所以我们人类认识事物会记住关键的特征,一些没有必要的特征信息,我们是不需要知道的。而我们的神经网络也应该如此。
image.png

如图,每个格子代表的是一个像素点。一个像素点相当于我们神经网络的输入。根据刚才的理论。
image.png

我们可以把这一块当作一个输入。
那么问题来了,九个像素点怎么当一个输入呢?加和?取最大值?都不是,而是卷积!

卷积

我们的目的是把图上的橙色矩形块变成一个数字!(初衷不要走歪了)

卷积核

我们的橙色矩形想要变成一个数字的话,是肯定需要一个函数的。我们定义这个函数为。
y=Ax+B
其中x就是橙色小块。y为转化后的输出。待定系数是A和B。
那么这个A就是卷积核。 对就是这样,学术界说的太高大上了。其实就是一个函数的待定系数。

卷积计算。

直接看图。我们定义我们的原始图像为。
image.png
卷积核为
image.png
计算方式
image.png

橙色矩形 变成一个输入实数!
y=1*1+1*0+1*1+0*1+1*1+1*0+1*0+0*0+1*1=4
那么输出
image.png
我们把结果矩阵叫做Feature map
动态图为
6.gif

我们可以明显的看到我们把一个5*5 的图像压缩到了3*3。这样压缩之后不是损失了精确度了么?恰好相反,我们需要计算机拥有模糊记忆能力。就算图像发生了形变,光照变化,都我们的结果都不产生影响。
所以一般卷积层会当作第一层把原始图像做一下卷积处理。提取特征。当然输入层到卷积层也可以需要激励函数。一般使用的是Relu激励函数。

池化层(Pooling Layer)

迟化层的目的跟卷积层几乎是一样的。
目的:
1、做特征提取。
2、减少数据处理量。
只不过它的 处理对象不再是原图像,而是我经过卷积后处理的feature map。

Max Pooling

就是字面意思。就是取一个“窗口”取最大值。
image.png
这样做了之后,我们的图像就又抽象了很多。也抛弃了很多像素点。

那么这样做完之后不是损失了很多么?这两层做完了之后我们肉眼根本看不出来图像成了什么鬼。但是对我们的正确性确实有利的!
原因之前也说了,我们现在的面孔与儿时有很大的变化,很久不见的远房亲戚也能认出来 你,这是为什么呢?这是因为其实有的特征根本就不重要。就好比如就算波多野结衣打上了马赛克,大家也照样能知道是谁一样。我们认识事物不是记得具体的事物,而是记住的是事物的模型。而这个模型的细微变化,只要在容忍范围内就不会对我们的认知产生影响。图像也是一样的,我们的图像Ga经过卷积 和池化处理之后Sa。如果图像Ga扭曲旋转得到新的图像Gb。我们会发现Gb图像的像素变化与Ga相比会很大。Gb但是经过卷积和迟化处理之后的Sb。Sa与Sb就相差不是很大。因为这两层做了相应的特征提取和细节上的过滤。

代码部分

#前言其实之前使用的bp前馈神经网络就是一个全连接神经网络,现在就是要把它封装成一个层。在卷积神经网络中会使用到。#卷积神经网路(CNN)卷积神经网络也是一种前馈神经网络,相对于传统的神经网络,它的人工神经元可以响应一部分**覆盖范围内**的周围单元,对于大型图像处理有出色表现(摘自维基百科)。怎么去解释和理解这句话呢?之前实现的是一个全连接神经网络,也就是说每个神经元对应一个输入,当前层的输出就是下一层的输入。之前的识别手写的代码也可以看到28*28维的小型图片输入层的神经元就要784个神经元,这一层就有784个w和b需要更新。假设我们的图片很大,1000*1000的,这图片也不是很少见。那么输入层的神经元多大上百万个。怎么办呢。针对上述这种情况这时候就有卷积神经网络。卷积神经网络有很多策略提高模型的准确性和和速度。#卷积层**在卷积神经网中必须有一个卷积层**##问题引出那么卷积层是用来干什么的呢?回到我们之前我们的输入层每一个神经元对应一个像素点,那么像素点多了之后网络计算会爆炸。我们要思考一下难道我们每一像素点都是有用的么?这是否定的。因为一个像素点 实在是太小了。可以想象一下,你少一根头发丝你父母也还认识你的。甚至你脸上打了马赛克,你父母也是可以认识你的。所以我们人类认识事物会记住关键的特征,一些没有必要的特征信息,我们是不需要知道的。而我们的神经网络也应该如此。![image.png](http://upload-images.jianshu.io/upload_images/9085642-8aad4f8fd7af3996.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)如图,每个格子代表的是一个像素点。一个像素点相当于我们神经网络的输入。根据刚才的理论。![image.png](http://upload-images.jianshu.io/upload_images/9085642-7e4dc79ec4a00ba6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)我们可以把这一块当作一个输入。那么问题来了,九个像素点怎么当一个输入呢?加和?取最大值?都不是,而是卷积!##卷积我们的目的是把图上的**橙色矩形块变成一个数字!**(初衷不要走歪了)###卷积核我们的橙色矩形想要变成一个数字的话,是肯定需要一个函数的。我们定义这个函数为。y=Ax+B其中x就是橙色小块。y为转化后的输出。待定系数是A和B。**那么**这个A就是卷积核。 对就是这样,学术界说的太高大上了。其实就是一个函数的待定系数。###卷积计算。直接看图。我们定义我们的原始图像为。![image.png](http://upload-images.jianshu.io/upload_images/9085642-07d713f7d64a69cf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)卷积核为![image.png](http://upload-images.jianshu.io/upload_images/9085642-a41b32a597e45540.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)计算方式![image.png](http://upload-images.jianshu.io/upload_images/9085642-09df4b78bae95b40.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)橙色矩形 变成一个输入实数!y=1*1+1*0+1*1+0*1+1*1+1*0+1*0+0*0+1*1=4那么输出![image.png](http://upload-images.jianshu.io/upload_images/9085642-21336ac48e236877.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)我们把结果矩阵叫做Feature map动态图为![6.gif](http://upload-images.jianshu.io/upload_images/9085642-eb6eab3dfde7fc71.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)我们可以明显的看到我们把一个5*5 的图像压缩到了3*3。这样压缩之后不是损失了精确度了么?恰好相反,我们需要计算机拥有模糊记忆能力。就算图像发生了形变,光照变化,都我们的结果都不产生影响。所以一般卷积层会当作第一层把原始图像做一下卷积处理。提取特征。当然输入层到卷积层也可以需要激励函数。一般使用的是Relu激励函数。#池化层(Pooling Layer)迟化层的目的跟卷积层几乎是一样的。目的:1、做特征提取。2、减少数据处理量。只不过它的 处理对象不再是原图像,而是我经过卷积后处理的feature map。##Max Pooling就是字面意思。就是取一个“窗口”取最大值。![image.png](http://upload-images.jianshu.io/upload_images/9085642-05778e8f905d8984.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)这样做了之后,我们的图像就又抽象了很多。也抛弃了很多像素点。那么这样做完之后不是损失了很多么?这两层做完了之后我们肉眼根本看不出来图像成了什么鬼。但是对我们的正确性确实有利的!原因之前也说了,我们现在的面孔与儿时有很大的变化,很久不见的远房亲戚也能认出来 你,这是为什么呢?这是因为其实有的特征根本就不重要。就好比如就算波多野结衣打上了马赛克,大家也照样能知道是谁一样。我们认识事物不是记得具体的事物,而是记住的是事物的模型。而这个模型的细微变化,只要在容忍范围内就不会对我们的认知产生影响。图像也是一样的,我们的图像Ga经过卷积 和池化处理之后Sa。如果图像Ga扭曲旋转得到新的图像Gb。我们会发现Gb图像的像素变化与Ga相比会很大。Gb但是经过卷积和迟化处理之后的Sb。Sa与Sb就相差不是很大。因为这两层做了相应的特征提取和细节上的过滤。#代码部分```python<div class="se-preview-section-delimiter"></div># -*- coding: utf-8 -*-<div class="se-preview-section-delimiter"></div># @Time    : 2017/12/3 上午10:55<div class="se-preview-section-delimiter"></div># @Author  : SkullFang<div class="se-preview-section-delimiter"></div># @Email   : yzhang.private@gmail.com<div class="se-preview-section-delimiter"></div># @File    : ConvPoolLayer.py<div class="se-preview-section-delimiter"></div># @Software: PyCharmimport numpy as npimport theanoimport theano.tensor as Tfrom theano.tensor import shared_randomstreamsfrom theano.tensor.nnet import sigmoidfrom theano.tensor.signal.pool import pool_2dfrom theano.tensor import nnetGPU=Falseif GPU:    print "Trying to run under a GPU"    try:        theano.config.device='gpu'    except:        pass    theano.config.floatX='float32'else:    print "Running with a Cpu"class ConvPoolLayer(object):    def __init__(self,filter_shape,image_shape,poolsize=(2,2),activation_fn=sigmoid):        """        卷积和池化        :param filter_shape: (filter的个数,输入的feature map的个数,filter的高,filter的宽)         :param image_shape: (filter的个数,输入的feature map的个数,图片高,图片宽)        :param poolsize:         :param activation:         """        self.filter_shape=filter_shape;        self.image_shape=image_shape;        self.poolsize=poolsize        self.activation_fn=activation_fn        #算出有多少个输出        #np.prod()算矩阵中的乘法 filter_shape[2:]那不就是feature map的高和宽么。        #因为feature map是池化层的输入。那么最终的输出就是除以窗口的大小。poolsize就是窗口的大小。        #filter[0]是feature_map的个数。        """        a=np.array([1,2,3,4])        np.prod(a)        24        np.prod(a[2:])        12        """        n_out=(filter_shape[0] * np.prod(filter_shape[2:]) / np.prod(poolsize))        #初始化卷积核        self.w = theano.shared(            np.asarray(                np.random.normal(loc=0, scale=np.sqrt(1.0 / n_out), size=filter_shape),                dtype=theano.config.floatX),            borrow=True)        self.b = theano.shared(            np.asarray(                np.random.normal(loc=0, scale=1.0, size=(filter_shape[0],)),                dtype=theano.config.floatX),            borrow=True)        self.params = [self.w, self.b]    def set_inpt(self, inpt, inpt_dropout, mini_batch_size):        self.inpt = inpt.reshape(self.image_shape)        conv_out = nnet.conv2d(            input=self.inpt, filters=self.w, filter_shape=self.filter_shape,            input_shape=self.image_shape)        pooled_out = pool_2d(            input=conv_out, ws=self.poolsize, ignore_border=True)        self.output = self.activation_fn(            pooled_out + self.b.dimshuffle('x', 0, 'x', 'x'))        self.output_dropout = self.output  # no dropout in the convolutional layersdef dropout_layer(layer, p_dropout):    srng = shared_randomstreams.RandomStreams(        np.random.RandomState(0).randint(999999))    mask = srng.binomial(n=1, p=1 - p_dropout, size=layer.shape)    return layer * T.cast(mask, theano.config.floatX)<div class="se-preview-section-delimiter"></div>

“`

原创粉丝点击