From 5af3a382dd5b31edb1af34f84c8ede69aa96b3cc Mon Sep 17 00:00:00 2001 From: liuxinwei Date: Fri, 10 Jan 2025 12:26:22 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pages.yml | 60 + .github/workflows/python-publish.yml | 33 + .gitignore | 159 + .readthedocs.yaml | 35 + LICENSE | 201 + README.md | 40 + SECURITY.md | 16 + doc/CHANGELOG.md | 1 + doc/CODE_OF_CONDUCT.md | 3 + doc/CONTRIBUTING.md | 3 + doc/_ext/gallery_directive.py | 145 + doc/_ext/rtd_version.py | 49 + doc/_static/css/custom.css | 24 + doc/_static/css/tippy.css | 5 + doc/_static/images/favicon.jpg | Bin 0 -> 6901 bytes doc/_static/images/logo.jpg | Bin 0 -> 25906 bytes doc/_static/references/articles.bib | 270 + doc/_static/references/book.bib | 9 + doc/_static/switcher.json | 12 + doc/_templates/custom-template.html | 6 + doc/_templates/navbar-version.html | 2 + doc/_templates/theme-switcher.html | 5 + doc/about/index.md | 9 + doc/about/zreferences.md | 14 + doc/conf.py | 245 + doc/frontend/caffe/index.md | 6 + doc/frontend/caffe/network.ipynb | 213 + doc/frontend/caffe/ops.ipynb | 3694 ++ doc/frontend/caffe_utils.py | 237 + doc/frontend/index.md | 9 + doc/frontend/onnx/converters.ipynb | 182 + .../onnx/images/linear_regressor-onnx.jpg | Bin 0 -> 6499 bytes doc/frontend/onnx/index.md | 11 + doc/frontend/onnx/intro.ipynb | 1295 + doc/frontend/onnx/onnxscript/chunk.ipynb | 127 + .../onnx/onnxscript/eager-mode-eval.ipynb | 111 + doc/frontend/onnx/onnxscript/export-lib.ipynb | 109 + doc/frontend/onnx/onnxscript/gelu.ipynb | 73 + .../onnxscript/images/custom_aten_add.jpg | Bin 0 -> 8803 bytes .../onnxscript/images/custom_aten_gelu.jpg | Bin 0 -> 7101 bytes .../onnxscript/images/custom_aten_gelu2.jpg | Bin 0 -> 25614 bytes .../onnxscript/images/custon_aten_add_2.jpg | Bin 0 -> 11506 bytes .../onnxscript/images/ten_chunks_model.png | Bin 0 -> 1084072 bytes doc/frontend/onnx/onnxscript/index.md | 21 + doc/frontend/onnx/onnxscript/intro.ipynb | 144 + doc/frontend/onnx/onnxscript/ir/index.md | 6 + doc/frontend/onnx/onnxscript/ir/start.ipynb | 315 + doc/frontend/onnx/onnxscript/ir/tensors.ipynb | 27 + .../onnx/onnxscript/model-local-funs.ipynb | 198 + .../onnx/onnxscript/model-props.ipynb | 95 + doc/frontend/onnx/onnxscript/opt/index.md | 5 + .../onnx/onnxscript/opt/optimizer.ipynb | 247 + .../onnxscript/pattern/generic_pattern.ipynb | 451 + doc/frontend/onnx/onnxscript/pattern/index.md | 6 + .../onnx/onnxscript/pattern/rewriting.ipynb | 518 + doc/frontend/onnx/onnxscript/registry.ipynb | 571 + .../onnxscript/report_dynamo_export.sarif | 26 + doc/frontend/onnx/onnxscript/selu.ipynb | 137 + .../onnx/onnxscript/square-loss.ipynb | 160 + doc/frontend/onnx/onnxscript/tools/index.md | 6 + .../onnx/onnxscript/tools/onnx2script.ipynb | 80 + .../onnx/onnxscript/tools/optimize.ipynb | 80 + doc/frontend/onnx/onnxscript/tutorial.ipynb | 589 + doc/frontend/onnx/relay2onnx.ipynb | 100 + doc/frontend/onnx/save-model.ipynb | 107 + doc/frontend/onnx/set_env.py | 8 + doc/frontend/tf/.gitignore | 2 + doc/frontend/tf/Graph.ipynb | 319 + doc/frontend/tf/graph_transforms.py | 31 + ...imagenet_2012_validation_synset_labels.txt | 50000 ++++++++++++++++ .../tf-slim/imagenet_lsvrc_2015_synsets.txt | 1000 + .../tf/imagenet/tf-slim/imagenet_metadata.txt | 21842 +++++++ .../images/Giant_Panda_in_Beijing_Zoo_1.jpg | Bin 0 -> 116068 bytes doc/frontend/tf/index.md | 11 + doc/frontend/tf/pb2onnx.ipynb | 1103 + doc/frontend/tf/set_env.py | 5 + doc/frontend/tf/test.py | 62 + doc/frontend/tf/test_sigmoid.py | 181 + doc/frontend/tf/tf-slim/.gitignore | 1 + doc/frontend/tf/tf-slim/index.md | 13 + doc/frontend/tf/tf-slim/set_env.py | 5 + doc/frontend/tf/tf-slim/tf1-pb.ipynb | 317 + doc/frontend/tf/tf-slim/tf1-tf2.ipynb | 713 + doc/frontend/tf/tf-slim/tf1.ipynb | 331 + doc/frontend/tf/tf-slim/tf2-keras.ipynb | 664 + doc/frontend/tf/tf-slim/tf2.ipynb | 263 + doc/frontend/tf/tf1.ipynb | 1947 + doc/frontend/tf2onnx/index.md | 5 + doc/frontend/tf2onnx/intro.ipynb | 27 + doc/frontend/torch2onnx/index.md | 5 + doc/frontend/torch2onnx/opt/GatherND.ipynb | 20 + doc/frontend/torch2onnx/opt/L2.ipynb | 190 + doc/frontend/torch2onnx/opt/Scatter.ipynb | 220 + .../torch2onnx/opt/ScatterElements.ipynb | 20 + doc/frontend/torch2onnx/opt/ScatterND.ipynb | 328 + .../torch2onnx/opt/SequenceConstruct.ipynb | 156 + doc/frontend/torch2onnx/opt/Unsqueeze.ipynb | 415 + doc/frontend/torch2onnx/opt/Upsample.ipynb | 432 + doc/frontend/torch2onnx/opt/aa.py | 29 + doc/frontend/torch2onnx/opt/bn-conv.ipynb | 229 + .../torch2onnx/opt/conv-reshape.ipynb | 250 + doc/frontend/torch2onnx/opt/expand.ipynb | 227 + doc/frontend/torch2onnx/opt/flatten.ipynb | 362 + doc/frontend/torch2onnx/opt/hardswish.ipynb | 117 + doc/frontend/torch2onnx/opt/images/L2.jpg | Bin 0 -> 7261 bytes .../torch2onnx/opt/images/ScatterND-s.jpg | Bin 0 -> 7662 bytes .../torch2onnx/opt/images/ScatterND.jpg | Bin 0 -> 69300 bytes .../opt/images/SequenceConstruct.jpg | Bin 0 -> 8394 bytes .../torch2onnx/opt/images/bn-conv.jpg | Bin 0 -> 21668 bytes doc/frontend/torch2onnx/opt/images/expand.jpg | Bin 0 -> 17691 bytes .../torch2onnx/opt/images/flatten.jpg | Bin 0 -> 8163 bytes .../torch2onnx/opt/images/index-data.jpg | Bin 0 -> 6659 bytes doc/frontend/torch2onnx/opt/images/repeat.png | Bin 0 -> 6850 bytes .../torch2onnx/opt/images/reshape-1.jpg | Bin 0 -> 17347 bytes doc/frontend/torch2onnx/opt/images/slice.jpg | Bin 0 -> 8127 bytes doc/frontend/torch2onnx/opt/index-data.ipynb | 174 + doc/frontend/torch2onnx/opt/index.md | 9 + doc/frontend/torch2onnx/opt/repeat.ipynb | 196 + doc/frontend/torch2onnx/opt/resize.ipynb | 77 + doc/frontend/torch2onnx/opt/slice.ipynb | 161 + doc/frontend/torch2onnx/opt/split.ipynb | 211 + doc/index.md | 18 + doc/read/dpl/PatternContext.ipynb | 665 + doc/read/dpl/StructInfo.ipynb | 235 + doc/read/dpl/backtrack.ipynb | 150 + doc/read/dpl/demo.py | 52 + doc/read/dpl/index.md | 23 + doc/read/dpl/iterative-rewrite.ipynb | 258 + doc/read/dpl/match.ipynb | 1273 + .../dpl/rewrite-without-trivial-binding.ipynb | 124 + doc/read/dpl/rewrite.ipynb | 601 + doc/read/dpl/same-shape.ipynb | 142 + doc/read/ffi/Makefile | 30 + doc/read/ffi/_init_api.ipynb | 146 + doc/read/ffi/datastruct.ipynb | 159 + doc/read/ffi/funcs.ipynb | 127 + doc/read/ffi/index.md | 16 + doc/read/ffi/libinfo.ipynb | 273 + doc/read/ffi/register-func.ipynb | 151 + doc/read/ffi/register-object.ipynb | 359 + doc/read/ffi/src/test_obj.cc | 44 + doc/read/ffi/src/tvm_ext.cc | 11 + doc/read/ffi/testing.py | 60 + doc/read/index.md | 8 + doc/topics/extension/Makefile | 35 + doc/topics/extension/NDSubClass.ipynb | 158 + doc/topics/extension/cpp-call.ipynb | 113 + doc/topics/extension/cpp/bind_add/Makefile | 29 + .../extension/cpp/bind_add/src/tvm_ext.cc | 13 + doc/topics/extension/cpp/device_api/Makefile | 29 + .../extension/cpp/device_api/src/tvm_ext.cc | 13 + doc/topics/extension/cpp/extern_func/Makefile | 29 + .../extension/cpp/extern_func/src/tvm_ext.cc | 4 + .../extension/cpp/mini_runtime/Makefile | 29 + .../extension/cpp/mini_runtime/src/tvm_ext.cc | 17 + doc/topics/extension/cpp/python_ext/Makefile | 29 + .../extension/cpp/python_ext/src/tvm_ext.cc | 13 + .../cpp/python_ext/tvm_ext/__init__.py | 5 + .../cpp/python_ext/tvm_ext/_ffi_api.py | 4 + doc/topics/extension/cpp/sym_add/Makefile | 29 + .../extension/cpp/sym_add/src/tvm_ext.cc | 13 + doc/topics/extension/index.md | 10 + doc/topics/extension/plugin-module.ipynb | 126 + doc/topics/extension/py-call.ipynb | 652 + doc/topics/extension/register/extension.ipynb | 117 + doc/topics/extension/register/index.md | 6 + .../extension/register/runtime/index.md | 6 + .../extension/register/runtime/measure.ipynb | 134 + .../register/runtime/module-export.ipynb | 388 + doc/topics/extension/set_env.py | 7 + doc/topics/extension/src/plugin_module.cc | 49 + doc/topics/extension/src/testing/_make.cc | 6 + doc/topics/extension/src/testing/bind_add.cc | 13 + .../extension/src/testing/device_api.cc | 13 + .../extension/src/testing/extern_func.cc | 4 + doc/topics/extension/src/testing/make_node.cc | 21 + .../extension/src/testing/mini_runtime.cc | 17 + doc/topics/extension/src/testing/sym_add.cc | 13 + doc/topics/extension/src/tvm_ext.cc | 1 + doc/topics/extension/tests/tvm_ext2.cc | 44 + doc/topics/extension/tests/tvm_ext22.cc | 124 + doc/topics/extension/transform-intro.ipynb | 152 + .../extension/tvm_ext/testing/__init__.py | 0 .../extension/tvm_ext/testing/_ffi_api.py | 4 + doc/topics/extension/tvm_ext/testing/demo.py | 48 + doc/topics/gallery/XGrammar.ipynb | 231 + doc/topics/gallery/index.md | 6 + doc/topics/gallery/mlc-llm/images/diff.png | Bin 0 -> 588068 bytes doc/topics/gallery/mlc-llm/index.md | 6 + doc/topics/gallery/mlc-llm/intro.ipynb | 242 + .../gallery/mlc-llm/new-model-arch.ipynb | 1247 + doc/topics/gallery/mlc-llm/set_env.py | 7 + doc/topics/gallery/set_env.py | 7 + doc/topics/images/bus.jpg | Bin 0 -> 487438 bytes doc/topics/index.md | 9 + doc/topics/mlc/cc-jit-load.ipynb | 115 + doc/topics/mlc/index.md | 6 + doc/topics/mlc/mlc-python.ipynb | 486 + doc/topics/other/codegen/c-host.ipynb | 368 + doc/topics/other/codegen/extern.ipynb | 300 + doc/topics/other/codegen/index.md | 7 + doc/topics/other/codegen/static-init.ipynb | 112 + doc/topics/other/explorer/index.md | 7 + doc/topics/other/explorer/intro.ipynb | 66 + doc/topics/other/index.md | 9 + doc/topics/other/podman/index.md | 7 + doc/topics/other/podman/intro.ipynb | 76 + ...e-jaguar-f-type-car-red-cars-wallpaper.jpg | Bin 0 -> 395073 bytes doc/topics/other/ultralytics/index.md | 7 + doc/topics/other/ultralytics/relax-opt.ipynb | 1058 + doc/topics/other/ultralytics/relax.ipynb | 1630 + doc/topics/other/ultralytics/relay.ipynb | 1470 + doc/topics/other/ultralytics/test.ipynb | 266 + doc/topics/other/ultralytics/test.py | 27 + .../other/ultralytics/utils/__init__.py | 0 doc/topics/other/wsl/index.md | 5 + doc/topics/other/wsl/news.md | 3 + doc/topics/set_env.py | 11 + doc/tutorials/index.md | 8 + doc/tutorials/msc/graph/codegen.ipynb | 260 + doc/tutorials/msc/graph/index.md | 12 + doc/tutorials/msc/graph/intro.ipynb | 617 + doc/tutorials/msc/graph/model.py | 24 + doc/tutorials/msc/images/msc.jpeg | Bin 0 -> 129640 bytes doc/tutorials/msc/images/pipeline.jpg | Bin 0 -> 142442 bytes doc/tutorials/msc/images/runner.jpg | Bin 0 -> 168796 bytes doc/tutorials/msc/images/tools.jpg | Bin 0 -> 87904 bytes doc/tutorials/msc/index.md | 11 + doc/tutorials/msc/intro.md | 18 + doc/tutorials/msc/pipeline/MSCManager.ipynb | 178 + doc/tutorials/msc/pipeline/TorchDynamic.ipynb | 177 + doc/tutorials/msc/pipeline/index.md | 11 + doc/tutorials/msc/pipeline/intro.md | 26 + doc/tutorials/msc/plugin/index.md | 7 + doc/tutorials/msc/plugin/set_env.py | 7 + doc/tutorials/msc/plugin/test.ipynb | 127 + doc/tutorials/msc/plugin/utils.py | 301 + doc/tutorials/msc/runner/TVMRunner.ipynb | 161 + .../msc/runner/TensorflowRunner.ipynb | 215 + doc/tutorials/msc/runner/TorchRunner.ipynb | 187 + doc/tutorials/msc/runner/index.md | 24 + doc/tutorials/msc/set_env.py | 7 + doc/tutorials/msc/tests/index.md | 8 + doc/tutorials/msc/tests/transform.ipynb | 208 + doc/tutorials/msc/tests/translate-relax.ipynb | 1169 + doc/tutorials/msc/tests/translate-relay.ipynb | 1134 + .../msc/tests/translate-tensorflow.ipynb | 1846 + .../msc/tests/translate-tensorrt.ipynb | 882 + doc/tutorials/msc/tests/translate-torch.ipynb | 1204 + doc/tutorials/msc/tests/translate.ipynb | 361 + doc/tutorials/msc/tools/index.md | 11 + doc/tutorials/msc/tools/intro.md | 15 + doc/tutorials/msc/tools/pruner.ipynb | 144 + doc/tutorials/msc/tools/quantizer.ipynb | 175 + doc/tutorials/msc/tools/set_env.py | 7 + doc/tutorials/msc/tools/test.ipynb | 146 + doc/tutorials/msc/tools/tracker.ipynb | 102 + doc/tutorials/msc/tools/utils.py | 138 + doc/tutorials/start/IRModule.ipynb | 823 + doc/tutorials/start/Relax/creation.ipynb | 675 + doc/tutorials/start/Relax/index.md | 10 + doc/tutorials/start/Relax/set_env.py | 7 + .../start/Relax/transformation.ipynb | 538 + doc/tutorials/start/TensorIR/creation.ipynb | 523 + doc/tutorials/start/TensorIR/index.md | 6 + doc/tutorials/start/TensorIR/set_env.py | 7 + .../start/TensorIR/transformation.ipynb | 599 + doc/tutorials/start/customize-opt.ipynb | 3642 ++ doc/tutorials/start/demo.ipynb | 357 + doc/tutorials/start/e2e-opt.ipynb | 336 + doc/tutorials/start/env.md | 84 + doc/tutorials/start/index.md | 14 + doc/tutorials/start/opt-llm.ipynb | 739 + doc/tutorials/start/rpc.ipynb | 385 + doc/tutorials/start/set_env.py | 7 + doc/utils/links.py | 32 + pyproject.toml | 64 + src/tvm_book/__init__.py | 2 + src/tvm_book/config/__init__.py | 1 + src/tvm_book/config/env.py | 43 + src/tvm_book/data/__init__.py | 0 src/tvm_book/data/imagenet/__init__.py | 11 + src/tvm_book/data/imagenet/attrs.py | 1015 + src/tvm_book/tvm_ext/__init__.py | 1 + src/tvm_book/tvm_ext/_ffi_api.py | 4 + src/tvm_book/tvm_ext/libinfo.py | 22 + tasks.py | 23 + tests/.gitignore | 2 + tests/env.py | 12 + tests/main.ipynb | 171 + tests/rpc.ipynb | 274 + tests/tools/__init__.py | 1 + tests/tools/assert_diagnostic.py | 66 + tests/tools/external_codegen.py | 125 + tests/tools/frontends.py | 0 tests/tools/ref_funcs.py | 48 + tests/tools/set_env.py | 6 + tests/tools/set_pytorch.py | 6 + tests/tools/set_tensorflow.py | 10 + tests/tools/tag_span.py | 108 + tests/tools/torch_utils.py | 177 + 301 files changed, 130117 insertions(+) create mode 100755 .github/workflows/pages.yml create mode 100755 .github/workflows/python-publish.yml create mode 100755 .gitignore create mode 100755 .readthedocs.yaml create mode 100755 LICENSE create mode 100755 README.md create mode 100644 SECURITY.md create mode 100755 doc/CHANGELOG.md create mode 100755 doc/CODE_OF_CONDUCT.md create mode 100755 doc/CONTRIBUTING.md create mode 100644 doc/_ext/gallery_directive.py create mode 100644 doc/_ext/rtd_version.py create mode 100644 doc/_static/css/custom.css create mode 100644 doc/_static/css/tippy.css create mode 100755 doc/_static/images/favicon.jpg create mode 100755 doc/_static/images/logo.jpg create mode 100755 doc/_static/references/articles.bib create mode 100644 doc/_static/references/book.bib create mode 100755 doc/_static/switcher.json create mode 100755 doc/_templates/custom-template.html create mode 100755 doc/_templates/navbar-version.html create mode 100755 doc/_templates/theme-switcher.html create mode 100755 doc/about/index.md create mode 100755 doc/about/zreferences.md create mode 100755 doc/conf.py create mode 100644 doc/frontend/caffe/index.md create mode 100644 doc/frontend/caffe/network.ipynb create mode 100644 doc/frontend/caffe/ops.ipynb create mode 100644 doc/frontend/caffe_utils.py create mode 100644 doc/frontend/index.md create mode 100644 doc/frontend/onnx/converters.ipynb create mode 100644 doc/frontend/onnx/images/linear_regressor-onnx.jpg create mode 100644 doc/frontend/onnx/index.md create mode 100644 doc/frontend/onnx/intro.ipynb create mode 100644 doc/frontend/onnx/onnxscript/chunk.ipynb create mode 100644 doc/frontend/onnx/onnxscript/eager-mode-eval.ipynb create mode 100644 doc/frontend/onnx/onnxscript/export-lib.ipynb create mode 100644 doc/frontend/onnx/onnxscript/gelu.ipynb create mode 100644 doc/frontend/onnx/onnxscript/images/custom_aten_add.jpg create mode 100644 doc/frontend/onnx/onnxscript/images/custom_aten_gelu.jpg create mode 100644 doc/frontend/onnx/onnxscript/images/custom_aten_gelu2.jpg create mode 100644 doc/frontend/onnx/onnxscript/images/custon_aten_add_2.jpg create mode 100644 doc/frontend/onnx/onnxscript/images/ten_chunks_model.png create mode 100644 doc/frontend/onnx/onnxscript/index.md create mode 100644 doc/frontend/onnx/onnxscript/intro.ipynb create mode 100644 doc/frontend/onnx/onnxscript/ir/index.md create mode 100644 doc/frontend/onnx/onnxscript/ir/start.ipynb create mode 100644 doc/frontend/onnx/onnxscript/ir/tensors.ipynb create mode 100644 doc/frontend/onnx/onnxscript/model-local-funs.ipynb create mode 100644 doc/frontend/onnx/onnxscript/model-props.ipynb create mode 100644 doc/frontend/onnx/onnxscript/opt/index.md create mode 100644 doc/frontend/onnx/onnxscript/opt/optimizer.ipynb create mode 100644 doc/frontend/onnx/onnxscript/pattern/generic_pattern.ipynb create mode 100644 doc/frontend/onnx/onnxscript/pattern/index.md create mode 100644 doc/frontend/onnx/onnxscript/pattern/rewriting.ipynb create mode 100644 doc/frontend/onnx/onnxscript/registry.ipynb create mode 100644 doc/frontend/onnx/onnxscript/report_dynamo_export.sarif create mode 100644 doc/frontend/onnx/onnxscript/selu.ipynb create mode 100644 doc/frontend/onnx/onnxscript/square-loss.ipynb create mode 100644 doc/frontend/onnx/onnxscript/tools/index.md create mode 100644 doc/frontend/onnx/onnxscript/tools/onnx2script.ipynb create mode 100644 doc/frontend/onnx/onnxscript/tools/optimize.ipynb create mode 100644 doc/frontend/onnx/onnxscript/tutorial.ipynb create mode 100644 doc/frontend/onnx/relay2onnx.ipynb create mode 100644 doc/frontend/onnx/save-model.ipynb create mode 100644 doc/frontend/onnx/set_env.py create mode 100644 doc/frontend/tf/.gitignore create mode 100644 doc/frontend/tf/Graph.ipynb create mode 100644 doc/frontend/tf/graph_transforms.py create mode 100644 doc/frontend/tf/imagenet/tf-slim/imagenet_2012_validation_synset_labels.txt create mode 100644 doc/frontend/tf/imagenet/tf-slim/imagenet_lsvrc_2015_synsets.txt create mode 100644 doc/frontend/tf/imagenet/tf-slim/imagenet_metadata.txt create mode 100644 doc/frontend/tf/images/Giant_Panda_in_Beijing_Zoo_1.jpg create mode 100644 doc/frontend/tf/index.md create mode 100644 doc/frontend/tf/pb2onnx.ipynb create mode 100644 doc/frontend/tf/set_env.py create mode 100644 doc/frontend/tf/test.py create mode 100644 doc/frontend/tf/test_sigmoid.py create mode 100644 doc/frontend/tf/tf-slim/.gitignore create mode 100644 doc/frontend/tf/tf-slim/index.md create mode 100755 doc/frontend/tf/tf-slim/set_env.py create mode 100644 doc/frontend/tf/tf-slim/tf1-pb.ipynb create mode 100644 doc/frontend/tf/tf-slim/tf1-tf2.ipynb create mode 100644 doc/frontend/tf/tf-slim/tf1.ipynb create mode 100644 doc/frontend/tf/tf-slim/tf2-keras.ipynb create mode 100644 doc/frontend/tf/tf-slim/tf2.ipynb create mode 100644 doc/frontend/tf/tf1.ipynb create mode 100644 doc/frontend/tf2onnx/index.md create mode 100644 doc/frontend/tf2onnx/intro.ipynb create mode 100644 doc/frontend/torch2onnx/index.md create mode 100644 doc/frontend/torch2onnx/opt/GatherND.ipynb create mode 100644 doc/frontend/torch2onnx/opt/L2.ipynb create mode 100644 doc/frontend/torch2onnx/opt/Scatter.ipynb create mode 100644 doc/frontend/torch2onnx/opt/ScatterElements.ipynb create mode 100644 doc/frontend/torch2onnx/opt/ScatterND.ipynb create mode 100644 doc/frontend/torch2onnx/opt/SequenceConstruct.ipynb create mode 100644 doc/frontend/torch2onnx/opt/Unsqueeze.ipynb create mode 100644 doc/frontend/torch2onnx/opt/Upsample.ipynb create mode 100644 doc/frontend/torch2onnx/opt/aa.py create mode 100644 doc/frontend/torch2onnx/opt/bn-conv.ipynb create mode 100644 doc/frontend/torch2onnx/opt/conv-reshape.ipynb create mode 100644 doc/frontend/torch2onnx/opt/expand.ipynb create mode 100644 doc/frontend/torch2onnx/opt/flatten.ipynb create mode 100644 doc/frontend/torch2onnx/opt/hardswish.ipynb create mode 100644 doc/frontend/torch2onnx/opt/images/L2.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/ScatterND-s.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/ScatterND.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/SequenceConstruct.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/bn-conv.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/expand.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/flatten.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/index-data.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/repeat.png create mode 100644 doc/frontend/torch2onnx/opt/images/reshape-1.jpg create mode 100644 doc/frontend/torch2onnx/opt/images/slice.jpg create mode 100644 doc/frontend/torch2onnx/opt/index-data.ipynb create mode 100644 doc/frontend/torch2onnx/opt/index.md create mode 100644 doc/frontend/torch2onnx/opt/repeat.ipynb create mode 100644 doc/frontend/torch2onnx/opt/resize.ipynb create mode 100644 doc/frontend/torch2onnx/opt/slice.ipynb create mode 100644 doc/frontend/torch2onnx/opt/split.ipynb create mode 100755 doc/index.md create mode 100644 doc/read/dpl/PatternContext.ipynb create mode 100644 doc/read/dpl/StructInfo.ipynb create mode 100644 doc/read/dpl/backtrack.ipynb create mode 100644 doc/read/dpl/demo.py create mode 100644 doc/read/dpl/index.md create mode 100644 doc/read/dpl/iterative-rewrite.ipynb create mode 100644 doc/read/dpl/match.ipynb create mode 100644 doc/read/dpl/rewrite-without-trivial-binding.ipynb create mode 100644 doc/read/dpl/rewrite.ipynb create mode 100644 doc/read/dpl/same-shape.ipynb create mode 100755 doc/read/ffi/Makefile create mode 100644 doc/read/ffi/_init_api.ipynb create mode 100644 doc/read/ffi/datastruct.ipynb create mode 100644 doc/read/ffi/funcs.ipynb create mode 100644 doc/read/ffi/index.md create mode 100644 doc/read/ffi/libinfo.ipynb create mode 100644 doc/read/ffi/register-func.ipynb create mode 100644 doc/read/ffi/register-object.ipynb create mode 100644 doc/read/ffi/src/test_obj.cc create mode 100755 doc/read/ffi/src/tvm_ext.cc create mode 100644 doc/read/ffi/testing.py create mode 100644 doc/read/index.md create mode 100644 doc/topics/extension/Makefile create mode 100644 doc/topics/extension/NDSubClass.ipynb create mode 100644 doc/topics/extension/cpp-call.ipynb create mode 100644 doc/topics/extension/cpp/bind_add/Makefile create mode 100644 doc/topics/extension/cpp/bind_add/src/tvm_ext.cc create mode 100644 doc/topics/extension/cpp/device_api/Makefile create mode 100644 doc/topics/extension/cpp/device_api/src/tvm_ext.cc create mode 100644 doc/topics/extension/cpp/extern_func/Makefile create mode 100644 doc/topics/extension/cpp/extern_func/src/tvm_ext.cc create mode 100644 doc/topics/extension/cpp/mini_runtime/Makefile create mode 100644 doc/topics/extension/cpp/mini_runtime/src/tvm_ext.cc create mode 100644 doc/topics/extension/cpp/python_ext/Makefile create mode 100644 doc/topics/extension/cpp/python_ext/src/tvm_ext.cc create mode 100644 doc/topics/extension/cpp/python_ext/tvm_ext/__init__.py create mode 100755 doc/topics/extension/cpp/python_ext/tvm_ext/_ffi_api.py create mode 100644 doc/topics/extension/cpp/sym_add/Makefile create mode 100644 doc/topics/extension/cpp/sym_add/src/tvm_ext.cc create mode 100644 doc/topics/extension/index.md create mode 100644 doc/topics/extension/plugin-module.ipynb create mode 100644 doc/topics/extension/py-call.ipynb create mode 100644 doc/topics/extension/register/extension.ipynb create mode 100644 doc/topics/extension/register/index.md create mode 100644 doc/topics/extension/register/runtime/index.md create mode 100644 doc/topics/extension/register/runtime/measure.ipynb create mode 100644 doc/topics/extension/register/runtime/module-export.ipynb create mode 100644 doc/topics/extension/set_env.py create mode 100644 doc/topics/extension/src/plugin_module.cc create mode 100644 doc/topics/extension/src/testing/_make.cc create mode 100644 doc/topics/extension/src/testing/bind_add.cc create mode 100644 doc/topics/extension/src/testing/device_api.cc create mode 100644 doc/topics/extension/src/testing/extern_func.cc create mode 100644 doc/topics/extension/src/testing/make_node.cc create mode 100644 doc/topics/extension/src/testing/mini_runtime.cc create mode 100644 doc/topics/extension/src/testing/sym_add.cc create mode 100644 doc/topics/extension/src/tvm_ext.cc create mode 100644 doc/topics/extension/tests/tvm_ext2.cc create mode 100644 doc/topics/extension/tests/tvm_ext22.cc create mode 100644 doc/topics/extension/transform-intro.ipynb create mode 100755 doc/topics/extension/tvm_ext/testing/__init__.py create mode 100755 doc/topics/extension/tvm_ext/testing/_ffi_api.py create mode 100644 doc/topics/extension/tvm_ext/testing/demo.py create mode 100644 doc/topics/gallery/XGrammar.ipynb create mode 100644 doc/topics/gallery/index.md create mode 100644 doc/topics/gallery/mlc-llm/images/diff.png create mode 100644 doc/topics/gallery/mlc-llm/index.md create mode 100644 doc/topics/gallery/mlc-llm/intro.ipynb create mode 100644 doc/topics/gallery/mlc-llm/new-model-arch.ipynb create mode 100644 doc/topics/gallery/mlc-llm/set_env.py create mode 100644 doc/topics/gallery/set_env.py create mode 100644 doc/topics/images/bus.jpg create mode 100644 doc/topics/index.md create mode 100644 doc/topics/mlc/cc-jit-load.ipynb create mode 100644 doc/topics/mlc/index.md create mode 100644 doc/topics/mlc/mlc-python.ipynb create mode 100644 doc/topics/other/codegen/c-host.ipynb create mode 100644 doc/topics/other/codegen/extern.ipynb create mode 100644 doc/topics/other/codegen/index.md create mode 100644 doc/topics/other/codegen/static-init.ipynb create mode 100644 doc/topics/other/explorer/index.md create mode 100644 doc/topics/other/explorer/intro.ipynb create mode 100644 doc/topics/other/index.md create mode 100644 doc/topics/other/podman/index.md create mode 100644 doc/topics/other/podman/intro.ipynb create mode 100644 doc/topics/other/ultralytics/images/vehicle-jaguar-f-type-car-red-cars-wallpaper.jpg create mode 100644 doc/topics/other/ultralytics/index.md create mode 100644 doc/topics/other/ultralytics/relax-opt.ipynb create mode 100644 doc/topics/other/ultralytics/relax.ipynb create mode 100644 doc/topics/other/ultralytics/relay.ipynb create mode 100644 doc/topics/other/ultralytics/test.ipynb create mode 100644 doc/topics/other/ultralytics/test.py create mode 100644 doc/topics/other/ultralytics/utils/__init__.py create mode 100644 doc/topics/other/wsl/index.md create mode 100644 doc/topics/other/wsl/news.md create mode 100644 doc/topics/set_env.py create mode 100644 doc/tutorials/index.md create mode 100644 doc/tutorials/msc/graph/codegen.ipynb create mode 100644 doc/tutorials/msc/graph/index.md create mode 100644 doc/tutorials/msc/graph/intro.ipynb create mode 100644 doc/tutorials/msc/graph/model.py create mode 100644 doc/tutorials/msc/images/msc.jpeg create mode 100644 doc/tutorials/msc/images/pipeline.jpg create mode 100644 doc/tutorials/msc/images/runner.jpg create mode 100644 doc/tutorials/msc/images/tools.jpg create mode 100644 doc/tutorials/msc/index.md create mode 100644 doc/tutorials/msc/intro.md create mode 100644 doc/tutorials/msc/pipeline/MSCManager.ipynb create mode 100644 doc/tutorials/msc/pipeline/TorchDynamic.ipynb create mode 100644 doc/tutorials/msc/pipeline/index.md create mode 100644 doc/tutorials/msc/pipeline/intro.md create mode 100644 doc/tutorials/msc/plugin/index.md create mode 100644 doc/tutorials/msc/plugin/set_env.py create mode 100644 doc/tutorials/msc/plugin/test.ipynb create mode 100644 doc/tutorials/msc/plugin/utils.py create mode 100644 doc/tutorials/msc/runner/TVMRunner.ipynb create mode 100644 doc/tutorials/msc/runner/TensorflowRunner.ipynb create mode 100644 doc/tutorials/msc/runner/TorchRunner.ipynb create mode 100644 doc/tutorials/msc/runner/index.md create mode 100644 doc/tutorials/msc/set_env.py create mode 100644 doc/tutorials/msc/tests/index.md create mode 100644 doc/tutorials/msc/tests/transform.ipynb create mode 100644 doc/tutorials/msc/tests/translate-relax.ipynb create mode 100644 doc/tutorials/msc/tests/translate-relay.ipynb create mode 100644 doc/tutorials/msc/tests/translate-tensorflow.ipynb create mode 100644 doc/tutorials/msc/tests/translate-tensorrt.ipynb create mode 100644 doc/tutorials/msc/tests/translate-torch.ipynb create mode 100644 doc/tutorials/msc/tests/translate.ipynb create mode 100644 doc/tutorials/msc/tools/index.md create mode 100644 doc/tutorials/msc/tools/intro.md create mode 100644 doc/tutorials/msc/tools/pruner.ipynb create mode 100644 doc/tutorials/msc/tools/quantizer.ipynb create mode 100644 doc/tutorials/msc/tools/set_env.py create mode 100644 doc/tutorials/msc/tools/test.ipynb create mode 100644 doc/tutorials/msc/tools/tracker.ipynb create mode 100644 doc/tutorials/msc/tools/utils.py create mode 100644 doc/tutorials/start/IRModule.ipynb create mode 100644 doc/tutorials/start/Relax/creation.ipynb create mode 100644 doc/tutorials/start/Relax/index.md create mode 100644 doc/tutorials/start/Relax/set_env.py create mode 100644 doc/tutorials/start/Relax/transformation.ipynb create mode 100644 doc/tutorials/start/TensorIR/creation.ipynb create mode 100644 doc/tutorials/start/TensorIR/index.md create mode 100644 doc/tutorials/start/TensorIR/set_env.py create mode 100644 doc/tutorials/start/TensorIR/transformation.ipynb create mode 100644 doc/tutorials/start/customize-opt.ipynb create mode 100644 doc/tutorials/start/demo.ipynb create mode 100644 doc/tutorials/start/e2e-opt.ipynb create mode 100644 doc/tutorials/start/env.md create mode 100644 doc/tutorials/start/index.md create mode 100644 doc/tutorials/start/opt-llm.ipynb create mode 100644 doc/tutorials/start/rpc.ipynb create mode 100644 doc/tutorials/start/set_env.py create mode 100644 doc/utils/links.py create mode 100644 pyproject.toml create mode 100644 src/tvm_book/__init__.py create mode 100644 src/tvm_book/config/__init__.py create mode 100644 src/tvm_book/config/env.py create mode 100644 src/tvm_book/data/__init__.py create mode 100644 src/tvm_book/data/imagenet/__init__.py create mode 100644 src/tvm_book/data/imagenet/attrs.py create mode 100644 src/tvm_book/tvm_ext/__init__.py create mode 100644 src/tvm_book/tvm_ext/_ffi_api.py create mode 100644 src/tvm_book/tvm_ext/libinfo.py create mode 100755 tasks.py create mode 100644 tests/.gitignore create mode 100755 tests/env.py create mode 100644 tests/main.ipynb create mode 100644 tests/rpc.ipynb create mode 100644 tests/tools/__init__.py create mode 100644 tests/tools/assert_diagnostic.py create mode 100644 tests/tools/external_codegen.py create mode 100644 tests/tools/frontends.py create mode 100644 tests/tools/ref_funcs.py create mode 100755 tests/tools/set_env.py create mode 100644 tests/tools/set_pytorch.py create mode 100644 tests/tools/set_tensorflow.py create mode 100644 tests/tools/tag_span.py create mode 100644 tests/tools/torch_utils.py diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100755 index 00000000..79f8a384 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,60 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs + - name: Checkout + uses: actions/checkout@main + - name: 🐍 Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + cache: "pip" + cache-dependency-path: "pyproject.toml" + - name: 🔧 Build HTML + run: | + sudo apt-get install graphviz + pip install .[doc,dev] + pip install --pre -U -f https://mlc.ai/wheels mlc-llm-nightly-cpu mlc-ai-nightly-cpu + conda install -c conda-forge pandoc + invoke doc + - name: Setup Pages + uses: actions/configure-pages@main + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: 'doc/_build/html/' + - name: 🚀 Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@main + # uses: peaceiris/actions-gh-pages@v3.6.1 diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100755 index 00000000..ef19ce33 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,33 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package +on: + release: + types: [published] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: "3.x" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..32a26545 --- /dev/null +++ b/.gitignore @@ -0,0 +1,159 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# PDM +.pdm.toml +pdm.lock + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ +.pkl_memoize_py3/ +draft/ +*.tar +*.so +*.o + +# PDM +pdm.lock +.pdm-python + +# temp +.temp/ +temp/ +*.torchscript +*.pt +*.pth +*.onnx +*.onnxlib +*.pb +*.bak +*.dat +*.pickle +*.tar +*.npz +*.npy +doc/autoapi/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100755 index 00000000..c66d64ea --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,35 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + # You can also specify other tool versions: + # nodejs: "16" + # rust: "1.55" + # golang: "1.17" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: doc/conf.py + +# If using Sphinx, optionally build your docs in additional formats such as PDF +# Build PDF & ePub * HTML +formats: + - htmlzip + # - epub + - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - method: pip + path: . + extra_requirements: + - doc diff --git a/LICENSE b/LICENSE new file mode 100755 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100755 index 00000000..055f8459 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# TVM 手册 + +[![PyPI][pypi-badge]][pypi-link] +[![GitHub issues][issue-badge]][issue-link] +[![GitHub forks][fork-badge]][fork-link] +[![GitHub stars][star-badge]][star-link] +[![GitHub license][license-badge]][license-link] +[![contributors][contributor-badge]][contributor-link] +[![watcher][watcher-badge]][watcher-link] +[![Binder][binder-badge]][binder-link] +[![Downloads][download-badge]][download-link] +[![PyPI - Downloads][install-badge]][install-link] +![repo size](https://img.shields.io/github/repo-size/xinetzone/tvm-book.svg) +[![Downloads Week](https://pepy.tech/badge/tvm-book/week)](https://pepy.tech/project/tvm-book) +[![Documentation Status][rtd-badge]][rtd-link] + +[pypi-badge]: https://img.shields.io/pypi/v/tvm-book.svg +[pypi-link]: https://pypi.org/project/tvm-book/ +[issue-badge]: https://img.shields.io/github/issues/xinetzone/tvm-book +[issue-link]: https://github.com/xinetzone/tvm-book/issues +[fork-badge]: https://img.shields.io/github/forks/xinetzone/tvm-book +[fork-link]: https://github.com/xinetzone/tvm-book/network +[star-badge]: https://img.shields.io/github/stars/xinetzone/tvm-book +[star-link]: https://github.com/xinetzone/tvm-book/stargazers +[license-badge]: https://img.shields.io/github/license/xinetzone/tvm-book +[license-link]: https://github.com/xinetzone/tvm-book/LICENSE +[contributor-badge]: https://img.shields.io/github/contributors/xinetzone/tvm-book +[contributor-link]: https://github.com/xinetzone/tvm-book/contributors +[watcher-badge]: https://img.shields.io/github/watchers/xinetzone/tvm-book +[watcher-link]: https://github.com/xinetzone/tvm-book/watchers +[binder-badge]: https://mybinder.org/badge_logo.svg +[binder-link]: https://mybinder.org/v2/gh/xinetzone/tvm-book/main +[install-badge]: https://img.shields.io/pypi/dw/tvm-book?label=pypi%20installs +[install-link]: https://pypistats.org/packages/tvm-book +[download-badge]: https://pepy.tech/badge/tvm-book +[download-link]: https://pepy.tech/project/tvm-book +[rtd-badge]: https://readthedocs.org/projects/tvm-book/badge/?version=latest +[rtd-link]: https://tvm-book.readthedocs.io/zh-cn/latest/?badge=latest + +打造优质的 TVM 中文社区。 diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..e7dd65f2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,16 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 0.1.x | :white_check_mark: | +| < 0.0.18 | :x: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md new file mode 100755 index 00000000..b80cbda9 --- /dev/null +++ b/doc/CHANGELOG.md @@ -0,0 +1 @@ +# 变更日志 \ No newline at end of file diff --git a/doc/CODE_OF_CONDUCT.md b/doc/CODE_OF_CONDUCT.md new file mode 100755 index 00000000..824f1e16 --- /dev/null +++ b/doc/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# 行为准则 + +请参阅 [行为准则](https://daobook.github.io/.github/CODE_OF_CONDUCT.html)。 diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md new file mode 100755 index 00000000..da65da2a --- /dev/null +++ b/doc/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# 贡献 + +请参阅 [贡献指南](https://daobook.github.io/.github/CONTRIBUTING.html)。 \ No newline at end of file diff --git a/doc/_ext/gallery_directive.py b/doc/_ext/gallery_directive.py new file mode 100644 index 00000000..b34a701c --- /dev/null +++ b/doc/_ext/gallery_directive.py @@ -0,0 +1,145 @@ +"""A directive to generate a gallery of images from structured data. + +Generating a gallery of images that are all the same size is a common +pattern in documentation, and this can be cumbersome if the gallery is +generated programmatically. This directive wraps this particular use-case +in a helper-directive to generate it with a single YAML configuration file. + +It currently exists for maintainers of the pydata-sphinx-theme, +but might be abstracted into a standalone package if it proves useful. +""" + +from pathlib import Path +from typing import Any, ClassVar, Dict, List + +from docutils import nodes +from docutils.parsers.rst import directives +from sphinx.application import Sphinx +from sphinx.util import logging +from sphinx.util.docutils import SphinxDirective +from yaml import safe_load + + +logger = logging.getLogger(__name__) + + +TEMPLATE_GRID = """ +`````{{grid}} {columns} +{options} + +{content} + +````` +""" + +GRID_CARD = """ +````{{grid-item-card}} {title} +{options} + +{content} +```` +""" + + +class GalleryGridDirective(SphinxDirective): + """A directive to show a gallery of images and links in a Bootstrap grid. + + The grid can be generated from a YAML file that contains a list of items, or + from the content of the directive (also formatted in YAML). Use the parameter + "class-card" to add an additional CSS class to all cards. When specifying the grid + items, you can use all parameters from "grid-item-card" directive to customize + individual cards + ["image", "header", "content", "title"]. + + Danger: + This directive can only be used in the context of a Myst documentation page as + the templates use Markdown flavored formatting. + """ + + name = "gallery-grid" + has_content = True + required_arguments = 0 + optional_arguments = 1 + final_argument_whitespace = True + option_spec: ClassVar[dict[str, Any]] = { + # A class to be added to the resulting container + "grid-columns": directives.unchanged, + "class-container": directives.unchanged, + "class-card": directives.unchanged, + } + + def run(self) -> List[nodes.Node]: + """Create the gallery grid.""" + if self.arguments: + # If an argument is given, assume it's a path to a YAML file + # Parse it and load it into the directive content + path_data_rel = Path(self.arguments[0]) + path_doc, _ = self.get_source_info() + path_doc = Path(path_doc).parent + path_data = (path_doc / path_data_rel).resolve() + if not path_data.exists(): + logger.info("Could not find grid data at %s.", path_data) + nodes.text("No grid data found at {path_data}.") + return + yaml_string = path_data.read_text() + else: + yaml_string = "\n".join(self.content) + + # Use all the element with an img-bottom key as sites to show + # and generate a card item for each of them + grid_items = [] + for item in safe_load(yaml_string): + # remove parameters that are not needed for the card options + title = item.pop("title", "") + + # build the content of the card using some extra parameters + header = f"{item.pop('header')} \n^^^ \n" if "header" in item else "" + image = f"![image]({item.pop('image')}) \n" if "image" in item else "" + content = f"{item.pop('content')} \n" if "content" in item else "" + + # optional parameter that influence all cards + if "class-card" in self.options: + item["class-card"] = self.options["class-card"] + + loc_options_str = "\n".join(f":{k}: {v}" for k, v in item.items()) + " \n" + + card = GRID_CARD.format( + options=loc_options_str, content=header + image + content, title=title + ) + grid_items.append(card) + + # Parse the template with Sphinx Design to create an output container + # Prep the options for the template grid + class_ = "gallery-directive" + f' {self.options.get("class-container", "")}' + options = {"gutter": 2, "class-container": class_} + options_str = "\n".join(f":{k}: {v}" for k, v in options.items()) + + # Create the directive string for the grid + grid_directive = TEMPLATE_GRID.format( + columns=self.options.get("grid-columns", "1 2 3 4"), + options=options_str, + content="\n".join(grid_items), + ) + + # Parse content as a directive so Sphinx Design processes it + container = nodes.container() + self.state.nested_parse([grid_directive], 0, container) + + # Sphinx Design outputs a container too, so just use that + return [container.children[0]] + + +def setup(app: Sphinx) -> Dict[str, Any]: + """Add custom configuration to sphinx app. + + Args: + app: the Sphinx application + + Returns: + the 2 parallel parameters set to ``True``. + """ + app.add_directive("gallery-grid", GalleryGridDirective) + + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/_ext/rtd_version.py b/doc/_ext/rtd_version.py new file mode 100644 index 00000000..b8dc28be --- /dev/null +++ b/doc/_ext/rtd_version.py @@ -0,0 +1,49 @@ +import os +from sphinx.application import Sphinx +from sphinx.util.typing import ExtensionMetadata + +def setup(app: Sphinx) -> ExtensionMetadata: + # Define the json_url for our version switcher. + json_url = f"https://{app.config.project}.readthedocs.io/zh-cn/latest/_static/switcher.json" + # Define the version we use for matching in the version switcher. + version_match = os.environ.get("READTHEDOCS_VERSION") + # If READTHEDOCS_VERSION doesn't exist, we're not on RTD + # If it is an integer, we're in a PR build and the version isn't correct. + # If it's "latest" → change to "dev" (that's what we want the switcher to call it) + if not version_match or version_match.isdigit() or version_match == "latest": + # For local development, infer the version to match from the package. + if "dev" in app.config.release or "rc" in app.config.release: + version_match = "dev" + # We want to keep the relative reference if we are in dev mode + # but we want the whole url if we are effectively in a released version + json_url = "_static/switcher.json" + else: + version_match = f"v{app.config.release}" + elif version_match == "stable": + version_match = f"v{app.config.release}" + app.config["html_theme_options"].update({"switcher": { + "json_url": json_url, + "version_match": version_match, + },}) + # -- To demonstrate ReadTheDocs switcher ------------------------------------- + # This links a few JS and CSS files that mimic the environment that RTD uses + # so that we can test RTD-like behavior. We don't need to run it on RTD and we + # don't wanted it loaded in GitHub Actions because it messes up the lighthouse + # results. + if not os.environ.get("READTHEDOCS") and not os.environ.get("GITHUB_ACTIONS"): + app.add_css_file( + "https://assets.readthedocs.org/static/css/readthedocs-doc-embed.css" + ) + app.add_css_file("https://assets.readthedocs.org/static/css/badge_only.css") + + # Create the dummy data file so we can link it + # ref: https://github.com/readthedocs/readthedocs.org/blob/bc3e147770e5740314a8e8c33fec5d111c850498/readthedocs/core/static-src/core/js/doc-embed/footer.js # noqa: E501 + app.add_js_file("rtd-data.js") + app.add_js_file( + "https://assets.readthedocs.org/static/javascript/readthedocs-doc-embed.js", + priority=501, + ) + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/doc/_static/css/custom.css b/doc/_static/css/custom.css new file mode 100644 index 00000000..46abbbd2 --- /dev/null +++ b/doc/_static/css/custom.css @@ -0,0 +1,24 @@ +/* Background of stsable should be green */ +#version_switcher a[data-version-name*="stable"] { + background-color: #e2ffe2; +} + +/* Color of explicit versions should be orange */ +#version_switcher + a:not([data-version-name*="stable"]):not([data-version-name="dev"]) { + background-color: #d9dadc; + color: rgb(243, 234, 234); +} + +/* If we're on a dev version, make the switcher button orange */ +#version_switcher_button[data-active-version-name*="dev"] { + background-color: rgb(255 138 62); +} + +.bd-sidebar-primary, .bd-sidebar-secondary { + background-color: #e4e7eb; +} + +.sphinx-contributors img { + border-radius: 50%; +} diff --git a/doc/_static/css/tippy.css b/doc/_static/css/tippy.css new file mode 100644 index 00000000..518bd77d --- /dev/null +++ b/doc/_static/css/tippy.css @@ -0,0 +1,5 @@ +.tippy-box { + background-color:var(--pst-color-surface); + color:var(--pst-color-text-base); + border: 1px solid var(--pst-color-border); +} \ No newline at end of file diff --git a/doc/_static/images/favicon.jpg b/doc/_static/images/favicon.jpg new file mode 100755 index 0000000000000000000000000000000000000000..ede82f2624f43bb20fe98c62666238947d34e739 GIT binary patch literal 6901 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 literal 0 HcmV?d00001 diff --git a/doc/_static/images/logo.jpg b/doc/_static/images/logo.jpg new file mode 100755 index 0000000000000000000000000000000000000000..c32993fc702b86124b0a977aca88657c6eb578d2 GIT binary patch literal 25906 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 JD&g<^{{x + This is a community-supported theme. + If you'd like to contribute, + check out our GitHub repository + Your contributions are welcome! + diff --git a/doc/_templates/navbar-version.html b/doc/_templates/navbar-version.html new file mode 100755 index 00000000..b23c1ca1 --- /dev/null +++ b/doc/_templates/navbar-version.html @@ -0,0 +1,2 @@ + +TEST: v{{ version }} diff --git a/doc/_templates/theme-switcher.html b/doc/_templates/theme-switcher.html new file mode 100755 index 00000000..8d7be422 --- /dev/null +++ b/doc/_templates/theme-switcher.html @@ -0,0 +1,5 @@ + + + + + diff --git a/doc/about/index.md b/doc/about/index.md new file mode 100755 index 00000000..72f6e0ff --- /dev/null +++ b/doc/about/index.md @@ -0,0 +1,9 @@ +# 关于 + +```{toctree} + +zreferences +../CODE_OF_CONDUCT +../CONTRIBUTING +../CHANGELOG +``` diff --git a/doc/about/zreferences.md b/doc/about/zreferences.md new file mode 100755 index 00000000..59e82ef4 --- /dev/null +++ b/doc/about/zreferences.md @@ -0,0 +1,14 @@ +# 参考文献 + + +```{rubric} 核心文献 +``` + +```{bibliography} ../_static/references/book.bib +``` + +```{rubric} 其他文献 +``` + +```{bibliography} ../_static/references/articles.bib +``` diff --git a/doc/conf.py b/doc/conf.py new file mode 100755 index 00000000..aaaa10d7 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,245 @@ +import os +# === Path setup ===================================================================================== +import sys +if sys.platform == 'win32': + import asyncio + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) +from pathlib import Path +ROOT = Path(__file__).resolve().parents[1] +sys.path.extend([str(ROOT/'doc')]) +from utils.links import icon_links + +# == Project 信息 ===================================================================================== +project = 'tvm-book' # 项目名称 +author = 'xinetzone' # 文档的作者 +copyright = '2022, xinetzone' # 版权信息 + +# == 国际化输出 ======================================================================================= +language = 'zh_CN' +locale_dirs = ['../locales/'] # 翻译文件的路径 +gettext_compact = False # 为每个翻译创建单独的 .po 文件。 + +# 通用配置 +# ===================================================================================================== +# 表示 Sphinx 扩展的模块名称的字符串列表。它们可以是 +# Sphinx 自带的插件(命名为 'sphinx.ext.*')或您自定义的插件。 +# ------------------------------------------------------------------------------------- +extensions = [ + "myst_nb", + "sphinx_design", + "sphinx.ext.viewcode", # 添加到高亮源代码的链接 + "sphinx.ext.extlinks", # 缩短外部链接 + "sphinx.ext.intersphinx", # 链接到其他文档 + 'sphinx_copybutton', # 为代码块添加复制按钮。 + "sphinx_comments", # 为 Sphinx 文档添加评论和注释功能。 + "sphinx.ext.napoleon", # 支持 Google 和 Numpy 风格的文档字符串 + "_ext.gallery_directive", # 自定义画廊指令 +] + +# 在此添加包含模板的任何路径,相对于此目录。 +# ------------------------------------------------------------------------------------- +templates_path = ['_templates'] +# 相对于源目录的模式列表,用于匹配在查找源文件时要忽略的文件和目录。 +# 此模式还会影响 html_static_path 和 html_extra_path。 +# ------------------------------------------------------------------------------------- +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +# 链接到其他项目的文档 +# ------------------------------------------------------------------------------------- +intersphinx_mapping = { + "python": ("https://docs.python.org/3.12", None), + "sphinx": ("https://daobook.github.io/sphinx/", None), + "tvm": ("https://xinetzone.github.io/tvm/", None), + "torch": ("https://pytorch.org/docs/stable/", None), +} +# 缩短外部链接 +# ------------------------------------------------------------------------------------- +extlinks = { + 'daobook': ('https://daobook.github.io/%s', 'Daobook %s'), + 'xinetzone': ('https://xinetzone.github.io/%s', 'xinetzone %s'), +} +# == 配置复制按钮 ==================================================================================== +# 使用 ``:not()`` 排除复制按钮出现在笔记本单元格编号上 +# 默认的 copybutton 选择器是 `div.highlight pre` +copybutton_exclude = '.linenos, .gp' # 跳过 Pygments 生成的所有提示符 +copybutton_selector = ":not(.prompt) > div.highlight pre" + +# == HTML 输出 ======================================================================================= +# 用于 HTML 和 HTML Help 页面的主题 +# ------------------------------------------------------------------------------------- +html_theme = 'xyzstyle' # 使用的主题名称 +html_logo = "_static/images/logo.jpg" +html_title = "TVM 开发指南" +html_copy_source = True +html_favicon = "_static/images/favicon.jpg" +html_last_updated_fmt = '%Y-%m-%d, %H:%M:%S' # 文档的最后更新时间格式 +# 在此添加包含自定义静态文件(如样式表)的任何路径,相对于此目录。 +# 它们会在内置静态文件之后被复制,因此名为 "default.css" 的文件将覆盖内置的 "default.css"。 +html_static_path = ['_static'] +html_css_files = ["css/custom.css", "css/tippy.css"] + +# == 主题选项 ======================================================================================== +# 选项字典,影响所选主题的外观和感觉。这些选项是特定于主题的。 +# ------------------------------------------------------------------------------------- +html_theme_options = { + # "navigation_depth": 5, # 控制导航层级的数量 + "use_sidenotes": True, # 启用侧边注释/页边注释。 + "repository_url": f"https://github.com/xinetzone/{project}", + "use_repository_button": True, # 显示“在 GitHub 上查看”按钮。 + "announcement": "👋欢迎进入编程视界!👋", # 公告横幅 + "use_source_button": True, # 显示“查看源代码”按钮。 + "use_edit_page_button": True, # 显示“编辑此页”按钮。 + "use_issues_button": True, # 显示“报告问题”按钮。 + # 图标链接是一组图像和图标,每个图标都链接到一个页面或外部网站。 + # 如果你希望展示社交媒体图标、GitHub 徽章或项目标志,它们会很有帮助。 + "icon_links": icon_links, +} + +# 为您的Sphinx网站添加评论和注释功能 +# ------------------------------------------------------------------------------------- +comments_config = { + "hypothesis": True, + # "dokieli": True, + "utterances": { + "repo": f"xinetzone/{project}", + "optional": "config", + } +} + +# 展示丰富的悬停提示 +# ------------------------------------------------------------------------------------- +extensions.append("sphinx_tippy") +# tippy_enable_mathjax = True +# tippy_anchor_parent_selector = "div.content" +# tippy_logo_svg = Path("tippy-logo.svg").read_text("utf8") +# tippy_custom_tips = { +# "https://example.com": "

This is a custom tip for example.com

", +# "https://atomiks.github.io/tippyjs": ( +# f"{tippy_logo_svg}

Using Tippy.js, the complete tooltip, popover, dropdown, " +# "and menu solution for the web, powered by Popper.

" +# ), +# } +tippy_rtd_urls = [ + "https://docs.readthedocs.io/en/stable/", + "https://www.sphinx-doc.org/zh-cn/master/", +] + +# ===================== 可选 ========================================================== +# 用户可以使用 BibTeX 格式的参考文献数据库,并在文档中插入引用和生成参考文献列表。 +# ------------------------------------------------------------------------------------- +extensions.append('sphinxcontrib.bibtex') +bibtex_bibfiles = ['_static/references/book.bib', "_static/references/articles.bib"] +# 自动生成 API 文档的路径 +# ------------------------------------------------------------------------------------- +extensions.append("autoapi.extension") +autoapi_dirs = [f"../src/{project.replace('-', "_")}"] +# 在文档中嵌入 Graphviz 图 +# ------------------------------------------------------------------------------------- +extensions.append("sphinx.ext.graphviz") +graphviz_output_format = "svg" +inheritance_graph_attrs = dict( + rankdir="LR", + fontsize=14, + ratio="compress", +) +# 在 Sphinx 文档页面中渲染指定 GitHub 仓库的贡献者列表 +# ------------------------------------------------------------------------------------- +extensions.append('sphinx_contributors') +# 配置用于交互的启动按钮 +# ------------------------------------------------------------------------------------- +# 这些按钮将在页面底部显示,可用于启动笔记本或演示。 +extensions.append("sphinx_thebe") +html_theme_options.update({ + "repository_branch": "main", + "path_to_docs": "doc", + "launch_buttons": { + "binderhub_url": "https://mybinder.org", + "colab_url": "https://colab.research.google.com/", + "deepnote_url": "https://deepnote.com/", + "notebook_interface": "jupyterlab", + "thebe": True, + # "jupyterhub_url": "https://datahub.berkeley.edu", # For testing + }, +}) +thebe_config = { + "repository_url": f"https://github.com/xinetzone/{project}", + "repository_branch": "main", + "selector": "div.highlight", + # "selector": ".thebe", + # "selector_input": "", + # "selector_output": "", + # "codemirror-theme": "blackboard", # Doesn't currently work + # "always_load": True, # To load thebe on every page +} +# 为 Sphinx 文档添加 Open Graph 元数据。 +# ------------------------------------------------------------------------------------- +extensions.append("sphinxext.opengraph") +ogp_site_url = f"https://{project}.readthedocs.io/zh-cn/latest/" +ogp_social_cards = { + "site_url": f"{project}lib.readthedocs.io", # 请将此替换为您的站点 URL + "image": "_static/images/logo.jpg", # 请确保您的图片是 PNG 或 JPEG 图片,而不是 SVG + "font": "Noto Sans CJK JP", # 支持中文字体 + "line_colors": "#4078c0", +} +# 用于生成多版本和多语言的 sitemaps.org 兼容的站点地图 +# ------------------------------------------------------------------------------------- +extensions.append("sphinx_sitemap") +sitemap_url_scheme = "{lang}{version}{link}" +if not os.environ.get("READTHEDOCS"): + html_baseurl = os.environ.get("SITEMAP_URL_BASE", "http://127.0.0.1:8000/") + sitemap_url_scheme = "{link}" +elif os.environ.get("GITHUB_ACTIONS"): + html_baseurl = os.environ.get("SITEMAP_URL_BASE", "https://xinetzone.github.io/") +sitemap_locales = [None] # 语言列表 + +# 其他配置 +# ------------------------------------------------------------------------------------- +nitpick_ignore = [ + ("py:class", "docutils.nodes.document"), + ("py:class", "docutils.parsers.rst.directives.body.Sidebar"), +] +# application/vnd.plotly.v1+json and application/vnd.bokehjs_load.v0+json +# unknown_mime_type - application/vnd.plotly.v1+json and application/vnd.bokehjs_load.v0+json +# domains - sphinx_proof.domain::prf needs to have `resolve_any_xref` method +# mime_priority - latex priority not set in myst_nb for text/html, application/javascript +suppress_warnings = [ + "mystnb.unknown_mime_type", "mystnb.mime_priority", # 禁用 application/vnd.plotly.v1+json and application/vnd.bokehjs_load.v0+json 警告 + "myst.xref_missing", "myst.domains", # 禁用 myst 警告 + "ref.ref", + "autoapi.python_import_resolution", "autoapi.not_readable" # 禁用 autoapi 警告 +] +numfig = True + +myst_enable_extensions = [ + "dollarmath", + "amsmath", + "deflist", + # "html_admonition", + # "html_image", + "colon_fence", + # "smartquotes", + "replacements", + # "linkify", + "substitution", +] + +# 添加版本切换器下拉菜单 +extensions.append("_ext.rtd_version") +html_theme_options['primary_sidebar_end'] = ["version-switcher",] +# 定制侧边栏 +html_sidebars = { + "reference/blog/*": [ + "navbar-logo.html", + "search-field.html", + "ablog/postcard.html", + "ablog/recentposts.html", + "ablog/tagcloud.html", + "ablog/categories.html", + "ablog/archives.html", + "sbt-sidebar-nav.html", + ] +} + +# 排除笔记本不执行 +nb_execution_excludepatterns = ["test/"] +nb_execution_mode = "off" # "off", "cache" +extensions.append("sphinxcontrib.icon") diff --git a/doc/frontend/caffe/index.md b/doc/frontend/caffe/index.md new file mode 100644 index 00000000..efeb1801 --- /dev/null +++ b/doc/frontend/caffe/index.md @@ -0,0 +1,6 @@ +# Caffe + +```{toctree} +ops +network +``` \ No newline at end of file diff --git a/doc/frontend/caffe/network.ipynb b/doc/frontend/caffe/network.ipynb new file mode 100644 index 00000000..d871fd83 --- /dev/null +++ b/doc/frontend/caffe/network.ipynb @@ -0,0 +1,213 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# caffe 网络" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%cd ../..\n", + "import set_env\n", + "from caffe_utils import _test_network" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from tvm.contrib.download import download_testdata\n", + "from caffe import params as P" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Mobilenetv2" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_mobilenetv2(data):\n", + " \"\"\"One iteration of Mobilenetv2\"\"\"\n", + " mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)\n", + " mean_val = np.reshape(mean_val, (1, 3, 1, 1))\n", + " mean_val = np.tile(mean_val, (1, 1, 224, 224))\n", + " data_process = data - mean_val\n", + " data_process = data_process / 58.8\n", + " data_process = data_process.astype(np.float32)\n", + "\n", + " proto_file_url = (\n", + " \"https://github.com/shicai/MobileNet-Caffe/raw/master/mobilenet_v2_deploy.prototxt\"\n", + " )\n", + " blob_file_url = (\n", + " \"https://github.com/shicai/MobileNet-Caffe/blob/master/mobilenet_v2.caffemodel?raw=true\"\n", + " )\n", + " proto_file = download_testdata(proto_file_url, \"mobilenetv2.prototxt\", module=\"model\")\n", + " blob_file = download_testdata(blob_file_url, \"mobilenetv2.caffemodel\", module=\"model\")\n", + " _test_network(data_process, proto_file, blob_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "data = np.random.randint(0, 256, size=(1, 3, 224, 224)).astype(np.float32)\n", + "_test_mobilenetv2(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Alexnet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pytest\n", + "def _test_alexnet(data):\n", + " \"\"\"One iteration of Alexnet\"\"\"\n", + " mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)\n", + " mean_val = np.reshape(mean_val, (1, 3, 1, 1))\n", + " mean_val = np.tile(mean_val, (1, 1, 227, 227))\n", + " data_process = data - mean_val\n", + " data_process = data_process.astype(np.float32)\n", + "\n", + " proto_file_url = (\n", + " \"https://github.com/BVLC/caffe/raw/master/models/\" + \"bvlc_alexnet/deploy.prototxt\"\n", + " )\n", + " blob_file_url = \"http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel\"\n", + " proto_file = download_testdata(proto_file_url, \"alexnet.prototxt\", module=\"model\")\n", + " blob_file = download_testdata(blob_file_url, \"alexnet.caffemodel\", module=\"model\")\n", + " _test_network(data_process, proto_file, blob_file)\n", + "\n", + "\n", + "@pytest.mark.skip(reason=\"See https://github.com/apache/tvm/issues/13227\")\n", + "def test_forward_Alexnet():\n", + " \"\"\"Alexnet\"\"\"\n", + " data = np.random.randint(0, 256, size=(1, 3, 227, 227)).astype(np.float32)\n", + " _test_alexnet(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Resnet50" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_resnet50(data):\n", + " \"\"\"One iteration of Resnet50\"\"\"\n", + " mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)\n", + " mean_val = np.reshape(mean_val, (1, 3, 1, 1))\n", + " mean_val = np.tile(mean_val, (1, 1, 224, 224))\n", + " data_process = data - mean_val\n", + " data_process = data_process.astype(np.float32)\n", + "\n", + " proto_file_url = (\n", + " \"https://github.com/fernchen/CaffeModels/raw/master/resnet/ResNet-50-deploy.prototxt\"\n", + " )\n", + " blob_file_url = (\n", + " \"https://github.com/fernchen/CaffeModels/raw/master/resnet/ResNet-50-model.caffemodel\"\n", + " )\n", + "\n", + " proto_file = download_testdata(proto_file_url, \"resnet50.prototxt\", module=\"model\")\n", + " blob_file = download_testdata(blob_file_url, \"resnet50.caffemodel\", module=\"model\")\n", + "\n", + " _test_network(data_process, proto_file, blob_file)\n", + "\n", + "\n", + "def test_forward_Resnet50():\n", + " \"\"\"Resnet50\"\"\"\n", + " data = np.random.randint(0, 256, size=(1, 3, 224, 224)).astype(np.float32)\n", + " _test_resnet50(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Inceptionv4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_inceptionv1(data):\n", + " \"\"\"One iteration of Inceptionv4\"\"\"\n", + " mean_val = np.array([103.939, 116.779, 123.68], dtype=np.float32)\n", + " mean_val = np.reshape(mean_val, (1, 3, 1, 1))\n", + " mean_val = np.tile(mean_val, (1, 1, 224, 224))\n", + " data_process = data - mean_val\n", + " data_process = data_process / 58.8\n", + " data_process = data_process.astype(np.float32)\n", + "\n", + " proto_file_url = (\n", + " \"https://github.com/BVLC/caffe/raw/master/models\" + \"/bvlc_googlenet/deploy.prototxt\"\n", + " )\n", + " blob_file_url = \"http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel\"\n", + " proto_file = download_testdata(proto_file_url, \"inceptionv1.prototxt\", module=\"model\")\n", + " blob_file = download_testdata(blob_file_url, \"inceptionv1.caffemodel\", module=\"model\")\n", + " _test_network(data_process, proto_file, blob_file)\n", + "\n", + "\n", + "@pytest.mark.skip(reason=\"See issue https://github.com/apache/tvm/issues/13227\")\n", + "def test_forward_Inceptionv1():\n", + " \"\"\"Inceptionv4\"\"\"\n", + " data = np.random.randint(0, 256, size=(1, 3, 224, 224)).astype(np.float32)\n", + " _test_inceptionv1(data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xxx", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/caffe/ops.ipynb b/doc/frontend/caffe/ops.ipynb new file mode 100644 index 00000000..c3cd4524 --- /dev/null +++ b/doc/frontend/caffe/ops.ipynb @@ -0,0 +1,3694 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Caffe 算子测试" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/media/pc/data/lxw/ai/tvm-book/doc/topics\n" + ] + } + ], + "source": [ + "%cd ../..\n", + "import set_env" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import logging\n", + "import numpy as np\n", + "\n", + "from google.protobuf import text_format\n", + "import caffe\n", + "from caffe import layers as L, params as P\n", + "from caffe.proto import caffe_pb2 as pb\n", + "\n", + "import tvm\n", + "import tvm.testing\n", + "from tvm import relay\n", + "from tvm.contrib import graph_executor\n", + "from tvm.contrib.download import download_testdata\n", + "os.environ[\"GLOG_minloglevel\"] = \"2\"\n", + "\n", + "logging.basicConfig(level=logging.ERROR)\n", + "\n", + "def save_prototxt(n_netspec, f_path):\n", + " \"\"\"Generate .prototxt file according to caffe.NetSpec\"\"\"\n", + " s = n_netspec.to_proto()\n", + " with open(f_path, \"w\") as f:\n", + " f.write(str(s))\n", + "\n", + "\n", + "def save_solver(solver_file, proto_file, blob_file):\n", + " \"\"\"Define a solver proto, you can change the configs.\"\"\"\n", + " blob_file_prefix = blob_file.split(\".caffemodel\")[0]\n", + " s = pb.SolverParameter()\n", + " s.train_net = proto_file\n", + " s.base_lr = 0.01\n", + " s.momentum = 0.9\n", + " s.weight_decay = 0.0005\n", + " s.lr_policy = \"inv\"\n", + " s.gamma = 0.0001\n", + " s.power = 0.75\n", + " s.display = 1\n", + " s.max_iter = 100000\n", + " s.snapshot = 100000\n", + " s.snapshot_prefix = blob_file_prefix\n", + "\n", + " with open(solver_file, \"w\") as f:\n", + " f.write(str(s))\n", + "\n", + "\n", + "def save_caffemodel(solver_file, blob_file):\n", + " \"\"\"Generate .caffemodel file.\"\"\"\n", + " solver = caffe.SGDSolver(solver_file)\n", + " solver.net.save(blob_file)\n", + "\n", + "def gen_model_files(n_netspec, proto_file, blob_file, solver_file):\n", + " save_prototxt(n_netspec, proto_file)\n", + " save_solver(solver_file, proto_file, blob_file)\n", + " save_caffemodel(solver_file, blob_file)\n", + "\n", + "def run_caffe(data, proto_file, blob_file):\n", + " \"\"\"Run caffe model by Caffe according to .caffemodel and .prototxt\"\"\"\n", + " net = caffe.Net(proto_file, blob_file, caffe.TEST)\n", + " if isinstance(data, (list, tuple)):\n", + " for idx, d in enumerate(data):\n", + " net.blobs[\"data\" + str(idx)].data[...] = d\n", + " else:\n", + " net.blobs[\"data\"].data[...] = data\n", + " out = net.forward()\n", + "\n", + " caffe_output = []\n", + " for i in range(len(out.keys())):\n", + " if \"output\" + str(i) not in out.keys():\n", + " caffe_output.clear()\n", + " return list(out.values())\n", + " caffe_output.append(out[\"output\" + str(i)])\n", + " return caffe_output" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def siso_op(shape, func, *args, **kwargs):\n", + " \"\"\"Create single input and single output Caffe op\"\"\"\n", + " n = caffe.NetSpec()\n", + " n.data = L.Input(input_param={\"shape\": {\"dim\": list(shape)}})\n", + " n.output = func(n.data, *args, **kwargs)\n", + " return n\n", + "\n", + "def miso_op(shapes, func, *args, **kwargs):\n", + " \"\"\"Create multi input and single output Caffe op\"\"\"\n", + " n = caffe.NetSpec()\n", + " if not isinstance(shapes, (tuple, list)):\n", + " raise TypeError(f\"Need tuple or list but get {type(shapes)}\")\n", + " input_list = []\n", + " for idx, shape in enumerate(shapes):\n", + " n[\"data\" + str(idx)] = L.Input(input_param={\"shape\": {\"dim\": list(shape)}})\n", + " input_list.append(n[\"data\" + str(idx)])\n", + " n.output = func(*input_list, *args, **kwargs)\n", + " return n\n", + "\n", + "\n", + "def simo_op(shape, func, *args, **kwargs):\n", + " \"\"\"Create single input and multi output Caffe op\"\"\"\n", + " n = caffe.NetSpec()\n", + " n.data = L.Input(input_param={\"shape\": {\"dim\": list(shape)}})\n", + " output_list = func(n.data, *args, **kwargs)\n", + " for idx, out in enumerate(output_list):\n", + " n[\"output\" + str(idx)] = out\n", + " return n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def creat_op(shapes, func_op, **kwargs):\n", + " shape_list = []\n", + " if isinstance(shapes, (list, tuple)):\n", + " n = miso_op(shapes, func_op, **kwargs)\n", + " for shape in shapes:\n", + " shape_list.extend(list(shape))\n", + " else:\n", + " output_num = 1\n", + " if \"ntop\" in kwargs:\n", + " output_num = kwargs[\"ntop\"]\n", + " if output_num == 1:\n", + " n = siso_op(shapes, func_op, **kwargs)\n", + " else:\n", + " n = simo_op(shapes, func_op, **kwargs)\n", + " shape_list = list(shapes)\n", + " return n, shape_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe BatchNorm" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: Logging before InitGoogleLogging() is written to STDERR\n", + "I0914 09:12:10.797545 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/BatchNorm.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/BatchNorm\"\n", + "I0914 09:12:10.797695 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/BatchNorm.prototxt\n", + "I0914 09:12:10.798242 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data\"\n", + " type: \"Input\"\n", + " top: \"data\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"BatchNorm\"\n", + " bottom: \"data\"\n", + " top: \"output\"\n", + " batch_norm_param {\n", + " moving_average_fraction: 0.999\n", + " eps: 1e-05\n", + " }\n", + "}\n", + "I0914 09:12:10.798317 1956768 layer_factory.hpp:77] Creating layer data\n", + "I0914 09:12:10.798336 1956768 net.cpp:86] Creating Layer data\n", + "I0914 09:12:10.798341 1956768 net.cpp:382] data -> data\n", + "I0914 09:12:10.798357 1956768 net.cpp:124] Setting up data\n", + "I0914 09:12:10.798362 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:10.798367 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:10.798370 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:10.798384 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:10.798388 1956768 net.cpp:408] output <- data\n", + "I0914 09:12:10.798391 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:10.798404 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:10.798408 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:10.798411 1956768 net.cpp:139] Memory required for data: 2400\n", + "I0914 09:12:10.798420 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:10.798424 1956768 net.cpp:202] data does not need backward computation.\n", + "I0914 09:12:10.798426 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:10.798430 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:10.798439 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:10.799118 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:10.799129 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:10.799131 1956768 _caffe.cpp:142] Net('./.temp/BatchNorm.prototxt', 1, weights='./.temp/BatchNorm.caffemodel')\n", + "I0914 09:12:10.799191 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data\"\n", + " type: \"Input\"\n", + " top: \"data\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"BatchNorm\"\n", + " bottom: \"data\"\n", + " top: \"output\"\n", + " batch_norm_param {\n", + " moving_average_fraction: 0.999\n", + " eps: 1e-05\n", + " }\n", + "}\n", + "I0914 09:12:10.799225 1956768 layer_factory.hpp:77] Creating layer data\n", + "I0914 09:12:10.799233 1956768 net.cpp:86] Creating Layer data\n", + "I0914 09:12:10.799237 1956768 net.cpp:382] data -> data\n", + "I0914 09:12:10.799245 1956768 net.cpp:124] Setting up data\n", + "I0914 09:12:10.799249 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:10.799254 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:10.799257 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:10.799263 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:10.799266 1956768 net.cpp:408] output <- data\n", + "I0914 09:12:10.799270 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:10.799283 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:10.799285 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:10.799289 1956768 net.cpp:139] Memory required for data: 2400\n", + "I0914 09:12:10.799297 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:10.799301 1956768 net.cpp:202] data does not need backward computation.\n", + "I0914 09:12:10.799304 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:10.799309 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:10.800050 1956768 upgrade_proto.cpp:79] Attempting to upgrade batch norm layers using deprecated params: ./.temp/BatchNorm.caffemodel\n", + "I0914 09:12:10.800057 1956768 upgrade_proto.cpp:82] Successfully upgraded batch norm layers using deprecated params.\n" + ] + } + ], + "source": [ + "op_name = \"BatchNorm\"\n", + "root_dir = \"./.temp\"\n", + "proto_file = f\"{root_dir}/{op_name}.prototxt\"\n", + "blob_file = f\"{root_dir}/{op_name}.caffemodel\"\n", + "solver_file = f\"{root_dir}/{op_name}_solver.prototxt\"\n", + "shape = (1, 3, 10, 10)\n", + "n_netspec = siso_op(shape, L.BatchNorm, moving_average_fraction=0.999, eps=1e-5)\n", + "# obtain the .caffemodel file and .prototxt file\n", + "gen_model_files(n_netspec, proto_file, blob_file, solver_file)\n", + "# run model in Caffe\n", + "data = np.random.rand(*shape).astype(np.float32)\n", + "caffe_out = run_caffe(data, proto_file, blob_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data: Tensor[(1, 3, 10, 10), float32] /* ty=Tensor[(1, 3, 10, 10), float32] */) -> Tensor[(1, 3, 10, 10), float32] {\n",
+       "  %0 = multiply(%data, meta[relay.Constant][0] /* ty=Tensor[(3, 1, 1), float32] */) /* ty=Tensor[(1, 3, 10, 10), float32] */;\n",
+       "  add(%0, meta[relay.Constant][1] /* ty=Tensor[(3, 1, 1), float32] */) /* ty=Tensor[(1, 3, 10, 10), float32] */\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "init_net = pb.NetParameter()\n", + "predict_net = pb.NetParameter()\n", + "# load model\n", + "with open(proto_file, \"r\") as f:\n", + " text_format.Merge(f.read(), predict_net)\n", + "# load blob\n", + "with open(blob_file, \"rb\") as f:\n", + " init_net.ParseFromString(f.read())\n", + "shape_dict = {\"data\": shape}\n", + "dtype_dict = {\"data\": \"float32\"}\n", + "mod, params = relay.frontend.from_caffe(init_net, predict_net, shape_dict, dtype_dict)\n", + "with tvm.transform.PassContext(opt_level=3):\n", + " mod = relay.quantize.prerequisite_optimize(mod, params)\n", + "mod.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe concat" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.5722476838666538,\n", + " array([[[[0.61123624, 0.37588209, 0.02169732, 0.18100491, 0.95849767,\n", + " 0.02395107, 0.20080887, 0.33766822, 0.11885211, 0.86539518],\n", + " [0.10359814, 0.3886911 , 0.65470521, 0.05712175, 0.71074179,\n", + " 0.42249166, 0.37142238, 0.65421255, 0.99183236, 0.9922702 ],\n", + " [0.11899492, 0.46457062, 0.89906396, 0.33470963, 0.48111082,\n", + " 0.86251228, 0.52144183, 0.91341972, 0.77010121, 0.49809878],\n", + " [0.89288594, 0.59797711, 0.41111909, 0.37215822, 0.82308275,\n", + " 0.43773541, 0.48900654, 0.09655104, 0.6752475 , 0.73714895],\n", + " [0.94505647, 0.751491 , 0.79973422, 0.49016049, 0.98444054,\n", + " 0.74379714, 0.10746913, 0.25731962, 0.25730886, 0.74203572],\n", + " [0.31960305, 0.73112817, 0.87677291, 0.15800022, 0.80400933,\n", + " 0.44788138, 0.9895867 , 0.42715959, 0.71428694, 0.16113941],\n", + " [0.1914514 , 0.75825183, 0.50116843, 0.65810231, 0.75718552,\n", + " 0.53124754, 0.4343793 , 0.32263688, 0.65770697, 0.61356753],\n", + " [0.19378037, 0.6395654 , 0.94830926, 0.37040329, 0.43761136,\n", + " 0.79517072, 0.49994165, 0.87566226, 0.76793298, 0.08770912],\n", + " [0.24788341, 0.76420478, 0.69379041, 0.31979159, 0.38141878,\n", + " 0.87133286, 0.48002551, 0.99319249, 0.92158005, 0.41340018],\n", + " [0.76364848, 0.14923229, 0.58972456, 0.6497025 , 0.72261034,\n", + " 0.46587944, 0.65899584, 0.06284198, 0.10116845, 0.69050762]],\n", + " \n", + " [[0.55086051, 0.41049861, 0.72613161, 0.10209068, 0.77561294,\n", + " 0.60741189, 0.0990884 , 0.97687032, 0.48856226, 0.65001529],\n", + " [0.42668348, 0.85970584, 0.9009646 , 0.16837185, 0.07728554,\n", + " 0.49002088, 0.14818526, 0.95035504, 0.87802133, 0.91886464],\n", + " [0.18567169, 0.82489557, 0.0105433 , 0.08790348, 0.00896896,\n", + " 0.93911221, 0.69070265, 0.88624885, 0.01078138, 0.78754388],\n", + " [0.9911567 , 0.3502372 , 0.86614406, 0.69255045, 0.10446331,\n", + " 0.99044252, 0.44933799, 0.89952532, 0.60757778, 0.81763927],\n", + " [0.60009809, 0.65632015, 0.2662486 , 0.56157217, 0.82138236,\n", + " 0.1753327 , 0.01276561, 0.01786617, 0.58354147, 0.50236365],\n", + " [0.15670643, 0.03074663, 0.57945941, 0.48933184, 0.47575001,\n", + " 0.2786405 , 0.30590399, 0.15175435, 0.95480545, 0.60934913],\n", + " [0.62542567, 0.36184765, 0.48864965, 0.78854085, 0.47227953,\n", + " 0.20096491, 0.40530239, 0.66738742, 0.7947208 , 0.97882672],\n", + " [0.71914019, 0.28877839, 0.77869619, 0.98258026, 0.75842418,\n", + " 0.27776089, 0.61026718, 0.11026115, 0.35014719, 0.85779448],\n", + " [0.43332412, 0.13963806, 0.22700522, 0.2184799 , 0.95821739,\n", + " 0.60884812, 0.41895097, 0.39532951, 0.94120575, 0.88304259],\n", + " [0.36188015, 0.71448186, 0.12941785, 0.59089551, 0.3402902 ,\n", + " 0.1287766 , 0.92626208, 0.31594477, 0.35793065, 0.74701252]]]]))" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.random.rand(), np.random.rand(1, 2, 10, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_concat(shape_list, axis=1, op_name=\"concat\",):\n", + " proto_file = f\"{root_dir}/{op_name}.prototxt\"\n", + " blob_file = f\"{root_dir}/{op_name}.caffemodel\"\n", + " solver_file = f\"{root_dir}/{op_name}_solver.prototxt\"\n", + " n_netspec = miso_op(shape_list, L.Concat, axis=axis)\n", + " # obtain the .caffemodel file and .prototxt file\n", + " gen_model_files(n_netspec, proto_file, blob_file, solver_file)\n", + " # run model in Caffe\n", + " data = [np.random.rand(*shape).astype(np.float32) for shape in shape_list]\n", + " caffe_out = run_caffe(data, proto_file, blob_file)\n", + " init_net = pb.NetParameter()\n", + " predict_net = pb.NetParameter()\n", + " # load model\n", + " with open(proto_file, \"r\") as f:\n", + " text_format.Merge(f.read(), predict_net)\n", + " # load blob\n", + " with open(blob_file, \"rb\") as f:\n", + " init_net.ParseFromString(f.read())\n", + " shape_dict = [{f\"data_{k}\": shape} for k, shape in enumerate(shape_list)]\n", + " dtype_dict = [{f\"data_{k}\": \"float32\"} for k, shape in enumerate(shape_list)]\n", + " mod, params = relay.frontend.from_caffe(init_net, predict_net, shape_dict, dtype_dict)\n", + " return mod, params" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.276784 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/concat.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/concat\"\n", + "I0914 09:12:11.276893 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/concat.prototxt\n", + "I0914 09:12:11.276965 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 2\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Concat\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " concat_param {\n", + " axis: 1\n", + " }\n", + "}\n", + "I0914 09:12:11.277004 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.277014 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.277019 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.277031 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.277035 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.277040 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.277045 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:11.277050 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:11.277055 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:11.277061 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:11.277065 1956768 net.cpp:131] Top shape: 1 2 10 10 (200)\n", + "I0914 09:12:11.277068 1956768 net.cpp:139] Memory required for data: 2000\n", + "I0914 09:12:11.277072 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.277088 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.277092 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.277097 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:11.277102 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.277109 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.277113 1956768 net.cpp:131] Top shape: 1 5 10 10 (500)\n", + "I0914 09:12:11.277117 1956768 net.cpp:139] Memory required for data: 4000\n", + "I0914 09:12:11.277120 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.277124 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:11.277127 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.277130 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.277135 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.277148 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.277402 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.277412 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.277415 1956768 _caffe.cpp:142] Net('./.temp/concat.prototxt', 1, weights='./.temp/concat.caffemodel')\n", + "I0914 09:12:11.277477 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 2\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Concat\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " concat_param {\n", + " axis: 1\n", + " }\n", + "}\n", + "I0914 09:12:11.277510 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.277516 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.277521 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.277529 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.277534 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.277537 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.277541 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:11.277546 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:11.277550 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:11.277557 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:11.277560 1956768 net.cpp:131] Top shape: 1 2 10 10 (200)\n", + "I0914 09:12:11.277565 1956768 net.cpp:139] Memory required for data: 2000\n", + "I0914 09:12:11.277567 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.277575 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.277577 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.277581 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:11.277586 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.277592 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.277596 1956768 net.cpp:131] Top shape: 1 5 10 10 (500)\n", + "I0914 09:12:11.277599 1956768 net.cpp:139] Memory required for data: 4000\n", + "I0914 09:12:11.277603 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.277606 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:11.277609 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.277612 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.277617 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "mod, params = _test_concat([(1, 3, 10, 10), (1, 2, 10, 10)], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %data1) {\n",
+       "  %0 = (%data0, %data1);\n",
+       "  concatenate(%0, axis=1)\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.297618 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/concat.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/concat\"\n", + "I0914 09:12:11.297690 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/concat.prototxt\n", + "I0914 09:12:11.297744 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 2\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Concat\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " concat_param {\n", + " axis: 0\n", + " }\n", + "}\n", + "I0914 09:12:11.297775 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.297782 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.297786 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.297796 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.297799 1956768 net.cpp:131] Top shape: 3 10 10 (300)\n", + "I0914 09:12:11.297804 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.297807 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:11.297812 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:11.297816 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:11.297822 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:11.297825 1956768 net.cpp:131] Top shape: 2 10 10 (200)\n", + "I0914 09:12:11.297829 1956768 net.cpp:139] Memory required for data: 2000\n", + "I0914 09:12:11.297832 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.297837 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.297842 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.297844 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:11.297849 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.297855 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.297858 1956768 net.cpp:131] Top shape: 5 10 10 (500)\n", + "I0914 09:12:11.297863 1956768 net.cpp:139] Memory required for data: 4000\n", + "I0914 09:12:11.297865 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.297869 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:11.297873 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.297875 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.297880 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.297889 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.298053 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.298061 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.298064 1956768 _caffe.cpp:142] Net('./.temp/concat.prototxt', 1, weights='./.temp/concat.caffemodel')\n", + "I0914 09:12:11.298123 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 2\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Concat\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " concat_param {\n", + " axis: 0\n", + " }\n", + "}\n", + "I0914 09:12:11.298153 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.298161 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.298164 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.298172 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.298177 1956768 net.cpp:131] Top shape: 3 10 10 (300)\n", + "I0914 09:12:11.298180 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.298184 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:11.298188 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:11.298192 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:11.298198 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:11.298202 1956768 net.cpp:131] Top shape: 2 10 10 (200)\n", + "I0914 09:12:11.298205 1956768 net.cpp:139] Memory required for data: 2000\n", + "I0914 09:12:11.298208 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.298215 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.298218 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.298223 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:11.298228 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.298233 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.298236 1956768 net.cpp:131] Top shape: 5 10 10 (500)\n", + "I0914 09:12:11.298240 1956768 net.cpp:139] Memory required for data: 4000\n", + "I0914 09:12:11.298243 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.298246 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:11.298249 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.298252 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.298256 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "mod, params = _test_concat([(3, 10, 10), (2, 10, 10)], axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %data1) {\n",
+       "  %0 = (%data0, %data1);\n",
+       "  concatenate(%0)\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Convolution" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_conv2d(shape_list, op_name=\"conv2d\", **kwargs):\n", + " proto_file = f\"{root_dir}/{op_name}.prototxt\"\n", + " blob_file = f\"{root_dir}/{op_name}.caffemodel\"\n", + " solver_file = f\"{root_dir}/{op_name}_solver.prototxt\"\n", + " n_netspec = miso_op(shape_list, L.Convolution, **kwargs)\n", + " # obtain the .caffemodel file and .prototxt file\n", + " gen_model_files(n_netspec, proto_file, blob_file, solver_file)\n", + " # run model in Caffe\n", + " data = [np.random.rand(*shape).astype(np.float32) for shape in shape_list]\n", + " caffe_out = run_caffe(data, proto_file, blob_file)\n", + " init_net = pb.NetParameter()\n", + " predict_net = pb.NetParameter()\n", + " # load model\n", + " with open(proto_file, \"r\") as f:\n", + " text_format.Merge(f.read(), predict_net)\n", + " # load blob\n", + " with open(blob_file, \"rb\") as f:\n", + " init_net.ParseFromString(f.read())\n", + " shape_dict = [{f\"data_{k}\": shape} for k, shape in enumerate(shape_list)]\n", + " dtype_dict = [{f\"data_{k}\": \"float32\"} for k, _ in enumerate(shape_list)]\n", + " mod, params = relay.frontend.from_caffe(init_net, predict_net, shape_dict, dtype_dict)\n", + " return mod, params" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.327899 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/conv2d.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/conv2d\"\n", + "I0914 09:12:11.327972 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/conv2d.prototxt\n", + "I0914 09:12:11.328034 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " pad: 0\n", + " kernel_size: 3\n", + " stride: 2\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " }\n", + "}\n", + "I0914 09:12:11.328068 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.328075 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.328079 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.328088 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.328092 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.328097 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.328100 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.328121 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.328126 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.328131 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.328189 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.328195 1956768 net.cpp:131] Top shape: 1 20 4 4 (320)\n", + "I0914 09:12:11.328200 1956768 net.cpp:139] Memory required for data: 2480\n", + "I0914 09:12:11.328207 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.328210 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.328213 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.328218 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.328227 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.328648 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.328657 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.328660 1956768 _caffe.cpp:142] Net('./.temp/conv2d.prototxt', 1, weights='./.temp/conv2d.caffemodel')\n", + "I0914 09:12:11.328723 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " pad: 0\n", + " kernel_size: 3\n", + " stride: 2\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " }\n", + "}\n", + "I0914 09:12:11.328754 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.328761 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.328765 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.328773 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.328778 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.328781 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.328785 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.328792 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.328795 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.328800 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.328820 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.328824 1956768 net.cpp:131] Top shape: 1 20 4 4 (320)\n", + "I0914 09:12:11.328828 1956768 net.cpp:139] Memory required for data: 2480\n", + "I0914 09:12:11.328835 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.328838 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.328841 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.328845 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "shape_list = [(1, 3, 10, 10)]\n", + "mod, params = _test_conv2d(\n", + " shape_list,\n", + " num_output=20,\n", + " bias_term=True,\n", + " pad=0,\n", + " kernel_size=3,\n", + " stride=2,\n", + " dilation=1,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %v_param_1: Tensor[(20, 3, 3, 3), float32], %v_param_2: Tensor[(20), float32]) {\n",
+       "  %0 = nn.conv2d(%data0, %v_param_1, strides=[2, 2], padding=[0, 0, 0, 0], channels=20, kernel_size=[3, 3]);\n",
+       "  nn.bias_add(%0, %v_param_2)\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.350931 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/conv2d.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/conv2d\"\n", + "I0914 09:12:11.351027 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/conv2d.prototxt\n", + "I0914 09:12:11.351083 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: false\n", + " pad: 1\n", + " pad: 2\n", + " kernel_size: 3\n", + " stride: 2\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " }\n", + "}\n", + "I0914 09:12:11.351116 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.351125 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.351128 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.351137 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.351141 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.351146 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.351150 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.351156 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.351161 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.351166 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.351183 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.351187 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.351191 1956768 net.cpp:139] Memory required for data: 3600\n", + "I0914 09:12:11.351197 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.351200 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.351203 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.351207 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.351217 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.351402 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.351411 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.351414 1956768 _caffe.cpp:142] Net('./.temp/conv2d.prototxt', 1, weights='./.temp/conv2d.caffemodel')\n", + "I0914 09:12:11.351477 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: false\n", + " pad: 1\n", + " pad: 2\n", + " kernel_size: 3\n", + " stride: 2\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " }\n", + "}\n", + "I0914 09:12:11.351508 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.351516 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.351519 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.351527 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.351531 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.351536 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.351538 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.351545 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.351549 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.351553 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.351572 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.351575 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.351579 1956768 net.cpp:139] Memory required for data: 3600\n", + "I0914 09:12:11.351584 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.351588 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.351590 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.351595 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "mod, params = _test_conv2d(\n", + " shape_list,\n", + " num_output=20,\n", + " bias_term=False,\n", + " pad=[1, 2],\n", + " kernel_size=3,\n", + " stride=2,\n", + " dilation=1,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %v_param_1: Tensor[(20, 3, 3, 3), float32]) {\n",
+       "  nn.conv2d(%data0, %v_param_1, strides=[2, 2], padding=[1, 2, 1, 2], channels=20, kernel_size=[3, 3])\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.373440 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/conv2d.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/conv2d\"\n", + "I0914 09:12:11.373510 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/conv2d.prototxt\n", + "I0914 09:12:11.373567 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " pad: 1\n", + " pad: 2\n", + " kernel_size: 3\n", + " kernel_size: 5\n", + " stride: 2\n", + " stride: 1\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " dilation: 2\n", + " }\n", + "}\n", + "I0914 09:12:11.373600 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.373607 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.373612 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.373620 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.373625 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.373629 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.373633 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.373639 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.373643 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.373648 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.373670 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.373674 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.373678 1956768 net.cpp:139] Memory required for data: 3600\n", + "I0914 09:12:11.373685 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.373688 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.373692 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.373696 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.373704 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.373950 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.373958 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.373962 1956768 _caffe.cpp:142] Net('./.temp/conv2d.prototxt', 1, weights='./.temp/conv2d.caffemodel')\n", + "I0914 09:12:11.374025 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " pad: 1\n", + " pad: 2\n", + " kernel_size: 3\n", + " kernel_size: 5\n", + " stride: 2\n", + " stride: 1\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " dilation: 2\n", + " }\n", + "}\n", + "I0914 09:12:11.374056 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.374063 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.374068 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.374075 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.374079 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.374084 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.374089 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.374094 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.374099 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.374104 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.374125 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.374128 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.374132 1956768 net.cpp:139] Memory required for data: 3600\n", + "I0914 09:12:11.374138 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.374142 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.374145 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.374150 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "mod, params = _test_conv2d(\n", + " shape_list,\n", + " num_output=20,\n", + " bias_term=True,\n", + " pad=[1, 2],\n", + " kernel_size=[3, 5],\n", + " stride=[2, 1],\n", + " dilation=[1, 2],\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %v_param_1: Tensor[(20, 3, 3, 5), float32], %v_param_2: Tensor[(20), float32]) {\n",
+       "  %0 = nn.conv2d(%data0, %v_param_1, strides=[2, 1], padding=[1, 2, 1, 2], dilation=[1, 2], channels=20, kernel_size=[3, 5]);\n",
+       "  nn.bias_add(%0, %v_param_2)\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.396004 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/conv2d.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/conv2d\"\n", + "I0914 09:12:11.396075 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/conv2d.prototxt\n", + "I0914 09:12:11.396133 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " pad_h: 1\n", + " pad_w: 2\n", + " kernel_h: 3\n", + " kernel_w: 5\n", + " stride_h: 2\n", + " stride_w: 1\n", + " dilation: 1\n", + " dilation: 2\n", + " }\n", + "}\n", + "I0914 09:12:11.396165 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.396173 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.396178 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.396186 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.396190 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.396195 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.396198 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.396205 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.396209 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.396214 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.396234 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.396239 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.396243 1956768 net.cpp:139] Memory required for data: 3600\n", + "I0914 09:12:11.396250 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.396252 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.396255 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.396260 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.396268 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.396432 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.396442 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.396445 1956768 _caffe.cpp:142] Net('./.temp/conv2d.prototxt', 1, weights='./.temp/conv2d.caffemodel')\n", + "I0914 09:12:11.396507 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 3\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " pad_h: 1\n", + " pad_w: 2\n", + " kernel_h: 3\n", + " kernel_w: 5\n", + " stride_h: 2\n", + " stride_w: 1\n", + " dilation: 1\n", + " dilation: 2\n", + " }\n", + "}\n", + "I0914 09:12:11.396538 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.396545 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.396549 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.396557 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.396561 1956768 net.cpp:131] Top shape: 1 3 10 10 (300)\n", + "I0914 09:12:11.396565 1956768 net.cpp:139] Memory required for data: 1200\n", + "I0914 09:12:11.396569 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.396575 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.396579 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.396584 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.396605 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.396608 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.396612 1956768 net.cpp:139] Memory required for data: 3600\n", + "I0914 09:12:11.396618 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.396621 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.396624 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.396628 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "mod, params = _test_conv2d(\n", + " shape_list,\n", + " num_output=20,\n", + " bias_term=True,\n", + " pad_h=1,\n", + " pad_w=2,\n", + " kernel_h=3,\n", + " kernel_w=5,\n", + " stride_h=2,\n", + " stride_w=1,\n", + " dilation=[1, 2],\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %v_param_1: Tensor[(20, 3, 3, 5), float32], %v_param_2: Tensor[(20), float32]) {\n",
+       "  %0 = nn.conv2d(%data0, %v_param_1, strides=[2, 1], padding=[1, 2, 1, 2], dilation=[1, 2], channels=20, kernel_size=[3, 5]);\n",
+       "  nn.bias_add(%0, %v_param_2)\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:11.421512 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"./.temp/conv2d.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"./.temp/conv2d\"\n", + "I0914 09:12:11.421586 1956768 solver.cpp:92] Creating training net from train_net file: ./.temp/conv2d.prototxt\n", + "I0914 09:12:11.421649 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 2\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " pad: 1\n", + " pad: 2\n", + " kernel_size: 3\n", + " kernel_size: 5\n", + " group: 2\n", + " stride: 2\n", + " stride: 1\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " dilation: 2\n", + " }\n", + "}\n", + "I0914 09:12:11.421682 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.421690 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.421695 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.421705 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.421708 1956768 net.cpp:131] Top shape: 1 2 10 10 (200)\n", + "I0914 09:12:11.421712 1956768 net.cpp:139] Memory required for data: 800\n", + "I0914 09:12:11.421716 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.421723 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.421726 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.421731 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.421751 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.421754 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.421758 1956768 net.cpp:139] Memory required for data: 3200\n", + "I0914 09:12:11.421765 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.421769 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.421772 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.421777 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:11.421784 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:11.421972 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:11.421981 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:11.421985 1956768 _caffe.cpp:142] Net('./.temp/conv2d.prototxt', 1, weights='./.temp/conv2d.caffemodel')\n", + "I0914 09:12:11.422055 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 1\n", + " dim: 2\n", + " dim: 10\n", + " dim: 10\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Convolution\"\n", + " bottom: \"data0\"\n", + " top: \"output\"\n", + " convolution_param {\n", + " num_output: 20\n", + " bias_term: true\n", + " pad: 1\n", + " pad: 2\n", + " kernel_size: 3\n", + " kernel_size: 5\n", + " group: 2\n", + " stride: 2\n", + " stride: 1\n", + " weight_filler {\n", + " type: \"xavier\"\n", + " }\n", + " bias_filler {\n", + " type: \"xavier\"\n", + " }\n", + " dilation: 1\n", + " dilation: 2\n", + " }\n", + "}\n", + "I0914 09:12:11.422086 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:11.422092 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:11.422096 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:11.422104 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:11.422108 1956768 net.cpp:131] Top shape: 1 2 10 10 (200)\n", + "I0914 09:12:11.422112 1956768 net.cpp:139] Memory required for data: 800\n", + "I0914 09:12:11.422116 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:11.422122 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:11.422127 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:11.422132 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:11.422149 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:11.422153 1956768 net.cpp:131] Top shape: 1 20 5 6 (600)\n", + "I0914 09:12:11.422158 1956768 net.cpp:139] Memory required for data: 3200\n", + "I0914 09:12:11.422163 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:11.422168 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:11.422170 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:11.422174 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "mod, params = _test_conv2d(\n", + " [(1, 2, 10, 10)],\n", + " num_output=20,\n", + " bias_term=True,\n", + " pad=[1, 2],\n", + " kernel_size=[3, 5],\n", + " stride=[2, 1],\n", + " dilation=[1, 2],\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " group=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
def @main(%data0, %v_param_1: Tensor[(20, 1, 3, 5), float32], %v_param_2: Tensor[(20), float32]) {\n",
+       "  %0 = nn.conv2d(%data0, %v_param_1, strides=[2, 1], padding=[1, 2, 1, 2], dilation=[1, 2], groups=2, channels=20, kernel_size=[3, 5]);\n",
+       "  nn.bias_add(%0, %v_param_2)\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mod.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe crop" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "from caffe_utils import _test_op\n", + "\n", + "def _test_crop(data, **kwargs):\n", + " \"\"\"One iteration of Crop\"\"\"\n", + " _test_op(data, L.Crop, \"Crop\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Crop():\n", + " \"\"\"Crop\"\"\"\n", + " _test_crop([np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)])\n", + " _test_crop([np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=1)\n", + " _test_crop([np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=1, offset=2)\n", + " _test_crop(\n", + " [np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=1, offset=[1, 2, 4]\n", + " )\n", + " _test_crop(\n", + " [np.random.rand(10, 10, 120, 120), np.random.rand(10, 5, 50, 60)], axis=2, offset=[2, 4]\n", + " )\n", + " _test_crop([np.random.rand(10, 120, 120), np.random.rand(5, 50, 60)], axis=1, offset=[2, 4])\n", + " _test_crop([np.random.rand(120, 120), np.random.rand(50, 60)], axis=0, offset=[2, 4])" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "I0914 09:12:30.343927 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60\"\n", + "I0914 09:12:30.344040 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60.prototxt\n", + "I0914 09:12:30.344126 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + "}\n", + "I0914 09:12:30.344178 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:30.344192 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:30.344200 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:30.344216 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:30.344221 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:30.344230 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:30.344236 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:30.344244 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:30.344250 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:30.344260 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:30.344265 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:30.344271 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:30.344276 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:30.344298 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:30.344303 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:30.344309 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:30.344316 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:30.344332 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:30.344336 1956768 net.cpp:131] Top shape: 10 10 50 60 (300000)\n", + "I0914 09:12:30.344343 1956768 net.cpp:139] Memory required for data: 7560000\n", + "I0914 09:12:30.344348 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:30.344352 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:30.344357 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:30.344362 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:30.344368 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:30.344383 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:30.344502 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:30.344512 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:30.344517 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60.caffemodel')\n", + "I0914 09:12:30.344587 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + "}\n", + "I0914 09:12:30.344625 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:30.344635 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:30.344640 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:30.344650 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:30.344655 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:30.344663 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:30.344668 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:30.344676 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:30.344681 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:30.344688 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:30.344692 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:30.344700 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:30.344705 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:30.344712 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:30.344717 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:30.344722 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:30.344727 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:30.344738 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:30.344743 1956768 net.cpp:131] Top shape: 10 10 50 60 (300000)\n", + "I0914 09:12:30.344748 1956768 net.cpp:139] Memory required for data: 7560000\n", + "I0914 09:12:30.344753 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:30.344758 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:30.344761 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:30.344765 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:30.344771 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:31.032979 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1\"\n", + "I0914 09:12:31.033103 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1.prototxt\n", + "I0914 09:12:31.033195 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " }\n", + "}\n", + "I0914 09:12:31.033250 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:31.033263 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:31.033272 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:31.033289 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:31.033295 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:31.033304 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:31.033313 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:31.033320 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:31.033326 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:31.033335 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:31.033339 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.033346 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:31.033350 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:31.033358 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:31.033363 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:31.033370 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:31.033376 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:31.033390 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:31.033396 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.033401 1956768 net.cpp:139] Memory required for data: 6960000\n", + "I0914 09:12:31.033406 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:31.033411 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:31.033416 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:31.033421 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:31.033427 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:31.033443 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:31.033558 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:31.033568 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:31.033573 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1.caffemodel')\n", + "I0914 09:12:31.033648 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " }\n", + "}\n", + "I0914 09:12:31.033689 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:31.033696 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:31.033702 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:31.033713 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:31.033718 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:31.033725 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:31.033731 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:31.033737 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:31.033744 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:31.033752 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:31.033758 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.033764 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:31.033769 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:31.033775 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:31.033780 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:31.033785 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:31.033792 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:31.033803 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:31.033808 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.033814 1956768 net.cpp:139] Memory required for data: 6960000\n", + "I0914 09:12:31.033819 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:31.033824 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:31.033828 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:31.033833 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:31.033839 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:31.330210 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_2.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_2\"\n", + "I0914 09:12:31.330330 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_2.prototxt\n", + "I0914 09:12:31.330410 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " offset: 2\n", + " }\n", + "}\n", + "I0914 09:12:31.330456 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:31.330467 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:31.330474 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:31.330490 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:31.330494 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:31.330502 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:31.330507 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:31.330513 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:31.330518 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:31.330528 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:31.330530 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.330536 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:31.330540 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:31.330546 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:31.330551 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:31.330555 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:31.330561 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:31.330574 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:31.330577 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.330582 1956768 net.cpp:139] Memory required for data: 6960000\n", + "I0914 09:12:31.330586 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:31.330590 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:31.330595 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:31.330598 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:31.330605 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:31.330617 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:31.330727 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:31.330736 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:31.330740 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_2.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_2.caffemodel')\n", + "I0914 09:12:31.330806 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " offset: 2\n", + " }\n", + "}\n", + "I0914 09:12:31.330840 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:31.330848 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:31.330853 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:31.330863 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:31.330868 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:31.330873 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:31.330878 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:31.330883 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:31.330888 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:31.330896 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:31.330900 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.330905 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:31.330909 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:31.330914 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:31.330919 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:31.330922 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:31.330929 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:31.330937 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:31.330941 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.340920 1956768 net.cpp:139] Memory required for data: 6960000\n", + "I0914 09:12:31.340931 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:31.340935 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:31.340939 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:31.340942 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:31.340947 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:31.659914 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_1_2_4.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_1_2_4\"\n", + "I0914 09:12:31.660022 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_1_2_4.prototxt\n", + "I0914 09:12:31.660095 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " offset: 1\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:31.660136 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:31.660146 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:31.660152 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:31.660166 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:31.660171 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:31.660177 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:31.660181 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:31.660187 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:31.660192 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:31.660199 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:31.660202 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.660207 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:31.660210 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:31.660215 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:31.660219 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:31.660224 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:31.660228 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:31.660239 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:31.660243 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.660247 1956768 net.cpp:139] Memory required for data: 6960000\n", + "I0914 09:12:31.660250 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:31.660254 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:31.660257 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:31.660260 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:31.660265 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:31.660279 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:31.660377 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:31.660384 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:31.660387 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_1_2_4.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_1_1_2_4.caffemodel')\n", + "I0914 09:12:31.660446 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " offset: 1\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:31.660477 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:31.660483 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:31.660488 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:31.660496 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:31.660501 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:31.660506 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:31.660509 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:31.660514 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:31.660521 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:31.660526 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:31.660530 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.660534 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:31.660537 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:31.660542 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:31.660545 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:31.660549 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:31.660553 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:31.660562 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:31.660564 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:31.660569 1956768 net.cpp:139] Memory required for data: 6960000\n", + "I0914 09:12:31.660573 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:31.660575 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:31.660578 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:31.660581 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:31.660585 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:32.000172 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_2_2_4.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_2_2_4\"\n", + "I0914 09:12:32.000275 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_2_2_4.prototxt\n", + "I0914 09:12:32.000347 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 2\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:32.000389 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:32.000399 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:32.000406 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:32.000419 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:32.000423 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:32.000430 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:32.000433 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:32.000439 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:32.000444 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:32.000450 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:32.000454 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:32.000459 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:32.000463 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:32.000468 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:32.000473 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:32.000476 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:32.000481 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:32.000491 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:32.000495 1956768 net.cpp:131] Top shape: 10 10 50 60 (300000)\n", + "I0914 09:12:32.000500 1956768 net.cpp:139] Memory required for data: 7560000\n", + "I0914 09:12:32.000504 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:32.000507 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:32.000510 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:32.000514 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:32.000519 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:32.000531 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:32.000640 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:32.000648 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:32.000651 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_2_2_4.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_10_120_120_10_5_50_60_2_2_4.caffemodel')\n", + "I0914 09:12:32.000711 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 2\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:32.000746 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:32.000751 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:32.000756 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:32.000764 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:32.000768 1956768 net.cpp:131] Top shape: 10 10 120 120 (1440000)\n", + "I0914 09:12:32.000773 1956768 net.cpp:139] Memory required for data: 5760000\n", + "I0914 09:12:32.000777 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:32.000782 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:32.000788 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:32.000793 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:32.000797 1956768 net.cpp:131] Top shape: 10 5 50 60 (150000)\n", + "I0914 09:12:32.000802 1956768 net.cpp:139] Memory required for data: 6360000\n", + "I0914 09:12:32.000805 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:32.000809 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:32.000813 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:32.000818 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:32.000821 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:32.000829 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:32.000833 1956768 net.cpp:131] Top shape: 10 10 50 60 (300000)\n", + "I0914 09:12:32.000837 1956768 net.cpp:139] Memory required for data: 7560000\n", + "I0914 09:12:32.000840 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:32.000844 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:32.000847 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:32.000850 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:32.000854 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:32.305437 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_120_120_5_50_60_1_2_4.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_120_120_5_50_60_1_2_4\"\n", + "I0914 09:12:32.305541 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_120_120_5_50_60_1_2_4.prototxt\n", + "I0914 09:12:32.305613 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:32.305655 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:32.305665 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:32.305670 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:32.305683 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:32.305688 1956768 net.cpp:131] Top shape: 10 120 120 (144000)\n", + "I0914 09:12:32.305694 1956768 net.cpp:139] Memory required for data: 576000\n", + "I0914 09:12:32.305697 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:32.305703 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:32.305707 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:32.305714 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:32.305717 1956768 net.cpp:131] Top shape: 5 50 60 (15000)\n", + "I0914 09:12:32.305721 1956768 net.cpp:139] Memory required for data: 636000\n", + "I0914 09:12:32.305724 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:32.305730 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:32.305734 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:32.305738 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:32.305743 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:32.305752 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:32.305756 1956768 net.cpp:131] Top shape: 10 50 60 (30000)\n", + "I0914 09:12:32.305760 1956768 net.cpp:139] Memory required for data: 756000\n", + "I0914 09:12:32.305764 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:32.305768 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:32.305770 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:32.305774 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:32.305779 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:32.305790 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:32.305888 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:32.305896 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:32.305899 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_120_120_5_50_60_1_2_4.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_10_120_120_5_50_60_1_2_4.caffemodel')\n", + "I0914 09:12:32.305958 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 10\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 5\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 1\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:32.305989 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:32.305995 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:32.306000 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:32.306008 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:32.306011 1956768 net.cpp:131] Top shape: 10 120 120 (144000)\n", + "I0914 09:12:32.306017 1956768 net.cpp:139] Memory required for data: 576000\n", + "I0914 09:12:32.306020 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:32.306025 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:32.306030 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:32.306035 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:32.306041 1956768 net.cpp:131] Top shape: 5 50 60 (15000)\n", + "I0914 09:12:32.306046 1956768 net.cpp:139] Memory required for data: 636000\n", + "I0914 09:12:32.306048 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:32.306053 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:32.306056 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:32.306061 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:32.306064 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:32.306072 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:32.306077 1956768 net.cpp:131] Top shape: 10 50 60 (30000)\n", + "I0914 09:12:32.306080 1956768 net.cpp:139] Memory required for data: 756000\n", + "I0914 09:12:32.306083 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:32.306087 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:32.306090 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:32.306093 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:32.306097 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:32.559347 1956768 solver.cpp:45] Initializing solver from parameters: \n", + "train_net: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_120_120_50_60_0_2_4.prototxt\"\n", + "base_lr: 0.01\n", + "display: 1\n", + "max_iter: 100000\n", + "lr_policy: \"inv\"\n", + "gamma: 0.0001\n", + "power: 0.75\n", + "momentum: 0.9\n", + "weight_decay: 0.0005\n", + "snapshot: 100000\n", + "snapshot_prefix: \"/home/ai/.tvm_test_data/caffe_test/Crop/Crop_120_120_50_60_0_2_4\"\n", + "I0914 09:12:32.559437 1956768 solver.cpp:92] Creating training net from train_net file: /home/ai/.tvm_test_data/caffe_test/Crop/Crop_120_120_50_60_0_2_4.prototxt\n", + "I0914 09:12:32.559511 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TRAIN\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 0\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:32.559547 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:32.559556 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:32.559561 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:32.559571 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:32.559574 1956768 net.cpp:131] Top shape: 120 120 (14400)\n", + "I0914 09:12:32.559579 1956768 net.cpp:139] Memory required for data: 57600\n", + "I0914 09:12:32.559583 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:32.559587 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:32.559592 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:32.559598 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:32.559602 1956768 net.cpp:131] Top shape: 50 60 (3000)\n", + "I0914 09:12:32.559605 1956768 net.cpp:139] Memory required for data: 69600\n", + "I0914 09:12:32.559608 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:32.559613 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:32.559617 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:32.559621 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:32.559625 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:32.559634 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:32.559638 1956768 net.cpp:131] Top shape: 50 60 (3000)\n", + "I0914 09:12:32.559641 1956768 net.cpp:139] Memory required for data: 81600\n", + "I0914 09:12:32.559644 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:32.559648 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:32.559651 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:32.559654 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:32.559659 1956768 net.cpp:257] Network initialization done.\n", + "I0914 09:12:32.559669 1956768 solver.cpp:57] Solver scaffolding done.\n", + "W0914 09:12:32.559760 1956768 _caffe.cpp:139] DEPRECATION WARNING - deprecated use of Python interface\n", + "W0914 09:12:32.559768 1956768 _caffe.cpp:140] Use this instead (with the named \"weights\" parameter):\n", + "W0914 09:12:32.559772 1956768 _caffe.cpp:142] Net('/home/ai/.tvm_test_data/caffe_test/Crop/Crop_120_120_50_60_0_2_4.prototxt', 1, weights='/home/ai/.tvm_test_data/caffe_test/Crop/Crop_120_120_50_60_0_2_4.caffemodel')\n", + "I0914 09:12:32.559827 1956768 net.cpp:53] Initializing net from parameters: \n", + "state {\n", + " phase: TEST\n", + " level: 0\n", + "}\n", + "layer {\n", + " name: \"data0\"\n", + " type: \"Input\"\n", + " top: \"data0\"\n", + " input_param {\n", + " shape {\n", + " dim: 120\n", + " dim: 120\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"data1\"\n", + " type: \"Input\"\n", + " top: \"data1\"\n", + " input_param {\n", + " shape {\n", + " dim: 50\n", + " dim: 60\n", + " }\n", + " }\n", + "}\n", + "layer {\n", + " name: \"output\"\n", + " type: \"Crop\"\n", + " bottom: \"data0\"\n", + " bottom: \"data1\"\n", + " top: \"output\"\n", + " crop_param {\n", + " axis: 0\n", + " offset: 2\n", + " offset: 4\n", + " }\n", + "}\n", + "I0914 09:12:32.559859 1956768 layer_factory.hpp:77] Creating layer data0\n", + "I0914 09:12:32.559864 1956768 net.cpp:86] Creating Layer data0\n", + "I0914 09:12:32.559870 1956768 net.cpp:382] data0 -> data0\n", + "I0914 09:12:32.559876 1956768 net.cpp:124] Setting up data0\n", + "I0914 09:12:32.559880 1956768 net.cpp:131] Top shape: 120 120 (14400)\n", + "I0914 09:12:32.559885 1956768 net.cpp:139] Memory required for data: 57600\n", + "I0914 09:12:32.559888 1956768 layer_factory.hpp:77] Creating layer data1\n", + "I0914 09:12:32.559892 1956768 net.cpp:86] Creating Layer data1\n", + "I0914 09:12:32.559896 1956768 net.cpp:382] data1 -> data1\n", + "I0914 09:12:32.559901 1956768 net.cpp:124] Setting up data1\n", + "I0914 09:12:32.559906 1956768 net.cpp:131] Top shape: 50 60 (3000)\n", + "I0914 09:12:32.559911 1956768 net.cpp:139] Memory required for data: 69600\n", + "I0914 09:12:32.559914 1956768 layer_factory.hpp:77] Creating layer output\n", + "I0914 09:12:32.559918 1956768 net.cpp:86] Creating Layer output\n", + "I0914 09:12:32.559922 1956768 net.cpp:408] output <- data0\n", + "I0914 09:12:32.559926 1956768 net.cpp:408] output <- data1\n", + "I0914 09:12:32.559931 1956768 net.cpp:382] output -> output\n", + "I0914 09:12:32.559937 1956768 net.cpp:124] Setting up output\n", + "I0914 09:12:32.559942 1956768 net.cpp:131] Top shape: 50 60 (3000)\n", + "I0914 09:12:32.559944 1956768 net.cpp:139] Memory required for data: 81600\n", + "I0914 09:12:32.559947 1956768 net.cpp:202] output does not need backward computation.\n", + "I0914 09:12:32.559952 1956768 net.cpp:202] data1 does not need backward computation.\n", + "I0914 09:12:32.559954 1956768 net.cpp:202] data0 does not need backward computation.\n", + "I0914 09:12:32.559957 1956768 net.cpp:244] This network produces output output\n", + "I0914 09:12:32.559962 1956768 net.cpp:257] Network initialization done.\n" + ] + } + ], + "source": [ + "test_forward_Crop()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Deconvolution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_deconvolution(data, **kwargs):\n", + " \"\"\"One iteration of Deconvolution\"\"\"\n", + " _test_op(data, L.Deconvolution, \"Deconvolution\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Deconvolution():\n", + " \"\"\"Deconvolution\"\"\"\n", + " data = np.random.rand(1, 16, 32, 32).astype(np.float32)\n", + " _test_deconvolution(\n", + " data,\n", + " convolution_param=dict(\n", + " num_output=20,\n", + " bias_term=True,\n", + " pad=0,\n", + " kernel_size=3,\n", + " stride=2,\n", + " dilation=1,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " ),\n", + " )\n", + " _test_deconvolution(\n", + " data,\n", + " convolution_param=dict(\n", + " num_output=20,\n", + " bias_term=False,\n", + " pad=[1, 2],\n", + " kernel_size=3,\n", + " stride=2,\n", + " dilation=1,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " ),\n", + " )\n", + " _test_deconvolution(\n", + " data,\n", + " convolution_param=dict(\n", + " num_output=20,\n", + " bias_term=True,\n", + " pad_h=1,\n", + " pad_w=2,\n", + " kernel_h=3,\n", + " kernel_w=5,\n", + " stride_h=2,\n", + " stride_w=1,\n", + " dilation=1,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " ),\n", + " )\n", + " _test_deconvolution(\n", + " data,\n", + " convolution_param=dict(\n", + " num_output=16,\n", + " bias_term=False,\n", + " pad=0,\n", + " kernel_size=2,\n", + " stride=2,\n", + " dilation=1,\n", + " group=16,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " ),\n", + " )\n", + " data = np.random.rand(1, 100, 32, 32).astype(np.float32)\n", + " _test_deconvolution(\n", + " data,\n", + " convolution_param=dict(\n", + " num_output=100,\n", + " bias_term=False,\n", + " pad=0,\n", + " kernel_size=2,\n", + " stride=2,\n", + " dilation=1,\n", + " group=100,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " ),\n", + " )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Dropout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_dropout(data, **kwargs):\n", + " \"\"\"One iteration of Dropout\"\"\"\n", + " _test_op(data, L.Dropout, \"Dropout\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Dropout():\n", + " \"\"\"Dropout\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_dropout(data)\n", + " _test_dropout(data, dropout_ratio=0.7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Eltwise" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_eltwise(data_list, **kwargs):\n", + " \"\"\"One iteration of Eltwise\"\"\"\n", + " _test_op(data_list, L.Eltwise, \"Eltwise\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Eltwise():\n", + " \"\"\"Eltwise\"\"\"\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=0,\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=1,\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=2,\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=1,\n", + " coeff=[0.5, 1],\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=0,\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=1,\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=2,\n", + " )\n", + " _test_eltwise(\n", + " [\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " np.random.rand(1, 3, 10, 11).astype(np.float32),\n", + " ],\n", + " operation=1,\n", + " coeff=[0.5, 1, 0.2, 1.8, 3.1, 0.1],\n", + " )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Flatten" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_flatten(data, axis=1):\n", + " \"\"\"One iteration of Flatten\"\"\"\n", + " _test_op(data, L.Flatten, \"Flatten\", axis=axis)\n", + "\n", + "\n", + "def test_forward_Flatten():\n", + " \"\"\"Flatten\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_flatten(data)\n", + " _test_flatten(data, axis=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe InnerProduct" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_inner_product(data, **kwargs):\n", + " \"\"\"One iteration of InnerProduct\"\"\"\n", + " _test_op(data, L.InnerProduct, \"InnerProduct\", **kwargs)\n", + "\n", + "\n", + "def test_forward_InnerProduct():\n", + " \"\"\"InnerProduct\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10)\n", + " _test_inner_product(data, num_output=20, bias_term=False, weight_filler=dict(type=\"xavier\"))\n", + " _test_inner_product(\n", + " data,\n", + " num_output=20,\n", + " bias_term=True,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " _test_inner_product(\n", + " np.random.rand(20, 10).astype(np.float32),\n", + " num_output=30,\n", + " bias_term=True,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe LRN" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def _test_lrn(data, local_size=5, alpha=1.0, beta=0.75, k=1.0):\n", + " \"\"\"One iteration of LRN\"\"\"\n", + " _test_op(data, L.LRN, \"LRN\", local_size=local_size, alpha=alpha, beta=beta, k=k)\n", + "\n", + "\n", + "def test_forward_LRN():\n", + " \"\"\"LRN\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_lrn(data)\n", + " _test_lrn(data, local_size=3)\n", + " _test_lrn(data, local_size=3, alpha=2.0)\n", + " _test_lrn(\n", + " data,\n", + " local_size=3,\n", + " alpha=2.0,\n", + " beta=0.5,\n", + " )\n", + " _test_lrn(data, local_size=3, alpha=2.0, beta=0.5, k=2.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Permute" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def _test_permute(data, **kwargs):\n", + " \"\"\"One iteration of Permute.\"\"\"\n", + " _test_op(data, L.Permute, \"Permute\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Permute():\n", + " \"\"\"Permute\"\"\"\n", + " data = np.random.rand(2, 3, 4).astype(np.float32)\n", + " _test_permute(data, permute_param={\"order\": [0, 1, 2]})\n", + " _test_permute(data, permute_param={\"order\": [0, 2, 1]})\n", + " _test_permute(data, permute_param={\"order\": [1, 0, 2]})\n", + " _test_permute(data, permute_param={\"order\": [1, 2, 0]})\n", + " _test_permute(data, permute_param={\"order\": [2, 0, 1]})\n", + " _test_permute(data, permute_param={\"order\": [2, 1, 0]})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Pooling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_pooling(data, **kwargs):\n", + " \"\"\"One iteration of Pooling.\"\"\"\n", + " _test_op(data, L.Pooling, \"Pooling\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Pooling():\n", + " \"\"\"Pooing\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " # MAX Pooling\n", + " _test_pooling(data, kernel_size=2, stride=2, pad=0, pool=P.Pooling.MAX)\n", + " _test_pooling(\n", + " data, kernel_h=2, kernel_w=3, stride_h=2, stride_w=1, pad_h=1, pad_w=2, pool=P.Pooling.MAX\n", + " )\n", + " _test_pooling(data, pool=P.Pooling.MAX, global_pooling=True)\n", + "\n", + " # AVE Pooing\n", + " _test_pooling(data, kernel_size=2, stride=2, pad=0, pool=P.Pooling.AVE)\n", + " _test_pooling(\n", + " data, kernel_h=2, kernel_w=3, stride_h=2, stride_w=1, pad_h=1, pad_w=2, pool=P.Pooling.AVE\n", + " )\n", + " _test_pooling(data, pool=P.Pooling.AVE, global_pooling=True)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Power" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_power(data, **kwargs):\n", + " \"\"\"One iteration of Power.\"\"\"\n", + " _test_op(data, L.Power, \"Power\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Power():\n", + " \"\"\"Power\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_power(data, power_param={\"power\": 0.37, \"scale\": 0.83, \"shift\": -2.4})\n", + " _test_power(data, power_param={\"power\": 0.37, \"scale\": 0.83, \"shift\": 0.0})\n", + " _test_power(data, power_param={\"power\": 0.0, \"scale\": 0.83, \"shift\": -2.4})\n", + " _test_power(data, power_param={\"power\": 1.0, \"scale\": 0.83, \"shift\": -2.4})\n", + " _test_power(data, power_param={\"power\": 2.0, \"scale\": 0.34, \"shift\": -2.4})\n", + " _test_power(data, power_param={\"power\": 1.0, \"scale\": 1.0, \"shift\": 0.0})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe PReLU" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_prelu(data, **kwargs):\n", + " \"\"\"One iteration of PReLU.\"\"\"\n", + " _test_op(data, L.PReLU, \"PReLU\", **kwargs)\n", + "\n", + "\n", + "def test_forward_PReLU():\n", + " \"\"\"PReLU\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_prelu(data, filler=dict(type=\"constant\", value=0.5))\n", + " _test_prelu(data)\n", + " _test_prelu(np.random.rand(10, 20).astype(np.float32))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe ReLU" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_relu(data, **kwargs):\n", + " \"\"\"One iteration of ReLU.\"\"\"\n", + " _test_op(data, L.ReLU, \"ReLU\", **kwargs)\n", + "\n", + "\n", + "def test_forward_ReLU():\n", + " \"\"\"ReLU\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_relu(data)\n", + " _test_relu(np.random.rand(10, 20).astype(np.float32))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Reshape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_reshape(data, **kwargs):\n", + " \"\"\"One iteration of Reshape.\"\"\"\n", + " _test_op(data, L.Reshape, \"Reshape\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Reshape():\n", + " \"\"\"Reshape\"\"\"\n", + " data = np.random.rand(1, 8, 6).astype(np.float32)\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [4, 3, 4]}})\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [2, 0, 3]}})\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [2, 0, -1]}})\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [0, -1]}})\n", + "\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [2, 3]}, \"axis\": 2})\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [4, 3, 4]}, \"axis\": 1})\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [4, 3, 4]}, \"axis\": -3})\n", + "\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [2, 4]}, \"axis\": 1, \"num_axes\": 1})\n", + " _test_reshape(data, reshape_param={\"shape\": {\"dim\": [3, 16]}, \"axis\": 1, \"num_axes\": 2})\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Scale" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_scale(data, **kwargs):\n", + " \"\"\"One iteration of Scale.\"\"\"\n", + " _test_op(data, L.Scale, \"Scale\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Scale():\n", + " \"\"\"Scale\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_scale(data, filler=dict(type=\"xavier\"))\n", + " _test_scale(data, filler=dict(type=\"xavier\"), bias_term=True, bias_filler=dict(type=\"xavier\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Sigmoid" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_sigmoid(data, **kwargs):\n", + " \"\"\"One iteration of Sigmoid.\"\"\"\n", + " _test_op(data, L.Sigmoid, \"Sigmoid\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Sigmoid():\n", + " \"\"\"Sigmoid\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_sigmoid(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Slice" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_slice(data, **kwargs):\n", + " \"\"\"One iteration of Slice\"\"\"\n", + " _test_op(data, L.Slice, \"Slice\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Slice():\n", + " \"\"\"Slice\"\"\"\n", + " data = np.random.rand(1, 3, 10, 10).astype(np.float32)\n", + " _test_slice(data, ntop=2, slice_param=dict(axis=1, slice_point=[1]))\n", + " _test_slice(data, ntop=2, slice_param=dict(axis=-1, slice_point=[1]))\n", + " _test_slice(data, ntop=3, slice_param=dict(axis=2, slice_point=[1, 6]))\n", + " _test_slice(data, ntop=3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Softmax" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_softmax(data, **kwargs):\n", + " \"\"\"One iteration of Softmax\"\"\"\n", + " _test_op(data, L.Softmax, \"Softmax\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Softmax():\n", + " \"\"\"Softmax\"\"\"\n", + " _test_softmax(np.random.rand(1, 3, 10, 10).astype(np.float32))\n", + " _test_softmax(np.random.rand(1, 3, 10, 10).astype(np.float32), axis=2)\n", + " _test_softmax(np.random.rand(10, 10).astype(np.float32), axis=0)\n", + " _test_softmax(np.random.rand(2, 10, 10).astype(np.float32), axis=1)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe TanH" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_tanh(data, **kwargs):\n", + " \"\"\"One iteration of TanH\"\"\"\n", + " _test_op(data, L.TanH, \"TanH\", **kwargs)\n", + "\n", + "\n", + "def test_forward_TanH():\n", + " \"\"\"TanH\"\"\"\n", + " _test_tanh(np.random.rand(1, 3, 10, 10).astype(np.float32))\n", + " _test_tanh(np.random.rand(3, 10, 10).astype(np.float32))\n", + " _test_tanh(np.random.rand(10, 10).astype(np.float32))\n", + " _test_tanh(np.random.rand(10).astype(np.float32))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Reduction " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def _test_reduction(data, **kwargs):\n", + " \"\"\"One iteration of Reduction\"\"\"\n", + " _test_op(data, L.Reduction, \"Reduction\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Reduction():\n", + " \"\"\"Reduction\"\"\"\n", + " reduction_op = {\"SUM\": 1, \"ASUM\": 2, \"SUMSQ\": 3, \"MEAN\": 4}\n", + " _test_reduction(np.random.rand(10).astype(np.float32), operation=reduction_op[\"SUM\"], axis=0)\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32), operation=reduction_op[\"SUM\"], axis=3\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32), operation=reduction_op[\"SUM\"], axis=1\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10).astype(np.float32), operation=reduction_op[\"SUM\"], axis=0, coeff=0.5\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32),\n", + " operation=reduction_op[\"SUM\"],\n", + " axis=3,\n", + " coeff=5.0,\n", + " )\n", + " _test_reduction(np.random.rand(10).astype(np.float32), operation=reduction_op[\"ASUM\"])\n", + " _test_reduction(\n", + " np.random.rand(10, 20).astype(np.float32), operation=reduction_op[\"ASUM\"], axis=1\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32), operation=reduction_op[\"ASUM\"], axis=3\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10).astype(np.float32), operation=reduction_op[\"ASUM\"], axis=0, coeff=0.0\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30).astype(np.float32),\n", + " operation=reduction_op[\"ASUM\"],\n", + " axis=2,\n", + " coeff=7.0,\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40, 10).astype(np.float32),\n", + " operation=reduction_op[\"ASUM\"],\n", + " axis=3,\n", + " coeff=1.0,\n", + " )\n", + " _test_reduction(np.random.rand(10).astype(np.float32), operation=reduction_op[\"SUMSQ\"], axis=0)\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32), operation=reduction_op[\"SUMSQ\"], axis=3\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10).astype(np.float32), operation=reduction_op[\"SUMSQ\"], axis=0, coeff=0.0\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40, 50).astype(np.float32),\n", + " operation=reduction_op[\"SUMSQ\"],\n", + " axis=4,\n", + " coeff=2.0,\n", + " )\n", + " _test_reduction(np.random.rand(10).astype(np.float32), operation=reduction_op[\"MEAN\"], axis=0)\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32), operation=reduction_op[\"MEAN\"], axis=3\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10).astype(np.float32), operation=reduction_op[\"MEAN\"], axis=0, coeff=0.0\n", + " )\n", + " _test_reduction(\n", + " np.random.rand(10, 20, 30, 40).astype(np.float32),\n", + " operation=reduction_op[\"MEAN\"],\n", + " axis=3,\n", + " coeff=2.0,\n", + " )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## caffe Embed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_embed(data, **kwargs):\n", + " \"\"\"One iteration of Embed\"\"\"\n", + " _test_op(data, L.Embed, \"Embed\", **kwargs)\n", + "\n", + "\n", + "def test_forward_Embed():\n", + " \"\"\"Embed\"\"\"\n", + " k = 20\n", + " data = list(i for i in range(k))\n", + " np.random.shuffle(data)\n", + " # dimension is 1\n", + " data = np.asarray(data)\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=True,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=False,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " # dimension is 2\n", + " data = np.reshape(data, [4, 5])\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=True,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=False,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " # dimension is 3\n", + " data = np.reshape(data, [2, 2, 5])\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=True,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=False,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " # dimension is 4\n", + " data = np.reshape(data, [2, 2, 5, 1])\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=True,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + " _test_embed(\n", + " data,\n", + " num_output=30,\n", + " input_dim=k,\n", + " bias_term=False,\n", + " weight_filler=dict(type=\"xavier\"),\n", + " bias_filler=dict(type=\"xavier\"),\n", + " )\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xxx", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/caffe_utils.py b/doc/frontend/caffe_utils.py new file mode 100644 index 00000000..f7a4af65 --- /dev/null +++ b/doc/frontend/caffe_utils.py @@ -0,0 +1,237 @@ +import os +import logging + +from google.protobuf import text_format +import caffe +from caffe import layers as L +from caffe.proto import caffe_pb2 as pb + +import tvm +import tvm.testing +from tvm import relay +from tvm.contrib import graph_executor + +os.environ["GLOG_minloglevel"] = "2" + +logging.basicConfig(level=logging.ERROR) + +CURRENT_DIR = os.path.join(os.path.expanduser("~"), ".tvm_test_data", "caffe_test") + +####################################################################### +# Generic functions for TVM & Caffe +# ------------------------------------------ + + +def _create_dir(d_path): + """If the directory is not existed, create it""" + if not (os.path.exists(d_path) and os.path.isdir(d_path)): + os.makedirs(d_path) + + +def _list_to_str(ll): + """Convert list or tuple to str, separated by underline.""" + if isinstance(ll, (tuple, list)): + tmp = [str(i) for i in ll] + res = "_".join(tmp) + return res + + +def _gen_filename_str(op_name, data_shape, *args, **kwargs): + """Combining the filename according to the op_name, shape and other args.""" + file_dir = os.path.join(CURRENT_DIR, op_name) + _create_dir(file_dir) + res = op_name + "_" + shape_str = _list_to_str(list(data_shape)) + res += shape_str + for arg in args: + if isinstance(arg, (tuple, list)): + res += "_" + _list_to_str(arg) + elif isinstance(arg, (int, float, str)): + res += "_" + str(arg) + for _, v in kwargs.items(): + if isinstance(v, (tuple, list)): + res += "_" + _list_to_str(v) + elif isinstance(v, (int, float, str)): + res += "_" + str(v) + res = res.replace(".", "_") + res = res.replace("-", "_") + proto_file = os.path.join(file_dir, res + ".prototxt") + blob_file = os.path.join(file_dir, res + ".caffemodel") + solver_file = os.path.join(file_dir, res + "_solver.prototxt") + + return (proto_file, blob_file, solver_file) + + +def _save_prototxt(n_netspec, f_path): + """Generate .prototxt file according to caffe.NetSpec""" + s = n_netspec.to_proto() + with open(f_path, "w") as f: + f.write(str(s)) + + +def _save_solver(solver_file, proto_file, blob_file): + """Define a solver proto, you can change the configs.""" + blob_file_prefix = blob_file.split(".caffemodel")[0] + s = pb.SolverParameter() + s.train_net = proto_file + s.base_lr = 0.01 + s.momentum = 0.9 + s.weight_decay = 0.0005 + s.lr_policy = "inv" + s.gamma = 0.0001 + s.power = 0.75 + s.display = 1 + s.max_iter = 100000 + s.snapshot = 100000 + s.snapshot_prefix = blob_file_prefix + + with open(solver_file, "w") as f: + f.write(str(s)) + + +def _save_caffemodel(solver_file, blob_file): + """Generate .caffemodel file.""" + solver = caffe.SGDSolver(solver_file) + solver.net.save(blob_file) + + +def _gen_model_files(n_netspec, proto_file, blob_file, solver_file): + _save_prototxt(n_netspec, proto_file) + _save_solver(solver_file, proto_file, blob_file) + _save_caffemodel(solver_file, blob_file) + + +def _siso_op(data, func, *args, **kwargs): + """Create single input and single output Caffe op""" + n = caffe.NetSpec() + n.data = L.Input(input_param={"shape": {"dim": list(data.shape)}}) + n.output = func(n.data, *args, **kwargs) + return n + + +def _miso_op(data_list, func, *args, **kwargs): + """Create multi input and single output Caffe op""" + n = caffe.NetSpec() + if not isinstance(data_list, (tuple, list)): + raise TypeError(f"Need tuple or list but get {type(data_list)}") + input_list = [] + for idx, data in enumerate(data_list): + n["data" + str(idx)] = L.Input(input_param={"shape": {"dim": list(data.shape)}}) + input_list.append(n["data" + str(idx)]) + n.output = func(*input_list, *args, **kwargs) + return n + + +def _simo_op(data, func, *args, **kwargs): + """Create single input and multi output Caffe op""" + n = caffe.NetSpec() + n.data = L.Input(input_param={"shape": {"dim": list(data.shape)}}) + output_list = func(n.data, *args, **kwargs) + for idx, out in enumerate(output_list): + n["output" + str(idx)] = out + return n + + +def _run_caffe(data, proto_file, blob_file): + """Run caffe model by Caffe according to .caffemodel and .prototxt""" + net = caffe.Net(proto_file, blob_file, caffe.TEST) + if isinstance(data, (list, tuple)): + for idx, d in enumerate(data): + net.blobs["data" + str(idx)].data[...] = d + else: + net.blobs["data"].data[...] = data + out = net.forward() + + caffe_output = [] + for i in range(len(out.keys())): + if "output" + str(i) not in out.keys(): + caffe_output.clear() + return list(out.values()) + caffe_output.append(out["output" + str(i)]) + return caffe_output + + +def _run_tvm(data, proto_file, blob_file): + """Run caffe model by TVM according to .caffemodel and .prototxt""" + init_net = pb.NetParameter() + predict_net = pb.NetParameter() + + # load model + with open(proto_file, "r") as f: + text_format.Merge(f.read(), predict_net) + # load blob + with open(blob_file, "rb") as f: + init_net.ParseFromString(f.read()) + + shape_dict = {} + dtype_dict = {} + if isinstance(data, (tuple, list)): + for idx, d in enumerate(data): + shape_dict["data" + str(idx)] = d.shape + dtype_dict["data" + str(idx)] = "float32" + else: + shape_dict = {"data": data.shape} + dtype_dict = {"data": "float32"} + + mod, params = relay.frontend.from_caffe(init_net, predict_net, shape_dict, dtype_dict) + + target = "llvm" + + dev = tvm.cpu(0) + with tvm.transform.PassContext(opt_level=3): + lib = relay.build(mod, target=target, params=params) + dtype = "float32" + m = graph_executor.GraphModule(lib["default"](dev)) + if isinstance(data, (tuple, list)): + for idx, d in enumerate(data): + m.set_input("data" + str(idx), tvm.nd.array(d.astype(dtype))) + else: + m.set_input("data", tvm.nd.array(data.astype(dtype))) + # execute + m.run() + tvm_output = [] + # get outputs + for i in range(m.get_num_outputs()): + tvm_output.append(m.get_output(i).numpy()) + return tvm_output + + +def _compare_caffe_tvm(caffe_out, tvm_out, is_network=False): + for i, _ in enumerate(caffe_out): + if is_network: + caffe_out[i] = caffe_out[i][:1] + tvm.testing.assert_allclose(caffe_out[i], tvm_out[i], rtol=1e-5, atol=1e-5) + + +def _test_op(data, func_op, op_name, **kwargs): + """Single op testing pipline.""" + shape_list = [] + if isinstance(data, (list, tuple)): + n = _miso_op(data, func_op, **kwargs) + for d in data: + shape_list.extend(list(d.shape)) + else: + output_num = 1 + if "ntop" in kwargs: + output_num = kwargs["ntop"] + if output_num == 1: + n = _siso_op(data, func_op, **kwargs) + else: + n = _simo_op(data, func_op, **kwargs) + shape_list = list(data.shape) + + # obtain the .caffemodel file and .prototxt file + (proto_file, blob_file, solver_file) = _gen_filename_str(op_name, shape_list, **kwargs) + _gen_model_files(n, proto_file, blob_file, solver_file) + # run model in Caffe + caffe_out = _run_caffe(data, proto_file, blob_file) + # run model in TVM + tvm_out = _run_tvm(data, proto_file, blob_file) + _compare_caffe_tvm(caffe_out, tvm_out) + +def _test_network(data, proto_file, blob_file): + # run model in Caffe + caffe_out = _run_caffe(data, proto_file, blob_file) + # run model in TVM + tvm_out = _run_tvm(data, proto_file, blob_file) + _compare_caffe_tvm(caffe_out, tvm_out, is_network=True) diff --git a/doc/frontend/index.md b/doc/frontend/index.md new file mode 100644 index 00000000..cd19edbc --- /dev/null +++ b/doc/frontend/index.md @@ -0,0 +1,9 @@ +# 前端 + +```{toctree} +tf/index +onnx/index +torch2onnx/index +tf2onnx/index +caffe/index +``` diff --git a/doc/frontend/onnx/converters.ipynb b/doc/frontend/onnx/converters.ipynb new file mode 100644 index 00000000..9c8581e0 --- /dev/null +++ b/doc/frontend/onnx/converters.ipynb @@ -0,0 +1,182 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ONNX 格式转换\n", + "\n", + "在生产中使用 ONNX 意味着模型的预测函数可以用 ONNX 算子实现。必须选择一个运行时,该运行时在模型部署的平台上可用。检查差异并最终测量延迟。如果存在一个支持模型所有部分的转换库,则模型转换的第一步可能很容易。如果不是这种情况,必须在 ONNX 中实现缺失的部分。这可能会非常耗时。\n", + "\n", + "## ONNX 转换库\n", + "\n", + "机器学习库通常有自己独特的设计。这就是为什么每个库都有一个特定的转换库。许多转换库在以下链接列出:\n", + "\n", + "\n", + "- [sklearn-onnx](https://onnx.ai/sklearn-onnx/):将模型从 [scikit-learn](https://scikit-learn.org/stable/) 转换过来\n", + "- [tensorflow-onnx](https://github.com/onnx/tensorflow-onnx):将模型从 [TensorFlow](https://www.tensorflow.org/) 转换过来\n", + "- [onnxmltools](https://github.com/onnx/onnxmltools):将模型从 [LightGBM](https://lightgbm.readthedocs.io/)、[XGBoost](https://xgboost.readthedocs.io/en/stable/)、[PySpark](https://spark.apache.org/docs/latest/api/python/)、[LibSVM](https://github.com/cjlin1/libsvm) 转换过来\n", + "- [torch.onnx](https://pytorch.org/docs/master/onnx.html):将模型从 [PyTorch](https://pytorch.org/) 转换过来" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ONNX 转换的替代方案\n", + "\n", + "实现 ONNX 导出功能的一种替代方法是利用标准协议,如 [Array API 标准](https://data-apis.org/array-api/latest/),该标准规范了一组通用的数组算子。它使得代码可以在诸如 NumPy、JAX、PyTorch、CuPy 等库之间重用。[ndonnx](https://github.com/Quantco/ndonnx) 支持使用 ONNX 后端进行执行,并为符合 Array API 标准的代码提供即时 ONNX 导出。这减少了专用转换库代码的需求,因为用于实现大部分库的相同代码可以在 ONNX 转换中重用。它还为寻找类似 NumPy 体验的转换作者提供了一种方便的原始操作,用于构建 ONNX 计算图。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ONNX 从经验中学到的技巧\n", + "\n", + "ONNX 是强类型的,并针对深度学习中最常见的类型 float32 进行了优化。标准机器学习库同时使用 float32 和 float64。numpy 通常转换为最通用的类型,即 float64。当预测函数是连续的时,这没有显著影响。当不是连续的时,必须使用正确的类型。切换到 float 时遇到的问题提供了有关该主题的更多见解。\n", + "\n", + "并行化改变了计算的顺序。这通常并不重要,但它可以解释一些奇怪的差异。`1 + 1e17 - 1e17 = 0`,但 `1e17 - 1e17 + 1 = 1`。高数量级的情况虽然少见,但当模型使用矩阵的逆时并不罕见。" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.0" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1 + 1e17 - 1e17" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1e17 - 1e17 + 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "规避上述错误,可以:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "from decimal import Decimal\n", + "\n", + "a = Decimal('1')\n", + "b = Decimal('1e17')\n", + "c = Decimal('-1e17')\n", + "\n", + "result = a + b + c\n", + "print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "23283064.365386963" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1e17 / (1 << 32)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.005421010862427522" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1e17 / (1 << 64)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xxx", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/onnx/images/linear_regressor-onnx.jpg b/doc/frontend/onnx/images/linear_regressor-onnx.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bcaa4d0ff48492d2f9aa6ae5051244191a04fda4 GIT binary patch literal 6499 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\u001b[0m \u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mValueInfoProto\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDocstring:\u001b[0m Makes a ValueInfoProto based on the data type and shape.\n", + "\u001b[0;31mFile:\u001b[0m /media/pc/data/lxw/envs/anaconda3x/envs/xxx/lib/python3.12/site-packages/onnx/helper.py\n", + "\u001b[0;31mType:\u001b[0m function" + ] + } + ], + "source": [ + "make_tensor_value_info?" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "X = make_tensor_value_info('X', TensorProto.FLOAT, [None, None])\n", + "A = make_tensor_value_info('A', TensorProto.FLOAT, [None, None])\n", + "B = make_tensor_value_info('B', TensorProto.FLOAT, [None, None])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "查看 `X`:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "name: \"X\"\n", + "type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + "}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "创建输出变量:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "Y = make_tensor_value_info('Y', TensorProto.FLOAT, [None])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "将上述变量组织为计算图的节点:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "node1 = make_node('MatMul', ['X', 'A'], ['XA'])\n", + "node2 = make_node('Add', ['XA', 'B'], ['Y'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "查看 `node1`:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "input: \"X\"\n", + "input: \"A\"\n", + "output: \"XA\"\n", + "op_type: \"MatMul\"" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "node1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "将节点组织为计算图:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[0;31mSignature:\u001b[0m\n", + "\u001b[0mmake_graph\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mnodes\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mSequence\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNodeProto\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0minputs\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mSequence\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mValueInfoProto\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0moutputs\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mSequence\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mValueInfoProto\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0minitializer\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mOptional\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mSequence\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTensorProto\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mdoc_string\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mOptional\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mvalue_info\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mOptional\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mSequence\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mValueInfoProto\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0msparse_initializer\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mOptional\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mSequence\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSparseTensorProto\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0monnx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monnx_ml_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGraphProto\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDocstring:\u001b[0m\n", + "Construct a GraphProto\n", + "\n", + "Args:\n", + " nodes: list of NodeProto\n", + " name (string): graph name\n", + " inputs: list of ValueInfoProto\n", + " outputs: list of ValueInfoProto\n", + " initializer: list of TensorProto\n", + " doc_string (string): graph documentation\n", + " value_info: list of ValueInfoProto\n", + " sparse_initializer: list of SparseTensorProto\n", + "Returns:\n", + " GraphProto\n", + "\u001b[0;31mFile:\u001b[0m /media/pc/data/lxw/envs/anaconda3x/envs/xxx/lib/python3.12/site-packages/onnx/helper.py\n", + "\u001b[0;31mType:\u001b[0m function" + ] + } + ], + "source": [ + "make_graph?" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "graph = make_graph(\n", + " [node1, node2], # nodes\n", + " 'lr', # a name\n", + " [X, A, B], # inputs\n", + " [Y] # outputs\n", + ") " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "node {\n", + " input: \"X\"\n", + " input: \"A\"\n", + " output: \"XA\"\n", + " op_type: \"MatMul\"\n", + "}\n", + "node {\n", + " input: \"XA\"\n", + " input: \"B\"\n", + " output: \"Y\"\n", + " op_type: \"Add\"\n", + "}\n", + "name: \"lr\"\n", + "input {\n", + " name: \"X\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "input {\n", + " name: \"A\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "input {\n", + " name: \"B\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "output {\n", + " name: \"Y\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "graph" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "将计算图变换为模型:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "onnx_model = make_model(graph)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ir_version: 10\n", + "graph {\n", + " node {\n", + " input: \"X\"\n", + " input: \"A\"\n", + " output: \"XA\"\n", + " op_type: \"MatMul\"\n", + " }\n", + " node {\n", + " input: \"XA\"\n", + " input: \"B\"\n", + " output: \"Y\"\n", + " op_type: \"Add\"\n", + " }\n", + " name: \"lr\"\n", + " input {\n", + " name: \"X\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " input {\n", + " name: \"A\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " input {\n", + " name: \"B\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " output {\n", + " name: \"Y\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "opset_import {\n", + " version: 21\n", + "}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "onnx_model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```{note}\n", + "空的形状({data}`None`)意味着任何形状。\n", + "```\n", + "\n", + "## 访问 ONNX graph\n", + "\n", + "ONNX graph 也可以通过查看计算图中每个对象的字段来检查。\n", + "\n", + "查看输入列表:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[name: \"X\"\n", + "type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + "}\n", + ", name: \"A\"\n", + "type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + "}\n", + ", name: \"B\"\n", + "type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + "}\n", + "]\n" + ] + } + ], + "source": [ + "print(onnx_model.graph.input)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "更优雅的打印输入信息:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def shape2tuple(shape):\n", + " return tuple(getattr(d, 'dim_value', 0) for d in shape.dim)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name='X' dtype=1 shape=(0, 0)\n", + "name='A' dtype=1 shape=(0, 0)\n", + "name='B' dtype=1 shape=(0, 0)\n" + ] + } + ], + "source": [ + "for obj in onnx_model.graph.input:\n", + " print(\"name=%r dtype=%r shape=%r\" % (\n", + " obj.name, obj.type.tensor_type.elem_type,\n", + " shape2tuple(obj.type.tensor_type.shape)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "同样可以查看输出信息:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name='Y' dtype=1 shape=(0,)\n" + ] + } + ], + "source": [ + "for obj in onnx_model.graph.output:\n", + " print(\"name=%r dtype=%r shape=%r\" % (\n", + " obj.name, obj.type.tensor_type.elem_type,\n", + " shape2tuple(obj.type.tensor_type.shape)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "查看节点信息:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name='' type='MatMul' input=['X', 'A'] output=['XA']\n", + "name='' type='Add' input=['XA', 'B'] output=['Y']\n" + ] + } + ], + "source": [ + "for node in onnx_model.graph.node:\n", + " print(\"name=%r type=%r input=%r output=%r\" % (\n", + " node.name, node.op_type, node.input, node.output))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ONNX 序列化与反序列化\n", + "\n", + "onnx 中的每个对象(参见 [Protos](https://onnx.ai/onnx/api/classes.html#l-onnx-classes))都可以用 `SerializeToString` 方法序列化。" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "!mkdir -p .temp\n", + "with open(\".temp/linear_regression.onnx\", \"wb\") as f:\n", + " f.write(onnx_model.SerializeToString())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "反序列化,加载序列化的模型:" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "import onnx\n", + "\n", + "with open(\".temp/linear_regression.onnx\", \"rb\") as f:\n", + " onnx_model = onnx.load(f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "数据也可以序列化:" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from onnx.numpy_helper import from_array\n", + "\n", + "numpy_tensor = np.array([0, 1, 4, 5, 3], dtype=np.float32)\n", + "print(type(numpy_tensor))\n", + "\n", + "onnx_tensor = from_array(numpy_tensor)\n", + "print(type(onnx_tensor))\n", + "\n", + "serialized_tensor = onnx_tensor.SerializeToString()\n", + "print(type(serialized_tensor))\n", + "\n", + "with open(\".temp/saved_tensor.pb\", \"wb\") as f:\n", + " f.write(serialized_tensor)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "反序列化数据:" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "[0. 1. 4. 5. 3.]\n" + ] + } + ], + "source": [ + "from onnx import TensorProto\n", + "from onnx.numpy_helper import to_array\n", + "\n", + "with open(\".temp/saved_tensor.pb\", \"rb\") as f:\n", + " serialized_tensor = f.read()\n", + "print(type(serialized_tensor))\n", + "\n", + "onnx_tensor = TensorProto()\n", + "onnx_tensor.ParseFromString(serialized_tensor)\n", + "print(type(onnx_tensor))\n", + "\n", + "numpy_tensor = to_array(onnx_tensor)\n", + "print(numpy_tensor)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "也可以使用便捷函数 `load_tensor_from_string`:" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "from onnx import load_tensor_from_string\n", + "\n", + "with open(\"saved_tensor.pb\", \"rb\") as f:\n", + " serialized = f.read()\n", + "proto = load_tensor_from_string(serialized)\n", + "print(type(proto))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ONNX 初始化器与默认值\n", + "\n", + "之前的模型假设线性回归的系数也是模型的输入。那不太方便。它们应该作为常量或初始化项成为模型本身的一部分,以遵循 onnx 语义。下一个示例修改了前一个示例,将输入 `A` 和 `B` 更改为初始化式。(参见 [array](https://onnx.ai/onnx/api/numpy_helper.html#l-numpy-helper-onnx-array))。\n", + "\n", + "- `onnx.numpy_helper.to_array`: 将 ONNX 转换为 NumPy 数组。\n", + "- `onnx.numpy_helper.from_array`: 将 NumPy 数组转换为 ONNX。" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from onnx import numpy_helper, TensorProto\n", + "from onnx.helper import (\n", + " make_model, make_node, make_graph,\n", + " make_tensor_value_info)\n", + "from onnx.checker import check_model\n", + "\n", + "# initializers\n", + "value = np.array([0.5, -0.6], dtype=np.float32)\n", + "A = numpy_helper.from_array(value, name='A')\n", + "\n", + "value = np.array([0.4], dtype=np.float32)\n", + "C = numpy_helper.from_array(value, name='C')\n", + "\n", + "X = make_tensor_value_info('X', TensorProto.FLOAT, [None, None])\n", + "Y = make_tensor_value_info('Y', TensorProto.FLOAT, [None])\n", + "node1 = make_node('MatMul', ['X', 'A'], ['AX'])\n", + "node2 = make_node('Add', ['AX', 'C'], ['Y'])\n", + "graph = make_graph([node1, node2], 'lr', [X], [Y], [A, C])\n", + "onnx_model = make_model(graph)\n", + "check_model(onnx_model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "查看初始化值:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dims: 2\n", + "data_type: 1\n", + "name: \"A\"\n", + "raw_data: \"\\000\\000\\000?\\232\\231\\031\\277\"\n", + "\n", + "dims: 1\n", + "data_type: 1\n", + "name: \"C\"\n", + "raw_data: \"\\315\\314\\314>\"\n", + "\n" + ] + } + ], + "source": [ + "for init in onnx_model.graph.initializer:\n", + " print(init)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ONNX 节点属性" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ir_version: 10\n", + "graph {\n", + " node {\n", + " input: \"A\"\n", + " output: \"tA\"\n", + " op_type: \"Transpose\"\n", + " attribute {\n", + " name: \"perm\"\n", + " ints: 1\n", + " ints: 0\n", + " type: INTS\n", + " }\n", + " }\n", + " node {\n", + " input: \"X\"\n", + " input: \"tA\"\n", + " output: \"XA\"\n", + " op_type: \"MatMul\"\n", + " }\n", + " node {\n", + " input: \"XA\"\n", + " input: \"B\"\n", + " output: \"Y\"\n", + " op_type: \"Add\"\n", + " }\n", + " name: \"lr\"\n", + " input {\n", + " name: \"X\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " input {\n", + " name: \"A\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " input {\n", + " name: \"B\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " output {\n", + " name: \"Y\"\n", + " type {\n", + " tensor_type {\n", + " elem_type: 1\n", + " shape {\n", + " dim {\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "opset_import {\n", + " version: 21\n", + "}\n", + "\n" + ] + } + ], + "source": [ + "from onnx import TensorProto\n", + "from onnx.helper import (\n", + " make_model, make_node, make_graph,\n", + " make_tensor_value_info)\n", + "from onnx.checker import check_model\n", + "\n", + "# unchanged\n", + "X = make_tensor_value_info('X', TensorProto.FLOAT, [None, None])\n", + "A = make_tensor_value_info('A', TensorProto.FLOAT, [None, None])\n", + "B = make_tensor_value_info('B', TensorProto.FLOAT, [None, None])\n", + "Y = make_tensor_value_info('Y', TensorProto.FLOAT, [None])\n", + "\n", + "# 添加属性\n", + "node_transpose = make_node('Transpose', ['A'], ['tA'], perm=[1, 0])\n", + "\n", + "# unchanged except A is replaced by tA\n", + "node1 = make_node('MatMul', ['X', 'tA'], ['XA'])\n", + "node2 = make_node('Add', ['XA', 'B'], ['Y'])\n", + "\n", + "# node_transpose is added to the list\n", + "graph = make_graph([node_transpose, node1, node2],\n", + " 'lr', [X, A, B], [Y])\n", + "onnx_model = make_model(graph)\n", + "check_model(onnx_model)\n", + "\n", + "# the work is done, let's display it...\n", + "print(onnx_model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ONNX 评估与运行时\n", + "\n", + "完整 API 的描述见 [onnx.reference](https://onnx.ai/onnx/api/reference.html#l-reference-implementation)。它接受一个模型(ModelProto,文件名,…)。方法 `run` 返回字典中指定的一组给定输入的输出。" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[array([[-1.8057449],\n", + " [-2.0268912],\n", + " [-1.369731 ],\n", + " [-1.8334708]], dtype=float32)]\n" + ] + } + ], + "source": [ + "import numpy\n", + "from onnx import numpy_helper, TensorProto\n", + "from onnx.helper import (\n", + " make_model, make_node, set_model_props, make_tensor,\n", + " make_graph, make_tensor_value_info)\n", + "from onnx.checker import check_model\n", + "from onnx.reference import ReferenceEvaluator\n", + "\n", + "X = make_tensor_value_info('X', TensorProto.FLOAT, [None, None])\n", + "A = make_tensor_value_info('A', TensorProto.FLOAT, [None, None])\n", + "B = make_tensor_value_info('B', TensorProto.FLOAT, [None, None])\n", + "Y = make_tensor_value_info('Y', TensorProto.FLOAT, [None])\n", + "node1 = make_node('MatMul', ['X', 'A'], ['XA'])\n", + "node2 = make_node('Add', ['XA', 'B'], ['Y'])\n", + "graph = make_graph([node1, node2], 'lr', [X, A, B], [Y])\n", + "onnx_model = make_model(graph)\n", + "check_model(onnx_model)\n", + "\n", + "sess = ReferenceEvaluator(onnx_model)\n", + "\n", + "x = numpy.random.randn(4, 2).astype(numpy.float32)\n", + "a = numpy.random.randn(2, 1).astype(numpy.float32)\n", + "b = numpy.random.randn(1, 1).astype(numpy.float32)\n", + "feeds = {'X': x, 'A': a, 'B': b}\n", + "\n", + "print(sess.run(None, feeds))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ONNX 评估节点\n", + "\n", + "评估器还可以评估简单的节点,以检查算子在特定输入上的行为。" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[array([[1., 0.],\n", + " [0., 1.],\n", + " [0., 0.],\n", + " [0., 0.]], dtype=float32)]\n" + ] + } + ], + "source": [ + "import numpy\n", + "from onnx import numpy_helper, TensorProto\n", + "from onnx.helper import make_node\n", + "\n", + "from onnx.reference import ReferenceEvaluator\n", + "\n", + "node = make_node('EyeLike', ['X'], ['Y'])\n", + "\n", + "sess = ReferenceEvaluator(node)\n", + "\n", + "x = numpy.random.randn(4, 2).astype(numpy.float32)\n", + "feeds = {'X': x}\n", + "\n", + "print(sess.run(None, feeds))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "类似的代码也可以在 `GraphProto` 或 `FunctionProto` 上工作。\n", + "\n", + "### ONNX 逐步评估\n", + "\n", + "转换库接受使用机器学习框架(如 PyTorch、scikit-learn 等)训练的现有模型,并将其转换为 ONNX graph。复杂的模型通常不会在第一次尝试中工作,查看中间结果可能有助于找到未正确转换的部分。参数详细显示有关中间结果的信息。" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "------ verbose=1\n", + "\n", + "[array([[ 0.9199427 ],\n", + " [ 0.3668961 ],\n", + " [ 0.04145484],\n", + " [-0.4361933 ]], dtype=float32)]\n", + "\n", + "------ verbose=2\n", + "\n", + "MatMul(X, A) -> XA\n", + "Add(XA, B) -> Y\n", + "[array([[3.8724718],\n", + " [4.0825634],\n", + " [0.4058497],\n", + " [2.005159 ]], dtype=float32)]\n", + "\n", + "------ verbose=3\n", + "\n", + " +I X: float32:(4, 2) in [-1.1875110864639282, 1.6281424760818481]\n", + " +I A: float32:(2, 1) in [-1.774684190750122, -1.7485564947128296]\n", + " +I B: float32:(1, 1) in [0.5859348177909851, 0.5859348177909851]\n", + "MatMul(X, A) -> XA\n", + " + XA: float32:(4, 1) in [-2.718858480453491, 3.8624463081359863]\n", + "Add(XA, B) -> Y\n", + " + Y: float32:(4, 1) in [-2.1329236030578613, 4.448380947113037]\n", + "[array([[ 1.2496312 ],\n", + " [ 4.448381 ],\n", + " [-2.1329236 ],\n", + " [ 0.39690298]], dtype=float32)]\n", + "\n", + "------ verbose=4\n", + "\n", + " +I X: float32:(4, 2):1.1294219493865967,0.30637702345848083,-0.029152901843190193,0.06715787202119827,0.20514409244060516...\n", + " +I A: float32:(2, 1):[-0.08160115778446198, 1.6542348861694336]\n", + " +I B: float32:(1, 1):[-0.9010018110275269]\n", + "MatMul(X, A) -> XA\n", + " + XA: float32:(4, 1):[0.4146574139595032, 0.1134738028049469, 2.200101137161255, -0.3942927122116089]\n", + "Add(XA, B) -> Y\n", + " + Y: float32:(4, 1):[-0.4863443970680237, -0.7875280380249023, 1.299099326133728, -1.2952945232391357]\n", + "[array([[-0.4863444 ],\n", + " [-0.78752804],\n", + " [ 1.2990993 ],\n", + " [-1.2952945 ]], dtype=float32)]\n" + ] + } + ], + "source": [ + "import numpy\n", + "from onnx import numpy_helper, TensorProto\n", + "from onnx.helper import (\n", + " make_model, make_node, set_model_props, make_tensor,\n", + " make_graph, make_tensor_value_info)\n", + "from onnx.checker import check_model\n", + "from onnx.reference import ReferenceEvaluator\n", + "\n", + "X = make_tensor_value_info('X', TensorProto.FLOAT, [None, None])\n", + "A = make_tensor_value_info('A', TensorProto.FLOAT, [None, None])\n", + "B = make_tensor_value_info('B', TensorProto.FLOAT, [None, None])\n", + "Y = make_tensor_value_info('Y', TensorProto.FLOAT, [None])\n", + "node1 = make_node('MatMul', ['X', 'A'], ['XA'])\n", + "node2 = make_node('Add', ['XA', 'B'], ['Y'])\n", + "graph = make_graph([node1, node2], 'lr', [X, A, B], [Y])\n", + "onnx_model = make_model(graph)\n", + "check_model(onnx_model)\n", + "\n", + "for verbose in [1, 2, 3, 4]:\n", + " print()\n", + " print(f\"------ verbose={verbose}\")\n", + " print()\n", + " sess = ReferenceEvaluator(onnx_model, verbose=verbose)\n", + "\n", + " x = numpy.random.randn(4, 2).astype(numpy.float32)\n", + " a = numpy.random.randn(2, 1).astype(numpy.float32)\n", + " b = numpy.random.randn(1, 1).astype(numpy.float32)\n", + " feeds = {'X': x, 'A': a, 'B': b}\n", + "\n", + " print(sess.run(None, feeds))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ONNX 评估自定义节点\n", + "以下示例仍然实现了线性回归,但在 `A` 中添加了单位矩阵:\n", + "\n", + "$$\n", + "Y = X(A + I) + B\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "EyeLike(A) -> Eye\n", + "Add(A, Eye) -> A1\n", + "MatMul(X, A1) -> XA1\n", + "Add(XA1, B) -> Y\n", + "[array([[ 1.5872786 , 2.8542266 ],\n", + " [ 0.64192116, -1.225003 ],\n", + " [-1.0039632 , 1.1880492 ],\n", + " [-0.31344515, 0.10079634]], dtype=float32)]\n" + ] + } + ], + "source": [ + "import numpy\n", + "from onnx import numpy_helper, TensorProto\n", + "from onnx.helper import (\n", + " make_model, make_node, set_model_props, make_tensor,\n", + " make_graph, make_tensor_value_info)\n", + "from onnx.checker import check_model\n", + "from onnx.reference import ReferenceEvaluator\n", + "\n", + "X = make_tensor_value_info('X', TensorProto.FLOAT, [None, None])\n", + "A = make_tensor_value_info('A', TensorProto.FLOAT, [None, None])\n", + "B = make_tensor_value_info('B', TensorProto.FLOAT, [None, None])\n", + "Y = make_tensor_value_info('Y', TensorProto.FLOAT, [None])\n", + "node0 = make_node('EyeLike', ['A'], ['Eye'])\n", + "node1 = make_node('Add', ['A', 'Eye'], ['A1'])\n", + "node2 = make_node('MatMul', ['X', 'A1'], ['XA1'])\n", + "node3 = make_node('Add', ['XA1', 'B'], ['Y'])\n", + "graph = make_graph([node0, node1, node2, node3], 'lr', [X, A, B], [Y])\n", + "onnx_model = make_model(graph)\n", + "check_model(onnx_model)\n", + "with open(\"linear_regression.onnx\", \"wb\") as f:\n", + " f.write(onnx_model.SerializeToString())\n", + "\n", + "sess = ReferenceEvaluator(onnx_model, verbose=2)\n", + "\n", + "x = numpy.random.randn(4, 2).astype(numpy.float32)\n", + "a = numpy.random.randn(2, 2).astype(numpy.float32) / 10\n", + "b = numpy.random.randn(1, 2).astype(numpy.float32)\n", + "feeds = {'X': x, 'A': a, 'B': b}\n", + "\n", + "print(sess.run(None, feeds))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xxx", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/onnx/onnxscript/chunk.ipynb b/doc/frontend/onnx/onnxscript/chunk.ipynb new file mode 100644 index 00000000..93016d10 --- /dev/null +++ b/doc/frontend/onnx/onnxscript/chunk.ipynb @@ -0,0 +1,127 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ONNX Script chunk\n", + "\n", + "下面的例子是直接从新的 PyTorch ONNX 导出器改编而来,实现了对 {func}`torch.chunk` 的支持,该函数尝试将张量分割成指定数量的块。" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Sequence\n", + "from onnxscript import opset18 as op, script, FLOAT, INT64\n", + "\n", + "@script()\n", + "def aten_chunk(\n", + " tensor: FLOAT[...], chunks: int, dim: int = 0,\n", + ") -> Sequence[FLOAT[...]]:\n", + " neg_1 = op.Constant(value_ints=[-1])\n", + "\n", + " # Get size of specified dim\n", + " dim_size = op.Shape(tensor)[dim]\n", + "\n", + " # Compute size/chunk to get the number of data in one chunk\n", + " num_per_chunk = dim_size / chunks + op.Cast(dim_size % chunks > 0, to=INT64.dtype)\n", + "\n", + " # Compute real chunk number\n", + " num_chunk = dim_size / num_per_chunk\n", + "\n", + " # Get something like [n, n, n, n, ...], total num_chunk\n", + " list_split = op.Expand(num_per_chunk, op.Reshape(num_chunk, neg_1))\n", + "\n", + " remainder = dim_size % num_per_chunk\n", + " if remainder > 0:\n", + " # Append the remainder to the [n, n, n, n, ..., r]\n", + " list_split = op.Concat(list_split, op.Reshape(remainder, neg_1), axis=0)\n", + "\n", + " return op.SplitToSequence(tensor, list_split, axis=dim)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "我们从 onnxscript 导入我们想要使用的 ONNX opset(在这个例子中是版本18)、`@script` 装饰器,以及 FLOAT 和 INT64 的张量类型。在 ONNX Script 中,张量形状是通过类型下标表示的,例如 `FLOAT[2, 10]`,或者符号性地表示为 `FLOAT[\"M\", \"N\"]`,或者在张量形状未知的情况下使用 `FLOAT[...]`。如果没有下标(仅 FLOAT),该类型旨在表示标量(秩为 0 的张量)。\n", + "\n", + "接下来,我们定义了一个带有类型注解的 `aten_chunk` 函数,并使用内置的 Python 语法和显式的 ONNX 算子调用来实现函数体。这个例子使用了各种二元表达式和一个 `if` 语句,但也支持许多其他的 Python 惯用构造。\n", + "\n", + "我们还需要定义一个简单的模型来调用我们的 ONNX Script 函数,以便我们可以导出并验证一个端到端的例子:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "@script()\n", + "def ten_chunks_model(tensor: FLOAT[\"M\"]):\n", + " return aten_chunk(tensor, chunks=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "这个模型将简单地将提供的张量分割成十个张量,但它也展示了 ONNX 函数当然可以调用其他 ONNX 函数,而不仅仅是内置的 ONNX 算子。\n", + "\n", + "我们现在将把 ONNX Script 模型导出到 ONNX,并在 [Netron](https://netron.app/) 中探索它。使用 `@script` 装饰的函数允许它们使用 `to_model_proto` 函数进行导出。" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import onnx\n", + "onnx.save_model(\n", + " ten_chunks_model.to_model_proto(),\n", + " \"ten_chunks_model.onnx\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](images/ten_chunks_model.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "图表展示了我们的两个 ONNX 函数;我们可以观察到原始的输入张量从 `ten_chunks_model` 流入 `aten_chunk`,以及属性 chunks=10。返回的是一系列最多包含 10 个张量的序列。正如人们所期望的,ONNX 中的函数可以定义一次,并在模型中任意多次调用。*[阅读更多关于核心 ONNX 概念的信息](https://onnx.ai/onnx/intro/concepts.html#input-output-node-initializer-attributes)。*" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xin", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/onnx/onnxscript/eager-mode-eval.ipynb b/doc/frontend/onnx/onnxscript/eager-mode-eval.ipynb new file mode 100644 index 00000000..8aad977d --- /dev/null +++ b/doc/frontend/onnx/onnxscript/eager-mode-eval.ipynb @@ -0,0 +1,111 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ONNX Script 急切模式评估\n", + "onnxscript 函数可以直接作为 Python 函数执行(例如,使用 Python 调试器)。这对于调试 onnxscript 函数定义非常有用。这种执行利用了函数定义中使用的 ONNX 操作的后端实现。目前,后端实现使用 onnxruntime 来执行每个操作调用。这种执行模式被称为急切模式评估。\n", + "\n", + "下面的示例说明了这一点。我们首先定义一个 onnxscript 函数:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "from onnxscript import FLOAT, script\n", + "from onnxscript import opset15 as op\n", + "\n", + "\n", + "@script()\n", + "def linear(A: FLOAT[\"N\", \"K\"], W: FLOAT[\"K\", \"M\"], Bias: FLOAT[\"M\"]) -> FLOAT[\"N\", \"M\"]: # noqa: F821\n", + " T1 = op.MatMul(A, W)\n", + " T2 = op.Add(T1, Bias)\n", + " Y = op.Relu(T2)\n", + " return Y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "创建用于评估函数的输入:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(0)\n", + "m = 4\n", + "k = 16\n", + "n = 4\n", + "a = np.random.rand(k, m).astype(\"float32\").T\n", + "w = np.random.rand(n, k).astype(\"float32\").T\n", + "b = np.random.rand(n).astype(\"float32\").T" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "评估结果:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[3.7695956 3.8361263 5.116064 5.2047744]\n", + " [4.5182567 4.2103305 4.54666 5.6752048]\n", + " [4.0728097 3.1566992 4.821034 4.7809625]\n", + " [4.925565 3.558134 4.7679787 5.3899584]]\n" + ] + } + ], + "source": [ + "print(linear(a, w, b))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xin", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/onnx/onnxscript/export-lib.ipynb b/doc/frontend/onnx/onnxscript/export-lib.ipynb new file mode 100644 index 00000000..65167965 --- /dev/null +++ b/doc/frontend/onnx/onnxscript/export-lib.ipynb @@ -0,0 +1,109 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 生成 LibProto\n", + "\n", + "以下示例展示了我们如何定义一个由多个函数组成的库,并将其导出。\n", + "\n", + "这是原型的。要完全支持 LibProto,需要原型扩展。" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from onnxscript import export_onnx_lib, script\n", + "from onnxscript import opset15 as op\n", + "from onnxscript.values import Opset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "下面定义的库函数的域/版本" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "opset = Opset(\"com.mydomain\", 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "定义函数库:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "@script(opset)\n", + "def l2norm(X):\n", + " return op.ReduceSum(X * X, keepdims=1)\n", + "\n", + "\n", + "@script(opset)\n", + "def square_loss(X, Y):\n", + " return l2norm(op.Sub(X, Y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "将函数作为 ONNX 库导出。" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "export_onnx_lib([l2norm, square_loss], \"mylib.onnxlib\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xin", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/onnx/onnxscript/gelu.ipynb b/doc/frontend/onnx/onnxscript/gelu.ipynb new file mode 100644 index 00000000..23250b25 --- /dev/null +++ b/doc/frontend/onnx/onnxscript/gelu.ipynb @@ -0,0 +1,73 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ONNX Script GELU" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "from onnxscript import (\n", + " script, opset18 as op, FLOAT\n", + ")\n", + "\n", + "M_SQRT1_2 = math.sqrt(0.5)\n", + "\n", + "@script()\n", + "def gelu(X: FLOAT[...]):\n", + " phiX = 0.5 * (op.Erf(M_SQRT1_2 * X) + 1.0)\n", + " return X * phiX\n", + "\n", + "model = gelu.to_model_proto()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import onnx\n", + "onnx.save_model(\n", + " model,\n", + " \"gelu.onnx\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "xin", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/frontend/onnx/onnxscript/images/custom_aten_add.jpg b/doc/frontend/onnx/onnxscript/images/custom_aten_add.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f2019eb61037784d48fdb3ff749f2c8d3db0ed9d GIT binary patch literal 8803 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 U-lHO)C>i{BsQN$YqasfIA3%Wea{vGU literal 0 HcmV?d00001 diff --git a/doc/frontend/onnx/onnxscript/images/custom_aten_gelu.jpg b/doc/frontend/onnx/onnxscript/images/custom_aten_gelu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c9eef28ce24f6f136f35f35e553d54b75b929bef GIT binary patch literal 7101 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 aJDqTu=NSpp=9>Tjxojix7s`i`zWocyg|pBA literal 0 HcmV?d00001 diff --git a/doc/frontend/onnx/onnxscript/images/custom_aten_gelu2.jpg b/doc/frontend/onnx/onnxscript/images/custom_aten_gelu2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ecf6881f58db11f4da5ddea869ec6615bb38afa6 GIT binary patch literal 25614 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 literal 0 HcmV?d00001 diff --git a/doc/frontend/onnx/onnxscript/images/custon_aten_add_2.jpg b/doc/frontend/onnx/onnxscript/images/custon_aten_add_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..10f7b9b78158d5fbccd740063aadad828a0aeebc GIT binary patch literal 11506 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 DvHBrr literal 0 HcmV?d00001 diff --git a/doc/frontend/onnx/onnxscript/images/ten_chunks_model.png b/doc/frontend/onnx/onnxscript/images/ten_chunks_model.png new file mode 100644 index 0000000000000000000000000000000000000000..760cd204578b7b1f6340478031c7438c9ed21ae8 GIT binary patch literal 1084072 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⋘BogmcQ7QaW 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