当前位置: 移动技术网 > IT编程>网页制作>HTML > 深度卷积网络:第三课

深度卷积网络:第三课

2020年07月20日  | 移动技术网IT编程  | 我要评论

本文是《深度卷积网络 原理与实践》第4章的整理。

概念:

  1. 通道(channel) / 特征层(feature plane): n张图,可以看成n个通道或者n个特征层。
    • 例子:对于彩色图片,电脑会按照{R,G,B}三个通道存储,所以输入的图就已经是3张图。再通过3*n个卷积核就可以得到n张图

例子:找橘猫

思路一

  • 定义橘色的色彩范围
  • 对图像中的每个点进行判断是否是橘色,如果橘色超过全体点的10%,则认为有橘猫。
  • 实际上这个就是一个卷积核为1*1的卷积神经网络。

思路二

  • 实质上橘色是橘猫的一个特征,我们也可以选取其他特征,例如橘猫的纹理。
  • 我们可以在图像中试图寻找橘猫的纹理,然后计算区域的面积,达到1%面积就可认为图中有橘猫。
  • 这个思路中找橘猫纹理,实际上是寻找图像中的局部特征,这个任务可以被卷积神经网络完成。

卷积(Convolution)

通过下面这个例子,我们可以发现卷积这个操作可以提取图片中的一些特征信息。

  • 此外,通过卷积操作,原来n*n的图像的尺寸也会减少。
  • 卷积是一个线性操作。
  • 卷积也可以看成一个滤波器,可能类比于夫琅和费衍射里面的孔,信息光学里面对于频谱的操作❓❓
  • 实际卷积中,我们还会对在卷积核输出的数据上再加一项偏置。
    在这里插入图片描述

⚠️ 尺寸问题

  • 假设:
    • 原来图像n*n
    • 卷积核k*k
    • 卷积的步长(Stride) s:卷积核每做完一次卷积后移动几格。
    • Padding m,即加m圈零
  • 结论:
输入图像尺寸 卷积核尺寸 卷积步长 Padding 输出图像尺寸
n k - - n-k+1
n - - m n+2m
n k - m n+2m-k+1
n - s - n1s\left \lfloor \frac{n-1}{s} \right \rfloor+1
n k s - nks\left \lfloor \frac{n-k}{s} \right \rfloor+1
输入图像尺寸 Pooling Kernel尺寸 Pooling步长 输出图像尺寸
n a - n-a+1
n - b n1b\left \lfloor \frac{n-1}{b} \right \rfloor+1

...\left \lfloor ... \right \rfloor表示向下取整数。
其实Pooling和卷积核的尺寸计算一致。

  • 推导:
  • 加完Padding后图像的尺寸为(n+2m)(n+2m)(n+2*m)*(n+2*m)。我们其实可以固定卷积核左上角来计算,然后看卷积核左下角在卷积核在图像右下角这个情况下的坐标,所以为n+2m(k1)n+2*m-(k-1)
  • 则无Stride情况下,输出的图像为:(n+2m(k1))(n+2m(k1))(n+2*m-(k-1)) \cdot (n+2*m-(k-1))

一般情况下,我们经常取k=2m+1,即奇数大小的卷积核,这样在合适的padding(m个)之后,原来图像经过卷积之后还是n*n的。

  • 如果有步长s,无卷积核,输入图像的尺寸为nnn*n,输出图像尺寸为n1s+1\left \lfloor \frac{n-1}{s} \right \rfloor+1
    [依旧采用固定左上角,实际上问题等价于1到n里面有多少个被s除余1的数字,即等价于0到n-1里面有几个被s除余1的数字,即为(n-1)/s向下取整数+1,因为从0开始算]
  • 如果有步长s,有卷积核k,输入图像的尺寸为nnn*n,输出图像尺寸为nks+1\left \lfloor \frac{n-k}{s} \right \rfloor+1,这里的数字不同框架会略有不同。在MXNet中的规范是向下取整数。

池化(Pooling):一种缩小图像的方法

  • 对卷积后的图像进一步变换(局部):

    • 最大池化:可取最大值,即标志着图中是否存在这个特征。
    • 平均池化:平均值,标志着图中这个特征的密度。
    • 可只在n*n的区域取最大值或平均值。
  • 全局池化

    • 全局平均池化:取整张图像的平均值
    • 全局最大池化:取整张图像的最大值
    • 经常放在网络的末端。例如,在一个10分类任务中最后我们可以得到10个小图,然后对10个小图依次做全局平均池化可以得到10个数,再经过SoftMax可以得到最后的10个概率。
  • 例子:
    大小为2,步长为2,最大池化。
    在这里插入图片描述

转置卷积(Transposed Convolution):逐层生成一张不断增大的图像

  • 一种不严谨的称呼是反卷积

卷积和转置卷积的关系:

在这里插入图片描述

卷积网络的运作

  • 输出a张图片,通过a*b个卷积核可以得到b张图片。
  • 从输出2张图片到输出3张图片的例子:
    在这里插入图片描述

例子:AlphaGo的基本原理

网络的输入:one-hot编码

  1. 可以将19*19的棋盘上的棋子用-1,1,0表示。
  2. :它和它直接相连的同一方棋子周围的空点个数(只看上下左右方向,不包括斜线方向)。例如,下图中,横着的三个连着的棋子(灰色)的气都是4,而左上角的棋子的气是3。
    在这里插入图片描述
    之后可以采用one-hot编码来表示:有棋子的地方为1,否则为0。
  • 因此,我们可以将当前19*19的棋盘拆解为若干个特征层进行输入:
  1. 本方棋子
  2. 对方棋子
  3. 空点
  4. 各个气数的棋子
  5. 最后一手的位置

研究一个已经训练好的简单下棋模型中的3*3卷积核。

这个简化的网络的模型可以如下表示:

  • 我们可以研究对于不同特征层的卷积核的值,并对参数予以解释。然后将8个特征层经过卷积后的输出加和在一起得到最后的结果。
  • RQ:
    此模型的一个问题在于,如果去掉第8层(最后一手的位置),对于整体预测影响不大,而这个问题再更深的神经网络中将得到解决。

根据SoftMax的定义,如果两个点的分数差XX,选择的概率就差eXe^X倍。

卷积网络与全联接网络的比较

实际上,通过简单的计算,我们可以发现,对于完全符合卷积核的形式,卷积之后值最大。相反,如果不完全符合卷积核的形式,它的值就相对比较小。此时如果再进行ReLU操作,就会留下正值,即留下与特征匹配的位置。因此ReLU很适合与卷积配合

考虑以下问题:

  • 输入:3张32*32的图像(因为每张图像有3个通道。实际上就是一张彩色图)
  • 输出:64张30*30的图像

如果使用卷积神经网络

  • 需要3*64=192个333*3的卷积核,因为[(3230+1)=3][(32-30+1)=3]
  • 1个卷积核需要9个参数
  • 此外,每得到一个最终图像需要一个偏置项,即一共64个。
  • 因此,此问题如果使用卷积神经网络一共需要64+192*9=1792个参数

如果使用全连接神经网络:

  • 因为输出有643030=5760064*30*30=57600个像素,所以需要57600个神经元。
  • 因为每个神经元与33232=30723*32*32=3072个输入相连,再加上一个偏置,所以每个神经元有3073个参数。
  • 因此,此问题如果使用全连接神经网络一共需要57600*3073=177004800个参数,远比卷积神经网络多。因而容易过拟合。

卷积神经网络的运作和训练(理论部分)

  • 一个简单的例子(MSE损失):
    在这里插入图片描述
    前向传播:
    O11=x11w11+x12w12+x21w21+x22w22+bO_{11}=x_{11}w_{11}+x_{12}w_{12}+x_{21}w_{21}+x_{22}w_{22}+b
    O21=...O_{21}=...
    O12=...O_{12}=...
    O22=x22w22+x23w23+x32w32+x33w33+bO_{22}=x_{22}w_{22}+x_{23}w_{23}+x_{32}w_{32}+x_{33}w_{33}+b
    OUT=MAX(O11,O12,O21,O22)OUT = MAX(O_{11},O_{12},O_{21},O_{22})
    LOSS=LOSSMSE=(OUT)2LOSS=LOSS_{MSE}=(OUT-期望输出)^2
    反向传播:
  1. LOSSOUT=2(OUT)\frac{\partial LOSS}{\partial OUT}=2(OUT-期望输出)

  2. OUTOi,j\frac{\partial OUT}{\partial O_{i,j}}

    • 如果Oi,jO_{i,j}最大:OUTOi,j=1\frac{\partial OUT}{\partial O_{i,j}}=1
    • 否则:OUTOi,j=0\frac{\partial OUT}{\partial O_{i,j}}=0
  3. 再结合对应卷积核的定义就可以计算出Oi,jwk,l\frac{\partial O_{i,j}}{\partial w_{k,l}}

  4. 结合上面三个可以得到最后的LOSSwk,l\frac{\partial LOSS}{\partial w_k,l}

  • 更快的方法可以参考:im2col

用卷积网络解决MNIST问题

批规范化层(Batch Normalization, BN)

批规范化层,可以加速网络的收敛。常常防止在非线性激活层之前,甚者可以放在每个非线性激活层之前。

  • 参数个数为: 22*通道数

代码实现

  • 代码:1 / 4
import numpy as np
import os
import gzip #为了解压文件
import struct
import logging
import mxnet as mx
import matplotlib.pyplot as plt

logging.getLogger().setLevel(logging.DEBUG)
  • 代码:2 / 4
# 辅助读入训练数据
def read_data(label_url,image_url):
    with gzip.open(label_url) as flbl: #打开标签文件
        magic,num = struct.unpack(">II", flbl.read(8)) #读入标签文件头
        label = np.frombuffer(flbl.read(),dtype = np.int8) #读入标签内容

    with gzip.open(image_url,'rb') as fimg: #打开图像文件
        magic,num,rows,cols = struct.unpack(">IIII",fimg.read(16)) # 读入图像文件头,这里图像是28*28所以rows和cols都会是28
        image = np.frombuffer(fimg.read(), dtype=np.uint8) #读入图像内容
        image = image.reshape(len(label),1,rows,cols) # 设置为正确的数组格式
        imgae = image.astype(np.float32)/255.0 # 归一化到0到1的区间
    return (label,image)
    
# 读入数据
(train_lbl,train_img) = read_data('train-labels-idx1-ubyte.gz','train-images-idx3-ubyte.gz')
(val_lbl,val_img) = read_data('t10k-labels-idx1-ubyte.gz','t10k-images-idx3-ubyte.gz')
  • 代码:3 / 4
# 网络架构的定义

# 输入是一张(1,28,28)的图片,即1通道(灰度),28*28的图片
data = mx.symbol.Variable('data')

# 第1个卷积层,有32个5*5的卷积核,采用BN层,relu激活以及最大池化
conv1 = mx.sym.Convolution(data = data, name = "conv1", kernel=(5,5),num_filter=32)
bn1 = mx.sym.BatchNorm(data = conv1, name = "bn1", fix_gamma=False) #对于BN层,我们往往会加上fix_gamma=False这个参数
act1 = mx.sym.Activation(data = bn1, name = "act1", act_type="relu")
pool1 = mx.sym.Pooling(data = act1, name="pool1", pool_type="max", kernel=(3,3), stride=(2,2)) #3*3大小,2*2步长的最大池化层

# 第2个卷积层
conv2 = mx.sym.Convolution(data = pool1, name = "conv2", kernel=(5,5),num_filter=64)
bn2 = mx.sym.BatchNorm(data = conv2, name = "bn2", fix_gamma=False)
act2 = mx.sym.Activation(data = bn2, name = "act2", act_type="relu")
pool2 = mx.sym.Pooling(data = act2, name = "pool2", pool_type="max", kernel=(3,3), stride=(2,2))

# 第3个卷积层,有10个3*3的卷积(为了将数字归成10类,所以通过10个卷积核生成10张图片)
conv3 = mx.sym.Convolution(data = pool2, name="conv3", kernel=(3,3), num_filter=10)
pool3 = mx.sym.Pooling(data = conv3, name = "pool3", global_pool=True, pool_type="avg", kernel=(1,1)) #全局平均池化,最后每张图片会得到一个数字

# 将图像摊平,我感觉Flatten能把多个数组合并成为一个数组[[1],[1]] -> [1,1]我猜测
flatten = mx.sym.Flatten(data=pool3,name="flatten")
# SoftMax层,将10个数变为10个分类的概率
net = mx.sym.SoftmaxOutput(data = flatten, name="softmax")

相关文章:

验证码:
移动技术网