卷积核
在滑动过程中提取特征 卷积核的表达式:

这个和普通线性分类器看起来是一样的。
卷积核的工作原理

这是一个(5,5) 一共25个像素点的图片。每个像素点只有两个取值0或1
我们设置的卷积核的w和b:

黄色部分是一个(3,3)九个像素的小方框。从左到右,从上到下的与w完成内积,
最后再与b相加。

前面是w和当前黄色窗口的9个值的内积。计算结果是6,左上角这个黄色小方框经过卷积核的作用变成了6.
这个小的(6,6)的存储空间被我们称为卷积层的feature map
九个点信息被压缩到一个点,这肯定是一种有损压缩,而且无法还原回去。
这是一个信息抽象的过程,被我们从称作特征提取。
25个点的信息就会被为我们压缩成9个点。这就是特征提取以及压缩。
怎么学习这个w和b就与我们之前的BP网络一样了。初始化w和b经过一轮一轮的训练,目的就是为了降低损失函数的损失值,从而w和b不断的变化,最后学习到我们想要的w和b。
wx+b输出一般还会带一个激励函数。cnn中常用的Relu函数。或者直接不用激励函数,或者用其他激励函数。理由:
通常是为了一些特殊场景有好的表现,会采用别的激励函数,或者不采用激励函数。
卷积核中的w和b是通过训练得出来的,它是模型中非常重要的参数。
如果我们从物理意义上去理解就是我们输入了一个向量,可能是一张图片,我们用眼睛扫一眼,实际对于这张图片各个区域的关注度和采纳程度是不同的。
而这个关注程度和采纳程度就可以用w和b进行描述。
卷积层里的其他参数
padding: 用多少个像素单位来填充输入图片(向量)的边界
Striding: 每次滑动的单位

蓝色的这一圈被我们称padding。通常使用0值填充。实际中padding不会那么大。
800px paddding五个单位就很可以了。
保持图片的边缘信息: 如果不加padding的话,周围的这一圈只被卷积核扫了一遍。
而图像中间的会被扫多遍。加上padding就可以解决。
用途2: 输入图片尺寸有差异,我们可以采用padding补齐,使得输入图片的尺寸,保持一致。
在卷积层工作的时候striding可以理解为每次滑动的单位,

每次移动一个单位,striding设为1,保证细腻程度最好。
striding大可以获得性能提升,扫描的次数少了。
池化层(Pooling Layer)
池层, 是在一些cnn网络中非常喜欢设计的一个处理层。
实际是对feature map的处理数据进行了一次池化处理。
常见的池化层处理有两种:
- Max Poolong:最大化处理,在前面输入的数据中取最大值。
(2,2)滤波器将stride设成2, 一个(2,2)的滤波器,这个滤波器你可以理解成卷积核类似。

4个像素中取一个最大值填充到右边。
- Mean Pooling: 平均化

4个像素中取均值。
从左到右,从上到下,扫描完矩阵。
池化层的三个作用
- 又进行了一层特征的提取,肯定可以减小下一层数据处理的量。
- 特征的提取能够更大可能性获取更为抽象的数据。防止过拟合,提高泛化性。
- 由于这种抽象性,能对输入的变化有更大的容忍。
一些新的cnn网络的设计,没有池化层的设计。(不必要)
卷积层和池层的代码实现
我们定义一个类ConvPoolLayer,这个类同时实现了卷积层和池层
ImportError: cannot import name 'downsample'
解决方案;
from theano.tensor.signal import downsample
...
pooled_out = downsample.max_pool_2d( ... )
to
from theano.tensor.signal import pool
...
pooled_out = pool.pool_2d( ... )
# 卷积池层
class ConvPoolLayer(object):
def __init__(self, filter_shape, image_shape, poolsize=(2, 2),
activation_fn=sigmoid):
第一个参数是过滤器的shape, 第二个参数是Image的shape 第三个参数是池层的size大小,激励函数。
filter_shape: 元组类型,有四个维度。

这个三乘三的黄色格子就是我们定义的过滤器。shape(3,3)
我们图中只有一个过滤器,其实也可以有多个过滤器。feature map的个数,第一层是图片
filter_shape=(filter个数,输入的feature map个数,filter高,filter宽)
image_shape=(mini-batch的大小,输入的feature map个数, 图片高, 图片宽)
你上一层有多少个过滤器,本层就有多少个feature map。
保存四个变量。poolsize我们定义的是(2,2)的

输出大小等于 filter的宽高除以池层的size = 过滤器的大小。总共有多少个过滤器,filter[0]
创建共享变量: 初始化本层的w和b。这里的两个初始化和之前介绍的一模一样。
将w和b保存进params列表中。这就是卷积和池层的构造函数所做的所有事情。
跟之前全连接层的set_inpu方法一模一样,我们也要实现一个卷积层的set_input
input的形状,reshape一下,变成image_shape.接着我们使用theano里面提供的卷积函数来做卷积运算。
这里的参数和我们的构造函数中一模一样
conv_out = conv.conv2d(
input=self.inpt, filters=self.w, filter_shape=self.filter_shape,
image_shape=self.image_shape)
官方文档中查到这个函数。
我们调用theano里的池层函数来做池化。
pooled_out = pool.pool_2d(
input=conv_out, ds=self.poolsize, ignore_border=True)
池层接收卷积层的输出,以及pool_size的大小。
self.output = self.activation_fn(
pooled_out + self.b.dimshuffle('x', 0, 'x', 'x'))
池层的输出我们需要加上偏置。经过激励函数。
卷积层池层我们不做Dropout
网友评论