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

前言

其实之前使用的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

如图,每个格子代表的是一个像素点。一个像素点相当于我们神经网络的输入。根据刚才的理论。
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就相差不是很大。因为这两层做了相应的特征提取和细节上的过滤。

代码部分

# -*- coding: utf-8 -*-
# @Time    : 2017/12/3 上午10:55
# @Author  : SkullFang
# @Email   : yzhang.private@gmail.com
# @File    : ConvPoolLayer.py
# @Software: PyCharm
import numpy as np
import theano
import theano.tensor as T
from theano.tensor import shared_randomstreams
from theano.tensor.nnet import sigmoid
from theano.tensor.signal.pool import pool_2d
from theano.tensor import nnet

GPU=False
if 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 layers


def 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)

“`

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值