在笔者的上一篇博客中,提到了如何从tensorflow框架下提取出模型参数并转化为caffe框架下的模型参数,并在最后生成了一个1.1GB的.prototxt格式的参数文件,该文件里面主要记录了网络架构以及各层对应的参数。可是我们在使用caffe进行网络前传得到结果的时候,是需要使用一个caffemodel文件的。那么,如何通过.prototxt格式的参数文件去生成这个caffemodel文件呢?大家还记得tensorflow2caffe(1)这篇博客吗?里面讲述了caffemodel文件里面记载了什么,而在读caffemodel文件的时候,我们使用了ReadProtoFromBinaryFile函数将参数从二进制读出到proto中,搭配WriteProtoToTextFile函数将参数从proto中写入文件。
在生成caffemodel时,正好是该过程的逆。
根据读caffemodel的经验,笔者凭借直觉直接进入了caffe-master/src/caffe/util/io.cpp文件,并从中找到了可以利用的函数。我们可以先使用ReadProtoFromTextFile将文件中的参数写入proto,然后再使用WriteProtoToBinaryFile函数将proto中的参数转化为caffemodel。
具体代码如下所示:
#include <caffe/caffe.hpp>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <algorithm>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <iostream>
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/io.hpp"
using namespace caffe;
using namespace std;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::Message;
int main()
{
NetParameter proto;
ReadProtoFromTextFile("/home/cvlab/model/model.prototxt", &proto);
WriteProtoToBinaryFile(proto, "/home/cvlab/model/model.caffemodel");
return 0;
}
对应的CMakeLists.txt文件如下所示:
cmake_minimum_required (VERSION 2.8)
project (write_model)
add_executable(write_model wm.cpp)
include_directories ( /home/cvlab/caffe-master/include
/usr/local/include
/usr/local/cuda/include
/usr/include )
target_link_libraries(write_model
/home/cvlab/caffe-master/build/lib/libcaffe.so
/usr/lib/x86_64-linux-gnu/libglog.so
/usr/lib/x86_64-linux-gnu/libboost_system.so
)
然后我们运行一下该程序,首先编译:
然后运行:
可以看到,是不是生成了全新的model.caffemodel文件呢?大功告成!
到这里,tensorflow2caffe框架转换的工作就正式完成了!我们总结一下我们收获了什么呢:
在tensorflow2caffe(3)中我们重建了网络test.prototxt。
在本节中,我们得到了caffemodel。
那么,要得到网络的前传结果,就直接使用c++或者python的网络前传程序调用测试网络文件和模型参数进行网络前传得到结果就行了,具体操作可以参阅笔者的博客:
caffe工程化实例:将caffe分类程序编译成.so文件并在程序中调用
到此,使用tensorflow训练的模型就可以在caffe框架下运行了,tensorflow2caffe系列完满收官!
一些总结和感悟:
tensorflow到caffe的框架转换笔者认为是相对困难的,难在需要对tensorflow,caffe和深度学习理论有入门级的了解。因为tensorflow是一个高度支持自定制的框架。即不同的工程师有不同的网络实现方案与风格,因此在进行框架转换的时候,需要先读懂tensorflow程序,理解网络前传数据流程,然后再分层取出参数。然后在caffe上面复现网络前向传播的时候,需要对caffe有不浅的了解,因为涉及在caffe上面添加网络层,以及整理网络架构。对于笔者而言,进行一次框架转换,对于深度神经网络底层构造也熟悉了很多,受益匪浅。
总的来说,进行tensorflow2caffe框架转换,笔者探索的步骤如下:
(1) 首先弄懂caffemodel里面到底是什么?tensorflow2caffe(1)
(2) 从tensorflow中取出模型参数。tensorflow2caffe(2)
(3) 复现.prototxt格式的网络结构,按需在caffe上重写层,并将tensorflow中取出的模型参数转到caffe下,得到网络参数文件。tensorflow2caffe(3)
(4) 生成caffemodel,详见本篇博客上半部分。
(5) 利用网络结构文件与caffemodel进行网络的前向传播得到结果。 在c++程序中调用caffe训练完毕的模型进行分类
在本篇博客的尾声,笔者想告诉大家,在tensorflow2caffe系列中,笔者对于一些问题的描述也许过于平淡,如果读者朋友们遇到问题,很欢迎在评论区指出,笔者一定耐心回复。另外,笔者诚心希望,本系列也能解决各位读者朋友的其他问题,因为笔者的博客对大家有帮助是笔者最愿意看到的。同时,如果各位读者朋友觉得有必要,欢迎订阅笔者的博客,笔者会不定时分享一些有关深度学习的科研与项目方面的经验与记录,保证干货。
欢迎阅读笔者后续博客,各位读者朋友的支持与鼓励是我最大的动力!
written by jiong
凿井者,起于三寸之坎,以就万仞之深