从caffe编写自己的深度学习Forward框架,用于deploy

近期,在现在所在的公司从事人脸识别的工作。使用的深度学习工具是caffe。后需要将算法布置到项目中去甚至是ARM上去。即便caffe有自己的libcaffe库能使用,但是这个库本身带有反向学习功能,而实际上deploy并不需要,故deploy时明显可以对caffe进行瘦身。另caffe有众多的依赖项,尤其是依赖protobuf使得我在工作中有诸多不便(protobuf不但2和3版本兼容不好,某些老的protobuf也无法被更新的protobuf使用,这样会导致之前的网络可能无法被更新的caffe识别到)。


简化caffe实际上并不复杂。我们可以理一理需要做的事情:

我命名我的Net是 XYZNet,那么XYZNet能够计算,最少需要两类资源:

1:每一层的类型和其参数   2:每一层的权值(weights)和偏移值(bias),注意偏移值也可以是没有的。

以上两类资源都来自于你定义的caffe模型和训练好的model。可以简单将caffe的这些参数导出成二进制文件然后加载到XYZNet中。

由于层来源于文件,得到是每一个层的类型,故需要有一个能动态生成层对象的运行时结构。这样就能在读取文件时,创建每一个层的实例化对象,并将其指针保存至XYZNet的vector中。

为了能执行forward的计算,每一个层需要知道其输入的数据信息和输出的数据的大小,这些资源需要提前分配好或计算得到,以方便forward的计算,这里把能预处理的操作放在这里会比较合适。故每一个层都对应一个SetUp函数,来处理这些工作。

剩下的就是每一个层的forward的工作了。这部分的处理,即可以将caffe的对应代码COPY过来,也可以在掌握原理的情况下自己适当编写,因为有些层的caffe代码,实在是对于仅仅保留forward计算的时候,是可以简化许多的。

在分析以上需要做的事情后,就可以简单设计其forwrad框架了:

设计一个父类:baselayer,所有的具体层都继承于它。它需要最少3个函数:InitLayer 从文件中读取模型参数和训练好的权值model;SetUp 根据输入的数据的尺寸信息,计算出输出的尺寸信息并分配资源,这里也许会计算出中间的临时变量的值;Forward 函数,计算结果。在XYZNet中将有一个vector<baselayer* >,用来保存各种层的实例化对象。

建立一个链表,链表中包含层的类型名称和每一个层的构造函数,这样查找链表就能根据类型名创建层的实例化对象(caffe用的是map<string,func>,func是构造函数,这样来创建层的实例对象的)。

关于资源分配,为了能有效利用内存空间,建立一个内存管理类,每一次一个层需要分配输出数据空间时,将向这个管理类申请内存,并告诉管理类自己输出数据的名称,这段内存将由这个管理类管理,层本身将并不关心这个数据空间。而一个层需要输入数据时,将也像这个管理类提出申请,它需要提供自己输入数据的名称字符串,管理类将返回字符串对应的数据交给这个层,当层计算结束时,管理类将会知道本层输入数据已经计算完毕,它会做一些工作,以保障这个数据块能被其他层作为输出数据占用。

在forward的时候,首先需要申请得到输入输出数据存储空间,完成后将告诉内存管理器输入数据可以被释放。因为在forward计算中,输入的数据也就是caffe的bottom数据很多时候其数据是可以释放掉的,这样实际上能节约内存空间。

以上分析,大致能有一个清晰的forward设计思路。

一下是框架示意图:

猜你喜欢

转载自www.cnblogs.com/XYZYY/p/9275871.html