未验证 提交 257aecda 编写于 作者: X xiebaiyuan 提交者: GitHub

Merge pull request #996 from xiebaiyuan/develop

add some python tools for paddlemobile
# encoding:utf-8
import math
import re
def Real2HalfFloat(data):
MINNUM = -65536
MAXNUM = 65535
FloatVal = 0
if data:
if data < MINNUM:
data = MINNUM
if data > MAXNUM:
data = MAXNUM
sign = 0
if data < 0:
sign = 1
data = -data
exp = math.floor((math.log2(data)))
expout = exp + 16
Mantial = round(data / pow(2, exp - 10)) - 1024
if expout <= 0:
FloatVal = 0
else:
FloatVal = sign * 32768 + expout * 1024 + Mantial
return FloatVal
def ReadCfloatData(sourcefile):
input = []
with open(sourcfile, 'r') as f:
for line in f.readlines():
line = line.strip()
line = re.sub('\s+', ' ', line) # 两个数字间多个空格
input.append(line.split(' '))
destfile = sourcefile.replace('.dat', '')
destfile = destfile.replace('.txt', '')
destfile += 'Out.dat'
with open(destfile, 'w') as fw:
for i in range(len(input)):
if len(input[i]) == 2:
real = Real2HalfFloat(float(input[i][0]))
imag = Real2HalfFloat(float(input[i][1]))
result = real * 65536 + imag
if imag and not real:
fw.write('0x0000' + "%X" % result + '\n')
elif not imag and not real:
fw.write('0x00000000' + '\n')
else:
fw.write('0x' + "%X" % result + '\n')
elif len(input[i]) == 1:
result = Real2HalfFloat(float(input[i][0]))
if result:
fw.write('0x' + "%X" % result + '\n')
else:
fw.write('0x0000' + '\n')
if __name__ == '__main__':
print('Tips: Input number 0 if you want to exit!\n')
while True:
sourcfile = input("input source file:\n")
if sourcfile is '0':
break
ReadCfloatData(sourcfile)
print('Transfer Success!')
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package paddle_mobile.framework.proto;
enum AttrType {
INT = 0;
FLOAT = 1;
STRING = 2;
INTS = 3;
FLOATS = 4;
STRINGS = 5;
BOOLEAN = 6;
BOOLEANS = 7;
BLOCK = 8;
LONG = 9;
}
// OpDesc describes an instance of a C++ framework::OperatorBase
// derived class type.
message OpDesc {
message Attr {
required string name = 1;
required AttrType type = 2;
optional int32 i = 3;
optional float f = 4;
optional string s = 5;
repeated int32 ints = 6;
repeated float floats = 7;
repeated string strings = 8;
optional bool b = 10;
repeated bool bools = 11;
optional int32 block_idx = 12;
optional int64 l = 13;
};
message Var {
required string parameter = 1;
repeated string arguments = 2;
};
required string type = 3;
repeated Var inputs = 1;
repeated Var outputs = 2;
repeated Attr attrs = 4;
optional bool is_target = 5 [ default = false ];
};
// OpProto describes a C++ framework::OperatorBase derived class.
message OpProto {
// VarProto describes the C++ type framework::Variable.
message Var {
required string name = 1;
required string comment = 2;
optional bool duplicable = 3 [ default = false ];
optional bool intermediate = 4 [ default = false ];
optional bool dispensable = 5 [ default = false ];
}
// AttrProto describes the C++ type Attribute.
message Attr {
required string name = 1;
required AttrType type = 2;
required string comment = 3;
// If that attribute is generated, it means the Paddle third
// language binding has responsibility to fill that
// attribute. End-User should not set that attribute.
optional bool generated = 4 [ default = false ];
}
required string type = 1;
repeated Var inputs = 2;
repeated Var outputs = 3;
repeated Attr attrs = 4;
required string comment = 5;
}
message VarType {
enum Type {
// Pod Types
BOOL = 0;
INT16 = 1;
INT32 = 2;
INT64 = 3;
FP16 = 4;
FP32 = 5;
FP64 = 6;
// Other types that may need additional descriptions
LOD_TENSOR = 7;
SELECTED_ROWS = 8;
FEED_MINIBATCH = 9;
FETCH_LIST = 10;
STEP_SCOPES = 11;
LOD_RANK_TABLE = 12;
LOD_TENSOR_ARRAY = 13;
PLACE_LIST = 14;
READER = 15;
CHANNEL = 16;
// Any runtime decided variable type is raw
// raw variables should manage their own allocations
// in operators like nccl_op
RAW = 17;
TUPLE = 18;
}
required Type type = 1;
message TensorDesc {
// Should only be PODType. Is enforced in C++
required Type data_type = 1;
repeated int64 dims = 2; // [UNK, 640, 480] is saved as [-1, 640, 480]
}
optional TensorDesc selected_rows = 2;
message LoDTensorDesc {
required TensorDesc tensor = 1;
optional int32 lod_level = 2 [ default = 0 ];
}
optional LoDTensorDesc lod_tensor = 3;
message LoDTensorArrayDesc {
required TensorDesc tensor = 1;
optional int32 lod_level = 2 [ default = 0 ];
}
optional LoDTensorArrayDesc tensor_array = 4;
message ReaderDesc { repeated LoDTensorDesc lod_tensor = 1; }
optional ReaderDesc reader = 5;
message ChannelDesc {
required Type data_type = 1;
required int64 capacity = 2;
}
optional ChannelDesc channel = 6;
message Tuple { repeated Type element_type = 1; }
optional Tuple tuple = 7;
}
message VarDesc {
required string name = 1;
required VarType type = 2;
optional bool persistable = 3 [ default = false ];
}
message BlockDesc {
required int32 idx = 1;
required int32 parent_idx = 2;
repeated VarDesc vars = 3;
repeated OpDesc ops = 4;
optional int32 forward_block_idx = 5 [ default = -1 ];
}
// Please refer to
// https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/program.md
// for more details.
// TODO(panyx0718): A model can have multiple programs. Need a
// way to distinguish them. Maybe ID or name?
message ProgramDesc { repeated BlockDesc blocks = 1; }
此差异已折叠。
import datetime
import json
import os
import google.protobuf as pbg
import framework_pb2 as framework_pb2
def loadmdl(json_path):
print('mdl json path : ' + json_path)
with open(json_path, 'r') as f:
json_dick = json.load(f)
# print(json_dick)
layers = (json_dick['layer'])
for layer in layers:
print(layer)
import json
import os
import framework_pb2 as framework_pb2
import op_types as types
from swicher import Swichter
import shutil
def load_mdl(mdl_json_path):
# print('mdl json path : ' + mdl_json_path)
with open(mdl_json_path, 'r') as f:
return json.load(f)
class Converter:
'convert mdlmodel to fluidmodel'
def __init__(self, mdl_json_path):
self.mdl_json_path = mdl_json_path
print mdl_json_path
self.mdl_json = load_mdl(self.mdl_json_path)
self.program_desc = framework_pb2.ProgramDesc()
self.weight_list_ = []
self.deepwise_weight_list_ = []
# print(json_dick)
# layers = (json_dick['layer'])
# for layer in layers:
# print(layer)
def convert(self):
print 'convert begin.....'
# add block_desc
block_desc = self.program_desc.blocks.add()
block_desc.idx = 0
block_desc.parent_idx = -1
self.package_ops(block_desc)
self.package_vars(block_desc)
print 'blocks: '
print self.program_desc.blocks
print 'convert end.....'
desc_serialize_to_string = self.program_desc.SerializeToString()
shutil.rmtree('newyolo/')
shutil.copytree('multiobjects/float32s_nchw_with_head', 'newyolo/')
f = open("newyolo/__model__", "wb")
f.write(desc_serialize_to_string)
f.close()
def package_ops(self, block_desc):
self.add_op_feed(block_desc)
# add ops with layer
if 'layer' in self.mdl_json:
layers_ = self.mdl_json['layer']
for layer in layers_:
desc_ops_add = block_desc.ops.add()
# print layer
# for i in layer:
# print i
if 'name' in layer:
l_name = layer['name']
if 'type' in layer:
self.package_ops_type(desc_ops_add, layer)
if 'weight' in layer:
self.package_ops_weight2inputs(desc_ops_add, layer)
if 'output' in layer:
self.package_ops_outputs(desc_ops_add, layer)
if 'input' in layer:
self.package_ops_inputs(desc_ops_add, layer)
self.package_ops_attrs(desc_ops_add, layer)
self.add_op_fetch(block_desc)
def add_op_feed(self, block_desc):
desc_ops_add = block_desc.ops.add()
inputs_add = desc_ops_add.inputs.add()
inputs_add.parameter = 'X'
inputs_add.arguments.append('feed')
desc_ops_add.type = 'feed'
outputs_add = desc_ops_add.outputs.add()
outputs_add.parameter = 'Out'
outputs_add.arguments.append('data')
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'col'
# boolean
attrs_add.type = 0
attrs_add.i = 0
def add_op_fetch(self, block_desc):
desc_ops_add = block_desc.ops.add()
inputs_add = desc_ops_add.inputs.add()
inputs_add.parameter = 'X'
inputs_add.arguments.append('conv_pred_87')
desc_ops_add.type = 'fetch'
outputs_add = desc_ops_add.outputs.add()
outputs_add.parameter = 'Out'
outputs_add.arguments.append('fetch')
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'col'
# boolean
attrs_add.type = 0
attrs_add.i = 0
@staticmethod
def package_ops_attrs(desc_ops_add, layer):
# print l_params
# print desc_ops_add.type
if desc_ops_add.type == types.op_fluid_fusion_conv_add:
Converter.pack_fusion_conv_add_attr(desc_ops_add, layer)
elif desc_ops_add.type == types.op_fluid_relu:
# fusion_conv_add : attrs
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'use_mkldnn'
# boolean
attrs_add.type = 6
attrs_add.b = 0
@staticmethod
def pack_fusion_conv_add_attr(desc_ops_add, layer):
# fusion_conv_add : attrs
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'workspace_size_MB'
# 0-->INT
attrs_add.type = 0
attrs_add.i = 4096
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'data_format'
# 2-->STRING
attrs_add.type = 2
attrs_add.s = 'AnyLayout'
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'use_mkldnn'
# boolean
attrs_add.type = 6
attrs_add.b = 0
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'use_cudnn'
# boolean
attrs_add.type = 6
attrs_add.b = 1
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'dilations'
# ints
attrs_add.type = 3
attrs_add.ints.append(1)
attrs_add.ints.append(1)
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'axis'
# int
attrs_add.type = 0
attrs_add.i = 1
if 'param' in layer:
l_params = layer['param']
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'paddings'
# ints
attrs_add.type = 3
attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('paddings')])
attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('paddings')])
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'strides'
# ints
attrs_add.type = 3
attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('strides')])
attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('strides')])
attrs_add = desc_ops_add.attrs.add()
attrs_add.name = 'groups'
# int
attrs_add.type = 0
attrs_add.i = l_params[types.fusion_conv_add_attrs_dict.get('groups')]
# attrs_add.i = 1
#
# op_attrs_tupl = types.op_io_dict.get(desc_ops_add.type) \
# .get(types.mdl_attrs_key)
#
#
#
#
# # group stride padding
# print '----------------------'
# for i, val in enumerate(op_attrs_tupl):
# attrs_add = desc_ops_add.attrs.add()
# attr_name = op_attrs_tupl[i]
# print attr_name
# attrs_add.name = attr_name
# attrs_add.type = types.fluid_attrs_type_dict.get(attr_name)
# attrs_add.
# print l_params[types.fusion_conv_add_attrs_dict.get(attr_name)]
# for p in l_params:
# attrs_add = desc_ops_add.attrs.add()
@staticmethod
def package_ops_inputs(desc_ops_add, layer):
l_inputs = layer['input']
for i in l_inputs:
inputs_add = desc_ops_add.inputs.add()
# print i
inputs_add.parameter = types.op_io_dict.get(desc_ops_add.type).get(types.mdl_inputs_key)
inputs_add.arguments.append(i)
@staticmethod
def package_ops_outputs(desc_ops_add, layer):
l_outputs = layer['output']
for o in l_outputs:
# print o
outputs_add = desc_ops_add.outputs.add()
outputs_add.parameter = types.op_io_dict.get(desc_ops_add.type).get(types.mdl_outputs_key)
outputs_add.arguments.append(o)
def package_ops_weight2inputs(self, desc_ops_add, layer):
l_weights = layer['weight']
for w in l_weights:
self.weight_list_.append(w)
if layer['type'] == 'DepthwiseConvolutionLayer':
# print l_weights[0]
self.deepwise_weight_list_.append(l_weights[0])
op_weight_tup = types.op_io_dict.get(desc_ops_add.type).get(types.mdl_weight_key)
# print len(op_weight_tup)
for i, val in enumerate(op_weight_tup):
# print i
# print val
inputs_add = desc_ops_add.inputs.add()
inputs_add.parameter = op_weight_tup[i]
inputs_add.arguments.append(l_weights[i])
# for w in l_weights:
# inputs_add = desc_ops_add.inputs.add()
# # print w
# inputs_add.parameter = op_weight_tup[0]
# inputs_add.arguments.append(w)
@staticmethod
def package_ops_type(desc_ops_add, layer):
l_type = layer['type']
# print l_type
# print mdl2fluid_op_layer_dict.get(l_type)
desc_ops_add.type = types.mdl2fluid_op_layer_dict.get(l_type)
def package_vars(self, block_desc):
vars_add = block_desc.vars.add()
vars_add.name = 'feed'
vars_add.type.type = 9 # 9 is FEED_MINIBATCH
vars_add.persistable = 1
# fetch
vars_add = block_desc.vars.add()
vars_add.name = 'fetch'
vars_add.type.type = 10 # 10 is fetch list
vars_add.persistable = 1
json_matrix_ = self.mdl_json['matrix']
# print json_matrix_
for j in json_matrix_:
vars_add = block_desc.vars.add()
vars_add.name = j
vars_add.type.type = 7 # 7 is lodtensor
# print j
tensor = vars_add.type.lod_tensor.tensor
tensor.data_type = 5 # 5 is FP32
# print json_matrix_
dims_of_matrix = json_matrix_.get(j)
# dims_size = len(dims_of_matrix)
# print dims_size
# if dims_size == 4:
# tensor.dims.append(dims_of_matrix[0]) # N
# tensor.dims.append(dims_of_matrix[3]) # C
# tensor.dims.append(dims_of_matrix[1]) # H
# tensor.dims.append(dims_of_matrix[2]) # W
# else:
# issues in mdl model filter swich n and c
if j in self.deepwise_weight_list_ and len(dims_of_matrix) == 4:
print j
tensor.dims.append(dims_of_matrix[1])
tensor.dims.append(dims_of_matrix[0])
tensor.dims.append(dims_of_matrix[2])
tensor.dims.append(dims_of_matrix[3])
print tensor.dims
else:
for dims in dims_of_matrix:
# print dims
tensor.dims.append(dims)
if j in self.weight_list_:
vars_add.persistable = 1
dims_size = len(dims_of_matrix)
# print dims_size
if dims_size == 4:
# convert weight from nhwc to nchw
Swichter().nhwc2nchw_one_slice_add_head(
'/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nhwc/' + j + '.bin',
'/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw_with_head/' + j,
'/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw/' + j + '.tmp',
dims_of_matrix[0],
dims_of_matrix[1],
dims_of_matrix[2],
dims_of_matrix[3]
)
else:
Swichter().copy_add_head(
'/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nhwc/' + j + '.bin',
'/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw_with_head/' + j,
'/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw/' + j + '.tmp'
)
else:
vars_add.persistable = 0
mdl_path = "/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/YOLO_Universal.json"
converter = Converter(mdl_path)
converter.convert()
import os
import framework_pb2 as framework_pb2
def read_model(model_path):
print('read_model.')
path_8 = unicode(model_path, 'utf8')
try:
with open(path_8, "rb") as f_model:
print get_file_size(model_path)
desc = framework_pb2.ProgramDesc()
desc.ParseFromString(f_model.read())
print desc
# print desc.blocks
except IOError:
print ": File not found. Creating a new file."
def get_file_size(file_path):
file_path = unicode(file_path, 'utf8')
fsize = os.path.getsize(file_path)
fsize = fsize / float(1024 * 1024)
return round(fsize, 2)
path = "newyolo/__model__"
read_model(path)
# coding=utf-8
# mdl layers
layer_mdl_conv = 'ConvolutionLayer'
layer_mdl_deepwise_conv = 'DepthwiseConvolutionLayer'
layer_mdl_relu = 'ReluLayer'
layer_mdl_pointwise_add = 'PointwiseConvolutionLayer'
# fluid ops
op_fluid_fusion_conv_add = 'fusion_conv_add'
op_fluid_relu = 'relu'
# dict mdk layer --- fluid op
mdl2fluid_op_layer_dict = {
layer_mdl_conv: op_fluid_fusion_conv_add,
layer_mdl_deepwise_conv: op_fluid_fusion_conv_add,
layer_mdl_relu: op_fluid_relu,
layer_mdl_pointwise_add: op_fluid_fusion_conv_add
}
mdl_outputs_key = "outputs"
mdl_inputs_key = "inputs"
mdl_weight_key = "weights"
mdl_attrs_key = "params"
# dict of mdl-input _out param to fluid input out attrs
fusion_conv_add_dict = {
mdl_inputs_key: 'Input',
mdl_outputs_key: 'Out',
mdl_weight_key: ('Filter', 'Y'),
mdl_attrs_key: (
# 'workspace_size_MB', 'use_mkldnn', 'use_cudnn', 'data_format','dilations',
# dilations = [1,1]
'groups', 'paddings', 'strides'
# 'axis'
)
}
relu_dict = {
mdl_inputs_key: 'X',
mdl_outputs_key: 'Out',
mdl_weight_key: ()
}
# mdl layers --- fluid ops
op_io_dict = {
'fusion_conv_add': fusion_conv_add_dict,
'relu': relu_dict
}
# fluid attr key --- mdl params key
fusion_conv_add_attrs_dict = {
'paddings': 'pad',
'strides': 'stride',
'groups': 'group'
}
# fluid attr key --- mdl params key
fluid_attrs_type_dict = {
'paddings': 0,
'strides': 6,
'groups': 6
}
# '': "bias_term", 是不是要add 目前 yolo的模型都是 bias_term = 1
# attrs {
# name: "axis"
# type: INT
# i: 1
# }
# attrs_name = {
# 'name': "workspace_size_MB",
# 'type': 'INT',
# 'i': '4096'
# }
# attrs
# {
# name: "data_format"
# type: STRING
# s: "AnyLayout"
# }
# attrs
# {
# name: "use_mkldnn"
# type: BOOLEAN
# b: false
# }
# attrs
# {
# name: "use_cudnn"
# type: BOOLEAN
# b: true
# }
# attrs
# {
# name: "dilations"
# type: INTS
# ints: 1
# ints: 1
# }
# attrs
# {
# name: "groups"
# type: INT
# i: 1
# }
# attrs
# {
# name: "paddings"
# type: INTS
# ints: 0
# ints: 0
# }
# attrs
# {
# name: "strides"
# type: INTS
# ints: 1
# ints: 1
# }
from array import array
class Swichter:
def __init__(self):
pass
def nhwc2nchw_one_slice(self, from_file_name, to_file_name, batch, channel, height, width):
from_file = open(from_file_name, "rb")
to_file = open(to_file_name, "wb")
float_array = array("f")
float_array.fromfile(from_file, width * height * batch * channel)
float_write_array = array("f")
for b in range(batch):
for c in range(channel):
for h in range(height):
for w in range(width):
float_value = float_array[b * channel * width * height
+ channel * (h * width + w) + c]
float_write_array.append(float_value)
float_write_array.tofile(to_file)
from_file.close()
to_file.close()
def copy(self, from_file_name, to_file_name):
from_file = open(from_file_name, "rb")
to_file = open(to_file_name, "wb")
to_file.write(from_file.read())
from_file.close()
to_file.close()
def nhwc2nchw_one_slice_add_head(self, from_file_name, to_file_name, tmp_file_name, batch, channel, height, width):
from_file = open(from_file_name, "rb")
tmp_file = open(tmp_file_name, "wb+")
float_array = array("f")
float_array.fromfile(from_file, width * height * batch * channel)
float_write_array = array("f")
for b in range(batch):
for c in range(channel):
for h in range(height):
for w in range(width):
float_value = float_array[b * channel * width * height
+ channel * (h * width + w) + c]
float_write_array.append(float_value)
float_write_array.tofile(tmp_file)
tmp_file.close()
from_file.close()
tmp_file = open(tmp_file_name, "rb")
to_file = open(to_file_name, "wb")
tmp = tmp_file.read()
head = self.read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases')
to_file.write(head)
to_file.write(tmp)
tmp_file.close()
to_file.close()
def read_head(self, head_file):
from_file = open(head_file, "rb")
read = from_file.read(20)
# print read
from_file.close()
# print read
return read
def copy_add_head(self, from_file_name, to_file_name, tmp_file_name):
from_file = open(from_file_name, "rb")
to_file = open(to_file_name, "wb")
# tmp_file = open(tmp_file_name, "wb")
head = self.read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases')
to_file.write(head)
to_file.write(from_file.read())
from_file.close()
to_file.close()
pass
# Swichter().nhwc2nchw_one_slice(
# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nhwc/conv5_6_dw_0.bin',
# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw/conv5_6_dw_0', 1,
# 512, 3, 3)
Swichter().read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases')
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册