-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support conversion of recognize_digits models #19
Changes from 7 commits
48876b4
446dca8
82d1f81
d6a60e8
0035259
55f140c
233df53
b577b05
467775a
557e61b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
|
||
def get_op_io_info(op): | ||
inputs = dict([(name, op.input(name)) for name in op.input_names]) | ||
attrs = dict( | ||
[(name, op.attr(name)) | ||
for name in op.attr_names]) if op.attr_names is not None else None | ||
outputs = dict([(name, op.output(name)) for name in op.output_names]) | ||
|
||
return inputs, attrs, outputs |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,10 @@ | |
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import sys | ||
from onnx.helper import make_node | ||
from paddle.fluid.executor import fetch_var | ||
from fluid.utils import get_op_io_info | ||
""" | ||
Priority of ops (uniques) to figure out support for. | ||
|
||
|
@@ -55,8 +58,14 @@ def abs_op(): | |
pass | ||
|
||
|
||
def add_op(inputs, attrs, outputs): | ||
return make_node('Add', inputs=inputs, outputs=outputs, broadcast=1) | ||
def add_op(operator, scope): | ||
inputs, attrs, outputs = get_op_io_info(operator) | ||
return make_node( | ||
'Add', | ||
inputs=inputs['X'] + inputs['Y'], | ||
outputs=outputs['Out'], | ||
axis=attrs['axis'], | ||
broadcast=1) | ||
|
||
|
||
def and_op(): | ||
|
@@ -81,8 +90,17 @@ def averagepool_op(): | |
pass | ||
|
||
|
||
def batchnorm_op(): | ||
pass | ||
def batchnorm_op(operator, scope): | ||
inputs, attrs, outputs = get_op_io_info(operator) | ||
bn_op = make_node( | ||
'BatchNormalization', | ||
inputs=inputs['X'] + inputs['Scale'] + inputs['Bias'] + inputs['Mean'] + | ||
inputs['Variance'], | ||
outputs=outputs['Y'], | ||
is_test=attrs['is_test'], | ||
epsilon=attrs['epsilon'], | ||
momentum=attrs['momentum']) | ||
return bn_op | ||
|
||
|
||
def cast_op(): | ||
|
@@ -105,11 +123,21 @@ def constant_op(): | |
pass | ||
|
||
|
||
def conv_op(): | ||
""" | ||
Need to support broadcast. | ||
""" | ||
pass | ||
def conv2d_op(operator, scope): | ||
inputs, attrs, outputs = get_op_io_info(operator) | ||
kernel_shape = fetch_var( | ||
operator.input('Filter')[0].decode('string_escape'), scope).shape | ||
|
||
conv2d = make_node( | ||
'Conv', | ||
inputs=inputs['Input'] + inputs['Filter'], | ||
outputs=outputs['Output'], | ||
dilations=attrs['dilations'], | ||
kernel_shape=kernel_shape[-2:], | ||
strides=attrs['strides'], | ||
group=attrs['groups'], | ||
pads=attrs['paddings'] + attrs['paddings']) | ||
return conv2d | ||
|
||
|
||
def convtranspose_op(): | ||
|
@@ -224,8 +252,63 @@ def lppool_op(): | |
pass | ||
|
||
|
||
def matmul_op(inputs, attrs, outputs): | ||
return make_node('MatMul', inputs=inputs, outputs=outputs) | ||
def mul_op(operator, scope): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we can see, sometimes we can't implement the operator in Fluid by only operator in ONNX. So it would be better to make the function name ( |
||
inputs, attrs, outputs = get_op_io_info(operator) | ||
|
||
# Flatten input(X) and input(Y) into 2-D matries | ||
x_flat_out = [inputs['X'][0] + '@flatten_0'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please pay attention to the intermediate tensors between nodes. They should be named uniquely in the ONNX graph. |
||
y_flat_out = [inputs['Y'][0] + '@flatten_0'] | ||
flatten_x_node = make_node( | ||
'Flatten', | ||
inputs=inputs['X'], | ||
outputs=x_flat_out, | ||
axis=attrs['x_num_col_dims']) | ||
flatten_y_node = make_node( | ||
'Flatten', | ||
inputs=inputs['Y'], | ||
outputs=y_flat_out, | ||
axis=attrs['y_num_col_dims']) | ||
|
||
# Mat mul | ||
matmul_out = [outputs['Out'][0] + '@matmul_0'] | ||
matmul_node = make_node( | ||
'MatMul', inputs=x_flat_out + y_flat_out, outputs=matmul_out) | ||
|
||
# Get the shape of input(X) and input(Y) | ||
x_shape_out = [inputs['X'][0] + '@shape_0'] | ||
y_shape_out = [inputs['Y'][0] + '@shape_0'] | ||
x_shape_node = make_node('Shape', inputs=inputs['X'], outputs=x_shape_out) | ||
y_shape_node = make_node('Shape', inputs=inputs['Y'], outputs=y_shape_out) | ||
|
||
# Get the real shape of output(Out) | ||
x_shape_slice_out = [inputs['X'][0] + '@shape_slice_0'] | ||
y_shape_slice_out = [inputs['Y'][0] + '@shape_slice_0'] | ||
output_shape = [outputs['Out'][0] + '@shape_concat_0'] | ||
x_shape_slice_node = make_node( | ||
'Slice', | ||
inputs=x_shape_out, | ||
outputs=x_shape_slice_out, | ||
starts=[0], | ||
ends=[attrs['x_num_col_dims']]) | ||
y_shape_slice_node = make_node( | ||
'Slice', | ||
inputs=y_shape_out, | ||
outputs=y_shape_slice_out, | ||
starts=[attrs['y_num_col_dims']], | ||
ends=[sys.maxint]) | ||
output_shape_node = make_node( | ||
'Concat', | ||
inputs=x_shape_slice_out + y_shape_slice_out, | ||
outputs=output_shape, | ||
axis=0) | ||
|
||
# Reshpe output | ||
output_node = make_node( | ||
'Reshape', inputs=matmul_out + output_shape, outputs=outputs['Out']) | ||
|
||
return (flatten_x_node, flatten_y_node, matmul_node, x_shape_node, | ||
y_shape_node, x_shape_slice_node, y_shape_slice_node, | ||
output_shape_node, output_node) | ||
|
||
|
||
def max_op(): | ||
|
@@ -251,10 +334,6 @@ def min_op(): | |
pass | ||
|
||
|
||
def mul_op(): | ||
pass | ||
|
||
|
||
def neg_op(): | ||
pass | ||
|
||
|
@@ -281,6 +360,26 @@ def pad_op(): | |
pass | ||
|
||
|
||
def pool2d_op(operator, scope): | ||
inputs, attrs, outputs = get_op_io_info(operator) | ||
if attrs['global_pooling'] is False: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
op_type = {'max': 'MaxPool', 'ave': 'AveragePool'} | ||
pool2d = make_node( | ||
op_type[attrs['pooling_type']], | ||
inputs=inputs['X'], | ||
outputs=outputs['Out'], | ||
kernel_shape=attrs['ksize'], | ||
strides=attrs['strides'], | ||
pads=attrs['paddings'] + attrs['paddings'], ) | ||
else: | ||
op_type = {'max': 'GlobalMaxPool', 'ave': 'GlobalAveragePool'} | ||
pool2d = make_node( | ||
op_type[attrs['pooling_type']], | ||
inputs=inputs['X'], | ||
outputs=outputs['Out']) | ||
return pool2d | ||
|
||
|
||
def pow_op(): | ||
pass | ||
|
||
|
@@ -349,8 +448,9 @@ def reducesumsquare_op(): | |
pass | ||
|
||
|
||
def relu_op(): | ||
pass | ||
def relu_op(operator, scope): | ||
inputs, _, outputs = get_op_io_info(operator) | ||
return make_node('Relu', inputs=inputs['X'], outputs=outputs['Out']) | ||
|
||
|
||
def reshape_op(): | ||
|
@@ -377,8 +477,9 @@ def slice_op(): | |
pass | ||
|
||
|
||
def softmax_op(): | ||
pass | ||
def softmax_op(operator, scope): | ||
inputs, attrs, outputs = get_op_io_info(operator) | ||
return make_node('Softmax', inputs=inputs['X'], outputs=outputs['Out']) | ||
|
||
|
||
def softplus_op(): | ||
|
@@ -444,9 +545,6 @@ def xor_op(): | |
# Reference for paddle operator availability taken from: | ||
# https://github.com/PaddlePaddle/Paddle/issues/8028 | ||
|
||
# ONNX Ops that use multiple Paddle ops are keyed by '<op1>,<op2>' fed into the | ||
# modifier. | ||
|
||
node_maker = { | ||
# Paddle op name : (ONNX op name, modifier) | ||
'abs': ('Abs', abs_op), | ||
|
@@ -456,13 +554,13 @@ def xor_op(): | |
# 'ArgMax', NEEDS ATTENTION. | ||
# 'ArgMin', NEEDS ATTENTION. | ||
'': ('AveragePool', averagepool_op), | ||
'batch_norm': ('BatchNormalization', batchnorm_op), | ||
'batch_norm': batchnorm_op, | ||
'cast': ('Cast', cast_op), | ||
# 'Ceil', NEEDS ATTENTION. | ||
'cast': ('Clip', clip_op), | ||
'concat': ('Concat', concat_op), | ||
',': ('Constant', constant_op), | ||
'conv': ('Conv', conv_op), | ||
'conv2d': conv2d_op, | ||
|
||
# Need to continue the mapping below. | ||
'': 'ConvTranspose', | ||
|
@@ -498,12 +596,13 @@ def xor_op(): | |
'': 'MaxRoiPool', | ||
'mean': ('Mean', mean_op), | ||
'': 'Min', | ||
'mul': matmul_op, | ||
'mul': mul_op, | ||
',': 'Neg', | ||
'': 'Not', | ||
'': 'Or', | ||
'': 'PRelu', | ||
'': 'Pad', | ||
'pool2d': pool2d_op, | ||
'': 'Pow', | ||
',': 'RNN', | ||
'': 'RandomNormal', | ||
|
@@ -521,14 +620,14 @@ def xor_op(): | |
# 'ReduceProd', NEEDS ATTENTION. | ||
'': 'ReduceSum', | ||
',': 'ReduceSumSquare', | ||
'': 'Relu', | ||
'relu': relu_op, | ||
'': 'Reshape', | ||
# 'Selu', NEEDS ATTENTION. | ||
'': 'Shape', | ||
'': 'Sigmoid', | ||
'': 'Size', | ||
# 'Slice', NEEDS ATTENTION. | ||
'': 'Softmax', | ||
'softmax': softmax_op, | ||
'': 'Softplus', | ||
'': 'Softsign', | ||
'': 'SpaceToDepth', | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I add a new directory
fluid
here to put some modules related to Fluid but independent of ONNX.