Skip to content

Commit

Permalink
Merge pull request #404 from sony/feature/20190304-add-tf-converter
Browse files Browse the repository at this point in the history
Add tf convert support
  • Loading branch information
YukioOobuchi committed Apr 15, 2019
2 parents 9c9ff70 + 0f1b9f8 commit b776b68
Show file tree
Hide file tree
Showing 10 changed files with 358 additions and 11 deletions.
7 changes: 7 additions & 0 deletions build-tools/make/build-with-docker.mk
Expand Up @@ -31,6 +31,7 @@ DOCKER_IMAGE_DOC ?= $(DOCKER_IMAGE_NAME_BASE)-doc:$(shell md5sum $(NNABLA_DIRECT
DOCKER_IMAGE_BUILD ?= $(DOCKER_IMAGE_NAME_BASE)-build$(ARCH_SUFFIX):$(shell md5sum $(NNABLA_DIRECTORY)/docker/development/Dockerfile.build$(ARCH_SUFFIX) |cut -d \ -f 1)
DOCKER_IMAGE_NNABLA ?= $(DOCKER_IMAGE_NAME_BASE)-nnabla:$(shell md5sum $(NNABLA_DIRECTORY)/docker/development/Dockerfile.build |cut -d \ -f 1)
DOCKER_IMAGE_ONNX_TEST ?= $(DOCKER_IMAGE_NAME_BASE)-onnx-test$(ARCH_SUFFIX):$(shell md5sum $(NNABLA_DIRECTORY)/docker/development/Dockerfile.onnx-test$(ARCH_SUFFIX) |cut -d \ -f 1)
DOCKER_IMAGE_TF_TEST ?= $(DOCKER_IMAGE_NAME_BASE)-tf-test$(ARCH_SUFFIX):$(shell md5sum $(NNABLA_DIRECTORY)/docker/development/Dockerfile.tf-test |cut -d \ -f 1)

########################################################################################################################
# Docker images
Expand Down Expand Up @@ -63,6 +64,12 @@ docker_image_onnx_test$(DOCKER_IMAGE_TARGET_SUFFIX):
(cd $(NNABLA_DIRECTORY) && docker build $(DOCKER_BUILD_ARGS) -t $(DOCKER_IMAGE_ONNX_TEST) -f docker/development/Dockerfile.onnx-test$(ARCH_SUFFIX) .) \
fi

.PHONY: docker_image_tf_test$(DOCKER_IMAGE_TARGET_SUFFIX)
docker_image_tf_test$(DOCKER_IMAGE_TARGET_SUFFIX):
if ! docker image inspect $(DOCKER_IMAGE_TF_TEST) >/dev/null 2>/dev/null; then \
docker pull $(shell cat $(NNABLA_DIRECTORY)/docker/development/Dockerfile.tf-test$(ARCH_SUFFIX) |grep ^FROM |awk '{print $$2}') && \
(cd $(NNABLA_DIRECTORY) && docker build $(DOCKER_BUILD_ARGS) -t $(DOCKER_IMAGE_TF_TEST) -f docker/development/Dockerfile.tf-test$(ARCH_SUFFIX) .) \
fi


# for Android
Expand Down
133 changes: 133 additions & 0 deletions docker/development/Dockerfile.tf-test
@@ -0,0 +1,133 @@
# Copyright (c) 2017 Sony Corporation. 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.

FROM ubuntu:16.04

ENV LC_ALL C
ENV LANG C
ENV LANGUAGE C

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
bzip2 \
ca-certificates \
ccache \
clang-format-3.8 \
cmake \
curl \
g++ \
git \
libarchive-dev \
libgoogle-glog-dev \
libgtest-dev \
libhdf5-dev \
libiomp-dev \
libleveldb-dev \
liblmdb-dev \
libopencv-dev \
libopenmpi-dev \
libprotobuf-dev \
libsnappy-dev \
libssl-dev \
make \
openmpi-bin \
openmpi-doc \
openssl \
unzip \
wget \
zip \
graphviz \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

RUN cd /tmp \
&& curl -L https://www.libarchive.org/downloads/libarchive-3.3.2.tar.gz -o libarchive-3.3.2.tar.gz \
&& tar xfa libarchive-3.3.2.tar.gz \
&& mkdir libarchive-build \
&& cd libarchive-build \
&& cmake \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DENABLE_NETTLE=FALSE \
-DENABLE_OPENSSL=FALSE \
-DENABLE_LZO=FALSE \
-DENABLE_LZMA=FALSE \
-DENABLE_BZip2=FALSE \
-DENABLE_LIBXML2=FALSE \
-DENABLE_EXPAT=FALSE \
-DENABLE_PCREPOSIX=FALSE \
-DENABLE_LibGCC=FALSE \
-DENABLE_CNG=FALSE \
-DENABLE_TAR=FALSE \
-DENABLE_TAR_SHARED=FALSE \
-DENABLE_CPIO=FALSE \
-DENABLE_CPIO_SHARED=FALSE \
-DENABLE_CAT=FALSE \
-DENABLE_CAT_SHARED=FALSE \
-DENABLE_XATTR=FALSE \
-DENABLE_ACL=FALSE \
-DENABLE_ICONV=FALSE \
-DENABLE_TEST=FALSE \
../libarchive-3.3.2 \
&& make \
&& make install \
&& cd / \
&& rm -rf /tmp/*

ARG PYTHON_VERSION_MAJOR
ARG PYTHON_VERSION_MINOR
ENV PYVERNAME=${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}

ENV PATH /opt/miniconda3/bin:$PATH
ENV LD_LIBRARY_PATH /opt/miniconda3/lib:$LD_LIBRARY_PATH

RUN set -xe \
&& umask 0 \
&& wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh \
&& bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3 \
&& rm -rf Miniconda3-latest-Linux-x86_64.sh \
&& if test ${PYTHON_VERSION_MAJOR} -eq 3 -a ${PYTHON_VERSION_MINOR} -eq 5; \
then \
conda install -y conda=4.5.11 python=${PYVERNAME}; \
else \
conda install -y python=${PYVERNAME}; \
conda update -y --all; \
fi \
&& conda install -y \
boto3 \
future \
h5py \
ipython \
mako \
'numpy<1.16' \
opencv \
pip \
protobuf \
pytest \
scikit-image \
scipy \
tqdm \
wheel \
virtualenv \
&& pip install pyyaml onnx==1.3.0 future Cython autopep8 requests \
graphviz tensorflow onnx_tf \
&& pip install cntk || true \
&& conda install -y -c pytorch pytorch-nightly-cpu \
&& rm -rf /opt/miniconda3/pkgs

RUN cd /tmp \
&& git clone https://github.com/onnx/tensorflow-onnx.git \
&& cd tensorflow-onnx \
&& python setup.py install \
&& rm -rf /tmp/tensorflow-onnx
1 change: 1 addition & 0 deletions python/setup.py
Expand Up @@ -247,6 +247,7 @@ def extopts(library_name, library_dir):
'nnabla.utils.converter.nnabla',
'nnabla.utils.converter.nnablart',
'nnabla.utils.converter.onnx',
'nnabla.utils.converter.tensorflow',
'nnabla.utils.factorization',
'nnabla.utils.image_utils',
'nnabla_ext',
Expand Down
26 changes: 21 additions & 5 deletions python/src/nnabla/utils/converter/commands.py
Expand Up @@ -26,19 +26,32 @@


def _import_file(args, ifiles):
if len(ifiles) == 1 and os.path.splitext(ifiles[0])[1] == '.nnp':
args.import_format = 'NNP'
if len(ifiles) == 1 and os.path.splitext(ifiles[0])[1] == '.onnx':
args.import_format = 'ONNX'
if len(ifiles) == 1:
ext = os.path.splitext(ifiles[0])[1]
if ext == '.nnp':
args.import_format = 'NNP'
elif ext == '.onnx':
args.import_format = 'ONNX'
elif ext == '.pb':
args.import_format = "TF_PB"
elif ext == '.ckpt':
args.import_format = "TF_CKPT"

if args.import_format == 'NNP':
# Input file that has unsupported extension store into output nnp
# archive or directory.
return NnpImporter(*ifiles,
expand_network=not args.nnp_no_expand_network,
executor_index=args.nnp_import_executor_index).execute()

elif args.import_format == 'ONNX':
from .onnx import OnnxImporter
return OnnxImporter(*ifiles).execute()

elif args.import_format == 'TF_PB' or \
args.import_format == 'TF_CKPT':
from .tensorflow import TensorflowImporter
return TensorflowImporter(*ifiles, tf_format=args.import_format).execute()
return None


Expand Down Expand Up @@ -152,6 +165,9 @@ def _export_from_nnp(args, nnp, output, output_ext):
OnnxExporter(nnp, args.batch_size, opset=opset).execute(output)
else:
OnnxExporter(nnp, args.batch_size).execute(output)
elif output_ext == '.pb':
from .tensorflow import TensorflowExporter
TensorflowExporter(nnp, args.batch_size).execute(output)
else:
print('Output file ({})'.format(output_ext) +
' is not supported or output directory does not exist.')
Expand Down Expand Up @@ -284,7 +300,7 @@ def convert_files(args, ifiles, output):
else:
return _export_from_nnp(args, nnp, output, output_ext)
else:
print('Import from [{}] failed.'.format(ifiles))
print('Import from {} failed.'.format(ifiles))
return False


Expand Down
5 changes: 5 additions & 0 deletions python/src/nnabla/utils/converter/onnx/exporter.py
Expand Up @@ -1541,6 +1541,11 @@ def dump_graph(self):
print("{} : {}".format(i, in_d[i]))
print(node)

def export_model_proto(self):
self.create_model()
self.create_graph()
return self._model_proto

def execute(self, file_path):
# if debug, please uncomment it.
# self.dump_nnp(file_path)
Expand Down
10 changes: 8 additions & 2 deletions python/src/nnabla/utils/converter/onnx/importer.py
Expand Up @@ -440,7 +440,7 @@ def add_tensor_as_parameter(pb, tensor):


class OnnxImporter:
def __init__(self, file_path):
def __init__(self, file_path=''):
self._file_path = file_path

# We use an OrderedDict and not a set
Expand Down Expand Up @@ -1722,6 +1722,12 @@ class nnp:
nnp.other_files = []
return nnp

def import_from_onnx_model(self, onnx_model):
self._ir_version = onnx_model.ir_version
self._graph = onnx_model.graph
self._opset_import = onnx_model.opset_import

def execute(self):
self.get_onnx_graph_info()
if self._file_path != '':
self.get_onnx_graph_info()
return self.onnx_model_to_nnp_protobuf()
8 changes: 4 additions & 4 deletions python/src/nnabla/utils/converter/supported_info.py
Expand Up @@ -16,7 +16,7 @@

_SupportedInfo = collections.namedtuple(
'_SupportedInfo', 'import_name export_name')
extensions = _SupportedInfo(import_name=['.nnp', '.onnx'], export_name=[
'.nnp', '.nnb', '.onnx'])
formats = _SupportedInfo(import_name=['NNP', 'ONNX'], export_name=[
'NNP', 'NNB', 'CSRC', 'ONNX'])
extensions = _SupportedInfo(import_name=['.nnp', '.onnx', '.ckpt', '.pb'], export_name=[
'.nnp', '.nnb', '.onnx', '.ckpt', '.pb'])
formats = _SupportedInfo(import_name=['NNP', 'ONNX', 'TF_CKPT', 'TF_PB'], export_name=[
'NNP', 'NNB', 'CSRC', 'ONNX', 'TF_CKPT', 'TF_PB'])
16 changes: 16 additions & 0 deletions python/src/nnabla/utils/converter/tensorflow/__init__.py
@@ -0,0 +1,16 @@
# Copyright (c) 2017 Sony Corporation. 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.

from .importer import TensorflowImporter
from .exporter import TensorflowExporter
28 changes: 28 additions & 0 deletions python/src/nnabla/utils/converter/tensorflow/exporter.py
@@ -0,0 +1,28 @@
# Copyright (c) 2019 Sony Corporation. 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.

from ..onnx import OnnxExporter
from onnx_tf.backend import prepare


class TensorflowExporter:
def __init__(self, nnp, batch_size):
self._nnp = nnp
self._batch_size = batch_size

def execute(self, output):
onnx_model = OnnxExporter(
self._nnp, self._batch_size).export_model_proto()
tf_rep = prepare(onnx_model)
tf_rep.export_graph(output)

0 comments on commit b776b68

Please sign in to comment.