• (原)linux下caffe模型转tensorflow模型


    转载请注明出处:

    http://www.cnblogs.com/darkknightzh/p/7419352.html

    参考网址:

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

    https://github.com/ethereon/caffe-tensorflow/issues/53

    http://blog.csdn.net/zchang81/article/details/76229017

    提醒:1. 目前该开源程序不支持caffe中全连接层的bias=false的情况。如果caffe模型全连接层有这种情况,暂时不用往下看了。。。

    2. 增加的或者修改的代码用红色字体标注了,因而本文没有使用代码功能。

    具体步骤如下:

    1. caffe-tensorflow-masterkaffecaffe esolver.py下,增加如下两句:

    import sys

    sys.path.insert(0, "/home/xxx/caffe/caffe-master/python")

    注意:使用的系统是ubuntu14.04。如果caffe和tensorflow都配置好了,这步可能不需要吧。我这边由于caffe配置的有点问题,直接import caffe的话,失败,因而增加了caffe的路径。

    2. 默认该开源程序无法处理caffe中的global pooling,默认会提示:

    ValueError: Unable to determine kernel parameter!

    因而,在caffe-tensorflow-masterkaffelayers.py中,修改class LayerAdapter(object):

    class LayerAdapter(object):

        def __init__(self, layer, kind):

            self.layer = layer

            self.kind = kind

            self._input_shape = None

        @property

        def parameters(self):

            name = NodeDispatch.get_handler_name(self.kind)

            name = '_'.join((name, 'param'))

            try:

                return getattr(self.layer, name)

            except AttributeError:

                raise NodeDispatchError('Caffe parameters not found for layer kind: %s' % (self.kind))

        @staticmethod

        def get_kernel_value(scalar, repeated, idx, default=None):

            if scalar:

                return scalar

            if repeated:

                if isinstance(repeated, numbers.Number):

                    return repeated

                if len(repeated) == 1:

                    # Same value applies to all spatial dimensions

                    return int(repeated[0])

                assert idx < len(repeated)

                # Extract the value for the given spatial dimension

                return repeated[idx]

            if default is None:

                raise ValueError('Unable to determine kernel parameter!')

            return default

        def set_input_shape(self, input_shape):

            self._input_shape = input_shape

        @property

        def kernel_parameters(self):

            assert self.kind in (NodeKind.Convolution, NodeKind.Pooling)

            params = self.parameters

            global_pool = hasattr(params, 'global_pooling')

            if params.kernel_size:

                k_h = self.get_kernel_value(params.kernel_h, params.kernel_size, 0)

                k_w = self.get_kernel_value(params.kernel_w, params.kernel_size, 1)

            elif self._input_shape:

                k_h, k_w = [self._input_shape.height, self._input_shape.width]

            else: #errors out in get_kernel_value function

                k_h = self.get_kernel_value(params.kernel_h, params.kernel_size, 0)

                k_w = self.get_kernel_value(params.kernel_w, params.kernel_size, 1)

            s_h = self.get_kernel_value(params.stride_h, params.stride, 0, default=1)

            s_w = self.get_kernel_value(params.stride_w, params.stride, 1, default=1)

            p_h = self.get_kernel_value(params.pad_h, params.pad, 0, default=0)

            p_w = self.get_kernel_value(params.pad_h, params.pad, 1, default=0)

            return KernelParameters(k_h, k_w, s_h, s_w, p_h, p_w)

    3. 在caffe-tensorflow-masterkaffeshapes.py中第18行,增加下面代码:

    node.layer.set_input_shape(input_shape)

    4. 如果要在caffe-tensorflow-masterexamplesimagenet目录下测试转换后的模型,需要将转换后的模型的py文件放到examplesimagenetmodels文件夹内,生成的npy文件放到caffe-tensorflow-masterexamplesimagenet文件夹内,并修改caffe-tensorflow-masterexamplesimagenetmodelshelper.py文件:

    1)开头增加:

    from aaa import bbb

    其中,aaa为生成的py文件(不需要后缀)。bbb为aaa.py文件内生成的class名,如class bbb(Network)

    2)根据需要,在std_spec函数结束后,增加新的函数:

    def bbb_spec(batch_size=500):

        '''Parameters used by bbb and its variants.'''

        return DataSpec(batch_size=batch_size, scale_size=256, crop_size=128, isotropic=False)

    3)在MODELS中增加新生成的模型名字:

    MODELS = (AlexNet, CaffeNet, GoogleNet, NiN, ResNet50, ResNet101, ResNet152, VGG16, bbb)

    4)在MODEL_DATA_SPECS中增加新生成模型的初始化信息:

    MODEL_DATA_SPECS = {

        AlexNet: alexnet_spec(),

        CaffeNet: alexnet_spec(),

        GoogleNet: std_spec(batch_size=200, isotropic=False),

        ResNet50: std_spec(batch_size=25),

        ResNet101: std_spec(batch_size=25),

        ResNet152: std_spec(batch_size=25),

        NiN: std_spec(batch_size=500),

        VGG16: std_spec(batch_size=25),

        bbb: bbb_spec(batch_size=25)

    }

    5. 模型转换完之后,如果caffe模型最后还有一个concat层(用于concat之前每个层的特征),而输入的特征均为batch size*featDim类型的2D数组(之前层的concat输入的均为4D的数据,则正常),需要将转换后的模型的这层由

    .concat(3, name='concat_feature')

    手动改成

    .concat(1, name='concat_feature')

    原因是,该开源程序貌似无法判断输入数据维度(都没数据呢,哪里去判断。。。),因而默认都设置了从第3维来concat(tensorflow中第0维为batch,第1维为高,第2维为宽,第3维为特征维度)。如果concat的每维均为特征,则此时只是将多个batch size*featDim进行concat,故需要手动将此时的3改为1。不过不涉及到concat多个特征,则不需要修改这里。

    6. caffe-tensorflow-masterkaffe ensorflow中map_batch_norm函数修改如下:

    def map_batch_norm(self, node):
        if not (node.data is None):
            scale_offset = len(node.data) == 4
            kwargs = {} if scale_offset else {'scale_offset': False}
            return MaybeActivated(node, default=False)('batch_normalization', **kwargs)
        else:
            return MaybeActivated(node, default=False)('batch_normalization', {'scale_offset': False})

    7. 目前该开源程序不支持全连接层bias=false的情况,即便修改代码,能够设置bias=false,但是在真正使用模型时,依旧失败。因而这种情况下,或者等大神继续修改代码,或者自己修改代码,或者。。。放弃吧。

    8. 转换模型的代码(在caffe-tensorflow-master打开终端):

    ./convert.py aaa.prototxt --caffemodel aaa.caffemodel --code-output-path=aaa.py --data-output-path=aaa.npy

    注意:

    1)prototxt一定要输入。

    2)code-output-path若指定则会输出生成的模型文件。

    3)caffemodel若指定,则会从该模型中读取模型参数;data-output-path若指定,则会输出对应的模型参数,且需使用该开源程序来载入模型参数。

    8. 使用的话(这部分代码不记得能不能用。。。看着修改吧),可以结合caffe-tensorflow-masterexamplesimagenetvalidate.py进行修改。

    比如,增加:

    import sys

    sys.path.insert(0, "/home/xxx/caffe-tensorflow-master/kaffe")

    from kaffe.tensorflow import Network

    并且:

    import models

    主程序中:

    spec = models.get_data_spec(model_class=models.bbb)  # Get the data specifications for the bbb model

    input_node = tf.placeholder(tf.float32, shape=(None, img_size, img_size, img_channels))  # Create a placeholder for the input image

    net = models.bbb({'data': input_node})  # Construct the network

    当使用该模型时:

    with tf.Graph().as_default():

    with tf.Session() as sess:

            net.load(args.model_path, sess)    # Load the converted parameters

            for i in range(nrof_batches):

                # get images

                # Perform a forward pass through the network to get the class probabilities

                feat = sess.run(net.get_output(), feed_dict={input_node: images})

  • 相关阅读:
    制作类似QQ截图软件
    XML文件与实体类的互相转换
    MFC中真彩工具条的制作方法
    MFC使用技巧集锦(1)(转载)
    抽象工厂模式与工厂方法模式区别
    VC数据库编程分析
    如何让工具条显示256色图像
    华为软件编程规范和范例
    设计模式总结性试题
    VC++中基于ADO操作ACCESS数据库,FLEXGRID控件的综合应用
  • 原文地址:https://www.cnblogs.com/darkknightzh/p/7419352.html
Copyright © 2020-2023  润新知