caffe 模型转tensorflow

来源:互联网 发布:redis 源码注释 编辑:程序博客网 时间:2024/05/20 13:08

下载模型转换代码:

git clone https://github.com/ethereon/caffe-tensorflow

caffe-tensorflow模型转换文件为convert.py,可以将caffe的模型定义文件.prototxt和训练好的模型分别转换为tensorflow类,和tensorflow模型文件.在example文件夹下提供了examples/minist和examples/imagenet两个转换示例.

以手写字体为例,模型为lenet,examples/minist目录下提供了lenet.prototxt和训练好的caffe模lenet_iter_10000.caffemodel,caffe转换为tensorflow命令为:

python convert.py --def_path examples/mnist/lenet.prototxt --caffemodel examples/mnist/lenet_iter_10000.caffemodel --data-output-path lenet.npy --code-output-path lenet.py

运行命令后报错:

TypeError: Descriptors should not be created directly, but only retrieved from their parent.

Process finished with exit code 1

这是因为找不到caffe安装目录,解决方法是kaffe/caffe/resolver.py的第12行添加caffe安装目录:

import syscaffe_root = '/home/qinghua/program/caffe'sys.path.insert(0, caffe_root + '/python')import caffe

这里写图片描述

转换后得到lenet网络结构文件lenet.py:

from kaffe.tensorflow import Networkclass LeNet(Network):    def setup(self):        (self.feed('data')             .conv(5, 5, 20, 1, 1, padding='VALID', relu=False, name='conv1')             .max_pool(2, 2, 2, 2, name='pool1')             .conv(5, 5, 50, 1, 1, padding='VALID', relu=False, name='conv2')             .max_pool(2, 2, 2, 2, name='pool2')             .fc(500, name='ip1')             .fc(10, relu=False, name='ip2')             .softmax(name='prob'))

已经模型文件lenet.npy,我们可以加载该模型,并进行fine tuning,代码为examples/mnist/finetune_mnist.py

# Import the converted model's classimport numpy as npimport randomimport tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_datafrom lenet import LeNet as MyNetmnist = input_data.read_data_sets('MNIST_data', one_hot=True)batch_size = 32def gen_data(source):    while True:        indices = range(len(source.images))        random.shuffle(indices)        for i in indices:            image = np.reshape(source.images[i], (28, 28, 1))            label = source.labels[i]            yield image, labeldef gen_data_batch(source):    data_gen = gen_data(source)    while True:        image_batch = []        label_batch = []        for _ in range(batch_size):            image, label = next(data_gen)            image_batch.append(image)            label_batch.append(label)        yield np.array(image_batch), np.array(label_batch)images = tf.placeholder(tf.float32, [batch_size, 28, 28, 1])labels = tf.placeholder(tf.float32, [batch_size, 10])net = MyNet({'data': images})ip2 = net.layers['ip2']pred = tf.nn.softmax(ip2)loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=ip2, labels=labels), 0)opt = tf.train.RMSPropOptimizer(0.001)train_op = opt.minimize(loss)with tf.Session() as sess:    # Load the data    sess.run(tf.initialize_all_variables())    net.load('lenet.npy', sess)    data_gen = gen_data_batch(mnist.train)    for i in range(1000):        np_images, np_labels = next(data_gen)        feed = {images: np_images, labels: np_labels}        np_loss, np_pred, _ = sess.run([loss, pred, train_op], feed_dict=feed)        if i % 10 == 0:            print('Iteration: ', i, np_loss)

更新prototxt及model为最新的caffe版本

由于caffe版本不同,一些参数定义会有更改,转换的时候由于不同caffe版本的问题,可能会出现错误:

Error encountered: Unknown layer type encountered: 4

这时候就需要使用函数upgrade_net_proto_text和函数upgrade_net_proto_binary,更新prototxt及model为最新的caffe版本.

更新prototxt:

/home/caffe/build/tools/upgrade_net_proto_text LightenedCNN_A_deploy.prototxt_old LightenedCNN_A_deploy.prototxt

更新model:

 /home/caffe/build/tools/upgrade_net_proto_binary LightenedCNN_A.caffemodel_old LightenedCNN_A.caffemodel

对于错误2:

Error encountered: Multiple top nodes are not supported.

这是因为prototxt文件中定义了包含两个top node的层,如:

layer {  name: "slice1"  type: "Slice"  bottom: "pool1"  top: "slice1_1"  top: "slice1_2"  slice_param {    slice_dim: 1  }}

这时候就需要自己编写tensorflow代码.

但是完全自己编写也不太容易,这时候我们可以去掉不能转换的层,例如去掉Slice层,将Slice层的上下层连接,同时转换的时候只输入prototxt文件,即只对模型定义文件进行转换,以lightCNN为例,

python convert.py --def_path /home/face_verification_experiment/proto/LightenedCNN_A_deploy.prototxt  --code-output-path lightcnn.py

得到模型类为:

from kaffe.tensorflow import Networkclass DeepFace_set003_net(Network):    def setup(self):        (self.feed('input')             .conv(9, 9, 96, 1, 1, padding='VALID', relu=False, name='conv1')             .max_pool(2, 2, 2, 2, name='pool1')             .conv(5, 5, 192, 1, 1, padding='VALID', relu=False, name='conv2')             .max_pool(2, 2, 2, 2, name='pool2')             .conv(5, 5, 256, 1, 1, padding='VALID', relu=False, name='conv3')             .max_pool(2, 2, 2, 2, name='pool3')             .conv(4, 4, 384, 1, 1, padding='VALID', relu=False, name='conv4')             .max_pool(2, 2, 2, 2, name='pool4')             .fc(512, relu=False, name='fc1')             .dropout(0.699999988079, name='dropout1')             .fc(10575, relu=False, name='fc2')             .softmax(name='softmax'))

参考以上代码,就可以使用tensorflow快速的编写对应的模型代码.

编写好模型代码后,需要加载训练好的caffe模型,我们加载caffe模型文件,并保存参数数组.

import syscaffe_root = '/home/qinghua/program/caffe'sys.path.insert(0, caffe_root + '/python')# Try to import PyCaffe firstimport caffeimport cPickledir='/home/face_verification_experiment/'def_path=dir+'proto/LightenedCNN_A_deploy.prototxt_old'data_path=dir+'model/LightenedCNN_A.caffemodel'net = caffe.Net(def_path, data_path, caffe.TEST)data = lambda blob: blob.dataparams = [(k, map(data, v)) for k, v in net.params.items()]params1=dict()params1['params']=paramsblobs=net.blobsinput_dims = blobs['data'].shapewith open(dir+'model/LightenedCNN_A.pkl', 'wb') as pickle_file:    cPickle.dump(params1,pickle_file)

将所有训练好的变量值保存在LightenedCNN_A.pkl中,这样在可以使用tf.assign对tensorflow模型中的变量复制,再使用tf.saver.save()保存模型即可.这样最终完成了模型转换.

原创粉丝点击