2019-01-19 10:27:37 gukedream 阅读数 337
  • YOLOv3目标检测实战:网络模型改进方法

    YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。 本课程将学习YOLOv3实现darknet的网络模型改进方法。具体包括: • PASCAL VOC数据集的整理、训练与测试  • Eclipse IDE的安装与使用  • 改进1:不显示指定类别目标的方法 (增加功能)  • 改进2:合并BN层到卷积层 (加快推理速度)  • 改进3:使用GIoU指标和损失函数 (提高检测精度)  • 改进4:tiny YOLOv3 (简化网络模型) • AlexeyAB/darknet项目介绍 除本课程《YOLOv3目标检测实战:网络模型改进方法》外,本人推出了有关YOLOv3目标检测的系列课程,请关注该系列的其它课程,包括: 《YOLOv3目标检测实战:训练自己的数据集》 《YOLOv3目标检测实战:交通标志识别》 《YOLOv3目标检测:原理与源码解析》 在学习课程《YOLOv3目标检测实战:网络模型改进方法》前,建议先学习课程《YOLOv3目标检测实战:训练自己的数据集》和课程《YOLOv3目标检测实战:交通标志识别》之一和课程《YOLOv3目标检测:原理与源码解析》。

    275 人正在学习 去看看 白勇

卷积网络设计的初衷是通过卷积层和池化层逐级提取图像在各个不同抽象层次的特征,我们会有这样的疑问:现实结果真的是这样的吗?

先看图像卷积之后的结果。下面是一张卡车的图像:

卡车图像

用AlexNet网络处理之后,第一个卷积层的输出结果(我们把各个卷积核的结果依次排开了)是这样的:

卷层1的结果

可以看到这里抽取了一些边缘信息。第二个卷积层的输出结果是这样的:

卷层2的结果

它抽取了更大区域的特征。后面几个卷积层的结果是这样的:

卷层3—5的结果

卷积层3-5的结果在上图中依次排开。然后我们看全连接层,下图自上向下是3个全连接层的输出结果:

全连接层的结果

我们再来看卷积核的可视化结果。第一个卷积层的卷积核图像如下图所示:

     卷积层1的卷积核

可以看到,这些卷积核确实是在提取边缘,方向等信息。再看第2个卷积层的卷积核:

卷积层2的卷积核

看上去很杂乱,没有反应太多信息。有没有更好的办法?答案是肯定的,目前出现了一些文章解决卷积层可视化的问题。在这里,我们介绍一种典型的方法,通过反卷积运算将卷积核的效果可视化出来。

文献[1]设计了一种用反卷积操作可视化卷积层的方案。具体做法是,将卷积网络学习到的特征图像左乘产生这些特征图像对应的卷积核的转置矩阵,将图片特征从特征图像空间投影到像素空间,以发现是哪些像素激活了特定的特征图像,达到分析理解卷积网络的目的。这这操作称为反卷积,也叫转置卷积

对于卷积层,在反卷积运算时使用正向传播时的卷积核的转置矩阵对特征图像进行卷积,将特征图像还原到原始的像素图像空间得到重构的图像。通过反卷积操作得到卷积核的可视化图像如下图所示:

     通过反卷积进行可视化

上图表明,前面的层提取的特征比较简单,是一些颜色、边缘特征。越往后的卷积层提取的特征越复杂,是一些复杂的几何形状。这符合我们对卷积神经网络的设计初衷,即通过多层卷积完成对图像的逐层特征提取和抽象。

另外一种分析卷积网络机理的方法是根据卷积结果图像直接重构原始输入图像,如果根据卷积结果可以重构出原始输入图像,则说明卷积网络很大程度上保留了图像的信息。文献[2]设计了一种方法,通过卷积网络提取出来的特征反向表示图像来观察卷积网络的表达能力。在这里,反向表示是指由卷积网络编码后的向量近似重构原始输入图像。具体做法是给定卷积网络编码后的向量,寻找一张图像,这种图像通过卷积网络编码之后的向量与给定向量最匹配,这通过求解一个最优化问题实现。下图是根据卷积输出结果重构出来的图像:

卷积图像重构

其中,上面一行是原始图像,下面一行是重构后的图像。从这个结果可以看出,卷积神经网络确实提取出了图像的有用信息。

参考文献:

[1] Zeiler M D, Fergus R. Visualizing and Understanding Convolutional Networks. European Conference on Computer Vision, 2013.

[2] Aravindh Mahendran, Andrea Vedaldi. Understanding Deep Image Representations by Inverting Them. CVPR 2015.

 

 

2017-10-12 15:35:04 XJY104165 阅读数 5964
  • YOLOv3目标检测实战:网络模型改进方法

    YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。 本课程将学习YOLOv3实现darknet的网络模型改进方法。具体包括: • PASCAL VOC数据集的整理、训练与测试  • Eclipse IDE的安装与使用  • 改进1:不显示指定类别目标的方法 (增加功能)  • 改进2:合并BN层到卷积层 (加快推理速度)  • 改进3:使用GIoU指标和损失函数 (提高检测精度)  • 改进4:tiny YOLOv3 (简化网络模型) • AlexeyAB/darknet项目介绍 除本课程《YOLOv3目标检测实战:网络模型改进方法》外,本人推出了有关YOLOv3目标检测的系列课程,请关注该系列的其它课程,包括: 《YOLOv3目标检测实战:训练自己的数据集》 《YOLOv3目标检测实战:交通标志识别》 《YOLOv3目标检测:原理与源码解析》 在学习课程《YOLOv3目标检测实战:网络模型改进方法》前,建议先学习课程《YOLOv3目标检测实战:训练自己的数据集》和课程《YOLOv3目标检测实战:交通标志识别》之一和课程《YOLOv3目标检测:原理与源码解析》。

    275 人正在学习 去看看 白勇

mnist最佳实践中,使用的是全连接网络结构。在Tensorflow中训练一个卷积神经网络的流程和训练一个全连接神经网络没有任何区别。卷积神经网络和全连接神经网络的唯一区别就在于神经网络中相邻两层的连接方式

全连接网络的问题

使用全连接神经网络处理图像的最大问题在于全连接层的参数太多。参数过多,除了导致计算速度减慢,还很容易导致过拟合问题。

卷积神经网络

卷积神经网络中前几层中每一个节点只和上一层中部分的节点相连,如下图所示:
cnn
有效地减少神经网络中参数个数。

卷积神经网络主要由一下5种结构组成:

  1. 输入层:在处理图像时,它一般代表了一张图片的像素矩阵
  2. 卷积层:卷积层中每一个节点的输入只是上一层神经网络的一小块(通常的大小有3*3或5*5)。卷积层试图将神经网络中的每一小块进行更加深入地分析从而得到抽象程度更高的特征
  3. 池化层:池化层(pooling)不会改变三维矩阵的深度,但是它可以缩小矩阵的大小,进一步缩小最后全连接层中节点的个数,从而达到减少整个神经网络中参数的目的
  4. 全连接层:在经过多轮卷积卷积层和池化层的处理之后,在卷积神经网络的最后一般会由1-2个全连接层来给出最后的分类结果。经过几轮卷积和池化层的处理之后,可以认为图像中的信息已经被抽象成了信息含量更高的特征。我们可以将卷积层和池化层看成自动图像特征提取的过程。在特征提取完成之后,仍然需要使用全连接层来完成分类任务。
  5. Softmax层:主要用于分类问题。通过Softmax层,可以得到当前样例属于不用种类的概率分布情况。

卷积神经网络常用结构

卷积层

卷积层结构中最重要的部分—filter(过滤器,内核,卷积核)。过滤器可以将当前层神经网络上的一个子节点矩阵转化为下一层神经网络上的一个单位节点矩阵。

  • 过滤器尺寸:过滤器输入节点矩阵的大小
  • 过滤器深度:过滤器输出节点矩阵的深度

这里写图片描述

卷积层结构的前向过程

卷积层结构的前向过程,就是通过将一个过滤器从神经网络当前层的左上角移动到右下角,并且在移动中计算每一个对应的单位矩阵得到的。

cnn

卷积层参数共享机制

在卷积神经网络中,每一个卷积层中使用的过滤器中的参数都是一样的。从直观上理解,共享过滤器的参数可以使得图像上的内容不受位置的影响。同时,共享每一个卷积层中过滤器的参数可以巨幅减少神经网络上的参数。

Tensorflow实现卷积层

Tensorflow对卷积神经网络提供了非常好的支持。下面的程序实现了一个卷积层的前向传播过程:

import  tensorflow as tf

# 通过tf.get_variable的方式创建过滤器的权重变量和偏置项变量,这里声明的参数变量是一个四维矩阵,前面两个维度代表了过滤器
# 的尺寸,第三个维度表示当前层的深度,第四个维度表示过滤器的深度

filter_weight = tf.get_variable('weights', [5, 5, 3, 16],
                                initializer=tf.truncated_normal_initializer(stddev=0.1))
biases = tf.get_variable('biases', [16], initializer=tf.constant_initializer(0.1))

# tf.nn.conv2d提供了一个非常方便的函数来实现卷积层前向传播的算法。
# 这个函数的第一个输入为当前层的节点矩阵,这个节点矩阵是一个四维矩阵,后面三维对于一个节点矩阵,第一维对应一个输入batch;
# tf.nn.conv2d的第二个参数提供了卷积层的权重;
# tf.nn.conv2d的第三个参数为不同维度上的步长stride。虽然第三个参数提供的是一个长度为4的数组,但是第一维和最后一维的数字要求一定是1
# 这是因为卷积层的步长只对矩阵的长和宽有效
# tf.nn.conv2d的第四个参数是填充(padding)的方法,Tensorflow中提供SAME或者VALID两种选择。其中SAME表示添加全0填充,VALID表示不添加
conv = tf.nn.conv2d(input, filter_weight, strides=[1, 1, 1, 1], padding='SAME')

# tf.nn.bias_add提供了一个方便的函数给每一个节点加上偏置项。注意,这里不能直接使用加法,因为矩阵上不同位置的节点都需要加上同样的偏置项
bias = tf.nn.bias_add(conv, biases)

#将计算结果通过ReLU激活函数完成去线性化
actived_conv = tf.nn.relu(bias)

池化层

在卷积层之间往往会加上一个池化层(pooling layer)。池化层可以非常有效地缩小矩阵的尺寸,从而减少最后全连接层中的参数。使用池化层既可以加快计算速度也有防止过拟合的作用。
池化层前向传播的过程也是通过移动一个类似过滤器的结构完成的。不过池化层过滤器中的计算不是节点的加权和,而是采用更加简单的最大值或者平均值运算。
使用最大值操作的池化层被称之为最大池化层(max pooling),被使用得最多的池化层结构。
使用平均值操作的池化层被称之为平均池化层(average pooling)

与卷积层的过滤器类似,池化层的过滤器也需要人工设定过滤器的尺寸、是否使用全0填充已经过滤器移动的步长等设置。两者在移动方式上唯一的区别在于卷积层使用的过滤器是横跨整个深度的,而池化层使用的过滤器只影响一个深度上的节点。所以池化层的过滤器除了在长和宽两个维度移动之外,还需要在深度这个维度移动。

Tensorflow实现池化层

# tf.nn.max_pool实现了最大池化层的前向传播过程,它的参数和tf.nn.conv2d函数类似。ksize提供了过滤器的尺寸,strides提供了步长信息,
# padding提供了是否使用全0填充
pool = tf.nn.max_pool(actived_conv, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME')
2019-11-21 10:30:49 sdu_hao 阅读数 33
  • YOLOv3目标检测实战:网络模型改进方法

    YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。 本课程将学习YOLOv3实现darknet的网络模型改进方法。具体包括: • PASCAL VOC数据集的整理、训练与测试  • Eclipse IDE的安装与使用  • 改进1:不显示指定类别目标的方法 (增加功能)  • 改进2:合并BN层到卷积层 (加快推理速度)  • 改进3:使用GIoU指标和损失函数 (提高检测精度)  • 改进4:tiny YOLOv3 (简化网络模型) • AlexeyAB/darknet项目介绍 除本课程《YOLOv3目标检测实战:网络模型改进方法》外,本人推出了有关YOLOv3目标检测的系列课程,请关注该系列的其它课程,包括: 《YOLOv3目标检测实战:训练自己的数据集》 《YOLOv3目标检测实战:交通标志识别》 《YOLOv3目标检测:原理与源码解析》 在学习课程《YOLOv3目标检测实战:网络模型改进方法》前,建议先学习课程《YOLOv3目标检测实战:训练自己的数据集》和课程《YOLOv3目标检测实战:交通标志识别》之一和课程《YOLOv3目标检测:原理与源码解析》。

    275 人正在学习 去看看 白勇

卷积神经⽹络(convolutional neural network)是含有卷积层(convolutional layer)的神经⽹络。 本章中介绍的卷积神经网络均使⽤最常⻅的二维卷积层。它有高和宽两个空间维度,常⽤来处理图像数据。本节中,我们将介绍简单形式的二维卷积层的工作原理。

目录

1. 二维互相关运算

2. 二维卷积层

3. 图像中物体边缘检测

4. 通过数据学习核数组

5. 互相关运算和卷积运算

6. 特征图和感受野

7. 小结


1. 二维互相关运算

虽然卷积层得名于卷积(convolution)运算,但我们通常在卷积层中使用更加直观的互相关(cross- correlation)运算。在⼆维卷积层中,⼀个二维输⼊数组和⼀个⼆维核(kernel)数组通过互相关运算输出⼀个二维数组。 我们用⼀个具体例子来解释二维互相关运算的含义。如下图所示,输⼊是⼀个⾼和宽均为3的⼆维数组。我们把该数组的形状记为3x3或(3,3).核数组的高和宽分别为2.该数组在卷积计算中⼜称卷积核或过滤器(filter)。卷积核窗口(⼜称卷积窗⼝)的形状取决于卷积核的⾼和宽,即2x2.下图中的阴影部分为第一个输出元素及其计算所使⽤的输⼊和核数组元素:0x0+1x1+3x2+4x3 = 19.

在⼆维互相关运算中,卷积窗口从输⼊数组的最左上方开始,按从左往右、从上往下的顺序,依次在输入数组上滑动。当卷积窗口滑动到某一位置时,窗⼝中的输⼊子数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。下图中的输出数组⾼和宽分别为2,其中的4个元素由⼆维互相关运算得出:

下⾯我们将上述过程实现在corr2d函数里。它接受输⼊数组X与核数组K,并输出数组Y。

import torch 
from torch import nn

def corr2d(X, K):  # 可以把本函数保存在d2lzh_pytorch包中方便以后使用
    h, w = K.shape
    X, K = X.float(), K.float()
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i: i + h, j: j + w] * K).sum()
    return Y
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
K = torch.tensor([[0, 1], [2, 3]])
corr2d(X, K)

2. 二维卷积层

⼆维卷积层将输⼊和卷积核做互相关运算,并加上⼀个标量偏差来得到输出。卷积层的模型参数包括了卷积核和标量偏差。在训练模型的时候,通常我们先对卷积核随机初始化(或采用默认初始化方式),然后不断迭代卷积核和偏差。

下⾯基于corr2d函数来实现⼀个⾃定义的二维卷积层。在构造函数__init__里声明weight和bias两个参数。前向函数forward则是直接调用corr2d函数再加上偏差:

class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super(Conv2D, self).__init__()
        #自定义卷积层
        self.weight = nn.Parameter(torch.randn(kernel_size))
        self.bias = nn.Parameter(torch.randn(1))

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias

卷积窗口形状为pxq的卷积层称为pxq卷积层。同样,pxq卷积或pxq卷积核说明卷积核的高度和宽度分别为p,q。

 

3. 图像中物体边缘检测

下面我们来看⼀个卷积层的简单应用:检测图像中物体的边缘,即找到像素变化的位置。首先我们构造⼀张6x8的图像(即高和宽分别为6像素和8像素的图像)。它中间4列为黑(0),其余为白(1)。

X = torch.ones(6, 8)
X[:, 2:6] = 0
X

 

然后我们构造⼀个⾼和宽分别为1和2的卷积核K。当它与输入做互相关运算时,如果横向相邻元素相同,输出为0;否则输出为⾮0。

K = torch.tensor([[1, -1]])

下⾯将输⼊X和我们设计的卷积核K做互相关运算。可以看出,我们将从⽩到黑的边缘和从黑到白的边缘分别检测成了1和-1。其余部分的输出全是0。

Y = corr2d(X,K)
Y

由此,我们可以看出,卷积层可通过􏰁重复使用卷积核有效地表征局部空间。

 

4. 通过数据学习核数组

最后我们来看一个例子,它使用物体边缘检测中的输⼊数据X和输入数据Y来学习我们构造的核数组K。我们⾸先构造⼀个卷积层,其卷积核将被初始化成随机数组。接下来在每⼀次迭代中,我们使⽤平方误差来⽐较Y和卷积层的输出,然后计算梯度来更新权重􏰁。

# 构造一个核数组形状是(1, 2)的二维卷积层
conv2d = Conv2D(kernel_size=(1, 2))

step = 20
lr = 0.01
for i in range(step):
    Y_hat = conv2d(X)
    l = ((Y_hat - Y) ** 2).sum()
    l.backward()
    
    # 梯度下降
    conv2d.weight.data -= lr * conv2d.weight.grad
    conv2d.bias.data -= lr * conv2d.bias.grad
    
    # 梯度清0
    conv2d.weight.grad.fill_(0)
    conv2d.bias.grad.fill_(0)
    if (i + 1) % 5 == 0:
        print('Step %d, loss %.3f' % (i + 1, l.item()))

可以看到,20次迭代后误差已经降到了一个⽐较⼩的值。现在来看⼀下学习到的卷积核的参数。

print("weight: ", conv2d.weight.data)
print("bias: ", conv2d.bias.data)

可以看到,学到的卷积核的权重􏰁参数与我们之前定义的核数组K较接近,而偏置参数接近于0.

 

5. 互相关运算和卷积运算

实际上,卷积运算与互相关运算类似。为了得到卷积运算的输出,我们只需将核数组左右翻转并上下翻转,再与输⼊数组做互相关运算。可见,卷积运算和互相关运算虽然类似,但如果它们使⽤相同的核数组,对于同⼀个输入,输出往往并不相同。

那么,你也许会好奇卷积层为何能使用互相关运算替代卷积运算。其实,在深度学习中核数组都是学出来的:卷积层⽆论使⽤用互相关运算或卷积运算都不影响模型预测时的输出。为了解释这一点,假设卷积层使用互相关运算学出上图中的核数组。设其他条件不变,使⽤卷积运算学出的核数组即上图中的核数组按上下、左右翻转。也就是说,上图中的输入与学出的已翻转的核数组再做卷积运算时,依然得到上图中的输出。为了与⼤多数深度学习⽂献一致,如⽆特别说明,本书中提到的卷积运算均指互相 关运算。

 

6. 特征图和感受野

⼆维卷积层输出的⼆维数组可以看作是输⼊在空间维度(宽和高)上某⼀级的表征,也叫特征图 (feature map)。影响元素x的前向计算的所有可能输⼊区域(可能⼤于输⼊的实际尺⼨)叫做的x感受􏰀野(receptive field)。以上图为例,输入中阴影部分的四个元素是输出中阴影部分元素的感受野 我们将上图中形状为2*2的输出记为Y􏰀。并考虑⼀个更深的卷积神经⽹络:将Y另⼀个形状为2*2的核数组做互相关运算,输出单个元素z。那么,z在Y上的感受野包括Y的全部四个元素,在输⼊上的感受野􏰀包括其中全部9个元素。可⻅,我们可以通过更深的卷积神经⽹络使特征图中单个元素的感受􏰀野变得更加广阔,从⽽捕捉输⼊上更⼤尺寸的特征。

我们常使⽤“元素”⼀词来描述数组或矩阵中的成员。在神经⽹络的术语中,这些元素也可称为“单元”。 当含义明确时,不对这两个术语做严格区分。

7. 小结

1)⼆维卷积层的核⼼计算是⼆维互相关运算。在最简单的形式下,它对⼆维输⼊数据和卷积核做互相关运算然后加上偏差。

2)我们可以设计卷积核来检测图像中的边缘。

3)我们可以通过数据来学习卷积核。

 

2017-10-16 09:56:02 mydmdm 阅读数 118
  • YOLOv3目标检测实战:网络模型改进方法

    YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。 本课程将学习YOLOv3实现darknet的网络模型改进方法。具体包括: • PASCAL VOC数据集的整理、训练与测试  • Eclipse IDE的安装与使用  • 改进1:不显示指定类别目标的方法 (增加功能)  • 改进2:合并BN层到卷积层 (加快推理速度)  • 改进3:使用GIoU指标和损失函数 (提高检测精度)  • 改进4:tiny YOLOv3 (简化网络模型) • AlexeyAB/darknet项目介绍 除本课程《YOLOv3目标检测实战:网络模型改进方法》外,本人推出了有关YOLOv3目标检测的系列课程,请关注该系列的其它课程,包括: 《YOLOv3目标检测实战:训练自己的数据集》 《YOLOv3目标检测实战:交通标志识别》 《YOLOv3目标检测:原理与源码解析》 在学习课程《YOLOv3目标检测实战:网络模型改进方法》前,建议先学习课程《YOLOv3目标检测实战:训练自己的数据集》和课程《YOLOv3目标检测实战:交通标志识别》之一和课程《YOLOv3目标检测:原理与源码解析》。

    275 人正在学习 去看看 白勇

卷积层

在上面的几篇文章中,我们已经看到了全链接层的威力,但是,这还远远不够。在本文中,我们将看到DNN的一个重要特性,卷积层。
熟悉信号处理的朋友对于卷积的概念不会陌生,这就是我们常用的滤波。只是在很多应用场景中,不是我们常见的一维滤波,而是图像处理中常见的2D滤波(比如最常见的锐化,就是一个简单的高通滤波)。在深度学习的术语中,滤波器被叫做卷积核(kernal)。
在以图像为输入的DNN网络中,一个卷积核其实是针对于输入所有通道的一个滤波器组(group of filters)。比如以常见的MNIST数据为例,每个输入数据是28x28x3的像素集合(28x28是尺寸,3是RGB 通道)。一种常见的卷积核尺寸是5x5x3,就是说每5x5x3的立方体内所有的像素点都与系数做内积,得到输出的特征图上的一个点。
卷积核的常见参数包括

参数 含义
H×W Heights and Width
CI×CO 输入与输出的信号数目
S Stride 步长,即滤波器每次移动的像素点数,也可以理解为滤波之后的降采样因子
P Padding,填充。为了保持输出的尺寸在输入边界的位置填入的“0”的数目

经过简单的计算可以得到,在长或者宽的维度上,输入尺寸HDI×WDI×CI与输出尺寸HDO×WDO×CO之间的关系可以表述为

HDO=HDI+Ptop+PbottomHKSH+1WDO=WDI+Pleft+PrightWKSW+1

一般而言,为了简化控制流,我们会约定
Ptop=Pbottom=Pleft=Pright=PSH=SW=S

下面这篇文章对于卷积层的归纳相当不错,对比来看就会发现,还是信号处理中熟悉的味道 :)。
https://zhuanlan.zhihu.com/p/30074309?utm_source=wechat_session&utm_medium=social

卷积层的计算

正向传播

卷积层的正向传播和反向传播的基本运算是单通道的2D卷积(滤波)。为了简化下文的推导和展示,本文添加了一个虚拟层来表示单通道 2D卷积的输出。虚拟层进行加权求和之后可以得到卷积层的真正输出。

vcx,cyp,q=i,jxcxpSi,qSjwcx,cyi,jycyp,q=cxvcx,cyp,q=cx,i,jxcxpSi,qSjwcx,cyi,j

我们定义,p,q 代表在图像平面上的坐标。cx=1CI 代表输入的通道号,cy=1CO 代表输出的通道号。
从上面的计算可以看到,一个卷积层需要的参数的数目是HK×WK×CI×CO(bias未计入),通常而言这都是一个非常巨大的数目。即使是一个最简单的MNIST训练集和一层卷积层,你就会很明显的感受到训练速度的下降。

反向传播

简单起见,在进行反向传播的推导过程中,本文将仅仅计算最简单的S=1的情况。对于步长大于1 的情况,相当于在虚拟的卷积输出层进行upsample操作之后再进行反向传播计算。

dxcxp,q=cy,i,jdycyp+i,q+jycyp+i,q+jxcxp,q=cy,i,jdycyp+i,q+jwcx,cyi,j=cy,i,jdycypi,qjwcx,cyi,j

从上面的式子可以看出,卷积层的反向传播也是2D卷积的求和,只是区别在于要将二维卷积系数进行上下和左右的反转。

系数更新

卷积层的系数更新跟全连接层并没有太大的变化。

Jwcx,cyi,j=cy,p,qdycyp,qycyp,qwcx,cyi,j=cy,p,qdycyp,qxcxpi,qj

深度可分离的卷积(Depth-Separatable)

下面一部分是对于深度可分离的卷积的一点想法。如上面所述,可以将一个完整的卷积层拆分为两层,一个是二维的平面卷积,另外一个是将平面卷积结果作为输入的一维卷积(类似于全连接层)。

vcxp,q=i,jxcxpSi,qSjwcxi,jycyp,q=cxβcx,cyvcxp,q

这样的话,参数的数目将为HK×WK×CI+CO

我们来分两步看反向传播。vy 相当于一个全连接层。

dvcxp,qJβcx,cy=cydycyp,qβcx,cy=p,qdycyp,qvcxp,q

xv 是二维卷积。
dxcxp,qJwcxi,j=i,jdvcxp+i,q+jwcxi,j=i,jwcxi,jcyβcx,cydycypi,qj=p,qdvcxp,qxcxpi,qj

卷积层
2017-08-15 09:34:05 fireflychh 阅读数 227
  • YOLOv3目标检测实战:网络模型改进方法

    YOLOv3是一种基于深度学习的端到端实时目标检测方法,以速度快见长。 本课程将学习YOLOv3实现darknet的网络模型改进方法。具体包括: • PASCAL VOC数据集的整理、训练与测试  • Eclipse IDE的安装与使用  • 改进1:不显示指定类别目标的方法 (增加功能)  • 改进2:合并BN层到卷积层 (加快推理速度)  • 改进3:使用GIoU指标和损失函数 (提高检测精度)  • 改进4:tiny YOLOv3 (简化网络模型) • AlexeyAB/darknet项目介绍 除本课程《YOLOv3目标检测实战:网络模型改进方法》外,本人推出了有关YOLOv3目标检测的系列课程,请关注该系列的其它课程,包括: 《YOLOv3目标检测实战:训练自己的数据集》 《YOLOv3目标检测实战:交通标志识别》 《YOLOv3目标检测:原理与源码解析》 在学习课程《YOLOv3目标检测实战:网络模型改进方法》前,建议先学习课程《YOLOv3目标检测实战:训练自己的数据集》和课程《YOLOv3目标检测实战:交通标志识别》之一和课程《YOLOv3目标检测:原理与源码解析》。

    275 人正在学习 去看看 白勇

     在图像处理中,往往将图像转化为像素,如讲1000*1000的图像转化为1000000的向量。如果假设隐藏层也是为1000000时,则权值参数诶1000000000000个,这种权值参数太多了,无法进行训练,所以需要减少权值参数的个数。一般有两种方法进行减少:

      第一种称为局部感知野。一般认为人对外界的认知时从局部到全局的,而图像的空间联系也是局部像素联系较为紧密。所以每个神经元没有必要对全局进行感知,只需要对局部进行感知,然后由更高层将局部的信息综合起来就得到了全局的信息。假如每个神经元只和10*10个像素值相连,那么权值个数为1000000*100,减少了万分之一,而10*10个像素值对应的10*10个参数,就是卷积操作的卷积核。

      第二种称为参数共享。虽然采用局部感知的方式减少了权值,但是还是太多,这里通过权值共享,即这1000000个神经元的100个参数都是相同的,那么权值参数就变成了100了。

一个实例:

import tensorflow as tf
import numpy as np

image = np.array([[1,1,1,0,0],
                  [0,1,1,1,0],
                  [0,0,1,1,1],
                  [0,0,1,1,0],
                  [0,1,1,0,0]])

weight = np.array([[1,0,1],
                    [0,1,0],
                    [1,0,1]])
bias = 0
input = tf.constant(image, dtype=tf.float32)
filter = tf.constant(weight, dtype=tf.float32)
input = tf.reshape(input, [1,5,5,1])
filter = tf.reshape(filter, [3,3,1,1])
result = tf.nn.conv2d(input, filter, strides=[1,1,1,1], padding="VALID")
with tf.Session() as sess:
    idata = sess.run(input)
    filt = sess.run(filter)
    res = sess.run(result)
    print(res)

输出为1*3*3*1矩阵:

4  3  4

2  4  3

2  3  4


此时卷积的padding="VALID", 输出大小计算公式为((width - filter + 2*padding)/stride)+1,  对于VALID,为width/stride  向下取整, 本例中(5-3+0)+1=3,如果收入的width=6,stride=2,则输出等于2.5,实际输出为2.实例如下:

import tensorflow as tf
import numpy as np

image = np.array([[1,1,1,0,0,1],
                  [0,1,1,1,0,1],
                  [0,0,1,1,1,1],
                  [0,0,1,1,0,1],
                  [0,1,1,0,0,1],
                  [1,1,1,1,1,1]])

weight = np.array([[1,0,1],
                    [0,1,0],
                    [1,0,1]])
bias = 0
input = tf.constant(image, dtype=tf.float32)
filter = tf.constant(weight, dtype=tf.float32)
input = tf.reshape(input, [1,6,6,1])
filter = tf.reshape(filter, [3,3,1,1])
result = tf.nn.conv2d(input, filter, strides=[1,2,2,1], padding="VALID")
with tf.Session() as sess:
    idata = sess.run(input)
    filt = sess.run(filter)
    res = sess.run(result)
    print(res)

输出为1*2*2*1矩阵:

4    4

2    4


如果padding设置为SAME,此时输出为width/stride上取整, 则输出为:

import tensorflow as tf
import numpy as np
#convolution padding="SAME"
image = np.array([[1,1,1,0,0],
                  [0,1,1,1,0],
                  [0,0,1,1,1],
                  [0,0,1,1,0],
                  [0,1,1,0,0]])

weight = np.array([[1,0,1],
                    [0,1,0],
                    [1,0,1]])
bias = 0
input = tf.constant(image, dtype=tf.float32)
filter = tf.constant(weight, dtype=tf.float32)
input = tf.reshape(input, [1,5,5,1])
filter = tf.reshape(filter, [3,3,1,1])
result = tf.nn.conv2d(input, filter, strides=[1,1,1,1], padding="SAME")
with tf.Session() as sess:
    idata = sess.run(input)
    filt = sess.run(filter)
    res = sess.run(result)
    print(res)

输出为:1*5*5*1

2  2  3  1  1

1  4  3  4  1

1  2 4  3  1

1  2 3  4  1

0  2  2  1  1


stride=2时:

import tensorflow as tf
import numpy as np
#convolution padding="SAME"
image = np.array([[1,1,1,0,0],
                  [0,1,1,1,0],
                  [0,0,1,1,1],
                  [0,0,1,1,0],
                  [0,1,1,0,0]])

weight = np.array([[1,0,1],
                    [0,1,0],
                    [1,0,1]])
bias = 0
input = tf.constant(image, dtype=tf.float32)
filter = tf.constant(weight, dtype=tf.float32)
input = tf.reshape(input, [1,5,5,1])
filter = tf.reshape(filter, [3,3,1,1])
result = tf.nn.conv2d(input, filter, strides=[1,2,2,1], padding="SAME")
with tf.Session() as sess:
    idata = sess.run(input)
    filt = sess.run(filter)
    res = sess.run(result)
    print(res)

输出1*3*3*1:

2 3 1

1 4 3

0 2 1




没有更多推荐了,返回首页