http://www.abcplus.com.cn/course/67/activity/177/replay/6/entry
入门Caffe
Caffe优缺点
优点:
• 速度快。Google Protocol Buffer 数据标准为 Caffe 提升了效率。
• 学术论文采用此模型较多。不少论文都与 Caffe 有关(R-CNN,DSN,最近还有人用 Caffe 实现 LSTM)。
缺点:
• 曾更新过重要函数接口。有人反映,偶尔会出现接口变换的情况,自己很久前写的代码可能过了一段时间就不能和新版本很好地兼容了(现在更新速度放缓,接口逐步趋于稳定)。
• 对于某些研究方向的人并不适合。这个需要对 Caffe 的结构有一定了解(后面提到)。
Caffe 代码层次
回答里面有人说熟悉 Blob,Layer,Net,Solver 这样的几大类,我比较赞同。我基本是从这个顺序开始学习的,这四类复杂性从低到高,贯穿了整个 Caffe 。把他们分为三个层次介绍。
• Blob:是基础的数据结构,是用来保存学习到的参数以及网络传输过程中产生数据的类。
• Layer:是网络的基本单元,由此派生出了各种层类。修改这部分的人主要是研究特征表达方向的。
• Net:是网络的搭建,将 Layer 所派生出层类组合成网络。
• Solver:是 Net 的求解,修改这部分的人主要会是研究 DL 求解方向的。
跑程序
学习程序的第一步,先让程序跑起来,看看结果,这样就会有直观的感受。
Caffe 的官网上 Caffe Deep Learning Framework 提供了很多的examples,你可以很容易地开始训练一些已有的经典模型,如LeNet 。我建议先从 LeNet MNIST Tutorial 开始,因为数据集很小,网络也很小但很经典,用很少的时间就可以跑起来了。当你看到 terminal 刷拉拉的一行行输出,看到不断减少的 loss 和不断上升的 accuracy,训练结束你得到了99+%的准确率,会由衷产生成就感和学下去的信心。初学的时候,建议多跑跑几个例子,熟悉一下环境和接口。
单步调试,跟着Caffe 在网络里流动
在 Caffe 的接口稍微熟悉之后,已有的例子也没有新鲜感了,这时候要看看具体是怎么实现的。我觉得最好的方法是通过单步调试的方式跟着程序一步一步的在网络里前向传播,然后再被当成误差信息传回来。
Caffe 就像一个你平常编程中 Project,你可以使用 IDE 或者 GDB 去调试它,这里我们不细说调试的过程。你可以先跟踪前向传播的过程,无非就是从高层次到低层次的调用 forward 函数Solver->Net->Layer->Specific Layer (Convolution 等...)。后向传播也类似,但因为你对 Caffe 里面的各种变量运算不熟悉,当你跟踪完前向传播时可能已经头晕眼花了,还是休息一下,消化一下整个前向传播的流程。
刚刚开始你没有必要对每个 Layer 的计算细节都那么较真,大概知道程序的运算流程就好,这样你才可以比较快的对 Caffe 有个大体的把握。
个性化定制Caffe
到这里,你已经可以说自己有用过 Caffe 了,但是还不能算入门,因为你还不知道怎么修改源码,满足自己特定的需求。我们很多时候都需要自己定义新的层来完成特定的运算,这时你需要在 Caffe 里添加新的层。
你一开始肯定无从下手,脑子一片空白。幸运的是 Caffe github 上的Wiki Development · BVLC/caffe Wiki · GitHub 已经有了教程了,而且这是最接近 latest Caffe 的源码结构的教程,你在网上搜到的 Blog 很多是有点过时的,因为 Caffe 最近又重构了代码。你可以跟着它的指导去添加自己的层。
虽然你已经知道要在哪里添加自己的东西了,但你遇到最核心的问题是如何写下面这四个函数。
• forward_cpu()
• forward_gpu()
• backward_cpu()
• backward_gpu()
你可以先模仿已有的层去实现这四个函数,而且我相信 forward 函数很快就可以写出来了,但 backward 的还是一头雾水。这时我们就要补补神经网络里最核心的内容了——Backpropagation。
理解并实现Backpropagation
这个我觉得是与平台无关的,不管你是使用 Caffe 、Torch 7,还是Theano,你都需要深刻理解并掌握的。下面将推荐个人觉得比较好的学习步骤。
• 从浅层的神经网络(所谓的全连接层)的后向传播开始,因为这个比较简单,而且现在我们常说的 CNN 和 LSTM 的梯度计算也最终会回归到这里。
• 回去查看 Caffe 源码里 Convolution 层的实现,但发现自己好像没看懂。虽说卷积层和全连接层的推导大同小异,但思维上还是有个 gap 的。我建议你先去看看 Caffe 如何实现卷积的,Caffe 作者贾扬清大牛在知乎上的回答让人茅塞顿开。重点理解 im2col 和 col2im 。
• 这时你知道了 Convolution 的前向传播,还差一点就可以弄明白后向传播怎么实现了。我建议你死磕 Caffe 中 Convolution 层的计算过程,把每一步都搞清楚,经过痛苦的过程之后你会对反向传播有了新的体会的。在这之后,你应该有能力添加自己的层了。
• 最后,建议学习一下基本的 GPU Cuda 编程,虽然 Caffe 中已经把 Cuda 函数封装起来了,用起来很方便,但有时还是需要使用 kernel 函数等 Cuda 接口的函数。
初识神经网络
网络如图所示,整体上是采用 Unet+Resnet 的思想。里面每个Resnet Block 都是由多个卷积层和 bn 层和 relu 层组成的。我们只展示主体结构(整体深度大概150多层,这部分是参考了grt123 的网络结构)。
3D-CNN 算法思想
业界两套网络的做法比较普遍,比如用 Unet 切割或 Faster RCNN 检测,用 3D-CNN 分类,如下图所示。
这里用的是如下统一的一套模型架构,即 3D Faster RCNN 的 RPN 网络,没有后续的全连接做分类,也没有再在后面接一套 3D-CNN 来做降假阳,能减少需要调节的网络参数。
该 hard mining 的过程,其实就是用上一层的模型作为下一层的输入,每一层的训练数据都选取比上一层更难分的。
loss 函数的设计
在计算 loss 函数的时候,我们做了2点优化。
1)在使用 hard mining 的时候,每个 batchsize 里面负例的个数会明显多于正例。为了防止算 loss 的时候被负例主导。我们将 loss 函数分成3个部分,负例的 loss,正例的 loss 和边框的 loss 。
2)在上一节提到的层次化 hard mining,我们在最后一层训练模型的时候,会修改 loss 函数的计算,对于分错的负例和正例,做加权。这个思路和 focal loss 是很像的。
领取专属 10元无门槛券
私享最新 技术干货