Kaggle NCFM记录

现在的成绩:30/2129,Top 1.5%

QQ截图20170326211854

开始

第一次参加Kaggle,萌新表示非常激动,所以在博客写个日志记录一下参赛过程

获取数据集

训练数据集一共8类,一共3777张训练图像,每张图片的大小不等,样本数量按照类别分布如下:

  • ALB:1719
  • BET:200
  • DOL:117
  • LAG:67
  • NoF:465
  • SHARK:176
  • YFT:734
  • OTHER:299

按照train:validation=4:1分割:

  • train:3019
  • validation:758

类别不平衡,看看数据长什么样,依次是ALB、SHARK、YFT(金枪鱼?)、BET

img_02542img_07498img_00572img_05561

这里值得提及的一点是,鱼只占据了整幅图中很小的一部分。

评判标准

并不是分类的accuracy,而是分类任务的multi-class cross-entropy loss:

$$log loss = -\frac{1}{N}\sum_{i=1}^N\sum_{j=1}^My_{ij}\log(p_{ij}),$$

y是one-hot ground-truth,p可以理解成softmax的输出归一化概率吧。

训练数据的Data Leakage

先看对训练数据整个文件夹瞄一眼: 1 好多绿色好多黄色是不是,这里有一个Data Leakage:训练数据其实是在12个不同的Boat上采集的,每个Boat上有一个固定的摄像头,拍摄出的鱼类图像有固定背景,上面图片看上去很绿的图就是由一个camera拍出来的,这是可以利用的一个点。

第零次提交

  • 先拿了ResNet-50试了一下,发现有比较严重的overfitting现象,训练集的准确率逼近1,测试集的准确率只有0.94,不管这么多先提交一个结果。Score 1.21,750/1500,Top 50%。

第一次提交

  • 2017.2.18微博上Top 5%的solution做了一个warm start,经过25个epoch的training之后提交结果分数为1.04,排名大约265/1540,Top 20%。

模型解析

这里采用了GoogleLeNet的Inception V3 model,并把输入图像大小resize到299×299,将像素值范围规约到$$[-1,1]$$,去掉Inception的最后一层,加入8×8的Global Avg Pooling并将输出flatten,输入到Softmax分类器中。

数据增广

  • 像素值rescale:将$$[0,255]$$映射到$$[0,1]$$范围
  • 随机剪切
  • 随机缩放
  • 随机旋转
  • 水平/垂直方向移动
  • 水平/垂直方向翻转

模型平均

对Test Data做了上面的数据增广(5倍),输入到训练好的模型中,将多种增广策略输入的Softmax probability做平均,得到平均结果。

改造ResNet

2017.2.19:把特征提取部分用ResNet-50来代替Inception V3,并且保持前面大部分卷卷积层的参数fix只训练后面少数若干层的参数,加上之前的数据增广Trick结果提高到了0.96,排名165,Top 11%。

1

尝试VGG16

其实ResNet并不太适合这样的Transfer Learning,具体原因见我下一篇博文(即将发出来),所以采用VGG16试试。

将训练数据resize到320×640,对VGG16的参数在训练过程中保持fixed,对VGG16特征再加上三次的Convolution-Batch Normalization-Max Pooling,最后加上Global Avg Pooling-Softmax,仅仅优化加上的这些层的参数。

多模型平均

用上面的网络结构跑了20次,选出8个validation-loss<0.2的VGG16模型,在测试数据上输出结果后进行加权平均(也包括测试数据增广的平均策略),将产生的submission csv和之前ResNet0.96的结果再次平均,提交了一下Score达到了0.88。

Boat聚类

前面提过,数据集是由12个摄像头产生的,这个12是怎么来的呢?其实是我手动数出来的。于是接下来对训练数据resize到40×40,利用DBSCAN聚了个类,调了一下参数之后,印证了12个Boat/camera的想法。

1

得到12类之后,计算出每一类的平均图像,就当成每一个摄像头拍摄的背景,而图像中的其他内容(鱼类、人)就当作前景。对每张图片进行boat分类之后,减去此类的均值,重新构造数据集。数据集中的特征就少了很多,重新训练神经网络提交后Score:0.82,排名59/1588,Top 4%。

1

下一步:目标检测

资源整理

论坛上非常好的讨论帖

一些小问题

训练集重复图像/类别不平衡

最后的结果在validation set和test set上的cross-entropy loss差了好多,可能是因为训练集有很多非常相似的图像,因此将这些相似的图像分割成train/val set时,分类器在validation set上的表现要比它实际的效果会好。

训练集中每个类别的鱼类的样本数量相差很大,结合上面所述,需要更好的采样策略。

这里有一个很好的deep learning课程,Lesson 7讲的很不错。

MDNet:Learning Multi-Domain Convolutional Neural Networks for Visual Tracking

CVPR 2016的文章,似乎赢得了VOT 2015的冠军,目前tracking方法中的state-of-the-art,挺特别的一个算法。

特点

  • 从domain-specific的训练集中分离出domain-independent的信息
  • 浅层得到generic的feature representation
  • 深层得到domain-specific feature
  • Online Update

背景

与图像识别问题不同,tracking的目标是没有标签的,同一个物体在一个视频中可能是前景,在另一个视频中可能是背景,在跟踪算法运行之前也许网络并没有见过和目标同类的图像,如何用深度网络快速构建并表达未见样本的high-level feature便成为基于神经网络的跟踪算法需要解决的问题。

用神经网络表示object的共享结构,以及对应于某个视频的object快速建立起其特殊的high-level feature,是MD-net的基本思想。

网络结构

1

  • 整体框架由共享层之后级联了许多domain的分支网络构成
  • 在网络的共享层,学习物体的共享feature representation,这样学习到的是无标签的generic的特征
  • 从多个标注的视频序列中学习,每一个视频看做是一个单独的domain,这也就是Multi-Domain的由来

训练和测试

每一个domain对应的网络分支都是单独训练的,并且每次都更新共享层,由domain-specific layer得到依赖于domain的信息;测试的时候将最后的多个domain-specific layers换为一路即可,以适应新的domain,这样可以快速构建待跟踪物体的high-level feature,用来计算最终的跟踪结果。

Multi-Domain Representation Learning

训练一个multi-domain CNN以在任何domain辨别target和background,但是multi-domain中依然有很多共性,这些domain-independent的特征对于跟踪过程目标的变化有非常好的鲁棒性,因此先从domain-specific的信息中分离出domain-independent的信息,这些信息由网络的前三层表示。

训练时每次仅仅更新一个domain-specific layers,而shared layer则每次都更新

Long-Term Update:按照常规的帧间隔进行更新,这个时间表示为$$\tau_{l}$$

Short-Term Updates:当出现潜在的跟踪失败的时候进行更新,同理表示为$$\tau_{s}$$

为什么generic feature要用浅层来表达?

由于空间坐标的信息随着网络深度的加深变得稀释,generic的特征也不需要深层表达,另外是为了减少计算量。

Hard Negative mining

训练时由于正负样本数量上相差悬殊,在SGD的过程中容易造成跟踪框的drift,所以这里引入了hard negative mining来选取具有代表性的负样本,使得训练和测试交替进行,以识别hard negative example,也就是这些假的正样本。

将Hard Negative mining引入mini-batch的选择中,一个mini-batch中包含$$M^+$$个正样本和$$M^{-}$$个hard negatives,选取那些$$M^{-}(>M_{h}^{-})$$的即可

Bounding Box Regression

给定测试序列的第一帧,我们训练一个简单的线性回归模型来预测精确的目标位置,使用目标位置附近的样本的conv3特征。

Online Visual Tracking

在线微调仅仅针对共享层之后的网络分支进行,以快速适应新的domain;在视频的当前帧中随机选取目标输入网络,进行二值分类。为了估计每一帧的目标状态,在前一帧的目标框周围采样$$N$$个候选patch,并通过网络来evaluate,并得到每个patch的分类分数$$f^{+} (x_i )$$和$$f^{-}(x_i)$$,然后概率最大的自然就是目标识别的结果:

1

算法流程总结如下:

1

参考文献

KCF:High-Speed Tracking with Kernelized Correlation Filters

2014年提出的经典的Tracking算法KCF,核心思想是训练一个分类器,区分的对象自然就是图像块,判断图像块属于目标还是背景。

特点

  • 判别式的tracker,对sample patch判断其是object/environment
  • 对像素有重叠的patch去冗余:利用循环变换矩阵对临近的连续patch进行建模,并在DFT基下对角化循环变换矩阵以获得高计算性能
  • 对于非线性核回归的判别器来说,模型等价于一个核相关滤波器(KCF),并且加快了求解速度

算法细节

岭回归

KCF训练的分类器可以表述为:$$f(z)=w^T{z}$$,$$z$$为图像中的patch,$$f(z)$$为分类结果,因而需要优化的目标函数为一个岭回归的形式:

1

$$x_i$$是训练patch,$$y_i$$是这个patch对应的标签。这个目标函数是有闭式解的:

1

$$X$$的每一行$$x_i$$是一个patch,因为我们即将把算法推广到频域,所以将上式改写为复数形式比较方便:

1

这里$$X^H=(X^*)^T$$,对于实数来说上面两个式子是等价的。

求解这种线性系统是非常耗时的,不仅仅是大矩阵的乘法,还有求逆的操作,下面我们会陈述对于图像块重叠中的冗余信息(也就是$$x_i$$之间互为循环变换矩阵时),可以避免这种高时间复杂度的操作。

循环变换

图像相邻且重叠的块之间存在着大量的相似/冗余信息,如何利用这种相似性成为快速求解$$X^T{X}$$的关键,相邻图像块类似于是经过了一种变换之后得到的,下面详细介绍循环变换:

1

考虑一个图像块$$x$$,我们称为base sample;循环变换就是用$$x$$产生其他接近$$x$$的sample(但是产生的sample是负样本),利用循环变换操作符(也称为permutation matrix)来产生变换后的sample:

1

乘积$$Px=[x_n,x_1,x_2,…,x_{n-1}]^T$$是一种变换操作,这种操作一次变换$$x$$的一个元素,以此来对真实图像块的微小改变进行建模,将很多的$$P$$级联起来就可以得到$$P^{u}x$$,此时便可以对一个较为大的变换建模,图中展示了对一维信号和二维图片进行变换的步骤。

1

从图中看出循环变换是具有周期性的,所以我们这里就可以得到一个信号的变换集合:

1

这个集合的前一半可以视为向正方向变换,因为变换的周期性,集合的另一半可以视为反向变换。

循环矩阵

1

上图的一维信号循环矩阵可以表示为$$C(x)$$,循环矩阵有一个很好的性质:在DFT基下的表示可以对角化。

1

这里我们令$$\hat{x}=\mathcal{F}(x)=\sqrt{n}Fz$$,$$\hat{x}$$就是一个对角矩阵了。

框架

当训练数据包含大量由循环变换造成的冗余时,对对角矩阵进行操作是非常迅速的,因为所有的操作都可以用向量元素的点乘来完成。

对于矩阵$$X^{H}X$$(可以视为非中心化的协方差矩阵):

1

这里需要提及一下,因为DFT的基函数是正交的所以有$$F^{T}F=I$$,并且对角矩阵的乘法可以表示为元素点乘,所以上式可以简化为:

1

括号里的表达式可以叫做信号$$x$$的自相关系数,或者称为能量谱。这可以表示信号$$x$$在不同维度上的差异。

将这个表达式带入岭回归的表达式中可以得到$$\hat{w}$$的解:

1

或者更加明了一点:

1

这里的分号表示了元素的点除法,这个解看起来像是一个正则化的相关滤波器。

引入非线性回归

这里当然是用kernel trick啦,在很多文章里都用到的非常经典的技巧。这里先简单回顾一下核技法:

用函数$$\varphi{(x)}$$将输入$$x$$从一个线性空间映射到一个非线性空间:

  • 将待求解的$$w$$表示成非线性函数的线性组合:

1

因此这里需要优化的变量就是对偶空间中的$$\alpha$$而不再是原始空间中的$$w$$了

  • 定义核函数$$K(x,x’)=\varphi{^T(x)}\varphi{(x’)}$$

1

此时回归函数变成如下的形式:

1

但是随着训练样本的增多,核函数的计算负担会加大,下面说明如何用循环矩阵来减小这里的计算量。

快速核回归

加入了核函数的岭回归闭式解如下(文中有参考文献提及):

1

这里的$$K$$是核矩阵,$$\alpha=[\alpha_{1}…\alpha_{n}]$$,我们可以证明很多核函数$$K$$对于循环数据集来说也是循环的,那么就可以将上式中的$$K$$对角化并得到快速求解的方法。写成如下形式:

1

这里,$$k^{xx}$$是核矩阵的第一行,$$K=C(k^{xx})$$,$$\hat{}$$代表向量的频域表示。

我们在这里定义一个更加一般化的核相关,两个向量$$x$$和$$x’$$的核相关$$k^{xx’}$$表示为:

1

换句话说,它是对向量$$x$$,和向量$$x’$$的不同相对变换进行评估的kernel,而$$\hat{k}^{xx’}$$则是$$x$$的自相关。因为一个核操作等价于高维空间$$\varphi()$$的元素点乘操作,所以上式可以写为:

1

这个技巧大大减少了计算量,只需要计算所有$$x$$的自相关即可。

快速检测

对于候选patch来说,这些patch可以用循环变换来建模,因此每一次测试的时候可以对一批patch来测试,这里用$$K^z$$来表示训练patch和测试patch之间的核矩阵,训练patch是base sample $$x$$的循环变换,候选patch是base patch $$z$$的循环变换,所以$$K^z$$的元素就可以表示为$$\mathcal{K}(P^{i-1}z,P^{j-1}z)$$,而我们只需要第一行来定义这个核矩阵即可

1

外面加上$$C()$$表征了base patch $$z$$的循环位移,最后得到对于所有候选patch的回归函数:

1

注意到这里的$$f(z)$$是一个向量,包括了$$z$$的所有循环变换的输出结果,对其进行对角化来得到更快的计算效率:

1

对各个位置的$$z$$进行回归可以视为一种空间滤波操作,每一个$$f(z)$$是临近patch的核函数值的加权线性组合,权重为$$\alpha$$

快速核相关计算

核相关计算包含了计算两个向量的循环变换之间的核函数值,这里是最后的计算性能瓶颈,我们用循环变换的特性依然可以避免这种情况。

点积和多项式内核

点积核的形式:

1

那么$$k^{xx’}$$的元素表示为:

1

函数$$g$$若是对元素操作,那么上式可以改写为:

1

然后就可以对角化了:

1

这里$$\mathcal{F^{-1}}$$代表了逆DFT,对于多项式核函数:$$K(x,x’)=(x^{T}x’+a)^b$$,核函数可以这么计算:

1

因此,计算这些核函数只需要一些DFT/IDFT和逐元素运算,非常高效。

而对于RBF核:

1

核函数为:

1

特别地,对于高斯核:

1

核函数为:

1

多通道处理

求解对偶空间的参数有利于多通道视频帧的处理,只要在频域对其简单的求和就可以了。假设$$x$$包括了$$c$$个通道的信息:$$x=[x_1,…,x_c]$$,而计算核函数时只需要考虑$$x$$的范数和内积,对于范数来说,简单的将每个通道的范数相加即可;对于频域的内积来说,在频域简单的相加即可。对于线性核,只需要变换到频域然后用逐元素操作即可。

最后,算法的流程总结如下:

1

整个过程实现起来代码量很少,基于HOG特征或者原始像素点都可行,算法框架非常简洁,准确率上了70%,速度更是达到了200FPS以上,效果相当逆天…是个非常经典的工作。

参考文献

SiameseFC:Fully-Convolutional Siamese Networks for Object Tracking

读的第二篇有关Tracking的文章,依然用深度学习的方法做的Tracking,发表在ECCV 2016,项目主页:SaimeseFC Tracker,下面进入简介。

特点

  • Siamese的思想来做embedding
  • 离线训练&避免微调,以获得高FPS
  • 用卷积的方法来计算cross-correlation,比较新颖的metrics

Deep similarity learning for tracking

整个网络的结构其实非常简单,网络来学习一个函数$$f(z,x)$$,此函数用来比较exemplar image $$z$$和candidate image $$x$$,如果$$x,z$$是同一个objcet,那么函数$$f(z,x)$$返回值很大,反之则小。对于候选的所有$$x$$,贪心的比较所有的$$x$$即可,之后选取$$f(z,x)$$返回值最大的那个候选$$x$$。当前帧初始的$$x$$取objcet在上一帧的位置即可。

至于Similarity learning则选用Siamese network的模型,这里表示为函数$$\varphi$$,其实这里可以视为一个embedding的过程,因此$$f(z,x)$$可以重写为:$$f(z,x)= g(\varphi(z),\varphi(x))$$,函数$$g$$是距离/相似性的度量函数。

Fully-convolutional Siamese architecture

1

整个网络的结构如图,前面的fully-convolutional network相当于embedding的过程,后面用feature map的卷积求和来计算cross-correlation:$$f(z,x)=\varphi(z)*\varphi(x)+bI$$

网络的输出就是最后的那个score map,这个方法在最近的stereo matching中也用到了。

相对于score map中心的最大分数的位置乘以网络的stride,给出目标从帧到帧的位移。当然这里的evaluation是对multi-scale的搜索区域同时放在一个mini-batch中做的。具体的实现中对score map做了一个bicubic上采样,以得到更加精确的bounding-box定位。

Training

一个判别式的方法,对网络输入正负样例对,并采用logistic loss:$$l(y,v)=log(1+exp(-yv))$$,v是候选区域输入网络后的得分,$$y$$的取值为$$+1,-1$$。我们定义整个score map的损失函数为individual loss的均值:

1

那么优化网络的参数$$\theta$$直接用SGD就好了:

1

在网络训练的过程中忽略了label信息,object在图像中的尺度也被归一化。

1

当候选区域的大小大于帧的大小时,空白区域用图像像素均值来填充。

score map的值在距离中心(object的中心)R的区域内应该是正的,R和stride有关:

1

score map中所有点的loss被加权了以此来消除类别不平衡的问题。考虑以目标为中心的搜索图像是有效的,因为很可能最困难的子窗口以及对跟踪器的性能具有最大影响的子窗口是与目标相邻的那些子窗口。

因为网络是对称的:$$f(z,x)=f(x,z)$$,这其实允许我们对于不同的object使用不同的examplar尺寸,为了便于mini-batch的实现我们使用了uniform的size。

文章中Related work中提到有人用RNN来预测object的位置,以这种方法做Tracking,好像挺有意思。

效果

1

在VOT-14上的效果,还是非常不错的。

再看看今年VOT-2016,这个算法真是一颗赛艇!

1

search region 3x的时候能到86FPS,也是跑的比谁都快啊!(没有上篇GOTURN快)

打算用MXnet实现这个算法,敬请期待~

参考文献

CSDN:物体跟踪-Fully-Convolutional Siamese Networks for Object Tracking

GOTURN:Generic Object Tracking Using Regression Networks

文章标题为:Learning to Track at 100 FPS with Deep Regression Networks,发表在ECCV 2016,是Tracking中目前效果上的state-of-the-art,尤其在检测速度上达到了100FPS,Code用Caffe编写,这篇文章也是我看的第一篇有关Tracking的文章,下面进入简介。

简介

GOTURN这个方法有如下的特点和优势:

  • Offline Training:利用了大量数据离线训练的优势

  • Generic Object Tracking:可以跟踪未见过的类别样例(即不在训练集中出现的类别样例),对特定类别样例的跟踪效果更好

  • Avoid Fine-turning:以获取100FPS的速度

  • Regression-based Approach:不对patch进行classification,而是对object的bounding-box进行回归,以获得更高的FPS

算法细节

整个算法的框架其实非常简单:输入当前帧和前一帧进入网络,输出bounding-box的位置。

输入输出

以前一帧的目标区域为中心扩展(以接受一些背景信息),并切割出来。也就是说:在第$$t-1$$帧,Tracker预测的bounding-box位置为$$c=(c_x,c_y)$$,宽和高分别为$$w,h$$,crop出来的框大小为$$k_{1}w,k_1{1}h$$,$$k_1$$决定接受多少背景信息。

对于当前帧,也就是第$$t$$帧,基于上一帧的位置,找到待搜寻目标的区域(也就是文中的search region),网络的目的就是要回归目标在当前search region中的location.这里设置search region的坐标为$$c^{‘}=(c_{x}^{‘},c_{y}^{‘})=c$$,和前一帧框出来的区域是一样的,search region的大小为$$k_{2}w,k_{2}h$$,$$w,h$$是第$$t-1$$帧bounding-box的大小,文中设置$$k_1=k_2=2$$,对于快速移动的目标,$$k_1,k_2$$就需要增大了。

网络输出目标在search region上的相对坐标(top-left和bottom-right的位置)。

网络结构

go

其实很简单,在当前帧和前一帧分别crop出region之后,送入网络进行feature extraction(CaffeNet的卷积层),将这些feature级联并输入fully-connected层,fc层的目的是为了比较object的特征和当前帧的特征,以找到object被移动到了哪里。fc层学习到的是一个复杂的特征比较函数,输出目标的相对运动。随后fc层的输出被连接到一个4节点的层(分别代表bounding-box两个角的坐标),以输出object的位置。

如何理解Regression

整个文章的关键点就是这,回归的是什么?当然是bounding-box的坐标,那么回归的输入变量就是current frame,输出为bounding-box的坐标。当然前提是知道previous frame中object的坐标在中心位置。那么这个Regression Network学习到的就是:object在视频中前后帧的motion(包括位置改变、亮度变化、遮挡、畸变等等)到object坐标的变化!知道了object在前一帧的中心,找到object在当前帧的位置。

训练

利用视频和静态图片训练,优化predicted bounding-box和ground truth bounding-box之间的L1范数损失。

g

训练集中video的某些object带有bounding-box,按照前文所述将search region给crop出来,将两帧和当前帧bounding-box的坐标输入网络来优化。在训练的时候也可以在当前帧进行人为的random crop,以增加tracker的鲁棒性、增广数据集。

ggg

模型也可以用带有location的静态图片来优化,这里比较有意思,将静态图片中待跟踪的object放在中间并框定region(相当于作为t-1帧的region),之后将整张图当做第t帧来跟踪上一帧中的目标。当然对这里的静态图片做了一定程度的形变才作为第t帧,这个数据增广的trick是个亮点,避免了过拟合等问题。

整个训练过程从前一天下午3:40开始,到第二天早上8点结束,大约16.5个小时。训练数据集ALOV300++大约11GB,ILSVRC 2014 DET大约47GB。

运动的平稳性

因为物体在视频中相邻两帧的运动具有相对平稳的性质,形变、位移等变化不会太大,所以这里对bounding-box的位移进行一个建模

1

这里$$w\vartriangle{w}$$和$$h\vartriangle{h}$$就是物体的相对位移(和$$w,h$$有关),通过统计发现这里的$$\vartriangle{w}$$和$$\vartriangle{h}$$似乎是服从均值为0的拉普拉斯分布,也就是说实验数据支持相邻帧的motion具有平稳性这个性质。视频中的相邻帧大多是small motion。

同理对于bounding-box的size:

1

这里$$\gamma_{w}$$和$$\gamma_{h}$$就是物体的相对形变,通过统计发现这里的$$\gamma_{w}$$和$$\gamma_{h}$$似乎是服从均值为1的拉普拉斯分布,bounding-box的尺寸几乎不变,也就是说上述理论依然是成立的。

有了这个先验之后,就可以进行更加具有启发式的训练过程了:这里用ImageNet的数据集做增广,给单张静态图片中的object加上上述的位移和形变(就是刚说过的服从拉普拉斯分布的位移和形变),这样训练好的网络将更好的适应small motion。

效果

两个跟踪指标:Acurracy和Robustness,范围都是[0,1],当然每个视频都有一些属性:遮挡、光照变化、运动变化、尺度变化、摄像机运动,tracker在这几个指标上分别测量了Acurracy和Robustness并求了平均,以此作为测度指标。准确率和速度都是state-of-the-art

Tracker是如何工作的

两种假设:

  • 网络比较前后两帧,并找到目标在当前帧的位置,有点verification的意思
  • 网络就想一个通用的object detector,找到最近的目标

于是作者又做了一个实验,撤销网络的前一帧输入,跟踪的性能急剧下降,这时的网络表现的像一个通用的object detector。 而当当前帧出现较为严重的遮挡/相机运动,此时tracker可以从前一帧中获得非常大的性能提升,因为tracker记住了哪个objcet是要跟踪的,这种情况中,第一个假设扮演了重要的角色。而当帧间变化剧烈时,相邻帧的比较更为困难,此时假设二占主导,tracker表现的像一个通用object detector

Batch Normalization简介

本文讲述2015年深度学习领域影响比较大的一篇文章:

Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

目前已经运用到了很多网络的训练中,包括DCGAN-tensorflow,以加速网络的训练速度

网络训练的难题

训练深度神经网络的难处在于,在训练过程中,每层的参数在不断改变,因此每一层输入的分布是不断变化的,并且随着网络的加深,这种变化会被放大。这就要求每一层去拟合一个新的分布,因此这里就要求更小的学习速率和比较好的参数初始化,并且网络的参数位于sigmoid非线性函数快饱和的区域时,梯度的幅值会越来越小,这样网络就更难训练了,作者把这种特征在网络中的分布变化的现象称作internal covariate shift。

Batch Normalization

论文的核心目标就是通过减少网络中各层的internal covariate shift,通过使得网络每一层的输入近似同分布来做到。

网络的输入如果做了白化(使得数据具有零均值、单位方差、特征之间去相关),网络的训练过程会大大加快,但是训练集太大,对每一层网络的输入做白化处理会很费时间,并且也不再方便求导,所以这里要做的就是对网络每一层的输入做一个“近似的”白化处理:

1

$$x^{(k)}$$指的mini-batch中的单个样例在任一层的输入,均值$$E[x^{(k)}]$$,方差$$Var[x^{(k)}]$$,这里将输入零均值化并除以方差来近似白化。

但将数据白化之后,对原来的数据分布有所改变,为了补偿这一点,引入了一个线性变换:

2

这也是全篇最关键的一点,对于原始数据的重构!$$x$$的每个特征$$x^{(k)}$$都有不同的尺度缩放算子$$\gamma^{(k)}$$和平移算子$$\beta^{(k)}$$,这两个参数是在网络中学到的。

假设每个mini-batch有m个训练样本,论文中定义了Batch Normalizing Transform如下:

1

实际上就是在网络的输出层之前加了一个线性层,这个线性层首先将特征零均值化和方差单位化,再做一个补偿的线性变换。对于这个线性层的参数的求导也是很简单的,假设损失函数为$$l$$,那么通过链式法则,对$$\gamma$$和$$\beta$$的导数计算如下:

1

有了mini-batch上的均值和方差,在网络训练完成之后的测试阶段,就可以用参数的无偏估计计算出整个训练集上的均值(不变,也就是mini-batch上的均值)和方差:

1

因此整个网络的训练和测试过程可以描述如下:

1

因此测试样例输入网络时的BN层变换如下所示:

1

1

还需要提及的一点是,这里g为非线性激活函数,网络偏置参数$$b$$经过BN层后其实是没有用的,因为不管$$b$$的值为多少,最后也会被零均值化,但BN层后面还有个&&\beta&&参数作为偏置项,所以$$b$$这个参数就可省去。因此最后把BN层和激活函数层表示为:

1

如果使用更大的学习率,势必导致网络的参数变大,但是BN层对学习速率的设置非常鲁棒,考虑将参数$$W$$变大$$a$$倍,但是经过零均值化和方差归一化之后单层的输入是不随尺度算子$$a$$的改变而改变的,即:

1

因此有:

1

应用Batch Normalization到卷积神经网络

对于卷积层,我们希望feature map的不同位置是被一起归一化的,为了减少参数的数量,这里将一个feature map当做一个神经元处理,因此这里对于每一个feature map学习了两个参数$$\gamma^{(k)}$$和$$\beta^{(k)}$$,原先对于全连接层只需要用m个样例来估计单个特征的方差和均值,现在扩展一下,用m个样例在feature map上的特征来估计单个feature map的$$\gamma^{(k)}$$和$$\beta^{(k)}$$,若feature map的大小为$$(p,q)$$,那么用$$m\times{p}\times{q}$$个特征来估计这个mini-batch的方差和均值进而计算出$$\gamma^{(k)}$$和$$\beta^{(k)}$$

性能

性能肯定是好的,文章里说可以用更大的学习速率,更随意的初始化,甚至不用dropout了,速度提升了一个数量级(14 times fewer),和更高的识别率。

打赏

如果你觉得文章不错,打赏我一下吧~

3D7E26A0-EBC2-4BCE-87BA-1808C00CD707

搭建一台用于深度学习的工作站

最近老板评上优青,并且NVIDIA 5月发布了新显卡GTX 1080,于是决定买买买。

硬件配置

  • 显卡:NVIDIA GTX 1080 3块
  • CPU:Intel Core i7-5930K Haswell-E 6-Core 3.5GHz
  • 内存:128GB DDR4
  • 主板:GIGABYTE X99 GAMING 5P(四路PCI-e X16)
  • SSD:512GB
  • 硬盘:Samsung 850 Pro 3TB
  • 显示器:三星S22B310B 21.5英寸宽屏LED背光
  • 机箱:Corsair Carbide Air 540(NVIDIA DevBox同款)
  • 电源:EVGA 1600W 整套硬件买下来差不多4.5W RMB,价格还算比较合理。

为什么选用GTX 1080?

候选的显卡有3款:

  • NVIDIA GTX 1080
  • NVIDIA Titan X
  • NVIDIA Tesla K80

GTX 1080相对于Titan X来说,单精度浮点运算能力达到了9 TFLOPS>7 TFLOPS(Titan X),但是传输带宽、显存相对来说小一点,不多8GB的显存如果用MXnet这样的压榨显存的框架应该绰绰有余了,而K80在售价将近3W RMB的情况下,单精度运算能力才是GTX 1080的两倍有余,综合考虑性价比的情况下,选用了GTX 1080。

不过综合散热等因素的考虑,暂且只买了三块,反正主板上有4个PCIe插槽,并且可以满负荷运作,需要的话到时候再买即可。

驱动和框架的搭建

GTX 1080作为新产品,因为驱动不兼容、显示器超频、操作系统崩溃等各种原因,这部分花了一天的时间才调好…

选用的操作系统、驱动和框架:

  • Ubuntu 16.04
  • CUDA 8.0 rc1
  • NVIDIA driver version 367.27
  • cuDNN v5 for CUDA 8.0 rc
  • MXnet

按照其官方提供的安装方式即可。

环境配置中的问题和解决方法

NVDIA官方在近期推出GTX 1080的驱动版本为367.27,然而CUDA 8.0中自带的驱动才更新到361版本,安装完毕CUDA之后,执行:

$ nvidia-smi

连接不到NVIDIA的驱动啊… 于是这时候再把367.27版本的驱动打上,发现执行上面的命令出结果了:

1

跑一跑CUDA的例程deviceQuery,然而还是有问题:找不到GPU设备,貌似CUDA的环境没搭配好。 于是找到了下面这个解决方法:

2

0/1/2/3都试试,你会发现管用的。 就这么搞定了?当然没,因为驱动程序的关系我进入了lightdm login loop这个问题中。 然后发现在驱动安装的过程中,不要覆盖X window的配置就不会出现这个问题。 于是测试了一下MXnet的例程:

3

速度还不错~差不多是CPU的十倍左右

远程登录内网的工作站

ngrok

如何登陆内网的工作站?这玩意简直是个神器啊!

详见:http://ngrok.cc

你会感谢我的!

再配置完公网上阿里云的git服务器,整个过程就搞定了!

说好的图呢?

下面上图~

7661BE3A-FFED-4652-966C-E690CEEFF041

8FC1EF15-0EA9-4DD7-AC16-135E563D0937

8BB0A35D-F4A7-4DAD-81B5-94265A8F828B

总之还是很满意的,可以开心的干活儿了~

打赏

如果你觉得文章不错,那么打赏我一下吧~

3D7E26A0-EBC2-4BCE-87BA-1808C00CD707