目前为止已经有很多成熟的深度学习框架,比如tensorflow、caffe、pytorch、paddlepaddle等等,很多时候我们训练时使用了一个框架,但是部署时需要使用另一个框架。就比如,我们训练使用了caffe,但是部署到生产使用的时tensorflow。又比如,我们需要部署到移动设备上,这是我们可能选择了一些移动端深度学习推理框架(ncnn、mnn、armnn等)。但是这些框架的模型文件都是不同的,所以如果我们需要解决上面的情况,就需要对模型进行转换。
其实现在已经又很多开源的转换工具,比如微软出品的mmdnn,但是深入了解模型转换是又必要的,因为新算子的出现、各框架模型版本的跟新等等问题,很多时候我们还是需要自己写转换。
- tensorflow2caffe
下面我们就先来看看tensorflow模型到caffe模型的转换。先来看看tensorflow和caffe的模型文件:
tensorflow:xxx.meta、xxxx.index、xxx.0000-data-0001
caffe:deploy.prototxt、XXXX.caffemodel
deploy.prototxt是caffe描述网络结构的文件,而XXXX.caffemodel是caffe的权重参数文件。我们可以看到,只要把tensorflow模型文件中的网络解析出来,写入一个deploy.prototxt,把tensorflow中的权重参数解析出来,写入XXXX.caffemodel,是不是就可以完成模型的转换了。 - caffe的deploy.prototxt
先来看看deploy.prototxt中是怎么描述神经网络的层的:
layer {
name: "ReLU2_2" #relu层
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
上面是一个relu层的例子,基本上,caffe层的描述都是这样,name是层的名字,top是下一层的名字,bottom是上一层的名字,type是这一层的类型如(InnerProduct是全连接层等等)。当然还会有其他参数,比如BatchNorm层:
layer {
bottom: "linear"
top: "bn1"
name: "bn1"
type: "BatchNorm"
batch_norm_param {
use_global_stats: true
}
}
不同的层会有相应参数的增减。如果我们的模型是用tensorflow训练的,那么我们就可以根据我们的模型来写出一个deploy.prototxt。
- 读取tensorflow模型
接下来我们来解析权重
model_path='model/'
saver=tf.train.import_meta_graph(model_path+'model.resnet.ckpt.meta')
with tf.Session() as sess:
saver.restore(sess,tf.train.latest_checkpoint(model_path))
graph = tf.get_default_graph()
有了graph就可以取到模型中的各种权重参数了,比如:
linear_w=np.squeeze(graph.get_tensor_by_name('linear_model/w1'))
接着,我们创建caffe网络:
cf_prototxt = "deploy.prototxt"
net = caffe.Net(cf_prototxt, caffe.TEST)
#把解析上面从tensorflow得到的linear_w写到caffe的net中对应的层里
net.params['linear'][0].data[:]=np.transpose(linear_w, (1,0))
#当然可能还有偏移量b
linear_b=np.squeeze(graph.get_tensor_by_name('linear_model/b1'))
net.params['linear'][1].data[:]=linear_b
依次类推,我们可以一层一层的把tensorflow参数写进caffe的net中,最终完成模型的转换。
- 注意
注意这里只写了tensorflow到caffe模型转换的一般原理,但tensorflow和caffe的层不是一一对应的,很多层都略有不同,所以要根据实际稍加改动。
网友评论