def to_keras(self): """Convert a Onnx model to KerasNet model. """ # parse network inputs, aka parameters for init_tensor in self.graph.initializer: if not init_tensor.name.strip(): raise ValueError("Tensor's name is required.") self.initializer[init_tensor.name] = OnnxInput( name=init_tensor.name, zvalue=OnnxHelper.to_numpy(init_tensor)) # converting GraphProto message # i: ValueInfoProto for i in self.graph.input: if i.name in self.initializer: # we should have added that via graph._initializer self._all_tensors[i.name] = self.initializer[i.name] else: self._inputs[i.name] = OnnxInput( name=i.name, zvalue=OnnxHelper.get_shape_from_node(i)) self._all_tensors[i.name] = self._inputs[i.name] # constructing nodes, nodes are stored as directed acyclic graph # converting NodeProto message for node in self.graph.node: inputs = [] for i in node.input: if i == "": continue if i not in self._all_tensors: raise Exception("Cannot find {}".format(i)) inputs.append(self._all_tensors[i]) mapper = OperatorMapper.of(node, self.initializer, inputs) # update inputs and all_tensors for input in mapper.model_inputs: # Only update the original inputs here. if input.name in self._inputs: self._inputs[input.name] = input.zvalue self._all_tensors[input.name] = input.zvalue tensor = mapper.to_tensor() output_ids = list(node.output) assert len(output_ids) == 1 or node.op_type == "Dropout",\ "Only support single output for now" self._all_tensors[output_ids[0]] = OnnxInput(name=tensor.name, zvalue=tensor) output_tensors = [] for i in self.graph.output: if i.name not in self._all_tensors: raise Exception("The output haven't been calculate") output_tensors.append(self._all_tensors[i.name].zvalue) model = zmodels.Model(input=list(self._inputs.values()), output=output_tensors) return model
def create_operator(self): assert len(self.inputs) == 1, "Conv accept single input only" rank = len(self.inputs[0].get_input_shape()) W_weights = self.params[0] if (rank == 4): # NCHW nb_filter = W_weights.shape[0] nb_row = int(self.onnx_attr['kernel_shape'][0]) nb_col = int(self.onnx_attr['kernel_shape'][1]) subSample = [int(i) for i in self.onnx_attr['strides']] dim_ordering = "th" assert self.onnx_attr['dilations'] == (1, 1), "we only support dilations == (1, 1)" assert self.onnx_attr['group'] == 1, "we only support group == 1" bias = True if (len(self.params) > 1) else False # TODO: activation?? init?? W_regularizer?? border_mode, pads = OnnxHelper.get_padds(self.onnx_attr) conv = zlayers.Convolution2D(nb_filter=nb_filter, nb_row=nb_row, nb_col=nb_col, subsample=subSample, dim_ordering=dim_ordering, bias=bias, border_mode=border_mode, pads=pads) return conv else: raise Exception("not supported.")
def _to_tensor(self): input = self.model_inputs[0] W_weights = self.model_trainable_values[0] rank = len(input.zvalue.get_input_shape()) if (rank == 4): # NCHW nb_filter = W_weights.shape[0] nb_row = int(self.onnx_attr['kernel_shape'][0]) nb_col = int(self.onnx_attr['kernel_shape'][1]) subSample = [int(i) for i in self.onnx_attr['strides']] if "strides" in self.onnx_attr else (1, 1) dim_ordering = "th" assert 'dilations' not in self.onnx_attr or self.onnx_attr['dilations'] == ( 1, 1), "we only support dilations == (1, 1)" assert 'group' not in self.onnx_attr or self.onnx_attr[ 'group'] == 1, "we only support group == 1" bias = True if (len(self._input_list) > 2) else False border_mode, pads = OnnxHelper.get_padds(self.onnx_attr) conv = zlayers.Convolution2D(nb_filter=nb_filter, nb_row=nb_row, nb_col=nb_col, subsample=subSample, dim_ordering=dim_ordering, bias=bias, border_mode=border_mode, pads=pads) return conv(input.zvalue) else: raise Exception("not supported.")
def __init__(self, node, initializer, inputs): self.node = node self.op_name = node.op_type node_name = node.name.strip() # it would be None if user doesn't set it manually self.node_name = node_name if node_name else None self.onnx_attr = OnnxHelper.parse_attr( node.attribute) # dict(name: value) self._initializer = initializer self._input_list = inputs self.model_inputs = self._extract_model_inputs() self.model_trainable_values = self._extract_trainable_values() self.output = node.output[0]
def _to_tensor(self): assert len(self.model_inputs) == 1, "MaxPool accept single input only" rank = len(self.model_inputs[0].zvalue.shape) if "storage_order" in self.onnx_attr.keys(): assert self.onnx_attr['storage_order'] == 0 if (rank == 4): # NCHW pool_size = [int(i) for i in self.onnx_attr['kernel_shape']] if "strides" in self.onnx_attr.keys(): strides = [int(i) for i in self.onnx_attr['strides']] else: strides = [1 for i in self.onnx_attr['kernel_shape']] border_mode, pads = OnnxHelper.get_padds(self.onnx_attr) maxpool = zlayers.MaxPooling2D(pool_size=pool_size, strides=strides, border_mode=border_mode, pads=pads) return maxpool(self.model_inputs[0].zvalue) elif (rank == 3): pool_length = int(self.onnx_attr['kernel_shape'][0]) if "strides" in self.onnx_attr.keys(): stride = int(self.onnx_attr['strides'][0]) else: stride = 1 border_mode, pads = OnnxHelper.get_padds(self.onnx_attr) if border_mode is None and pads is None: border_mode = 'valid' if pads is None: pads = 0 permute = zlayers.Permute(dims=(2, 1))(self.model_inputs[0].zvalue) maxpool = zlayers.MaxPooling1D(pool_length=pool_length, stride=stride, border_mode=border_mode, pad=pads)(permute) return zlayers.Permute(dims=(2, 1))(maxpool) else: raise Exception("not supported.")
def __init__(self, node, _params, _all_tensors): self.node = node self.op_name = node.op_type node_name = node.name.strip() # it would be None if user doesn't set it manually self.node_name = node_name if node_name else None self.onnx_attr = OnnxHelper.parse_attr( node.attribute) # dict(name: value) self.params = [_params[i] for i in node.input if i in _params] self.inputs = [ _all_tensors[i] for i in node.input if i in _all_tensors ] self.all_tensors = _all_tensors assert len(node.output) == 1, "we only support single output for now" self.output = node.output[0]
def _to_tensor(self): assert len(self.model_inputs) == 1, "AveragePool accept single input only" rank = len(self.model_inputs[0].zvalue.shape) if (rank == 4): # NCHW poolSize = [int(i) for i in self.onnx_attr['kernel_shape']] strides = [int(i) for i in self.onnx_attr['strides']] count_include_pad = bool(self.onnx_attr['count_include_pad'])\ if "count_include_pad" in self.onnx_attr else False dim_ordering = "th" border_mode, pads = OnnxHelper.get_padds(self.onnx_attr) averagepool2d = zlayers.AveragePooling2D(pool_size=poolSize, strides=strides, dim_ordering=dim_ordering, pads=pads, count_include_pad=count_include_pad) return averagepool2d(self.model_inputs[0].zvalue) else: raise Exception("not supported.")
def _to_tensor(self): assert len(self.model_inputs) == 1, "Conv accept single input only" rank = len(self.model_inputs[0].zvalue.get_input_shape()) if (rank == 4): # NCHW pool_size = [int(i) for i in self.onnx_attr['kernel_shape']] if "strides" in self.onnx_attr.keys(): strides = [int(i) for i in self.onnx_attr['strides']] else: strides = [1 for i in self.onnx_attr['kernel_shape']] border_mode, pads = OnnxHelper.get_padds(self.onnx_attr) maxpool = zlayers.MaxPooling2D(pool_size=pool_size, strides=strides, border_mode=border_mode, pads=pads) return maxpool(self.model_inputs[0].zvalue) else: raise Exception("not supported.")
def _extract_model_inputs(self): """ :return: list of OnnxInput """ input = OnnxInput(name=self.op_name, zvalue=OnnxHelper.to_numpy(self.onnx_attr['value'])) return [self._to_zoo_input(input, is_constant=True)]