Skip to content

8. 如何添加新的Layer

8.1. 概述

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

box_process

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

box_process


8.2. Caffe proto 文件修改

8.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];
}

8.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同 名文件,然后按照如下顺序修改代码


8.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)


8.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])

8.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 支持添加完成


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

8.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。


8.6.2. 建议拆解流程

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

box_process


8.6.3. 数据对比及验证

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