Skip to content

附录Ⅰ. 如何添加新的Layer

1. 概述

本节仅适用于caffe 模型。对于sigmastar 还未实现的layer,用sigmastar 提供底层算子来组合实现。底层算子与 tensorflow 的算子类似,支持的算子参考DLA SDK支持:TensofFlow 支持算子 支持算子转换流程如下图

box_process

CaffeConvert Tool (代码位置:SGS_IPU_SDK/Scripts/ConvertTool/ConvertTool.py) caffe 模型转换工具借鉴了小米开源框架mace 的设计,要添加新的layer,请先到Xiaomi MACE下载原始代码,按照mace 官方文档配置 好编译环境,或者直接使用我们提供的docker 环境。 下面以reorg layer为例子,讲解如何添加新的layer,主要修改以下几个文件

box_process


2. Caffe proto 文件修改

2.1 修改caffe proto

Mace 原始代码下载后,用SGS_IPU_SDK/Scripts/CaffeConvertTool/third_party/caffe/caffe.proto 替换掉mace 工程 路径下mace/third_party/caffe 下caffe.proto 文件。因为sigmastar 在mace 基础上做了二次开发,所以sigmstar 支持 的caffe layer 已经远远多于原生的mace 支持数量。要添加新的layer,请以sigmastar 的caffe proto 文件作为基础 添加。

optional ReorgParameter reorg_param = 157;
}
message ReorgParameter {
optional uint32 stride = 1;
optional bool reverse = 2 [default = false];
}

2.2 编译proto 文件

在mace 开发环境中

cd pathToMace/
bazel build third_party/caffe/caffe_py

在bazel-genfiles 下生成caffe_pb2.py 将上面修改后的caffe.proto 和生成的caffe_pb2.py 替换SGS_IPU_SDK/Scripts/CaffeConvertTool/third_party/caffe同 名文件,然后按照如下顺序修改代码


3. 修改caffe_converter.py

文件路径SGS_IPU_SDK/Scripts/CaffeConvertTool/mace/python/tools/converter_tool/caffe_converter.py 该文件的作用是把caffe模型转换为mace模型,并保存该layer的参数

Reorg':self.convert_Reorg,
...
...
def convert_Reorg(self, caffe_op):
    op = self.convert_general_op(caffe_op)
    op.type = "Reorg"
    param = caffe_op.layer.reorg_param
    stride_arg = op.arg.add()
    stride_arg.name = "stride"
    stride_arg.i = 1 #default is true
    if param.HasField('stride'):
        stride_arg.i = int(param.stride)


4. 修改shape_inference.py

文件路径SGS_IPU_SDK/Scripts/CaffeConvertTool/mace/python/tools/converter_tool/shape_inference.py 该文件的作用是计算layer的output shape

Reorg': self.infer_shape_Reorg,
...
...
def infer_shape_Reorg(self, op):
    #only support stride is 2
    output_shape = self._output_shape_cache[op.input[0]]
    input_shape = list(self._output_shape_cache[op.input[0]])
    input_n = input_shape[0]
    input_c = input_shape[1]
    input_h = input_shape[2]
    input_w = input_shape[3]
    output_shape = [input_n,int(input_c*4),int(input_h/2),int(input_w/2)]
    self.add_output_shape(op, [output_shape])

5. 修改SGSModel_transform.py

如下图所示,我们发现reorg在NCHW的排列顺序下,它实际上是对数据做了一个重排。

box_process

因此,我们最后拆解出来的算子组合是

box_process

按照算子组合顺序,编写代码 文件路径SGS_IPU_SDK/Scripts/CaffeConvertTool/mace/python/tools/SGSModel_transform.py 该文件作用是增加该layer 的拆解函数。即用Sigmastar 提供的基本算子实现该layer。

Reorg':self.split_Reorg,
...
...
def split_Reorg(self, op):
#only support strid is 2
[n,c,h,w] = op.output_shape[0].dims[:]
c = int(c/4)
op_name = op.name
xi = op.input[0]
...
...
至此,新的layer 支持添加完成


6. Layer拆解注意事项与技巧

6.1. Layer拆解注意事项与技巧 数据维度的问题

在caffe网络中,使用NCHW数据排列。而sigmastar使用NHWC的顺序进行数据计算(与tensorflow类似)。所以在模型转换成sim模型的时候,会对所有4维度的shape和数据做一次转换。即NCHW转到NHWC 参考代码:SGS_IPU_SDK/Scripts/CaffeConvertTool/mace/python/tools/SGSModel_converter.py 对于tensor data的转换

def _creatBuffer(self):
...
...
if len(ori_shape) == 4:
#transpose data to NHWC
    six.print_("Reshape ",tensor.name,"to NHWC")
    data = np.array(ori_data)
    data = data.reshape(ori_shape)
    data = data.transpose(0,2,3,1)
对于shape的转换

def _creatTensor(self):
...
...
if len(shape) == 4 and data_format == mace_pb2.DT_NCHW:
    Transformer.transpose_shape(shape, [0, 2, 3, 1])
tflite.Tensor.TensorStartShapeVector(self._builder,len(shape))
因为shape在创建sim模型的时候会被强行改变,所以拆解的时候要注意

(1)有axis参数的,要注意顺序交换

比如`concat layer,caffe model里面,它要对C纬度做concat,其axis为1。网络转换后,C为换到了最低维,所 以要修改axis为3,代码如下。相似的还有split、PRelu等

def split_Concat(self, op):
...
...
if len(output_shape[0].dims) == 4:#nchw -> nhwc
    if arg[i].i == 1:
        arg[i].i = 3
    else if arg[i].i == 2:
        arg[i].i = 1
    else if arg[i].i == 3:
        arg[i].i = 2
(2)指定算子output_shape的时候,特别是4维的输出,要注意顺序变化带来的影响。比如希望tensor的输出是[A,B,C,D],那么代码中我们写的数值为[A,D,B,C]。因为[A,D,B,C]经过上面代码的转换,就得到了[A,B,C,D]这个顺序

(3)在NCHW 数据排列下有很强规律的layer,可以先转到NCHW 下操作。比如上面提到的reorg layer。

(4)用sdk 里面提供的Netron 工具打开转换后的sim 模型,方便查看各种属性和shape。


6.2. 建议拆解流程

综上所述,在拆解的过程中,我们建议按照如下流程进行

box_process


6.3. 数据对比及验证

前期可以用python 创建tensorflow 算子的方法,进行验证。 当验证完成,再修改SGS_IPU_SDK 的相关代码,参考Dump_Debug Tool章节,dump 出最后结果与golden 比对。