├── .idea └── vcs.xml ├── LICENSE ├── README.md ├── hookWorker.py ├── torchLayer_Graph.py ├── torchLayer_IMPL.py ├── torchLayer_Interpreter.py ├── torchLayer_ncnn.py └── transferMain.py /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2019, EricKing 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyBridge 2 | This a bridge for converting torch,and other AI training framework to C++ speed up infer library,like NCNN,and ect... 3 | 4 | Firstly, 5 | add pyBridge to your main pytorch project ,and refer to transferMain.py for details... 6 | 7 | Secondly, 8 | best way for converting pytorch to ncnn is hooking principle in torch, so essentially,every function in pytorch ,this hook_walker 9 | will can catch and convert it. 10 | 11 | Third, 12 | some graph layer was added for gv format refixing ,especially for graphviz.Maybe prime learning in AI field ,can see the entity 13 | of whole network when network is very big.... 14 | 15 | Fourth, 16 | some other networks like caffe and mxnet convertings will be update in some day ,or some pretty babies can help for you,that is 17 | very appricated.... 18 | 19 | Help yourself..... 20 | -------------------------------------------------------------------------------- /hookWorker.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from torch.autograd import Function 3 | 4 | import torch.nn.functional as F 5 | ########################################################### 6 | sys.path.append('G:\AI/your project main path/python2ncnn') ###Must changed for every project ,all locate pybridge package to fixed-location in Windows 7 | ########################################################### 8 | from torchLayer_Interpreter import Layer_Interpreter,TorchLayers_Keeper 9 | from torchLayer_ncnn import NCNN_FRAMEWORK_FACTORY 10 | from torchLayer_Graph import TorchGraph_Pen 11 | ###################################################################### 12 | old_function__call__ = Function.__call__ 13 | global_hooks_handles = [] 14 | ##will be supported later,maybe... 15 | FRAME_WORK_TYPE = { 16 | "DEFAULT" : 0, 17 | "CAFFE" : 1, 18 | "TENSOR_FLOW": 2, 19 | "ONNX" : 3 20 | } 21 | 22 | def module_forward_hooking(module,inputList, output): 23 | mdLayer = Layer_Interpreter(module,inputList, output) 24 | res = mdLayer.Layers_Interpretering(None,None) 25 | if res: 26 | print("module:", {id(module): str(module.__class__)}) 27 | else: 28 | print("*******your layers in model , something is Null or can not be interpretered...") 29 | 30 | ####################do some graph vision op later############## 31 | return True 32 | 33 | def funcs_forward_hooking(): 34 | res = Layer_Interpreter.funcs_Interpretering() 35 | return None 36 | 37 | 38 | def funcsParams_hook(): 39 | funcs_forward_hooking() 40 | print("funcs here...") 41 | 42 | def forward_hooks_mount2_Net(netModel): 43 | inum = 0 44 | def moduleParams_hook(netModule, inputs, output): 45 | inLists = list(inputs) # listed for tensor for hooks 46 | module_forward_hooking(netModule, inLists, output) 47 | 48 | for singleModel in netModel.modules(): 49 | singleModelSlices = list(singleModel.modules()) 50 | if len(singleModelSlices) == 1: 51 | hnd = singleModel.register_forward_hook(moduleParams_hook) 52 | print("$$$$$$$$$$$$$$$$$$$ Layer hooking$$$$$$$$$$$$$ ",inum) 53 | inum = inum + 1 54 | global_hooks_handles.append(hnd) 55 | ###here could hook funcs 56 | funcsParams_hook() 57 | 58 | return None 59 | def hookwork_assembed(): 60 | blobSize = 0 61 | if len(TorchLayers_Keeper) == 0: 62 | print("Make sure interpreter is working...") 63 | for item in TorchLayers_Keeper[:]: 64 | if len(item['inputs_layersName']) == 0: 65 | TorchLayers_Keeper.remove(item) 66 | ####################add outputs key################# 67 | lysize = len(TorchLayers_Keeper) 68 | ###################draw graph here is ok############################## 69 | if lysize > 0: 70 | g_pen = TorchGraph_Pen(TorchLayers_Keeper, "./outputs/ncnn") 71 | g_pen.makeLayer() 72 | for ll in range(0, lysize): 73 | cur_layer = TorchLayers_Keeper[ll] 74 | cur_layer_name = cur_layer['cur_layer_Name'] 75 | cur_layer['outputs_layersName'] = [] 76 | cur_layer_outputsname_list = [] 77 | indx = ll 78 | for next_layer in TorchLayers_Keeper[(ll+1):lysize]: #last - 1 79 | indx += 1 80 | next_layer_inputs = next_layer['inputs_layersName'] 81 | if cur_layer_name in next_layer_inputs: 82 | cur_layer['splitCnt'] += 1 83 | blobSize += 1 84 | cur_layer_outputsname_list.append(indx) 85 | 86 | if cur_layer['splitCnt'] < 2: 87 | cur_layer['outputs_layersName'].append(cur_layer_name) 88 | if cur_layer['splitCnt'] == 0: 89 | blobSize = blobSize + 1 90 | else: 91 | for k in range(0,cur_layer['splitCnt']): 92 | snm = cur_layer_name + '_splitncnn_' + str(k) 93 | cur_layer['outputs_layersName'].append(snm) 94 | lidx = cur_layer_outputsname_list[k] 95 | outlyr = TorchLayers_Keeper[lidx] 96 | if len(outlyr['inputs_layersName']) == 1: 97 | outlyr['inputs_layersName'][0] = snm 98 | else: 99 | for ik in range(0,len(outlyr['inputs_layersName'])): 100 | if outlyr['inputs_layersName'][ik] == cur_layer_name: 101 | outlyr['inputs_layersName'][ik] = snm 102 | 103 | print("layer interpreter is ok now.....") 104 | return blobSize 105 | 106 | def unMount_forward_hooks(): 107 | for hookhnd in global_hooks_handles: 108 | hookhnd.remove() 109 | return None 110 | 111 | def convert_walking(dstType = 0): 112 | blobNum = hookwork_assembed() ###call once### 113 | if dstType == FRAME_WORK_TYPE["DEFAULT"]: 114 | NCNN_NET = NCNN_FRAMEWORK_FACTORY("./outputs/") 115 | NCNN_NET.converting(TorchLayers_Keeper, blobNum) 116 | elif dstType == FRAME_WORK_TYPE["CAFFE"]: 117 | #elif FRAME_WORK_TYPE == FRAME_WORK_TYPE["TENSOR_FLOW"]: 118 | #elif FRAME_WORK_TYPE == FRAME_WORK_TYPE["ONNX"]: 119 | print("caffe is now") 120 | else: 121 | print("Sorry, some AI framework can not be supported...") 122 | 123 | 124 | def graph_walking(): 125 | print("draw network flow-graphic") 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /torchLayer_Graph.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/' ###make sure graph py could find your gv bin 3 | import sys 4 | import platform 5 | import graphviz as gv 6 | from string import Template 7 | ########################################################################### 8 | Attrib_Dicts = { 9 | 'Conv': dict(style='filled',align='top',fontsize='26',ranksep='0.1',height='0.5',color='red2',shape='circle'), 10 | 'BatchNorm': dict(style='filled',align='top',fontsize='22',ranksep='0.1',height='0.1',color='blue2',shape='box'), 11 | 'Default': dict(style='filled',align='top',fontsize='22',ranksep='0.1',height='0.1',shape='box'), 12 | } 13 | ########################################################################### 14 | class TorchGraph_Pen(object): 15 | def __init__(self, in_LayerDict, out_Path, gtype = 0, gnode_attr = {}): 16 | self.inSrcDict = in_LayerDict 17 | self.outputPath = out_Path 18 | self.graph = gv.Digraph(format='png', node_attr=Attrib_Dicts['Default']) 19 | 20 | def __str__(self): 21 | return str("gv-graph") 22 | 23 | 24 | #############color='red2',shape='circle',height='.5'########### 25 | def makeNodes(self,layerInfo,cur_node_label='',node_attrib={}): 26 | in_nodes = layerInfo['inputs_layersName'] 27 | cur_node = layerInfo['cur_layer_Name'] 28 | 29 | ###############add node ,edge into graph############## 30 | self.graph.node(cur_node,cur_node_label,node_attrib) 31 | edge_label = 'branch' 32 | edge_attri = '' 33 | if len(in_nodes) > 1: 34 | edge_label = '%d-inBranches' %(len(in_nodes)) 35 | 36 | for in_node in in_nodes: 37 | self.graph.edge(in_node, cur_node, edge_label,edge_attri) 38 | 39 | return 40 | 41 | def makeLayer(self): 42 | code = Template('''subgraph cluster_$index {\n 43 | color=white;\n 44 | node [style=solid,color=$color];\n 45 | $nodesB$nodesM$nodesE label = "layer $name($node_num)";\n 46 | }\n 47 | ''') 48 | if len(self.inSrcDict) <= 1: 49 | print("no right dicts for drawing") 50 | ###############give a input node########### 51 | 52 | for layer_Info in self.inSrcDict: 53 | layer_Type = layer_Info['layer_Type'] 54 | layername = layer_Info['cur_layer_Name'] 55 | node_label = '' 56 | node_attrib = {} 57 | if layer_Type == 'Convolution': 58 | c_inputs = layer_Info['number_of_Input_Feature_Channels'] 59 | c_output = layer_Info['number_of_Output_Feature_Channels'] 60 | node_label += layername 61 | node_label += "" "\n" "" 62 | node_label += "" "inChannle:{}""".format(c_inputs) 63 | node_label += "" "\n" "" 64 | node_label += "" "outChannle:{}""".format(c_output) 65 | node_label += "" "\n" "" 66 | node_attrib = Attrib_Dicts['Conv'] 67 | elif layer_Type == 'BatchNorm': 68 | channels = layer_Info['number_of_InOut_Feature_Channels'] 69 | node_label += layername 70 | node_label += "" "\n" "" 71 | node_label += "" "BChannle:{}""".format(channels) 72 | node_label += "" "\n" "" 73 | node_attrib = Attrib_Dicts['BatchNorm'] 74 | elif layer_Type == 'ReLU': 75 | node_label += layername 76 | node_label += "" "\n" "" 77 | node_attrib = Attrib_Dicts['Default'] 78 | elif layer_Info['layer_Type'] == 'Pooling': 79 | poolType = layer_Info['pooling_Type'] 80 | node_label += layername 81 | node_label += "" "\n" "" 82 | node_label += "" "Pool:{}""".format(poolType) 83 | node_label += "" "\n" "" 84 | node_attrib = Attrib_Dicts['Default'] 85 | elif layer_Info['layer_Type'] == 'Concat': 86 | inNum = len(layer_Info['inputs_layersName']) 87 | node_label += layername 88 | node_label += "" "\n" "" 89 | node_label += "" "In:{}""".format(inNum) 90 | node_label += "" "\n" "" 91 | node_attrib = Attrib_Dicts['Default'] 92 | elif layer_Info['layer_Type'] == 'Upsample': 93 | node_label += layername 94 | node_label += "" "\n" "" 95 | node_attrib = Attrib_Dicts['Default'] 96 | elif layer_Info['layer_Type'] == 'Permute': 97 | node_label += layername 98 | node_label += "" "\n" "" 99 | node_attrib = Attrib_Dicts['Default'] 100 | elif layer_Info['layer_Type'] == 'Reshape': 101 | node_label += layername 102 | node_label += "" "\n" "" 103 | node_attrib = Attrib_Dicts['Default'] 104 | elif layer_Info['layer_Type'] == 'Add': 105 | node_label += layername 106 | node_label += "" "\n" "" 107 | node_attrib = Attrib_Dicts['Default'] 108 | elif layer_Info['layer_Type'] == 'Softmax': 109 | node_label += layername 110 | node_label += "" "\n" "" 111 | node_attrib = Attrib_Dicts['Default'] 112 | else: 113 | print("Attention!!!!! some layer type not exsit!!!") 114 | pass 115 | self.makeNodes(layer_Info,node_label,node_attrib) 116 | pass 117 | self.graph.render(self.outputPath) 118 | gvPath = self.outputPath + '.gv' 119 | self.save_graphFile(self.graph.source, gvPath) 120 | return 121 | 122 | def save_graphFile(self, str, path): 123 | print (path) 124 | f = open(path,'w') 125 | f.write(str) 126 | f.close() 127 | ########################################################################## 128 | -------------------------------------------------------------------------------- /torchLayer_IMPL.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from torch.autograd import Variable 6 | import hashlib 7 | 8 | ############################################################################################### 9 | ############################################################################################### 10 | ###################Supporter OF Modules and Funcs FOR INTERPRETER############################## 11 | ############################################################################################### 12 | ############################################################################################### 13 | 14 | TYPE_ACTIVATION_FUNC = { 15 | 'None' : 0, 16 | 'Linear' : 1, 17 | 'Relu' : 2, 18 | 'TanH' : 3, 19 | 'Sigmoid' : 4, 20 | 'Absolute' : 5, 21 | 'Leaky' : 6, 22 | 23 | } 24 | 25 | TYPE_ELEMWISE_OP = { 26 | 'Add': 0, 27 | 'Mul': 1, 28 | 'Div': 2, 29 | 'Max': 3, 30 | 'Cat': 4, 31 | 'Relu': 5, 32 | 'Reshape': 6, 33 | 'Permute': 7, 34 | 'SoftMax': 8, 35 | 'ReduceMean': 9, 36 | } 37 | 38 | # TYPE_TENSOR_OP = { 39 | # 'Permute': 0, 40 | # 'Sub': 1, 41 | # } 42 | 43 | TYPE_POOLING = { 44 | 'Max' : 0, 45 | 'Avg' : 1, 46 | } 47 | 48 | TYPE_UPSAMPLE = { 49 | 'Nearest': 0, 50 | 'BiLinear': 1, 51 | 'Bicubic': 2 52 | } 53 | 54 | def create_StrUID(inStr): 55 | strMd5 = hashlib.md5(inStr.encode("utf-8")) 56 | strID = strMd5.hexdigest() 57 | return str(strID) 58 | 59 | gl_type_dicts_count = {} 60 | gl_layer_lists = [] 61 | gl_layer_NUM = 0 62 | def module_Interpreter_For_Conv2D(module, inputs, output): 63 | ##################################################### 64 | inp_id = id(inputs[0]) 65 | outp_id = id(output) 66 | if inp_id == outp_id: 67 | return {} 68 | ##################################################### 69 | global gl_type_dicts_count 70 | global gl_layer_lists 71 | global gl_layer_NUM 72 | layer_name = "" 73 | if len(gl_type_dicts_count) == 0: 74 | gl_type_dicts_count['Convolution'] = 1 75 | else: 76 | tn = 'Convolution' 77 | if tn in gl_type_dicts_count.keys(): 78 | gl_type_dicts_count['Convolution'] += 1 79 | else: 80 | gl_type_dicts_count['Convolution'] = 1 81 | convGroup = module.groups 82 | cvtypename = "Convolution" 83 | if convGroup > 1: 84 | cvtypename = "ConvolutionDepthWise" 85 | 86 | layer_name = cvtypename + str(gl_type_dicts_count['Convolution'] - 1) 87 | gl_layer_NUM += 1 88 | ##################################################### 89 | l_list = [] #[layer_name,inputs,output] 90 | l_list.append(layer_name) 91 | l_list.append(inputs[0]) 92 | l_list.append(output) 93 | if len(gl_layer_lists) > gl_layer_NUM: 94 | gl_layer_lists[gl_layer_NUM - 1] = l_list 95 | else: 96 | gl_layer_lists.append(l_list) 97 | 98 | layer_inputs = [] 99 | for j in range(0, gl_layer_NUM): 100 | curIndex = gl_layer_NUM - 1 - j 101 | for i_inp in inputs: 102 | if curIndex == 0: 103 | if i_inp.equal(gl_layer_lists[0][1]): # first 104 | layer_inputs.append("0") 105 | else: 106 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 107 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 108 | if len(layer_inputs) == 1: 109 | break 110 | if len(layer_inputs) < len(inputs[0]): # must <= 111 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 112 | # force no-owned input from last layer 113 | k = len(gl_layer_lists) - 1 114 | if k <= 0: 115 | assert(False) 116 | 117 | lyn = gl_layer_lists[k-1][0] 118 | layer_inputs.append(lyn) 119 | else: 120 | print("fuck error crashed....") 121 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 122 | print("cather wrong layer.....") 123 | ###################################################### 124 | torchOP_LayerInfos = {} 125 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 126 | torchOP_LayerInfos['layer_Type'] = 'Convolution' 127 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 128 | 129 | torchOP_LayerInfos['number_of_Input_Feature_Channels'] = inputs[0].shape[1] 130 | torchOP_LayerInfos['height_of_Input_Feature'] = inputs[0].shape[2] 131 | torchOP_LayerInfos['width_of_Input_Feature'] = inputs[0].shape[3] 132 | torchOP_LayerInfos['number_of_Output_Feature_Channels'] = output.shape[1] 133 | torchOP_LayerInfos['height_of_Output_Feature'] = output.shape[2] 134 | torchOP_LayerInfos['width_of_Output_Feature'] = output.shape[3] 135 | torchOP_LayerInfos['kernel_Height'] = module.kernel_size[0] 136 | torchOP_LayerInfos['kernel_Width'] = module.kernel_size[1] 137 | torchOP_LayerInfos['padding_Size_Y'] = module.padding[0] 138 | torchOP_LayerInfos['padding_Size_X'] = module.padding[1] 139 | torchOP_LayerInfos['stride_Size_Y'] = module.stride[0] 140 | torchOP_LayerInfos['stride_Size_X'] = module.stride[1] 141 | torchOP_LayerInfos['dilation_Size_Y'] = module.dilation[0] 142 | torchOP_LayerInfos['dilation_Size_X'] = module.dilation[1] 143 | torchOP_LayerInfos['activation_Type'] = TYPE_ACTIVATION_FUNC['None'] 144 | torchOP_LayerInfos['num_of_Group'] = module.groups 145 | torchOP_LayerInfos['splitCnt'] = 0 146 | if module.bias is None: 147 | torchOP_LayerInfos['if_Use_Bias'] = 0 148 | # cvvv = module.weight.data 149 | # cwww = cvvv.numpy() 150 | # ctt = torch.rand(4) 151 | # ctw0 = ctt.numpy().astype(np.float32) 152 | # ctw = np.around(ctt.numpy(),decimals=5).astype(np.float32) 153 | covnweights = module.weight.detach().numpy() 154 | torchOP_LayerInfos['weights_Numpy_NCHW_F32'] = covnweights.astype('float32') #np.around(module.weight.detach().numpy().ravel(),decimals=4) 155 | torchOP_LayerInfos['bias_Numpy_F32'] = np.zeros((output.shape[1],), dtype=np.float32).astype(np.float32) 156 | else: 157 | torchOP_LayerInfos['if_Use_Bias'] = 1 158 | convwt = module.weight.detach().numpy() 159 | torchOP_LayerInfos['weights_Numpy_NCHW_F32'] = convwt.astype(np.float32) 160 | convbias = module.bias.detach().numpy() 161 | torchOP_LayerInfos['bias_Numpy_F32'] = convbias.astype(np.float32) 162 | 163 | return torchOP_LayerInfos 164 | 165 | 166 | def module_Interpreter_For_BatchNorm(module, inputs, output): 167 | ##################################################### 168 | inp_id = id(inputs[0]) 169 | outp_id = id(output) 170 | if inp_id == outp_id: 171 | return {} 172 | 173 | ##################################################### 174 | global gl_type_dicts_count 175 | global gl_layer_lists 176 | global gl_layer_NUM 177 | layer_name = "" 178 | if len(gl_type_dicts_count) == 0: 179 | gl_type_dicts_count['BatchNorm'] = 1 180 | else: 181 | tn = 'BatchNorm' 182 | if tn in gl_type_dicts_count.keys(): 183 | gl_type_dicts_count['BatchNorm'] += 1 184 | else: 185 | gl_type_dicts_count['BatchNorm'] = 1 186 | 187 | layer_name = "BatchNorm" + str(gl_type_dicts_count['BatchNorm'] - 1) 188 | gl_layer_NUM += 1 189 | ##################################################### 190 | l_list = [] # [layer_name,inputs,output] 191 | l_list.append(layer_name) 192 | l_list.append(inputs[0]) 193 | l_list.append(output) 194 | if len(gl_layer_lists) > gl_layer_NUM: 195 | gl_layer_lists[gl_layer_NUM - 1] = l_list 196 | else: 197 | gl_layer_lists.append(l_list) 198 | 199 | layer_inputs = [] 200 | 201 | for j in range(0, gl_layer_NUM): 202 | curIndex = gl_layer_NUM - 1 - j 203 | for i_inp in inputs: 204 | if curIndex == 0: 205 | if i_inp.equal(gl_layer_lists[0][1]): # first 206 | layer_inputs.append("0") 207 | else: 208 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 209 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 210 | if len(layer_inputs) == 1: 211 | break 212 | 213 | if len(layer_inputs) < len(inputs[0]): # must <= 214 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 215 | # force no-owned input from last layer 216 | k = len(gl_layer_lists) - 1 217 | if k <= 0: 218 | assert(False) 219 | 220 | lyn = gl_layer_lists[k-1][0] 221 | layer_inputs.append(lyn) 222 | else: 223 | print("fuck error crashed....") 224 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 225 | print("cather wrong layer.....") 226 | ###################################################### 227 | torchOP_LayerInfos = {} 228 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 229 | torchOP_LayerInfos['layer_Type'] = 'BatchNorm' 230 | 231 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 232 | torchOP_LayerInfos['number_of_InOut_Feature_Channels'] = output.shape[1] 233 | torchOP_LayerInfos['height_of_InOut_Feature'] = output.shape[2] 234 | torchOP_LayerInfos['width_of_InOut_Feature'] = output.shape[3] 235 | npweight = module.weight.detach().numpy() 236 | bnbias = module.bias.detach().numpy() 237 | bnvar = module.running_var.detach().numpy() 238 | bnmean = module.running_mean.detach().numpy() 239 | torchOP_LayerInfos['slope_data'] = npweight.astype(np.float32) 240 | torchOP_LayerInfos['bias_data'] = bnbias.astype(np.float32) 241 | torchOP_LayerInfos['var_data'] = bnvar.astype(np.float32) 242 | torchOP_LayerInfos['mean_data'] = bnmean.astype(np.float32) 243 | torchOP_LayerInfos['splitCnt'] = 0 244 | return torchOP_LayerInfos 245 | 246 | def module_Interpreter_For_Relu(module, inputs, output): 247 | # if output.equal(inputs[0]): 248 | # return {} 249 | ##################################################### 250 | global gl_type_dicts_count 251 | global gl_layer_lists 252 | global gl_layer_NUM 253 | layer_name = "" 254 | if len(gl_type_dicts_count) == 0: 255 | gl_type_dicts_count['ReLU'] = 1 256 | else: 257 | tn = 'ReLU' 258 | if tn in gl_type_dicts_count.keys(): 259 | gl_type_dicts_count['ReLU'] += 1 260 | else: 261 | gl_type_dicts_count['ReLU'] = 1 262 | 263 | layer_name = "ReLU" + str(gl_type_dicts_count['ReLU'] - 1) 264 | gl_layer_NUM += 1 265 | ##################################################### 266 | l_list = [] # [layer_name,inputs,output] 267 | l_list.append(layer_name) 268 | l_list.append(inputs[0]) 269 | l_list.append(output) 270 | if len(gl_layer_lists) > gl_layer_NUM: 271 | gl_layer_lists[gl_layer_NUM - 1] = l_list 272 | else: 273 | gl_layer_lists.append(l_list) 274 | 275 | layer_inputs = [] 276 | for j in range(0, gl_layer_NUM): 277 | curIndex = gl_layer_NUM - 1 - j 278 | for i_inp in inputs: 279 | if curIndex == 0: 280 | if i_inp.equal(gl_layer_lists[0][1]): # first 281 | layer_inputs.append("0") 282 | else: 283 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 284 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 285 | 286 | if len(layer_inputs) == 1: 287 | break 288 | 289 | if len(layer_inputs) < len(inputs[0]): # must <= 290 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 291 | # force no-owned input from last layer 292 | k = len(gl_layer_lists) - 1 293 | if k <= 0: 294 | assert(False) 295 | 296 | lyn = gl_layer_lists[k-1][0] 297 | layer_inputs.append(lyn) 298 | else: 299 | print("fuck error crashed....") 300 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 301 | print("cather wrong layer.....") 302 | ###################################################### 303 | 304 | torchOP_LayerInfos = {} 305 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 306 | torchOP_LayerInfos['layer_Type'] = 'ReLU' 307 | 308 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 309 | torchOP_LayerInfos['number_of_InOut_Feature_Channels'] = output.shape[1] 310 | torchOP_LayerInfos['height_of_InOut_Feature'] = output.shape[2] 311 | torchOP_LayerInfos['width_of_InOut_Feature'] = output.shape[3] 312 | torchOP_LayerInfos['activation_Type'] = TYPE_ACTIVATION_FUNC['Relu'] 313 | torchOP_LayerInfos['splitCnt'] = 0 314 | return torchOP_LayerInfos 315 | ################################################################################ 316 | def module_Interpreter_For_MLinear(module, inputs, output): 317 | ##################################################### 318 | inp_id = id(inputs[0]) 319 | outp_id = id(output) 320 | if inp_id == outp_id: 321 | return {} 322 | 323 | ##################################################### 324 | global gl_type_dicts_count 325 | global gl_layer_lists 326 | global gl_layer_NUM 327 | layer_name = "" 328 | if len(gl_type_dicts_count) == 0: 329 | gl_type_dicts_count['MLinear'] = 1 330 | else: 331 | tn = 'MLinear' 332 | if tn in gl_type_dicts_count.keys(): 333 | gl_type_dicts_count['MLinear'] += 1 334 | else: 335 | gl_type_dicts_count['MLinear'] = 1 336 | 337 | layer_name = "MLinear" + str(gl_type_dicts_count['MLinear'] - 1) 338 | gl_layer_NUM += 1 339 | ##################################################### 340 | l_list = [] # [layer_name,inputs,output] 341 | l_list.append(layer_name) 342 | l_list.append(inputs[0]) 343 | l_list.append(output) 344 | if len(gl_layer_lists) > gl_layer_NUM: 345 | gl_layer_lists[gl_layer_NUM - 1] = l_list 346 | else: 347 | gl_layer_lists.append(l_list) 348 | 349 | layer_inputs = [] 350 | 351 | for j in range(0, gl_layer_NUM): 352 | curIndex = gl_layer_NUM - 1 - j 353 | for i_inp in inputs: 354 | if curIndex == 0: 355 | if i_inp.equal(gl_layer_lists[0][1]): # first 356 | layer_inputs.append("0") 357 | else: 358 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 359 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 360 | if len(layer_inputs) == 1: 361 | break 362 | 363 | if len(layer_inputs) < len(inputs[0]): # must <= 364 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 365 | # force no-owned input from last layer 366 | k = len(gl_layer_lists) - 1 367 | if k <= 0: 368 | assert(False) 369 | 370 | lyn = gl_layer_lists[k-1][0] 371 | layer_inputs.append(lyn) 372 | else: 373 | print("fuck error crashed....") 374 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 375 | print("cather wrong layer.....") 376 | ###################################################### 377 | torchOP_LayerInfos = {} 378 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 379 | torchOP_LayerInfos['layer_Type'] = 'MLinear' 380 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 381 | mlweight = module.weight.detach().numpy() 382 | mlbias = module.bias.detach().numpy() 383 | torchOP_LayerInfos['weights_data'] = mlweight.astype(np.float32) 384 | torchOP_LayerInfos['bias_data'] = mlbias.astype(np.float32) 385 | 386 | torchOP_LayerInfos['splitCnt'] = 0 387 | return torchOP_LayerInfos 388 | ################################################ 389 | 390 | 391 | def getUpsampleFunctionArguments(input, size=None, scale_factor=None, mode='nearest', align_corners=None): 392 | return {"size": size, "scale_factor": scale_factor, "mode": mode, "align_corners": align_corners } 393 | 394 | 395 | def getPoolingFunctionArguments(input, kernel_size, stride=None, padding=0, dilation=1, ceil_mode=False, 396 | return_indices=False): 397 | return {"kernel_size": kernel_size, "stride": stride, "padding": padding, "ceil_mode": ceil_mode, 398 | "dilation": dilation, "return_indices": return_indices} 399 | 400 | def getPermuteFunctionArguments(input,*dims): 401 | return {"dims":dims} 402 | 403 | def getReshapeFunctionArguments(input,*shape): 404 | return {"shape":shape} 405 | def getSoftMaxFunctionArguments(input,dim): 406 | return {"dim":dim} 407 | dict_origin_F = {} 408 | 409 | 410 | def func_forward_hooking(func, output, func_infos_List=[], *args, **kwargs): 411 | inputs = [a for a in args if isinstance(a, Variable)] 412 | inputs += [a for a in kwargs.values() if isinstance(a, Variable)] 413 | if len(inputs) == 0: 414 | inputs = [a for a in args[0] if isinstance(a, Variable)] 415 | inputs += [a for a in kwargs.values() if isinstance(a, Variable)] 416 | if func in AVALIABLE_FUNCTION_CONVERTER.keys(): 417 | func_ops_Info = {} 418 | func_ops_Info = AVALIABLE_FUNCTION_CONVERTER[func](func, inputs, output, *args, **kwargs) 419 | 420 | if len(func_ops_Info) == 0: 421 | return False 422 | 423 | func_infos_List.append(func_ops_Info) 424 | #print("@@@@@@@converting function@@@@@@@@ ", func_infos_dict) 425 | else: 426 | print("unsupport function converter of ",func) 427 | 428 | return True 429 | 430 | def overload_pooling(funcs_dict=[]): 431 | dict_origin_F['OVER_LOOAD_POOLING'] = {} 432 | dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Avg']] = F.avg_pool2d 433 | def new_functional_avg_pool2d(*args, **kwargs): 434 | output = dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Avg']](*args, **kwargs) 435 | # add hook func 436 | func_forward_hooking(dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Avg']], output, funcs_dict,*args, **kwargs) 437 | 438 | return output 439 | F.avg_pool2d = new_functional_avg_pool2d 440 | # 441 | # next overload avg_pool2d 442 | dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Max']] = F.max_pool2d 443 | def new_functional_max_pool2d(*args, **kwargs): 444 | output = dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Max']](*args, **kwargs) 445 | # add hook func 446 | func_forward_hooking(dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Max']], output, funcs_dict,*args, **kwargs) 447 | 448 | return output 449 | F.max_pool2d = new_functional_max_pool2d 450 | return None 451 | 452 | 453 | def overload_upsampling(funcs_dict=[]): 454 | dict_origin_F['OVER_LOOAD_UPSAMPLING'] = F.interpolate 455 | 456 | def new_functional_upsample(*args, **kwargs): 457 | output = dict_origin_F['OVER_LOOAD_UPSAMPLING'](*args, **kwargs) 458 | # add hook func 459 | func_forward_hooking(dict_origin_F['OVER_LOOAD_UPSAMPLING'], output,funcs_dict, *args, **kwargs) 460 | 461 | return output 462 | F.interpolate = new_functional_upsample 463 | return None 464 | 465 | def overload_elementwiseoperator(funcs_dict=[]): 466 | dict_origin_F['ElementWiseOperator'] = {} 467 | # 468 | # next overload add 469 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Add']] = torch.add 470 | 471 | def new_torch_add(*args, **kwargs): 472 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Add']](*args, **kwargs) 473 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Add']],output,funcs_dict, *args, **kwargs) 474 | 475 | return output 476 | 477 | torch.add = new_torch_add 478 | # 479 | # next overload mul 480 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Mul']] = torch.mul 481 | 482 | def new_torch_mul(*args, **kwargs): 483 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Mul']](*args, **kwargs) 484 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Mul']],output,funcs_dict, *args, **kwargs) 485 | 486 | return output 487 | 488 | torch.mul = new_torch_mul 489 | # 490 | # next overload div 491 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Div']] = torch.div 492 | 493 | def new_torch_div(*args, **kwargs): 494 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Div']](*args, **kwargs) 495 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Div']],output, funcs_dict, *args, **kwargs) 496 | 497 | return output 498 | 499 | torch.div = new_torch_div 500 | # 501 | # next overload max 502 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Max']] = torch.max 503 | 504 | def new_torch_max(*args, **kwargs): 505 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Max']](*args, **kwargs) 506 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Max']],output, funcs_dict, *args, **kwargs) 507 | 508 | return output 509 | 510 | torch.max = new_torch_max 511 | 512 | # next overload softmax 513 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['SoftMax']] = F.softmax 514 | def new_softmax(*args, **kwargs): 515 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['SoftMax']](*args, **kwargs) 516 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['SoftMax']], output, funcs_dict, *args, 517 | **kwargs) 518 | 519 | return output 520 | 521 | F.softmax = new_softmax 522 | # 523 | # next overload cat 524 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Cat']] = torch.cat 525 | def new_torch_cat(*args, **kwargs): 526 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Cat']](*args, **kwargs) 527 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Cat']],output,funcs_dict, *args, **kwargs) 528 | 529 | return output 530 | 531 | torch.cat = new_torch_cat 532 | # 533 | # next overload relue 534 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Relu']] = F.relu 535 | 536 | def new_torch_relu(*args, **kwargs): 537 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Relu']](*args, **kwargs) 538 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Relu']], output, funcs_dict, *args, 539 | **kwargs) 540 | 541 | return output 542 | F.relu = new_torch_relu 543 | # next overload permute 544 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Permute']] = torch.Tensor.permute 545 | def new_torch_permute(*args, **kwargs): 546 | #dims = (args[1], args[2],args[3],args[4]) 547 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Permute']](*args, **kwargs) 548 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Permute']], output, funcs_dict, *args, 549 | **kwargs) 550 | 551 | return output 552 | torch.Tensor.permute = new_torch_permute 553 | 554 | # next overload reshape 555 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Reshape']] = torch.Tensor.reshape 556 | def new_torch_reshape(*args, **kwargs): 557 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Reshape']](*args, **kwargs) 558 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['Reshape']], output, funcs_dict, 559 | *args, 560 | **kwargs) 561 | 562 | return output 563 | torch.Tensor.reshape = new_torch_reshape 564 | 565 | # next overload reduceMean 566 | dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['ReduceMean']] = torch.mean 567 | 568 | def new_torch_reducemean(*args, **kwargs): 569 | output = dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['ReduceMean']](*args, **kwargs) 570 | func_forward_hooking(dict_origin_F['ElementWiseOperator'][TYPE_ELEMWISE_OP['ReduceMean']], output, funcs_dict, 571 | *args, 572 | **kwargs) 573 | 574 | return output 575 | 576 | torch.mean = new_torch_reducemean 577 | return None 578 | ################## 579 | ################################################################################################ 580 | ################################################################################################ 581 | def function_Interpreter_For_ElementWiseOp_Add(func, inputs, output, *args, **kwargs): 582 | inp_ids = [id(inp) for inp in inputs] 583 | outp_id = id(output) 584 | if outp_id in inp_ids: 585 | return {} 586 | ##################################################### 587 | global gl_type_dicts_count 588 | global gl_layer_lists 589 | global gl_layer_NUM 590 | layer_name = "" 591 | if len(gl_type_dicts_count) == 0: 592 | gl_type_dicts_count['Add'] = 1 593 | else: 594 | tn = 'Add' 595 | if tn in gl_type_dicts_count.keys(): 596 | gl_type_dicts_count['Add'] += 1 597 | else: 598 | gl_type_dicts_count['Add'] = 1 599 | 600 | layer_name = "Add" + str(gl_type_dicts_count['Add'] - 1) 601 | gl_layer_NUM += 1 602 | ##################################################### 603 | l_list = [] # [layer_name,inputs,output] 604 | l_list.append(layer_name) 605 | l_list.append(inputs) 606 | l_list.append(output) 607 | if len(gl_layer_lists) > gl_layer_NUM: 608 | gl_layer_lists[gl_layer_NUM - 1] = l_list 609 | else: 610 | gl_layer_lists.append(l_list) 611 | 612 | layer_inputs = [] 613 | 614 | for j in range(0, gl_layer_NUM): 615 | curIndex = gl_layer_NUM - 1 - j 616 | for i_inp in inputs: 617 | if curIndex == 0: 618 | if i_inp.equal(gl_layer_lists[0][1]): # first 619 | layer_inputs.append("0") 620 | else: 621 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 622 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 623 | if len(layer_inputs) == 2: 624 | break 625 | 626 | if len(layer_inputs) < len(inputs): # must <= 627 | if 1 == (len(inputs) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 628 | # force no-owned input from last layer 629 | k = len(gl_layer_lists) - 1 630 | if k <= 0: 631 | assert (False) 632 | lyn = gl_layer_lists[k - 1][0] 633 | layer_inputs.append(lyn) 634 | else: 635 | print("fuck error crashed....") 636 | elif len(layer_inputs) > len(inputs): # some output is same ,please take nearest one 637 | print("cather wrong layer.....") 638 | ###################################################### 639 | torchOP_LayerInfos = {} 640 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 641 | torchOP_LayerInfos['layer_Type'] = 'Add' 642 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 643 | torchOP_LayerInfos['number_of_Input_Layers'] = len(inputs) 644 | torchOP_LayerInfos['operator_Type'] = TYPE_ELEMWISE_OP['Add'] 645 | torchOP_LayerInfos['activation_Type'] = TYPE_ACTIVATION_FUNC['None'] 646 | torchOP_LayerInfos['splitCnt'] = 0 647 | return torchOP_LayerInfos 648 | 649 | def function_Interpreter_For_ElementWiseOp_ArrMax(func, inputs, output, *args, **kwargs): 650 | 651 | inp_ids = [id(inp) for inp in inputs[0]] 652 | outp_id = id(output) 653 | if outp_id in inp_ids: 654 | return {} 655 | 656 | ##################################################### 657 | global gl_type_dicts_count 658 | global gl_layer_lists 659 | global gl_layer_NUM 660 | layer_name = "" 661 | if len(gl_type_dicts_count) == 0: 662 | gl_type_dicts_count['Max'] = 1 663 | else: 664 | tn = 'Max' 665 | if tn in gl_type_dicts_count.keys(): 666 | gl_type_dicts_count['Max'] += 1 667 | else: 668 | gl_type_dicts_count['Max'] = 1 669 | 670 | layer_name = "Max" + str(gl_type_dicts_count['Max'] - 1) 671 | gl_layer_NUM += 1 672 | ##################################################### 673 | l_list = [] # [layer_name,inputs,output] 674 | l_list.append(layer_name) 675 | l_list.append(inputs[0]) 676 | l_list.append(output) 677 | if len(gl_layer_lists) > gl_layer_NUM: 678 | gl_layer_lists[gl_layer_NUM - 1] = l_list 679 | else: 680 | gl_layer_lists.append(l_list) 681 | 682 | layer_inputs = [] 683 | 684 | for j in range(0, gl_layer_NUM): 685 | curIndex = gl_layer_NUM - 1 - j 686 | for i_inp in inputs: 687 | if curIndex == 0: 688 | if i_inp.equal(gl_layer_lists[0][1]): # first 689 | layer_inputs.append("0") 690 | else: 691 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 692 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 693 | if len(layer_inputs) == 1: 694 | break 695 | 696 | if len(layer_inputs) < len(inputs[0]): # must <= 697 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 698 | # force no-owned input from last layer 699 | k = len(gl_layer_lists) - 1 700 | if k <= 0: 701 | assert (False) 702 | 703 | lyn = gl_layer_lists[k - 1][0] 704 | layer_inputs.append(lyn) 705 | else: 706 | print("fuck error crashed....") 707 | elif len(layer_inputs) > len(inputs[0]): # some output is same ,please take nearest one 708 | print("cather wrong layer.....") 709 | ###################################################### 710 | torchOP_LayerInfos = {} 711 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 712 | torchOP_LayerInfos['layer_Type'] = 'Max' 713 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 714 | torchOP_LayerInfos['operator_Type'] = TYPE_ELEMWISE_OP['Max'] 715 | torchOP_LayerInfos['activation_Type'] = TYPE_ACTIVATION_FUNC['None'] 716 | torchOP_LayerInfos['splitCnt'] = 0 717 | return torchOP_LayerInfos 718 | 719 | 720 | def function_Interpreter_For_ElementWiseOp_Cat(func, inputs, output, *args, **kwargs): 721 | if len(inputs) == 1: 722 | ts_input = inputs[0] 723 | ts_output = output 724 | if ts_input.equal(ts_output): 725 | return {} 726 | else: 727 | print("Concat change sth") 728 | 729 | inp_ids = [inp for inp in inputs] 730 | outp_id = id(output) 731 | ##################################################### 732 | global gl_type_dicts_count 733 | global gl_layer_lists 734 | global gl_layer_NUM 735 | layer_name = "" 736 | if len(gl_type_dicts_count) == 0: 737 | gl_type_dicts_count['Concat'] = 1 738 | else: 739 | tn = 'Concat' 740 | if tn in gl_type_dicts_count.keys(): 741 | gl_type_dicts_count['Concat'] += 1 742 | else: 743 | gl_type_dicts_count['Concat'] = 1 744 | 745 | layer_name = "Concat" + str(gl_type_dicts_count['Concat'] - 1) 746 | gl_layer_NUM += 1 747 | ##################################################### 748 | l_list = [] # [layer_name,inputs,output] 749 | l_list.append(layer_name) 750 | inp_list = [] 751 | for i_inp in inputs: 752 | inp_list.append(i_inp) 753 | 754 | l_list.append(inp_list) 755 | l_list.append(output) 756 | if len(gl_layer_lists) > gl_layer_NUM: 757 | gl_layer_lists[gl_layer_NUM - 1] = l_list 758 | else: 759 | gl_layer_lists.append(l_list) 760 | 761 | layer_inputs = [] 762 | inps_dict = {} 763 | for j in range(0, gl_layer_NUM): 764 | curIndex = gl_layer_NUM - 1 - j 765 | inps_i = 0 766 | for i_inp in inp_list: 767 | inps_i += 1 768 | if curIndex == 0: 769 | if i_inp.equal(gl_layer_lists[0][1]): # first 770 | layer_inputs.append("0") 771 | else: 772 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 773 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 774 | inps_dict[inps_i - 1] = gl_layer_lists[curIndex - 1][0] 775 | 776 | if len(layer_inputs) == len(inp_list): 777 | if len(inps_dict) > 1: 778 | for idxx in range(0, len(inps_dict)): 779 | layer_inputs[idxx] = inps_dict[idxx] 780 | pass 781 | break 782 | 783 | if len(layer_inputs) < len(inputs): # must <= 784 | if 1 == (len(inputs) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 785 | # force no-owned input from last layer 786 | k = len(gl_layer_lists) - 1 787 | if k <= 0: 788 | assert (False) 789 | 790 | lyn = gl_layer_lists[k - 1][0] 791 | layer_inputs.append(lyn) 792 | else: 793 | print("fuck error crashed....") 794 | elif len(layer_inputs) > len(inputs):#some output is same ,please take nearest one 795 | print("cather wrong layer.....") 796 | ###################################################### 797 | 798 | torchOP_LayerInfos = {} 799 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 800 | torchOP_LayerInfos["layer_Type"] = "Concat" 801 | 802 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 803 | 804 | torchOP_LayerInfos['number_of_Input_Layers'] = len(inputs) 805 | 806 | torchOP_LayerInfos['number_of_InOut_Feature_Channels'] = output.shape[0] 807 | torchOP_LayerInfos['Concat_Dim'] = args[1] 808 | torchOP_LayerInfos['operator_Type'] = TYPE_ELEMWISE_OP['Cat'] 809 | torchOP_LayerInfos['activation_Type'] = TYPE_ACTIVATION_FUNC['None'] 810 | torchOP_LayerInfos['splitCnt'] = 0 811 | 812 | return torchOP_LayerInfos 813 | ##################################################################################### 814 | def function_Interpreter_For_Relu(func,inputs, output,*args, **kwargs): 815 | ##################################################### 816 | global gl_type_dicts_count 817 | global gl_layer_lists 818 | global gl_layer_NUM 819 | layer_name = "" 820 | if len(gl_type_dicts_count) == 0: 821 | gl_type_dicts_count['ReLU'] = 1 822 | else: 823 | tn = 'ReLU' 824 | if tn in gl_type_dicts_count.keys(): 825 | gl_type_dicts_count['ReLU'] += 1 826 | else: 827 | gl_type_dicts_count['ReLU'] = 1 828 | 829 | layer_name = "ReLU" + str(gl_type_dicts_count['ReLU'] - 1) 830 | gl_layer_NUM += 1 831 | ##################################################### 832 | l_list = [] # [layer_name,inputs,output] 833 | l_list.append(layer_name) 834 | l_list.append(inputs[0]) 835 | l_list.append(output) 836 | if len(gl_layer_lists) > gl_layer_NUM: 837 | gl_layer_lists[gl_layer_NUM - 1] = l_list 838 | else: 839 | gl_layer_lists.append(l_list) 840 | 841 | layer_inputs = [] 842 | for j in range(0, gl_layer_NUM): 843 | curIndex = gl_layer_NUM - 1 - j 844 | for i_inp in inputs: 845 | if curIndex == 0: 846 | if i_inp.equal(gl_layer_lists[0][1]): # first 847 | layer_inputs.append("0") 848 | else: 849 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 850 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 851 | 852 | if len(layer_inputs) == 1: 853 | break 854 | 855 | if len(layer_inputs) < len(inputs[0]): # must <= 856 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 857 | # force no-owned input from last layer 858 | k = len(gl_layer_lists) - 1 859 | if k <= 0: 860 | assert (False) 861 | 862 | lyn = gl_layer_lists[k - 1][0] 863 | layer_inputs.append(lyn) 864 | else: 865 | print("fuck error crashed....") 866 | elif len(layer_inputs) > len(inputs[0]): # some output is same ,please take nearest one 867 | print("cather wrong layer.....") 868 | ###################################################### 869 | 870 | torchOP_LayerInfos = {} 871 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 872 | torchOP_LayerInfos['layer_Type'] = 'ReLU' 873 | 874 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 875 | torchOP_LayerInfos['number_of_InOut_Feature_Channels'] = output.shape[1] 876 | torchOP_LayerInfos['height_of_InOut_Feature'] = output.shape[2] 877 | torchOP_LayerInfos['width_of_InOut_Feature'] = output.shape[3] 878 | torchOP_LayerInfos['activation_Type'] = TYPE_ACTIVATION_FUNC['Relu'] 879 | torchOP_LayerInfos['splitCnt'] = 0 880 | return torchOP_LayerInfos 881 | ##################################################################################### 882 | def function_Interpreter_For_ReduceMean(func, inputs, output,*args, **kwargs): 883 | if output.equal(inputs[0]): 884 | print("..... now is permute no work......") 885 | return {} 886 | ##################################################### 887 | global gl_type_dicts_count 888 | global gl_layer_lists 889 | global gl_layer_NUM 890 | layer_name = "" 891 | if len(gl_type_dicts_count) == 0: 892 | gl_type_dicts_count['ReduceMean'] = 1 893 | else: 894 | tn = 'ReduceMean' 895 | if tn in gl_type_dicts_count.keys(): 896 | gl_type_dicts_count['ReduceMean'] += 1 897 | else: 898 | gl_type_dicts_count['ReduceMean'] = 1 899 | 900 | layer_name = "ReduceMean" + str(gl_type_dicts_count['ReduceMean'] - 1) 901 | gl_layer_NUM += 1 902 | ##################################################### 903 | l_list = [] # [layer_name,inputs,output] 904 | l_list.append(layer_name) 905 | l_list.append(inputs[0]) 906 | l_list.append(output) 907 | if len(gl_layer_lists) > gl_layer_NUM: 908 | gl_layer_lists[gl_layer_NUM - 1] = l_list 909 | else: 910 | gl_layer_lists.append(l_list) 911 | 912 | layer_inputs = [] 913 | 914 | for j in range(0, gl_layer_NUM): 915 | curIndex = gl_layer_NUM - 1 - j 916 | for i_inp in inputs: 917 | if curIndex == 0: 918 | if i_inp.equal(gl_layer_lists[0][1]): # first 919 | layer_inputs.append("0") 920 | else: 921 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 922 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 923 | if len(layer_inputs) == 1: 924 | break 925 | if len(layer_inputs) < len(inputs[0]): # must <= 926 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 927 | # force no-owned input from last layer 928 | k = len(gl_layer_lists) - 1 929 | if k <= 0: 930 | assert (False) 931 | 932 | lyn = gl_layer_lists[k - 1][0] 933 | layer_inputs.append(lyn) 934 | else: 935 | print("Permute....fuck error crashed....") 936 | elif len(layer_inputs) > len(inputs[0]): # some output is same ,please take nearest one 937 | print("Permute....cather wrong layer.....") 938 | ###################################################### 939 | 940 | torchOP_LayerInfos = {} 941 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 942 | torchOP_LayerInfos['layer_Type'] = 'ReduceMean' 943 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 944 | torchOP_LayerInfos['params'] = (3 ,2 ,0.0625) 945 | torchOP_LayerInfos['splitCnt'] = 0 946 | return torchOP_LayerInfos 947 | ##################################################################################### 948 | def function_Interpreter_For_Permute(func, inputs, output,*args, **kwargs): 949 | if output.equal(inputs[0]): 950 | print("..... now is permute no work......") 951 | return {} 952 | ##################################################### 953 | global gl_type_dicts_count 954 | global gl_layer_lists 955 | global gl_layer_NUM 956 | layer_name = "" 957 | if len(gl_type_dicts_count) == 0: 958 | gl_type_dicts_count['Permute'] = 1 959 | else: 960 | tn = 'Permute' 961 | if tn in gl_type_dicts_count.keys(): 962 | gl_type_dicts_count['Permute'] += 1 963 | else: 964 | gl_type_dicts_count['Permute'] = 1 965 | 966 | layer_name = "Permute" + str(gl_type_dicts_count['Permute'] - 1) 967 | gl_layer_NUM += 1 968 | ##################################################### 969 | l_list = [] # [layer_name,inputs,output] 970 | l_list.append(layer_name) 971 | l_list.append(inputs[0]) 972 | l_list.append(output) 973 | if len(gl_layer_lists) > gl_layer_NUM: 974 | gl_layer_lists[gl_layer_NUM - 1] = l_list 975 | else: 976 | gl_layer_lists.append(l_list) 977 | 978 | layer_inputs = [] 979 | 980 | for j in range(0, gl_layer_NUM): 981 | curIndex = gl_layer_NUM - 1 - j 982 | for i_inp in inputs: 983 | if curIndex == 0: 984 | if i_inp.equal(gl_layer_lists[0][1]): # first 985 | layer_inputs.append("0") 986 | else: 987 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 988 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 989 | if len(layer_inputs) == 1: 990 | break 991 | if len(layer_inputs) < len(inputs[0]): # must <= 992 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 993 | # force no-owned input from last layer 994 | k = len(gl_layer_lists) - 1 995 | if k <= 0: 996 | assert (False) 997 | 998 | lyn = gl_layer_lists[k - 1][0] 999 | layer_inputs.append(lyn) 1000 | else: 1001 | print("Permute....fuck error crashed....") 1002 | elif len(layer_inputs) > len(inputs[0]): # some output is same ,please take nearest one 1003 | print("Permute....cather wrong layer.....") 1004 | ###################################################### 1005 | args_dict = getPermuteFunctionArguments(*args, **kwargs) 1006 | torchOP_LayerInfos = {} 1007 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 1008 | torchOP_LayerInfos['layer_Type'] = 'Permute' 1009 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 1010 | torchOP_LayerInfos['dims'] = args_dict['dims'] 1011 | torchOP_LayerInfos['splitCnt'] = 0 1012 | return torchOP_LayerInfos 1013 | 1014 | ####################################################################################### 1015 | def function_Interpreter_For_Reshape(func, inputs, output, *args, **kwargs): 1016 | if output.equal(inputs[0]): 1017 | print("..... now is reshape ......") 1018 | return {} 1019 | ##################################################### 1020 | global gl_type_dicts_count 1021 | global gl_layer_lists 1022 | global gl_layer_NUM 1023 | layer_name = "" 1024 | if len(gl_type_dicts_count) == 0: 1025 | gl_type_dicts_count['Reshape'] = 1 1026 | else: 1027 | tn = 'Reshape' 1028 | if tn in gl_type_dicts_count.keys(): 1029 | gl_type_dicts_count['Reshape'] += 1 1030 | else: 1031 | gl_type_dicts_count['Reshape'] = 1 1032 | 1033 | layer_name = "Reshape" + str(gl_type_dicts_count['Reshape'] - 1) 1034 | gl_layer_NUM += 1 1035 | ##################################################### 1036 | l_list = [] # [layer_name,inputs,output] 1037 | l_list.append(layer_name) 1038 | l_list.append(inputs[0]) 1039 | l_list.append(output) 1040 | if len(gl_layer_lists) > gl_layer_NUM: 1041 | gl_layer_lists[gl_layer_NUM - 1] = l_list 1042 | else: 1043 | gl_layer_lists.append(l_list) 1044 | 1045 | layer_inputs = [] 1046 | 1047 | for j in range(0, gl_layer_NUM): 1048 | curIndex = gl_layer_NUM - 1 - j 1049 | for i_inp in inputs: 1050 | if curIndex == 0: 1051 | if i_inp.equal(gl_layer_lists[0][1]): # first 1052 | layer_inputs.append("0") 1053 | else: 1054 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 1055 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 1056 | if len(layer_inputs) == 1: 1057 | break 1058 | if len(layer_inputs) < len(inputs[0]): # must <= 1059 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 1060 | # force no-owned input from last layer 1061 | k = len(gl_layer_lists) - 1 1062 | if k <= 0: 1063 | assert(False) 1064 | 1065 | lyn = gl_layer_lists[k-1][0] 1066 | layer_inputs.append(lyn) 1067 | else: 1068 | print("Reshape....fuck error crashed....") 1069 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 1070 | print("Reshape....cather wrong layer.....") 1071 | ###################################################### 1072 | 1073 | torchOP_LayerInfos = {} 1074 | args_dict = getReshapeFunctionArguments(*args, **kwargs) 1075 | rsparms = args_dict['shape'] 1076 | tupleNum = len(rsparms) 1077 | nsz = 1 1078 | tsize = inputs[0].size() 1079 | for i in range(len(tsize)): 1080 | nsz = nsz * inputs[0].size(i) 1081 | reshap_params = (rsparms[-1], round(nsz / rsparms[-1]), 1) 1082 | 1083 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 1084 | torchOP_LayerInfos['layer_Type'] = 'Reshape' 1085 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 1086 | torchOP_LayerInfos['shap'] = reshap_params 1087 | torchOP_LayerInfos['splitCnt'] = 0 1088 | return torchOP_LayerInfos 1089 | ####################################################################################### 1090 | def function_Interpreter_For_Pooling(func, inputs, output, *args, **kwargs): 1091 | 1092 | if output.equal(inputs[0]): 1093 | return {} 1094 | ##################################################### 1095 | global gl_type_dicts_count 1096 | global gl_layer_lists 1097 | global gl_layer_NUM 1098 | layer_name = "" 1099 | if len(gl_type_dicts_count) == 0: 1100 | gl_type_dicts_count['Pooling'] = 1 1101 | else: 1102 | tn = 'Pooling' 1103 | if tn in gl_type_dicts_count.keys(): 1104 | gl_type_dicts_count['Pooling'] += 1 1105 | else: 1106 | gl_type_dicts_count['Pooling'] = 1 1107 | 1108 | layer_name = "Pooling" + str(gl_type_dicts_count['Pooling'] - 1) 1109 | gl_layer_NUM += 1 1110 | ##################################################### 1111 | l_list = [] # [layer_name,inputs,output] 1112 | l_list.append(layer_name) 1113 | l_list.append(inputs[0]) 1114 | l_list.append(output) 1115 | if len(gl_layer_lists) > gl_layer_NUM: 1116 | gl_layer_lists[gl_layer_NUM - 1] = l_list 1117 | else: 1118 | gl_layer_lists.append(l_list) 1119 | 1120 | layer_inputs = [] 1121 | 1122 | for j in range(0, gl_layer_NUM): 1123 | curIndex = gl_layer_NUM - 1 - j 1124 | for i_inp in inputs: 1125 | if curIndex == 0: 1126 | if i_inp.equal(gl_layer_lists[0][1]): # first 1127 | layer_inputs.append("0") 1128 | else: 1129 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 1130 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 1131 | if len(layer_inputs) == 1: 1132 | break 1133 | if len(layer_inputs) < len(inputs[0]): # must <= 1134 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 1135 | # force no-owned input from last layer 1136 | k = len(gl_layer_lists) - 1 1137 | if k <= 0: 1138 | assert(False) 1139 | 1140 | lyn = gl_layer_lists[k-1][0] 1141 | layer_inputs.append(lyn) 1142 | else: 1143 | print("fuck error crashed....") 1144 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 1145 | print("cather wrong layer.....") 1146 | ###################################################### 1147 | 1148 | torchOP_LayerInfos = {} 1149 | args_dict = getPoolingFunctionArguments(*args, **kwargs) 1150 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 1151 | torchOP_LayerInfos['layer_Type'] = 'Pooling' 1152 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 1153 | 1154 | torchOP_LayerInfos['number_of_Input_Feature_Channels'] = inputs[0].shape[1] 1155 | torchOP_LayerInfos['height_of_Input_Feature'] = inputs[0].shape[2] 1156 | torchOP_LayerInfos['width_of_Input_Feature'] = inputs[0].shape[3] 1157 | torchOP_LayerInfos['number_of_Output_Feature_Channels'] = output.shape[1] 1158 | torchOP_LayerInfos['height_of_Output_Feature'] = output.shape[2] 1159 | torchOP_LayerInfos['width_of_Output_Feature'] = output.shape[3] 1160 | torchOP_LayerInfos['splitCnt'] = 0 1161 | # get kernel size: 1162 | if isinstance(args_dict['kernel_size'], list) or isinstance(args_dict['kernel_size'], tuple): 1163 | kernel_sizes = list() 1164 | if len(kernel_sizes) == 1: 1165 | torchOP_LayerInfos['kernel_Height'] = kernel_sizes[0] 1166 | torchOP_LayerInfos['kernel_Width'] = kernel_sizes[0] 1167 | elif len(kernel_sizes) == 2: 1168 | torchOP_LayerInfos['kernel_Height'] = kernel_sizes[0] 1169 | torchOP_LayerInfos['kernel_Width'] = kernel_sizes[1] 1170 | else: 1171 | assert (False) 1172 | else: 1173 | torchOP_LayerInfos['kernel_Height'] = args_dict['kernel_size'] 1174 | torchOP_LayerInfos['kernel_Width'] = args_dict['kernel_size'] 1175 | 1176 | # get padding size: 1177 | if isinstance(args_dict['padding'], list) or isinstance(args_dict['padding'], tuple): 1178 | padding_sizes = list(args_dict['padding']) 1179 | if len(padding_sizes) == 1: 1180 | torchOP_LayerInfos['padding_Size_Y'] = padding_sizes[0] 1181 | torchOP_LayerInfos['padding_Size_X'] = padding_sizes[0] 1182 | elif len(padding_sizes) == 2: 1183 | torchOP_LayerInfos['padding_Size_Y'] = padding_sizes[0] 1184 | torchOP_LayerInfos['padding_Size_X'] = padding_sizes[1] 1185 | else: 1186 | assert (False) 1187 | else: 1188 | torchOP_LayerInfos['padding_Size_Y'] = args_dict['padding'] 1189 | torchOP_LayerInfos['padding_Size_X'] = args_dict['padding'] 1190 | 1191 | # get stride size: 1192 | # import pdb; pdb.set_trace() 1193 | if args_dict['stride'] is None: 1194 | args_dict['stride'] = args_dict['kernel_size'] 1195 | if isinstance(args_dict['stride'], list) or isinstance(args_dict['stride'], tuple): 1196 | stride_sizes = list(args_dict['stride']) 1197 | if len(padding_sizes) == 1: 1198 | torchOP_LayerInfos['stride_Size_Y'] = stride_sizes[0] 1199 | torchOP_LayerInfos['stride_Size_X'] = stride_sizes[0] 1200 | elif len(padding_sizes) == 2: 1201 | torchOP_LayerInfos['stride_Size_Y'] = stride_sizes[0] 1202 | torchOP_LayerInfos['stride_Size_X'] = stride_sizes[1] 1203 | else: 1204 | assert (False) 1205 | else: 1206 | torchOP_LayerInfos['stride_Size_Y'] = args_dict['stride'] 1207 | torchOP_LayerInfos['stride_Size_X'] = args_dict['stride'] 1208 | 1209 | # get pooling type: 1210 | if func == dict_origin_F['OVER_LOOAD_POOLING'][ 1211 | TYPE_POOLING['Max']]: 1212 | torchOP_LayerInfos['pooling_Type'] = TYPE_POOLING['Max'] 1213 | elif func == dict_origin_F['OVER_LOOAD_POOLING'][TYPE_POOLING['Avg']]: 1214 | torchOP_LayerInfos['pooling_Type'] = TYPE_POOLING['Avg'] 1215 | else: 1216 | print("unsupported Pooling Type Functons.") 1217 | assert (False) 1218 | return torchOP_LayerInfos 1219 | 1220 | 1221 | def function_Interpreter_For_Upsampling(func, inputs, output, *args, **kwargs): 1222 | if output.equal(inputs[0]): 1223 | return {} 1224 | ##################################################### 1225 | global gl_type_dicts_count 1226 | global gl_layer_lists 1227 | global gl_layer_NUM 1228 | layer_name = "" 1229 | if len(gl_type_dicts_count) == 0: 1230 | gl_type_dicts_count['Upsample'] = 1 1231 | else: 1232 | tn = 'Upsample' 1233 | if tn in gl_type_dicts_count.keys(): 1234 | gl_type_dicts_count['Upsample'] += 1 1235 | else: 1236 | gl_type_dicts_count['Upsample'] = 1 1237 | 1238 | layer_name = "Upsample" + str(gl_type_dicts_count['Upsample'] - 1) 1239 | gl_layer_NUM += 1 1240 | ##################################################### 1241 | l_list = [] # [layer_name,inputs,output] 1242 | l_list.append(layer_name) 1243 | l_list.append(inputs[0]) 1244 | l_list.append(output) 1245 | if len(gl_layer_lists) > gl_layer_NUM: 1246 | gl_layer_lists[gl_layer_NUM - 1] = l_list 1247 | else: 1248 | gl_layer_lists.append(l_list) 1249 | 1250 | layer_inputs = [] 1251 | 1252 | for j in range(0, gl_layer_NUM): 1253 | curIndex = gl_layer_NUM - 1 - j 1254 | for i_inp in inputs: 1255 | if curIndex == 0: 1256 | if i_inp.equal(gl_layer_lists[0][1]): # first 1257 | layer_inputs.append("0") 1258 | else: 1259 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 1260 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 1261 | if len(layer_inputs) == 1: 1262 | break 1263 | if len(layer_inputs) < len(inputs[0]): # must <= 1264 | if 1 == (len(inputs[0]) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 1265 | # force no-owned input from last layer 1266 | k = len(gl_layer_lists) - 1 1267 | if k <= 0: 1268 | assert(False) 1269 | 1270 | lyn = gl_layer_lists[k-1][0] 1271 | layer_inputs.append(lyn) 1272 | else: 1273 | print("fuck error crashed....") 1274 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 1275 | print("cather wrong layer.....") 1276 | ###################################################### 1277 | torchOP_LayerInfos = {} 1278 | args_dict = getUpsampleFunctionArguments(*args, **kwargs) 1279 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 1280 | torchOP_LayerInfos['layer_Type'] = 'Upsample' 1281 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 1282 | 1283 | torchOP_LayerInfos['number_of_InOut_Feature_Channels'] = output.shape[1] 1284 | torchOP_LayerInfos['height_of_Input_Feature'] = inputs[0].shape[2] 1285 | torchOP_LayerInfos['width_of_Input_Feature'] = inputs[0].shape[3] 1286 | torchOP_LayerInfos['height_of_Output_Feature'] = output.shape[2] 1287 | torchOP_LayerInfos['width_of_Output_Feature'] = output.shape[3] 1288 | torchOP_LayerInfos['upscale_Factor'] = args_dict['scale_factor'] 1289 | torchOP_LayerInfos['upsample_AlignCorner'] = 0 1290 | torchOP_LayerInfos['splitCnt'] = 0 1291 | if args_dict['align_corners'] is not None: 1292 | if args_dict['align_corners']: 1293 | torchOP_LayerInfos['upsample_AlignCorner'] = 1 1294 | if args_dict['mode'] == 'nearest': 1295 | torchOP_LayerInfos['upsample_Type'] = TYPE_UPSAMPLE['Nearest'] 1296 | elif args_dict['mode'] == 'bilinear': 1297 | torchOP_LayerInfos['upsample_Type'] = TYPE_UPSAMPLE['BiLinear'] 1298 | elif args_dict['mode'] == 'bicubic': 1299 | torchOP_LayerInfos['upsample_Type'] = TYPE_UPSAMPLE['Bicubic'] 1300 | else: 1301 | print("unsupport upsample type ", args_dict['mode']) 1302 | assert (False) 1303 | return torchOP_LayerInfos 1304 | 1305 | def function_Interpreter_For_SoftMax(func, inputs, output, *args, **kwargs): 1306 | 1307 | ##################################################### 1308 | global gl_type_dicts_count 1309 | global gl_layer_lists 1310 | global gl_layer_NUM 1311 | layer_name = "" 1312 | if len(gl_type_dicts_count) == 0: 1313 | gl_type_dicts_count['Softmax'] = 1 1314 | else: 1315 | tn = 'Softmax' 1316 | if tn in gl_type_dicts_count.keys(): 1317 | gl_type_dicts_count['Softmax'] += 1 1318 | else: 1319 | gl_type_dicts_count['Softmax'] = 1 1320 | 1321 | layer_name = "Softmax" + str(gl_type_dicts_count['Softmax'] - 1) 1322 | gl_layer_NUM += 1 1323 | ##################################################### 1324 | l_list = [] # [layer_name,inputs,output] 1325 | l_list.append(layer_name) 1326 | l_list.append(inputs[0]) 1327 | l_list.append(output) 1328 | if len(gl_layer_lists) > gl_layer_NUM: 1329 | gl_layer_lists[gl_layer_NUM - 1] = l_list 1330 | else: 1331 | gl_layer_lists.append(l_list) 1332 | 1333 | layer_inputs = [] 1334 | 1335 | for j in range(0, gl_layer_NUM): 1336 | curIndex = gl_layer_NUM - 1 - j 1337 | for i_inp in inputs: 1338 | if curIndex == 0: 1339 | if i_inp.equal(gl_layer_lists[0][1]): # first 1340 | layer_inputs.append("0") 1341 | else: 1342 | if i_inp.equal(gl_layer_lists[curIndex - 1][2]): # first 1343 | layer_inputs.append(gl_layer_lists[curIndex - 1][0]) 1344 | if len(layer_inputs) == 1: 1345 | break 1346 | if len(layer_inputs) < len(inputs[0]): # must <= 1347 | if 1 == (len(inputs) - len(layer_inputs)): ###Attention!!! maybe some data changed bettween layers 1348 | # force no-owned input from last layer 1349 | k = len(gl_layer_lists) - 1 1350 | if k <= 0: 1351 | assert(False) 1352 | 1353 | lyn = gl_layer_lists[k-1][0] 1354 | layer_inputs.append(lyn) 1355 | else: 1356 | print("fuck error crashed....") 1357 | elif len(layer_inputs) > len(inputs[0]):#some output is same ,please take nearest one 1358 | print("cather wrong layer.....") 1359 | ###################################################### 1360 | torchOP_LayerInfos = {} 1361 | args_dict = getSoftMaxFunctionArguments(*args, **kwargs) 1362 | torchOP_LayerInfos['cur_layer_Name'] = layer_name 1363 | torchOP_LayerInfos['layer_Type'] = 'Softmax' 1364 | torchOP_LayerInfos['inputs_layersName'] = layer_inputs 1365 | torchOP_LayerInfos['softmax_Dim'] = args_dict['dim'] 1366 | torchOP_LayerInfos['splitCnt'] = 0 1367 | 1368 | return torchOP_LayerInfos 1369 | ################################################################################################ 1370 | ################################################################################################# 1371 | PYTORCH_MODULE_SUPPORTER = { 1372 | ###KEY### : ###VALUE_FOR_IMPL### 1373 | nn.modules.conv.Conv2d.__name__: module_Interpreter_For_Conv2D, 1374 | nn.modules.batchnorm.BatchNorm2d.__name__: module_Interpreter_For_BatchNorm, 1375 | nn.modules.activation.ReLU.__name__: module_Interpreter_For_Relu, 1376 | nn.modules.Linear.__name__: module_Interpreter_For_MLinear, 1377 | 1378 | # nn.modules.pooling.AvgPool2d.__name__: module_Interpreter_For_AvgPool2d, 1379 | # nn.modules.upsampling.Upsample.__name__: function_Interpreter_For_Upsampling, 1380 | } 1381 | 1382 | PYTORCH_FUNCTION_SUPPORTER = { 1383 | 'Pooling' : overload_pooling, 1384 | 'Upsampling' : overload_upsampling, 1385 | 'ElementWiseOperator' : overload_elementwiseoperator, 1386 | } 1387 | AVALIABLE_FUNCTION_CONVERTER = { 1388 | ###KEY### : ###VALUE_FOR_IMPL### 1389 | torch.add : function_Interpreter_For_ElementWiseOp_Add, 1390 | torch.max : function_Interpreter_For_ElementWiseOp_ArrMax, 1391 | torch.cat : function_Interpreter_For_ElementWiseOp_Cat, 1392 | torch.mean : function_Interpreter_For_ReduceMean, 1393 | F.relu : function_Interpreter_For_Relu, 1394 | torch.Tensor.permute : function_Interpreter_For_Permute, 1395 | torch.Tensor.reshape : function_Interpreter_For_Reshape, 1396 | F.avg_pool2d : function_Interpreter_For_Pooling, 1397 | F.max_pool2d : function_Interpreter_For_Pooling, 1398 | F.interpolate : function_Interpreter_For_Upsampling, 1399 | F.softmax : function_Interpreter_For_SoftMax, 1400 | } 1401 | -------------------------------------------------------------------------------- /torchLayer_Interpreter.py: -------------------------------------------------------------------------------- 1 | import numpy as py 2 | import torch 3 | import torch.nn as nn 4 | from torchLayer_IMPL import PYTORCH_MODULE_SUPPORTER, PYTORCH_FUNCTION_SUPPORTER 5 | import pdb 6 | ################################################################## 7 | 8 | ############################################################################################### 9 | ############################################################################################### 10 | #################################CORE CLASS FOR INTERPRETER#################################### 11 | ############################################################################################### 12 | ############################################################################################### 13 | once_func_hooked = True 14 | TorchLayers_Keeper = [] 15 | #TorchOps_Keeper = {} 16 | class Layer_Interpreter(object): 17 | def __init__(self, moduleFuncs, inLists, output): 18 | self.inputs = inLists 19 | self.module_funcs = moduleFuncs 20 | self.output = output 21 | #self.once_func_hooked = True 22 | self.torchOP_Dicts = {} 23 | global TorchLayers_Keeper 24 | if TorchLayers_Keeper is None: 25 | TorchLayers_Keeper = [] 26 | 27 | def __str__(self): 28 | return str(self.torchOP_Dicts) 29 | 30 | @staticmethod 31 | def funcs_Interpretering(): 32 | for funcKey in PYTORCH_FUNCTION_SUPPORTER.keys(): 33 | print("......Pytorch function is hooked now for....", funcKey) 34 | PYTORCH_FUNCTION_SUPPORTER[funcKey](TorchLayers_Keeper) ########neeeed to be store in layer.... 35 | #TorchLayers_Keeper.append(TorchOps_Keeper) 36 | return True 37 | 38 | def Layers_Interpretering(self, *args, **kwargs): 39 | ret = False 40 | support_key = self.module_funcs.__class__.__name__ 41 | 42 | if isinstance(self.module_funcs, nn.Module): 43 | if support_key in PYTORCH_MODULE_SUPPORTER.keys(): 44 | ret = True 45 | #print(".....Pytorch module is interpreting for....", self.module_funcs) 46 | self.torchOP_Dicts = PYTORCH_MODULE_SUPPORTER[support_key](self.module_funcs, self.inputs, self.output) 47 | if len(self.torchOP_Dicts) == 0: 48 | ret = False 49 | return ret 50 | 51 | TorchLayers_Keeper.append(self.torchOP_Dicts) 52 | else: 53 | print("xxxxxxxxxxxxPytorch OP Can not interpreting xxxxxxxxxxxxx",support_key) 54 | ret = False 55 | pdb.set_trace() 56 | assert (False) 57 | ########################################################################### 58 | #########################WORK ONCE######################################### 59 | #self.func_hooked_loop() 60 | ########################################################################### 61 | return ret 62 | -------------------------------------------------------------------------------- /torchLayer_ncnn.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import fileinput 4 | 5 | try: 6 | import numpy as np 7 | except: 8 | os.system('conda install numpy') 9 | import numpy as np 10 | 11 | class NCNN_FRAMEWORK_FACTORY(object): 12 | def __init__(self, outDir = ''): 13 | self.paramFilePath = outDir + 'ncnn.param' 14 | self.binFilePath = outDir + 'ncnn.bin' 15 | self.layer_count = 0 16 | self.blob_count = 0 17 | self.net = {} 18 | self.layerSequential = [] 19 | if os.path.exists(self.binFilePath): 20 | os.remove(self.binFilePath) 21 | 22 | def __str__(self): 23 | return str(self.net) 24 | 25 | #0 => float32, 0x01306B47 => float16, otherwise => quantized int8 26 | def headWriter(self, path = None): 27 | if path is None: 28 | assert "nO header is no ncnn...." 29 | pass 30 | with open(path, "ab+") as fw: 31 | fw.write(np.uint32(0).tobytes()) 32 | 33 | def reWrite_locLine(self, filename, lineNo, newText, bLeft=True, bRight=False): 34 | if os.path.exists(filename): 35 | f = fileinput.input(filename, inplace=1) 36 | for line in f: 37 | line_txt = line.replace("\r\n","").replace("\n","") 38 | if f.lineno() == lineNo: 39 | if bLeft: 40 | print(line_txt + newText) 41 | elif bRight: 42 | print(newText + line_txt) 43 | else: 44 | print(newText) 45 | else: 46 | print(line_txt) 47 | else: 48 | print("No file can be rewrotten now....") 49 | 50 | def converting(self, torchLayer_List, blob_num): 51 | layersNum = len(torchLayer_List) 52 | if layersNum == 0: 53 | print("make sure...layer interpretor is running before...") 54 | ncnn_layer_Num = 0 55 | ncnn_blob_Num = 0 56 | #####################save input layer into param file################## 57 | with open(self.paramFilePath, "w") as fparam: 58 | strr = 7767517 59 | fparam.write('%d\n' % (strr)) 60 | fparam.write('%d %d\n' % (layersNum, blob_num)) #num is not ncnn's, not include split layer 61 | fparam.write('%s %s %d %d %d\n' % ('Input', '0', 0,1,0)) 62 | ncnn_layer_Num += 1 63 | ncnn_blob_Num += 1 64 | for layer_Info in torchLayer_List: 65 | inp_layersName = layer_Info['inputs_layersName'] 66 | inputlen = len(inp_layersName) 67 | inp_layersName = " ".join(x for x in inp_layersName) 68 | if layer_Info['layer_Type'] == 'Convolution': 69 | layername = layer_Info['cur_layer_Name'] 70 | c_inputs = layer_Info['number_of_Input_Feature_Channels'] 71 | c_output = layer_Info['number_of_Output_Feature_Channels'] 72 | kernel_w = layer_Info['kernel_Width'] 73 | kernel_h = layer_Info['kernel_Height'] 74 | dilation_w = layer_Info['dilation_Size_X'] 75 | dilation_h = layer_Info['dilation_Size_Y'] 76 | stride_w = layer_Info['stride_Size_X'] 77 | stride_h = layer_Info['stride_Size_Y'] 78 | pad_w = layer_Info['padding_Size_X'] 79 | pad_h = layer_Info['padding_Size_Y'] 80 | bias_term = layer_Info['if_Use_Bias'] 81 | weight_data_size0 = len(layer_Info['weights_Numpy_NCHW_F32']) 82 | convtypeName = 'Convolution' 83 | convgroup = layer_Info['num_of_Group'] 84 | weight_data_size = c_inputs * kernel_h * kernel_w * c_output 85 | if convgroup > 1: 86 | convtypeName = 'ConvolutionDepthWise' 87 | weight_data_size = c_inputs * kernel_h * kernel_w 88 | fparam.write( 89 | '%s %32s %32d %d %32s %s 0=%d 1=%d 11=%d 2=%d 12=%d 3=%d 13=%d 4=%d 14=%d 5=%d 6=%d 7=%d\n' % 90 | (convtypeName, layername, inputlen, 1, inp_layersName, layername, c_output, kernel_w, 91 | kernel_h, dilation_w, dilation_h, stride_w, stride_h, pad_w, pad_h, bias_term, 92 | weight_data_size,convgroup)) 93 | else: 94 | fparam.write('%s %32s %32d %d %32s %s 0=%d 1=%d 11=%d 2=%d 12=%d 3=%d 13=%d 4=%d 14=%d 5=%d 6=%d\n' % 95 | (convtypeName, layername, inputlen, 1, inp_layersName, layername, c_output, kernel_w, 96 | kernel_h, dilation_w,dilation_h, stride_w, stride_h, pad_w, pad_h, bias_term, weight_data_size)) 97 | 98 | 99 | ncnn_layer_Num += 1 100 | ncnn_blob_Num += 1 101 | pass 102 | #######split pooling into several outputs 103 | if layer_Info['splitCnt'] > 1: 104 | outnms = layer_Info['outputs_layersName'] 105 | splitCount = len(outnms) 106 | splitNames = " ".join([ str(sn) for sn in outnms]) 107 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 108 | ncnn_layer_Num += 1 109 | ncnn_blob_Num += splitCount 110 | ####################write bin file for weight and bias########## 111 | with open(self.binFilePath, "ab+") as fbin: 112 | tag_qz = np.int32(0) 113 | fbin.write(tag_qz.tobytes()) 114 | weight = layer_Info['weights_Numpy_NCHW_F32'] 115 | weightbin = weight.astype('float32').tobytes() 116 | fbin.write(weightbin) 117 | if bias_term != 0: 118 | bias = layer_Info['bias_Numpy_F32'] 119 | fbin.write(bias.astype('float32').tobytes()) 120 | pass 121 | pass 122 | 123 | elif layer_Info['layer_Type'] == 'BatchNorm': 124 | layername = layer_Info['cur_layer_Name'] 125 | channels = layer_Info['number_of_InOut_Feature_Channels'] 126 | fparam.write('%s %32s %32d %d %32s %s 0=%d\n' % ('BatchNorm', layername, inputlen, 1, inp_layersName,layername, channels)) 127 | ncnn_layer_Num += 1 128 | ncnn_blob_Num += 1 129 | #######split pooling into several outputs 130 | if layer_Info['splitCnt'] > 1: 131 | outnms = layer_Info['outputs_layersName'] 132 | splitCount = len(outnms) 133 | splitNames = " ".join([str(sn) for sn in outnms]) 134 | fparam.write( 135 | '%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 136 | ncnn_layer_Num += 1 137 | ncnn_blob_Num += splitCount 138 | pass 139 | ####################write bin file for weight and bias########## 140 | with open(self.binFilePath, "ab+") as fbin: 141 | weight_data = layer_Info['slope_data'] #scale 142 | mean_data = layer_Info['mean_data'] 143 | var_data = layer_Info['var_data'] 144 | bias_data = layer_Info['bias_data'] #B 145 | fbin.write(weight_data.astype('float32').tobytes()) 146 | fbin.write(mean_data.astype('float32').tobytes()) 147 | fbin.write(var_data.astype('float32').tobytes()) 148 | fbin.write(bias_data.astype('float32').tobytes()) 149 | pass 150 | pass 151 | elif layer_Info['layer_Type'] == 'MLinear': 152 | layername = layer_Info['cur_layer_Name'] 153 | 154 | fparam.write('%s %32s %32d %d %32s %s 0=8 1=1 2=512\n' % ('InnerProduct', layername, inputlen, 1, inp_layersName,layername)) 155 | ncnn_layer_Num += 1 156 | ncnn_blob_Num += 1 157 | #######split pooling into several outputs 158 | if layer_Info['splitCnt'] > 1: 159 | outnms = layer_Info['outputs_layersName'] 160 | splitCount = len(outnms) 161 | splitNames = " ".join([str(sn) for sn in outnms]) 162 | fparam.write( 163 | '%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 164 | ncnn_layer_Num += 1 165 | ncnn_blob_Num += splitCount 166 | pass 167 | ####################write bin file for weight and bias########## 168 | with open(self.binFilePath, "ab+") as fbin: 169 | weight_data = layer_Info['weights_data'] #scale 170 | bias_data = layer_Info['bias_data'] #B 171 | tag_qz = np.int32(0) 172 | fbin.write(tag_qz.tobytes()) 173 | fbin.write(weight_data.astype('float32').tobytes()) 174 | fbin.write(bias_data.astype('float32').tobytes()) 175 | pass 176 | pass 177 | elif layer_Info['layer_Type'] == 'ReLU': 178 | layername = layer_Info['cur_layer_Name'] 179 | ncnn_layer_Num += 1 180 | ncnn_blob_Num += 1 181 | fparam.write('%s %32s %32d %d %32s %s\n' % ('ReLU', layername, inputlen, 1, inp_layersName, layername)) 182 | #######split pooling into several outputs 183 | if layer_Info['splitCnt'] > 1: 184 | outnms = layer_Info['outputs_layersName'] 185 | splitCount = len(outnms) 186 | splitNames = " ".join([str(sn) for sn in outnms]) 187 | fparam.write( 188 | '%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 189 | ncnn_layer_Num += 1 190 | ncnn_blob_Num += splitCount 191 | elif layer_Info['layer_Type'] == 'Pooling': # split 192 | 193 | layername = layer_Info['cur_layer_Name'] 194 | poolType = layer_Info['pooling_Type'] 195 | kernel_w = layer_Info['kernel_Height'] 196 | kernel_h = layer_Info['kernel_Width'] 197 | stride_w = layer_Info['stride_Size_X'] 198 | stride_h = layer_Info['stride_Size_Y'] 199 | pad_left = layer_Info['padding_Size_X'] 200 | pad_right = layer_Info['padding_Size_X'] 201 | pad_top = layer_Info['padding_Size_Y'] 202 | pad_bottom = layer_Info['padding_Size_Y'] 203 | global_pooling = 0 #layer_Info[''] 204 | pad_mode = 1#layer_Info[''] 205 | ncnn_layer_Num += 1 206 | ncnn_blob_Num += 1 207 | fparam.write('%s %32s %32d %d %32s %s 0=%d 1=%d 11=%d 2=%d 12=%d 3=%d 13=%d 14=%d 15=%d 5=%d\n' % ('Pooling', layername, inputlen, 1, inp_layersName, layername, poolType,kernel_w,kernel_h,stride_w,stride_h, 208 | pad_left,pad_right,pad_top,pad_bottom,pad_mode)) 209 | pass 210 | #######split pooling into several outputs 211 | if layer_Info['splitCnt'] > 1: 212 | outnms = layer_Info['outputs_layersName'] 213 | splitCount = len(outnms) 214 | splitNames = " ".join([str(sn) for sn in outnms]) 215 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 216 | ncnn_layer_Num += 1 217 | ncnn_blob_Num += splitCount 218 | elif layer_Info['layer_Type'] == 'Concat': #split 219 | layername = layer_Info['cur_layer_Name'] 220 | ncnn_layer_Num += 1 221 | ncnn_blob_Num += 1 222 | dim = layer_Info['Concat_Dim'] 223 | fparam.write('%s %32s %32d %d %32s %s 0=%d\n' % ('Concat', layername, inputlen, 1, inp_layersName, layername,dim)) 224 | pass 225 | #######split pooling into several outputs 226 | if layer_Info['splitCnt'] > 1: 227 | outnms = layer_Info['outputs_layersName'] 228 | splitCount = len(outnms) 229 | splitNames = " ".join([str(sn) for sn in outnms]) 230 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 231 | ncnn_layer_Num += 1 232 | ncnn_blob_Num += splitCount 233 | elif layer_Info['layer_Type'] == 'Upsample':#split 234 | layername = layer_Info['cur_layer_Name'] 235 | ncnn_layer_Num += 1 236 | ncnn_blob_Num += 1 237 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Upsample', layername, 1, 1, inp_layersName, layername)) 238 | pass 239 | #######split pooling into several outputs 240 | if layer_Info['splitCnt'] > 1: 241 | outnms = layer_Info['outputs_layersName'] 242 | splitCount = len(outnms) 243 | splitNames = " ".join([str(sn) for sn in outnms]) 244 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 245 | ncnn_layer_Num += 1 246 | ncnn_blob_Num += splitCount 247 | 248 | pass 249 | elif layer_Info['layer_Type'] == 'Add':#split 250 | layername = layer_Info['cur_layer_Name'] 251 | ncnn_layer_Num += 1 252 | ncnn_blob_Num += 1 253 | fparam.write('%s %32s %32d %d %32s %s 0=0\n' % ('BinaryOp', layername, 2, 1, inp_layersName, layername)) 254 | pass 255 | #######split pooling into several outputs 256 | if layer_Info['splitCnt'] > 1: 257 | outnms = layer_Info['outputs_layersName'] 258 | splitCount = len(outnms) 259 | splitNames = " ".join([str(sn) for sn in outnms]) 260 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 261 | ncnn_layer_Num += 1 262 | ncnn_blob_Num += splitCount 263 | pass 264 | elif layer_Info['layer_Type'] == 'Permute':#split 265 | layername = layer_Info['cur_layer_Name'] 266 | ncnn_layer_Num += 1 267 | ncnn_blob_Num += 1 268 | dims = layer_Info['dims'] 269 | dim_params = "0=5" 270 | #dim_params = " ".join([(str(dims.index(sn))+'=' +str(sn)) for sn in dims]) 271 | fparam.write('%s %32s %32d %d %32s %s %s\n' % ('Permute', layername, 1, 1, inp_layersName, layername,dim_params)) 272 | pass 273 | #######split pooling into several outputs 274 | if layer_Info['splitCnt'] > 1: 275 | outnms = layer_Info['outputs_layersName'] 276 | splitCount = len(outnms) 277 | splitNames = " ".join([str(sn) for sn in outnms]) 278 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 279 | ncnn_layer_Num += 1 280 | ncnn_blob_Num += splitCount 281 | pass 282 | elif layer_Info['layer_Type'] == 'Reshape':#split 283 | layername = layer_Info['cur_layer_Name'] 284 | ncnn_layer_Num += 1 285 | ncnn_blob_Num += 1 286 | tshap = layer_Info['shap'] #(4,4,1) is bug ,cause 287 | 288 | shap_params = " ".join([(str(tshap.index(sn))+'=' +str(sn)) for sn in tshap]) 289 | fparam.write('%s %32s %32d %d %32s %s %s\n' % ('Reshape', layername, 1, 1, inp_layersName, layername,shap_params)) 290 | pass 291 | #######split pooling into several outputs 292 | if layer_Info['splitCnt'] > 1: 293 | outnms = layer_Info['outputs_layersName'] 294 | splitCount = len(outnms) 295 | splitNames = " ".join([str(sn) for sn in outnms]) 296 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 297 | ncnn_layer_Num += 1 298 | ncnn_blob_Num += splitCount 299 | pass 300 | elif layer_Info['layer_Type'] == 'Softmax':#split 301 | layername = layer_Info['cur_layer_Name'] 302 | ncnn_layer_Num += 1 303 | ncnn_blob_Num += 1 304 | paramDim = layer_Info['softmax_Dim'] 305 | 306 | fparam.write('%s %32s %32d %d %32s %s 0=%s\n' % ('Softmax', layername, 1, 1, inp_layersName, layername,paramDim)) 307 | pass 308 | #######split pooling into several outputs 309 | if layer_Info['splitCnt'] > 1: 310 | outnms = layer_Info['outputs_layersName'] 311 | splitCount = len(outnms) 312 | splitNames = " ".join([str(sn) for sn in outnms]) 313 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 314 | ncnn_layer_Num += 1 315 | ncnn_blob_Num += splitCount 316 | pass 317 | elif layer_Info['layer_Type'] == 'ReduceMean': 318 | layername = layer_Info['cur_layer_Name'] 319 | ncnn_layer_Num += 1 320 | ncnn_blob_Num += 1 321 | rparams = layer_Info['params'] #(4,4,1) is bug ,cause 322 | 323 | r_prams = " ".join([(str(rparams.index(sn))+'=' +str(sn)) for sn in rparams]) 324 | fparam.write('%s %32s %32d %d %32s %s %s\n' % ('ReduceMean', layername, 1, 1, inp_layersName, layername,r_prams)) 325 | pass 326 | #######split pooling into several outputs 327 | if layer_Info['splitCnt'] > 1: 328 | outnms = layer_Info['outputs_layersName'] 329 | splitCount = len(outnms) 330 | splitNames = " ".join([str(sn) for sn in outnms]) 331 | fparam.write('%s %32s %32d %d %32s %s\n' % ('Split', layername, 1, splitCount, layername, splitNames)) 332 | ncnn_layer_Num += 1 333 | ncnn_blob_Num += splitCount 334 | pass 335 | else: 336 | print("Type info is new ,no suitable ncnn layer for compared...") 337 | fparam.close() 338 | fbin.close() 339 | 340 | ####rewrite split layer counts### 341 | ltxt = str('%d %d' % (ncnn_layer_Num, ncnn_blob_Num)) 342 | self.reWrite_locLine(self.paramFilePath,2,ltxt,False,False) 343 | 344 | return True -------------------------------------------------------------------------------- /transferMain.py: -------------------------------------------------------------------------------- 1 | ######################################################################################################################## 2 | ##############This is your forward network main file for loading trained model and show reslut in these codes########### 3 | ######################################################################################################################## 4 | from torch.autograd import Variable, Function ##must import for using pytorch hooks function 5 | import hookWorker as HookWorker 6 | 7 | old_function__call__ = Function.__call__ 8 | global_hooks_handles = [] 9 | #########################################Hooks logical################################################################## 10 | def params_hook(NetModule, input, output): 11 | inLists = list(input) # listed for tensor for hooks 12 | HookWorker.forward_hooking(NetModule, inLists, output) 13 | 14 | def forward_hooks_mount2_Net(netModel): 15 | for singleModel in netModel.modules(): 16 | singleModelSlices = list(singleModel.modules()) 17 | if len(singleModelSlices) == 1: 18 | hnd = singleModel.register_forward_hook(params_hook) 19 | global_hooks_handles.append(hnd) 20 | return None 21 | 22 | def unMount_forward_hooks(): 23 | for hookhnd in global_hooks_handles: 24 | hookhnd.remove() 25 | return None 26 | ##########################################Main logical################################################################### 27 | def main: 28 | ##First step find your checkpoints model loader place and then hung on my hook into your every slice model## 29 | ##load model from ck or in other way ,like load_state_dict method 30 | ##support cpu mode or gpu ParallelData mode for pytorch(could escape from ONNX bugs)## 31 | NetModel = 'your model' 32 | inputShapeData = torch.rand(1, 3, 256, 256) #just for net-foward once is enough 33 | # step 1: register hooks for module or functions 34 | forward_hooks_mount2_Net(NetModel) 35 | # step 2: forward the net work 36 | output = NetModel(inputShapeData) 37 | # step 3: remove the hooks 38 | unMount_forward_hooks() 39 | # step 4: interpret into NCNN layer's weight and bias in ncnn param-bin file format 40 | 41 | 42 | if __name__ == '__main__': 43 | args = 'get model args whatever' 44 | main(args) --------------------------------------------------------------------------------