Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
Add more support for mxnet_to_coreml (#14222)
Browse files Browse the repository at this point in the history
* Add support of mxnet_to_coreml

 * Add PReLU
 * Add group support in Convolution
 * Skip _minus_scalar and _mul_scalar

* Comply with code style

* Add spare line between comment and code
* Add two spare lines between functions
* Change "Convert an leakyrelu" to "Convert a leakyrelu"

* Check if num_group exists in param before assigning value

* Add test cases for test_mxnet_converter

* Add test_tiny_prelu_leakyrelu_random_input
* Add test_really_tiny_conv_random_input_multi_group
* Add test_tiny_conv_random_input_multi_group
* Modify test_conv_random by adding num_group

* Rollback to not setting num_group

* Add "leaky" and "elu" in converter

* Add support of "leaky" and "elu"
* Add unit test for "leaky" and "elu"
  • Loading branch information
wagamama authored and nswamy committed Apr 5, 2019
1 parent f0cd148 commit e64cfaa
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 1 deletion.
46 changes: 45 additions & 1 deletion tools/coreml/converter/_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,49 @@ def convert_activation(net, node, module, builder):
output_name = output_name)


def convert_leakyrelu(net, node, module, builder):
"""Convert a leakyrelu layer from mxnet to coreml.
Parameters
----------
network: net
A mxnet network object.
layer: node
Node to convert.
module: module
An module for MXNet
builder: NeuralNetworkBuilder
A neural network builder object.
"""

input_name, output_name = _get_input_output_name(net, node)
name = node['name']
inputs = node['inputs']
args, _ = module.get_params()
mx_non_linearity = _get_attrs(node)['act_type']
if mx_non_linearity == 'elu':
non_linearity = 'ELU'
slope = _get_attrs(node)['slope'] if 'slope' in _get_attrs(node) else 0.25
params = slope
elif mx_non_linearity == 'leaky':
non_linearity = 'LEAKYRELU'
slope = _get_attrs(node)['slope'] if 'slope' in _get_attrs(node) else 0.25
params = [slope]
elif mx_non_linearity == 'prelu':
non_linearity = 'PRELU'
params = args[_get_node_name(net, inputs[1][0])].asnumpy()
else:
raise TypeError('Unknown activation type %s' % mx_non_linearity)
builder.add_activation(name = name,
non_linearity = non_linearity,
input_name = input_name,
output_name = output_name,
params = params)


def convert_elementwise_add(net, node, module, builder):
"""Convert an elementwise add layer from mxnet to coreml.
Expand Down Expand Up @@ -335,6 +378,7 @@ def convert_convolution(net, node, module, builder):
border_mode = "valid"

n_filters = int(param['num_filter'])
n_groups = int(param['num_group']) if 'num_group' in param else 1

W = args[_get_node_name(net, inputs[1][0])].asnumpy()
if has_bias:
Expand All @@ -361,7 +405,7 @@ def convert_convolution(net, node, module, builder):
stride_height=stride_height,
stride_width=stride_width,
border_mode=border_mode,
groups=1,
groups=n_groups,
W=W,
b=Wb,
has_bias=has_bias,
Expand Down
3 changes: 3 additions & 0 deletions tools/coreml/converter/_mxnet_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@
'elemwise_add' : _layers.convert_elementwise_add,
'Reshape' : _layers.convert_reshape,
'Deconvolution' : _layers.convert_deconvolution,
'LeakyReLU' : _layers.convert_leakyrelu,
}

_MXNET_SKIP_LAYERS = [
'_MulScalar',
'Dropout',
'_minus_scalar',
'_mul_scalar',
]

def _mxnet_remove_batch(input_data):
Expand Down
67 changes: 67 additions & 0 deletions tools/coreml/test/test_mxnet_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,33 @@ def test_tiny_tanh_activation_random_input(self):
net = mx.sym.Activation(net, name='tanh1', act_type="tanh")
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_tiny_elu_leakyrelu_random_input(self):
np.random.seed(1988)
input_shape = (1, 10)
net = mx.sym.Variable('data')
net = mx.sym.FullyConnected(data=net, name='fc1', num_hidden=5)
slope = 0.1
net = mx.sym.LeakyReLU(net, name='elu1', act_type="elu", slope=slope)
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_tiny_leaky_leakyrelu_random_input(self):
np.random.seed(1988)
input_shape = (1, 10)
net = mx.sym.Variable('data')
net = mx.sym.FullyConnected(data=net, name='fc1', num_hidden=5)
slope = 0.1
net = mx.sym.LeakyReLU(net, name='leaky1', act_type="leaky", slope=slope)
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_tiny_prelu_leakyrelu_random_input(self):
np.random.seed(1988)
input_shape = (1, 10)
net = mx.sym.Variable('data')
net = mx.sym.FullyConnected(data=net, name='fc1', num_hidden=5)
gamma = mx.sym.Variable('gamma')
net = mx.sym.LeakyReLU(net, gamma=gamma, name='prelu1', act_type="prelu")
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_really_tiny_conv_random_input(self):
np.random.seed(1988)
input_shape = (1, 1, 10, 10)
Expand Down Expand Up @@ -408,6 +435,26 @@ def test_really_tiny_conv_random_input_multi_filter(self):
)
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_really_tiny_conv_random_input_multi_group(self):
np.random.seed(1988)
input_shape = (1, 16, 10, 10)
num_filter = 16
num_group = 4
kernel = (1, 1)
stride = (1, 1)
pad = (0, 0)
net = mx.sym.Variable('data')
net = mx.symbol.Convolution(
data=net,
num_filter=num_filter,
num_group=num_group,
kernel=kernel,
stride=stride,
pad=pad,
name='conv_1'
)
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_tiny_conv_random_3d_input(self):
np.random.seed(1988)
input_shape = (1, 3, 10, 10)
Expand Down Expand Up @@ -444,6 +491,26 @@ def test_tiny_conv_random_input_multi_filter(self):
)
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_tiny_conv_random_input_multi_group(self):
np.random.seed(1988)
input_shape = (1, 16, 10, 10)
num_filter = 16
num_group = 4
kernel = (5, 5)
stride = (1, 1)
pad = (0, 0)
net = mx.sym.Variable('data')
net = mx.symbol.Convolution(
data=net,
num_filter=num_filter,
num_group=num_group,
kernel=kernel,
stride=stride,
pad=pad,
name='conv_1'
)
self._test_mxnet_model(net, input_shape=input_shape, mode='random')

def test_conv_random(self):
np.random.seed(1988)
input_shape = (1, 3, 10, 10)
Expand Down

0 comments on commit e64cfaa

Please sign in to comment.