在博客开始前,首先郑重感谢博主jiongnima的博客对我的帮助,我按照博主的方法顺利的把bcnn模型的tensorflow版转为caffe版,关于bcnn模型,它是个细粒度分类模型,我将在后续的博客中详细介绍。
首先隆重呈上博主的链接:
https://blog.csdn.net/jiongnima/article/details/78435500
转模型系列博文的操作主要基于博主的实验探索,中间也穿插着我自己的一些想法以及重新编排,在强烈膜拜原创的基础上,将转模型过程进行了亲自的实践并成功复现,因此暂时(不要脸)的将该系列博文归为原创。
下面进入正题部分。
上一篇博客https://blog.csdn.net/zl3090/article/details/89045038 讲到了将tensorflow提取出的权重转为caffe框架的shape,本篇重点讲如何将权重写入deploy文件,以及生成caffemodel。
首先是将权重写入deploy文件:
将权重写入deploy的过程实际就是把所得到的权重文件与对应的层文件拼接在一起,上文已经生成所有卷积层和全连接层的w和b,那么接下来简单的思路是把deploy文件拆分开来,然后用cat命令逐个将其连接,如下所示(由于不便截图,此处使用原作者的图,效果是一样的):
所得参数文件示意图:
其中参数的展示:
然后将data写入deploy,写入形式为:
layer {
name: "conv_layer_name"
type: "Convolution"
bottom: "bottom_blob"
top: "top_blob"
param { lr_mult: ... }
convolution_param {
num_output: output_dims
kernel_size: kernel_size
pad: padding_size
stride: stride
bias_term: false
}
#add params weight
blobs: {
data: ...
...
shape {
dim: ...
dim: ...
dim: ...
dim: ...
}
}
#add params bias
blobs: {
data: ...
...
shape {
dim: ...
dim: ...
dim: ...
dim: ...
}
}
}
因此就是把w和b按顺序写入对应层的layer即可,手动分割deploy文件示意图:
然后再将上图中的文件和转化得到的.prototxt格式的众多参数文件放在同一目录下,并且使用一个index.txt文件从上到下记录了拼接顺序:
然后使用一个名为ss.sh的脚本文件作拼接:
#!/bin/bash
cat index.txt |while read line
do
cat $line >>model.prototxt
done
然后我们运行ss.sh文件:
生成了一个很大的prototxt文件,这就是最终的模型文件,它将将被转化为.caffemodel的模型文件并在测试程序中被调用。
接下来讲述如何从prototxt生成caffemodel
还记得博客https://blog.csdn.net/zl3090/article/details/89040761 中探索了caffemodel存储了什么内容的过程吗?在读caffemodel文件的时候,我们使用了ReadProtoFromBinaryFile函数将参数从二进制读出到proto中,搭配WriteProtoToTextFile函数将参数从proto中写入文件。 因此在生成caffemodel时,正好是该过程的逆。
我们可以先使用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框架转换的工作就正式完成了!