zoukankan      html  css  js  c++  java
  • (原)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})

  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/darkknightzh/p/7419352.html
Copyright © 2011-2022 走看看