windows下用caffe加载二进制模型(linux下训练)的问题
最近,需要移植faster-rcnn的detect部分到android平台上,为方便删减代码与调试,需要跨平台兼容到windows下运行,windows下调试的时候,用的是linux下的模型定义proto与训练好的二进制模型,但是,一直加载模型不成功,逐步解决方法如下:(1)核对protobuf版本,均为2.5.0,不可能是因为版本不兼容所致;(2)核对cafe.proto,这个文件...
最近,需要移植faster-rcnn的detect部分到android平台上,为方便删减代码与调试,需要跨平台兼容到windows下运行,windows下调试的时候,用的是linux下的模型定义proto与训练好的二进制模型,但是,一直加载模型不成功,逐步解决方法如下:
(1)核对protobuf版本,均为2.5.0,不可能是因为版本不兼容所致;
(2)核对cafe.proto,这个文件在linux和windows下是相同的,编译出来的caffe.pb.h与caffe.pb.h.cc几乎完全相同(除个别处0填充外),因此不可能是proto定义不同引起的失败;
无奈,只能调试protobuf中的代码,逐步跟进:
(3)编译windows下protobuf代码(debug版本),注意protoc同时编译更新,并调试caffe的模型加载,发现问题如下:
具体表现为:读取模型buffer时,只读取很少部分便文件终止,因此,不能成功初始化每个layer的参数,问题出现在open/read文件操作函数,
actual-read-size = open(file-descriptor, buf-ptr, need-size),其中need-size默认patch size = 8192,读取到的actual-read-size为82, 远远没有读取完毕,怀疑是遇到了终止符;
用UltraEdit查看二进制模型,如下:
注意红色圆圈部分,为第83个字符, 1A对应的ASCII码为SUB,而在windows下,SUB是一种文本文件读取终止符,因此,读取模型buffer提前终止,所以失败,
1A对应的十进制整数为26, protobuf在save以及parse caffe model的时候(取决于caffe.pb.cc, 不同的网络对应的二进制模型可能出现26, 也可能不出现26,复杂程度不同而已),会插入tag作为分隔不同值域的标识,tag中出现了26, 即windows下的sub终止标识;
(4)为何会在二进制中出现sub?
按道理来说,都是二进制字节流。这就是windows下open/read存在的问题, 同时也是windows与linux处理二进制文件盒文本文件的方式不同。
(a) windows区分文本文件与二进制文件,linux下则不区分(均为字节流);
(b)open/read(系统函数)与fopen/fread(C语言API)是不同的,除了缓冲机制外(此处的缓冲机制与我们的问题无关),
在windows下,fopen可以指定“rb”二进制读取方式打开,read则需要联合O_RDONLY|O_BINARY使用,读取二进制模型。
而在linux, 只有O_RDONLY,无O_BINARY,, O_RDONLY一般定义在/usr/include/bits/fcntl.h------->fcntl-linux.h 中, 即便存在O_BINARY的话,对于打开读取二进制模型来说,O_RDONLY与O_RDONLY|O_BINARY是无差别的,fopen(file, "rb")与fopen(file, "r")也是无差别的;
那么,在caffe的src/util/io.cpp文件的ReadProtoFromBinaryFile函数中便存在一个小bug, 使得,caffe在windows下加载linux下训练的模型成为一种不可跨平台性(狭义的),
修正如下:
#ifdef _WIN32
int fd = open(filename, O_RDONLY|O_BINARY);
#else
int fd = open(filename, O_RDONLY);
#endif
当然,caffe源码中均未出现O_BINARY,需要在用到出现错误的同时,想到这点不同,并对应修正编译(本处caffe版本为faster-rcnn python版中对应的caffe分支, 请检查caffe最新分支是否更正过此所谓的bug(自定义bug ^_^))。
更多推荐
所有评论(0)