我希望能够将Tensorflow模型转换为Caffe模型。
我在谷歌上搜索但是我只能找到从caffe到tensorflow的转换器,但不是相反。
有没有人知道如何做到这一点?
谢谢, EVI
答案 0 :(得分:5)
我遇到了同样的问题并找到了解决方案。代码可以在这里找到(https://github.com/lFatality/tensorflow2caffe),我还在一些Youtube视频中记录了代码。
Part 1涵盖了在Caffe和VGG-19中构建tflearn的体系结构(TensorFlow的更高级API,对TensorFlow代码的一些更改也应该有效)。
在Part 2中,描述了将TensorFlow模型中的权重和偏差导出为numpy文件。在tflearn中,您可以获得如下图层的权重:
#get parameters of a certain layer
conv2d_vars = tflearn.variables.get_layer_variables_by_name(layer_name)
#get weights out of the parameters
weights = model.get_weights(conv2d_vars[0])
#get biases out of the parameters
biases = model.get_weights(conv2d_vars[1])
对于卷积层,layer_name为Conv_2D
。完全连接的层称为FullyConnected
。如果使用某个类型的多个图层,则使用带有前面下划线的上升整数(例如,第2个转换图层称为Conv_2D_1
)。我在TensorBoard的图表中找到了这些名字。如果在体系结构定义中命名图层,则这些layer_names可能会更改为您定义的名称。
在原生TensorFlow中,导出将需要不同的代码,但参数的格式应该相同,因此后续步骤仍然适用。
Part 3涵盖实际转化。当你创建caffemodel时,权重的转换是至关重要的(偏差可以在没有变化的情况下进行)。保存过滤器时,TensorFlow和Caffe使用不同的格式。虽然TensorFlow使用[height, width, depth, number of filters]
(TensorFlow docs, at the bottom),但Caffe使用[number of filters, depth, height, width]
(Caffe docs, chapter 'Blob storage and communication')。要在格式之间进行转换,您可以使用transpose
函数(例如:weights_of_first_conv_layer.transpose((3,2,0,1))
。可以通过枚举TensorFlow格式(原点)然后将其切换为3来获得3,2,0,1序列Caffe格式(目标格式),同时将数字保持在特定变量。)
如果要将张量输出连接到完全连接的层,事情会变得有点棘手。如果您使用输入尺寸为112x112的VGG-19,它看起来像这样。
fc1_weights = data_file[16][0].reshape((4,4,512,4096))
fc1_weights = fc1_w.transpose((3,2,0,1))
fc1_weights = fc1_w.reshape((4096,8192))
如果在张量和完全连接层之间的连接处导出参数,则从TensorFlow获得的是形状为[entries in the tensor, units in the fc-layer]
的数组(此处为:[8192, 4096]
)。您必须找出输出张量的形状,然后重新整形数组,使其符合TensorFlow格式(参见上文number of filters
为number of units in the fc-layer
)。之后,您使用先前使用过的转置转换,然后再次重新整形数组,反之亦然。虽然TensorFlow将fc层权重保存为[number of inputs, number of outputs]
,但Caffe却反过来
如果您将两个fc层相互连接,则不必执行前面描述的复杂过程,但您必须通过再次转置来考虑不同的fc层格式(fc_layer_weights.transpose((1,0))
)
然后,您可以使用
设置网络参数net.params['layer_name_in_prototxt'][0].data[...] = weights
net.params['layer_name_in_prototxt'][1].data[...] = biases
这是一个快速概述。如果你想要所有代码,它就在我的github存储库中。我希望它有所帮助。 :)
干杯,
死亡率
答案 1 :(得分:3)
正如@Patwie的评论中所建议的那样,你必须通过逐层复制权重来手动完成。例如,要将第一个转换层权重从张量流检查点复制到caffemodel,您必须执行以下操作:
sess = tf.Session()
new_saver = tf.train.import_meta_graph("/path/to/checkpoint.meta")
what = new_saver.restore(sess, "/path/to/checkpoint")
all_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)
conv1 = all_vars[0]
bias1 = all_vars[1]
conv_w1, bias_1 = sess.run([conv1,bias1])
net = caffe.Net('path/to/conv.prototxt', caffe.TEST)
net.params['conv_1'][0].data[...] = conv_w1
net.params['conv_1'][1].data[...] = bias_1
...
net.save('modelfromtf.caffemodel')
注1:此代码已经过 NOT 测试。我不确定这是否有效,但我认为应该如此。此外,这仅适用于一个转换层。实际上,您必须首先分析张量流检查点,以检查哪个图层权重在哪个索引处(print all_vars ),然后分别复制每个图层的权重。
注2:某些自动化可以通过迭代初始转换层来完成,因为它们通常遵循设定模式(conv1-> bn1-> relu1-> conv2-> bn2-> relu2 ......)
注3:Tensorflow可以进一步将每个层权重划分为单独的索引。例如:权重和偏见是针对conv层分开的,如上所示。此外, gamma , mean 和 variance 分离为批量规范化层。
答案 2 :(得分:0)
您可以使用Microsoft开发的实用程序MMDNN。 MMdnn是一个综合的跨框架工具,用于转换,可视化和诊断深度学习(DL)模型。