| @@ -75,7 +75,7 @@ jobs: | |||
| python3 -m pip install --upgrade pip | |||
| apt-get remove -y python3-setuptools | |||
| pip3 install -U setuptools==69.5.1 | |||
| pip3 install -U pytest wheel twine requests einops | |||
| pip3 install -U pytest wheel twine requests einops numpy==1.26.4 | |||
| cd ${{ci.workspace}} | |||
| wget -q https://github.com/Kitware/CMake/releases/download/v3.29.3/cmake-3.29.3-linux-x86_64.tar.gz | |||
| tar -xf cmake-3.29.3-linux-x86_64.tar.gz | |||
| @@ -124,7 +124,9 @@ set(pnnx_pass_level2_SRCS | |||
| pass_level2/F_conv2d.cpp | |||
| pass_level2/F_conv3d.cpp | |||
| pass_level2/F_conv_transpose123d.cpp | |||
| pass_level2/F_conv_transpose1d.cpp | |||
| pass_level2/F_conv_transpose2d.cpp | |||
| pass_level2/F_conv_transpose3d.cpp | |||
| pass_level2/F_dropout.cpp | |||
| pass_level2/F_dropout23d.cpp | |||
| pass_level2/F_elu.cpp | |||
| @@ -650,6 +652,7 @@ if(onnxruntime_FOUND) | |||
| pass_onnx/inline_containers.cpp | |||
| pass_onnx/model_stat.cpp | |||
| pass_onnx/shape_inference.cpp | |||
| pass_onnx/fuse_constant_as_attribute.cpp | |||
| pass_onnx/nn_AdaptiveAvgPool2d.cpp | |||
| pass_onnx/nn_AdaptiveAvgPool3d.cpp | |||
| @@ -34,6 +34,7 @@ | |||
| #include "pass_onnx/inline_containers.h" | |||
| #include "pass_onnx/model_stat.h" | |||
| #include "pass_onnx/shape_inference.h" | |||
| #include "pass_onnx/fuse_constant_as_attribute.h" | |||
| #include "pass_onnx.h" | |||
| @@ -652,6 +653,26 @@ int load_onnx(const std::string& onnxpath, Graph& pnnx_graph, | |||
| } | |||
| } | |||
| fprintf(stderr, "%-34s", "fuse_constant_as_attribute ... "); | |||
| t0 = get_current_time(); | |||
| onnx2pnnx::fuse_constant_as_attribute(model); | |||
| t1 = get_current_time(); | |||
| fprintf(stderr, "%8.2fms\n", t1 - t0); | |||
| fprintf(stderr, "%-34s", "dead_code_elimination ... "); | |||
| t0 = get_current_time(); | |||
| onnx2pnnx::dead_code_elimination(model); | |||
| t1 = get_current_time(); | |||
| fprintf(stderr, "%8.2fms\n", t1 - t0); | |||
| onnx2pnnx::ModelStat newstat = onnx2pnnx::get_model_stat(model); | |||
| onnx2pnnx::print_model_stat(oldstat, newstat); | |||
| @@ -77,4 +77,158 @@ pnnx.Output output 1 0 out | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_convmode, 10) | |||
| class F_conv1d_onnx : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| Conv op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv1d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 2 || pads[0] != pads[1]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0]}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv1d_onnx, 10) | |||
| class F_conv1d_onnx_0 : public F_conv1d_onnx | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| Conv op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv1d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv1d_onnx_0, 10) | |||
| class F_conv1d_onnx_1 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| Conv op_0 3 1 input weight bias out strides=%strides pads=%pads dilations=%dilations group=%group auto_pad=NOTSET | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv1d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 2 || pads[0] != pads[1]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0]}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv1d_onnx_1, 10) | |||
| } // namespace pnnx | |||
| @@ -98,4 +98,158 @@ pnnx.Output output 1 0 out | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv3d_0, 10) | |||
| class F_conv3d_onnx : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| Conv op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv3d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 6 || pads[0] != pads[3] || pads[1] != pads[4] || pads[2] != pads[5]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0], pads[1], pads[2]}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv3d_onnx, 10) | |||
| class F_conv3d_onnx_0 : public F_conv3d_onnx | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| Conv op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv3d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv3d_onnx_0, 10) | |||
| class F_conv3d_onnx_1 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| Conv op_0 3 1 input weight bias out strides=%strides pads=%pads dilations=%dilations group=%group auto_pad=NOTSET | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv3d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 6 || pads[0] != pads[3] || pads[1] != pads[4] || pads[2] != pads[5]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0], pads[1], pads[2]}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv3d_onnx_1, 10) | |||
| } // namespace pnnx | |||
| @@ -0,0 +1,276 @@ | |||
| // Tencent is pleased to support the open source community by making ncnn available. | |||
| // | |||
| // Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| // | |||
| // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| // in compliance with the License. You may obtain a copy of the License at | |||
| // | |||
| // https://opensource.org/licenses/BSD-3-Clause | |||
| // | |||
| // 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. | |||
| #include "pass_level2.h" | |||
| namespace pnnx { | |||
| class F_conv_transpose1d_onnx : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose1d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 2 || pads[0] != pads[1]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0]}; | |||
| op->params["output_padding"] = {0}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose1d_onnx, 10) | |||
| class F_conv_transpose1d_onnx_0 : public F_conv_transpose1d_onnx | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| ConvTranspose op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv_transpose1d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose1d_onnx_0, 10) | |||
| class F_conv_transpose1d_onnx_1 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out strides=%strides pads=%pads dilations=%dilations group=%group auto_pad=NOTSET | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose1d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 2 || pads[0] != pads[1]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0]}; | |||
| op->params["output_padding"] = {0}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose1d_onnx_1, 10) | |||
| class F_conv_transpose1d_onnx_2 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group output_padding=%output_padding | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose1d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("output_padding").type != 5) | |||
| return false; | |||
| if (captured_params.at("output_padding").ai.size() != 1) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 2 || pads[0] != pads[1]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0]}; | |||
| op->params["output_padding"] = captured_params.at("output_padding"); | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose1d_onnx_2, 10) | |||
| class F_conv_transpose1d_onnx_3 : public F_conv_transpose1d_onnx_2 | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| ConvTranspose op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group output_padding=%output_padding | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv_transpose1d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose1d_onnx_3, 10) | |||
| } // namespace pnnx | |||
| @@ -1,6 +1,6 @@ | |||
| // Tencent is pleased to support the open source community by making ncnn available. | |||
| // | |||
| // Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. | |||
| // Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| // | |||
| // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| // in compliance with the License. You may obtain a copy of the License at | |||
| @@ -172,4 +172,105 @@ pnnx.Output output 1 0 out | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose2d_onnx_1, 10) | |||
| class F_conv_transpose2d_onnx_2 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group output_padding=%output_padding | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 2) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 2) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 2) | |||
| return false; | |||
| if (captured_params.at("output_padding").type != 5) | |||
| return false; | |||
| if (captured_params.at("output_padding").ai.size() != 2) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 4 || pads[0] != pads[2] || pads[1] != pads[3]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0], pads[1]}; | |||
| op->params["output_padding"] = captured_params.at("output_padding"); | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose2d_onnx_2, 10) | |||
| class F_conv_transpose2d_onnx_3 : public F_conv_transpose2d_onnx_2 | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| ConvTranspose op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group output_padding=%output_padding | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv_transpose2d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose2d_onnx_3, 10) | |||
| } // namespace pnnx | |||
| @@ -0,0 +1,276 @@ | |||
| // Tencent is pleased to support the open source community by making ncnn available. | |||
| // | |||
| // Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| // | |||
| // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| // in compliance with the License. You may obtain a copy of the License at | |||
| // | |||
| // https://opensource.org/licenses/BSD-3-Clause | |||
| // | |||
| // 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. | |||
| #include "pass_level2.h" | |||
| namespace pnnx { | |||
| class F_conv_transpose3d_onnx : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose3d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 6 || pads[0] != pads[3] || pads[1] != pads[4] || pads[2] != pads[5]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0], pads[1], pads[2]}; | |||
| op->params["output_padding"] = {0, 0, 0}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose3d_onnx, 10) | |||
| class F_conv_transpose3d_onnx_0 : public F_conv_transpose3d_onnx | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| ConvTranspose op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv_transpose3d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose3d_onnx_0, 10) | |||
| class F_conv_transpose3d_onnx_1 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out strides=%strides pads=%pads dilations=%dilations group=%group auto_pad=NOTSET | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose3d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 6 || pads[0] != pads[3] || pads[1] != pads[4] || pads[2] != pads[5]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0], pads[1], pads[2]}; | |||
| op->params["output_padding"] = {0, 0, 0}; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose3d_onnx_1, 10) | |||
| class F_conv_transpose3d_onnx_2 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 5 4 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| pnnx.Input input_2 0 1 bias | |||
| ConvTranspose op_0 3 1 input weight bias out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group output_padding=%output_padding | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "F.conv_transpose3d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| if (captured_params.at("kernel_shape").type != 5) | |||
| return false; | |||
| if (captured_params.at("kernel_shape").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("strides").type != 5) | |||
| return false; | |||
| if (captured_params.at("strides").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("dilations").type != 5) | |||
| return false; | |||
| if (captured_params.at("dilations").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("output_padding").type != 5) | |||
| return false; | |||
| if (captured_params.at("output_padding").ai.size() != 3) | |||
| return false; | |||
| if (captured_params.at("group").type != 2) | |||
| return false; | |||
| if (captured_params.at("pads").type != 5) | |||
| return false; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() != 6 || pads[0] != pads[3] || pads[1] != pads[4] || pads[2] != pads[5]) | |||
| return false; | |||
| return true; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| op->params["stride"] = captured_params.at("strides"); | |||
| op->params["dilation"] = captured_params.at("dilations"); | |||
| op->params["groups"] = captured_params.at("group"); | |||
| op->params["padding"] = {pads[0], pads[1], pads[2]}; | |||
| op->params["output_padding"] = captured_params.at("output_padding"); | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose3d_onnx_2, 10) | |||
| class F_conv_transpose3d_onnx_3 : public F_conv_transpose3d_onnx_2 | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| ConvTranspose op_0 2 1 input weight out kernel_shape=%kernel_shape strides=%strides pads=%pads dilations=%dilations group=%group output_padding=%output_padding | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* replace_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 weight | |||
| F.conv_transpose3d conv 2 1 input weight out bias=None | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_conv_transpose3d_onnx_3, 10) | |||
| } // namespace pnnx | |||
| @@ -265,10 +265,9 @@ public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 4 3 | |||
| pnnx.Input input_0 0 1 input | |||
| pnnx.Input input_1 0 1 pad | |||
| Pad op_0 2 1 input pad out mode=constant | |||
| 3 2 | |||
| pnnx.Input input 0 1 input | |||
| Pad op_0 1 1 input out mode=%mode pads=%pads | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| @@ -277,8 +276,83 @@ pnnx.Output output 1 0 out | |||
| { | |||
| return "F.pad"; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| const std::string& mode = captured_params.at("mode").s; | |||
| if (mode == "constant") op->params["mode"] = "constant"; | |||
| if (mode == "reflect") op->params["mode"] = "reflect"; | |||
| if (mode == "edge") op->params["mode"] = "replicate"; | |||
| if (mode == "wrap") op->params["mode"] = "circular"; | |||
| const std::vector<int>& pads = captured_params.at("pads").ai; | |||
| if (pads.size() == 2) | |||
| op->params["pad"] = pads; | |||
| if (pads.size() == 4) | |||
| { | |||
| if (pads[0] == 0 && pads[2] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[1], pads[3]}; | |||
| else | |||
| op->params["pad"] = std::vector<int>{pads[1], pads[3], pads[0], pads[2]}; | |||
| } | |||
| if (pads.size() == 6) | |||
| { | |||
| if (pads[1] == 0 && pads[4] == 0 && pads[0] == 0 && pads[3] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[2], pads[5]}; | |||
| else if (pads[0] == 0 && pads[3] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[2], pads[5], pads[1], pads[4]}; | |||
| else | |||
| op->params["pad"] = std::vector<int>{pads[2], pads[5], pads[1], pads[4], pads[0], pads[3]}; | |||
| } | |||
| if (pads.size() == 8) | |||
| { | |||
| if (pads[1] == 0 && pads[5] == 0 && pads[0] == 0 && pads[4] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[3], pads[7], pads[2], pads[6]}; | |||
| else if (pads[0] == 0 && pads[4] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[3], pads[7], pads[2], pads[6], pads[1], pads[5]}; | |||
| else | |||
| op->params["pad"] = std::vector<int>{pads[3], pads[7], pads[2], pads[6], pads[1], pads[5], pads[0], pads[4]}; | |||
| } | |||
| if (pads.size() == 10) | |||
| { | |||
| if (pads[1] == 0 && pads[6] == 0 && pads[0] == 0 && pads[5] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[4], pads[9], pads[3], pads[8], pads[2], pads[7]}; | |||
| else if (pads[0] == 0 && pads[5] == 0) | |||
| op->params["pad"] = std::vector<int>{pads[4], pads[9], pads[3], pads[8], pads[2], pads[7], pads[1], pads[6]}; | |||
| else | |||
| op->params["pad"] = std::vector<int>{pads[4], pads[9], pads[3], pads[8], pads[2], pads[7], pads[1], pads[6], pads[0], pads[5]}; | |||
| } | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_pad_onnx, 10) | |||
| class F_pad_onnx_1 : public F_pad_onnx | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 3 2 | |||
| pnnx.Input input 0 1 input | |||
| Pad op_0 1 1 input out mode=%mode pads=%pads value=%value | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| F_pad_onnx::write(op, captured_params); | |||
| op->params["value"] = captured_params.at("value"); | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(F_pad_onnx_1, 10) | |||
| } // namespace pnnx | |||
| @@ -113,4 +113,41 @@ pnnx.Output output 1 0 out | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(Tensor_reshape_onnx_3, 20) | |||
| class Tensor_reshape_onnx_4 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 3 2 | |||
| pnnx.Input input 0 1 input | |||
| Reshape op_1 1 1 input out shape=%shape allowzero=* | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "Tensor.reshape"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(Tensor_reshape_onnx_4, 20) | |||
| class Tensor_reshape_onnx_5 : public Tensor_reshape_onnx_4 | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 3 2 | |||
| pnnx.Input input 0 1 input | |||
| Reshape op_1 1 1 input out shape=%shape | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(Tensor_reshape_onnx_5, 20) | |||
| } // namespace pnnx | |||
| @@ -180,4 +180,31 @@ pnnx.Output output 1 0 out | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(torch_mean_onnx_2, 20) | |||
| class torch_mean_onnx_3 : public GraphRewriterPass | |||
| { | |||
| public: | |||
| const char* match_pattern_graph() const | |||
| { | |||
| return R"PNNXIR(7767517 | |||
| 3 2 | |||
| pnnx.Input input 0 1 input | |||
| ReduceMean op_0 1 1 input out axes=%axes keepdims=%keepdims noop_with_empty_axes=0 | |||
| pnnx.Output output 1 0 out | |||
| )PNNXIR"; | |||
| } | |||
| const char* type_str() const | |||
| { | |||
| return "torch.mean"; | |||
| } | |||
| void write(Operator* op, const std::map<std::string, Parameter>& captured_params) const | |||
| { | |||
| op->params["dim"] = captured_params.at("axes"); | |||
| op->params["keepdim"] = captured_params.at("keepdims").i ? true : false; | |||
| } | |||
| }; | |||
| REGISTER_GLOBAL_PNNX_GRAPH_REWRITER_PASS(torch_mean_onnx_3, 20) | |||
| } // namespace pnnx | |||
| @@ -42,7 +42,7 @@ pnnx.Output output 1 0 out | |||
| const char* name_str() const | |||
| { | |||
| return "conv2d"; | |||
| return "padconv2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| @@ -131,7 +131,7 @@ pnnx.Output output 1 0 out | |||
| const char* name_str() const | |||
| { | |||
| return "conv2d"; | |||
| return "padconv2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| @@ -215,7 +215,7 @@ pnnx.Output output 1 0 out | |||
| const char* name_str() const | |||
| { | |||
| return "conv2d"; | |||
| return "padconv2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| @@ -293,7 +293,7 @@ pnnx.Output output 1 0 out | |||
| const char* name_str() const | |||
| { | |||
| return "conv2d"; | |||
| return "padconv2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| @@ -362,7 +362,7 @@ pnnx.Output output 1 0 out | |||
| const char* name_str() const | |||
| { | |||
| return "conv2d"; | |||
| return "padconv2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| @@ -431,7 +431,7 @@ pnnx.Output output 1 0 out | |||
| const char* name_str() const | |||
| { | |||
| return "conv2d"; | |||
| return "padconv2d"; | |||
| } | |||
| bool match(const std::map<std::string, Parameter>& captured_params) const | |||
| @@ -797,15 +797,6 @@ void pass_onnx(const onnx::ModelProto& model, Graph& pnnx_graph) | |||
| { | |||
| if (is_aten_op) | |||
| is_attr_list = true; | |||
| if (sim_op_type == "Reshape" && j == 1) | |||
| is_attr_list = true; | |||
| if (sim_op_type == "Pad" && j == 1) | |||
| is_attr_list = true; | |||
| if (sim_op_type == "ReduceMean" && j == 1) | |||
| is_attr_list = true; | |||
| } | |||
| bool is_attr_weight = false; | |||
| @@ -0,0 +1,271 @@ | |||
| // Tencent is pleased to support the open source community by making ncnn available. | |||
| // | |||
| // Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| // | |||
| // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| // in compliance with the License. You may obtain a copy of the License at | |||
| // | |||
| // https://opensource.org/licenses/BSD-3-Clause | |||
| // | |||
| // 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. | |||
| #include "fuse_constant_as_attribute.h" | |||
| #include <sstream> | |||
| #include <string> | |||
| #include <unordered_set> | |||
| #include <onnxruntime_c_api.h> | |||
| namespace pnnx { | |||
| namespace onnx2pnnx { | |||
| struct constant_as_attribute | |||
| { | |||
| const char* op_type; | |||
| int input_index; | |||
| const char* attribute; | |||
| }; | |||
| static constant_as_attribute caas[] = { | |||
| {"Pad", 1, "pads"}, | |||
| {"Pad", 2, "value"}, | |||
| {"ReduceMean", 1, "axes"}, | |||
| {"Reshape", 1, "shape"}, | |||
| }; | |||
| static const char* get_constant_as_attribute(const std::string& op_type, int input_index) | |||
| { | |||
| const int caas_count = sizeof(caas) / sizeof(caas[0]); | |||
| for (int i = 0; i < caas_count; i++) | |||
| { | |||
| if (op_type == caas[i].op_type && input_index == caas[i].input_index) | |||
| return caas[i].attribute; | |||
| } | |||
| return NULL; | |||
| } | |||
| void fuse_constant_as_attribute(onnx::ModelProto& model) | |||
| { | |||
| // collect initializers | |||
| std::unordered_map<std::string, int> initializers; | |||
| { | |||
| const onnx::GraphProto& graph = model.graph(); | |||
| for (int i = 0; i < graph.initializer_size(); i++) | |||
| { | |||
| initializers.insert(std::make_pair(graph.initializer(i).name(), i)); | |||
| } | |||
| } | |||
| onnx::GraphProto* graph = model.mutable_graph(); | |||
| for (int i = 0; i < graph->node_size(); i++) | |||
| { | |||
| onnx::NodeProto* node = graph->mutable_node(i); | |||
| if (!node->domain().empty()) | |||
| { | |||
| // native onnx op | |||
| continue; | |||
| } | |||
| const std::string& op_type = node->op_type(); | |||
| std::vector<int> fused_input_indexes; | |||
| for (int j = 0; j < node->input_size(); j++) | |||
| { | |||
| const std::string& input = node->input(j); | |||
| if (input.empty()) | |||
| continue; | |||
| if (initializers.find(input) == initializers.end()) | |||
| continue; | |||
| const char* attr_name = get_constant_as_attribute(op_type, j); | |||
| if (!attr_name) | |||
| continue; | |||
| // fprintf(stderr, "fuse_constant_as_attribute %s %d -> %s\n", op_type.c_str(), j, attr_name); | |||
| const onnx::TensorProto& tensor = graph->initializer(initializers.at(input)); | |||
| int64_t numel = 1; | |||
| for (int k = 0; k < tensor.dims_size(); k++) | |||
| { | |||
| numel *= tensor.dims(k); | |||
| } | |||
| if (numel == 1) | |||
| { | |||
| // int or float scalar | |||
| if (tensor.data_type() == onnx::TensorProto::INT32) | |||
| { | |||
| int i32; | |||
| if (tensor.has_raw_data()) | |||
| { | |||
| // assert tensor.raw_data().size() == 4 | |||
| i32 = ((int*)tensor.raw_data().data())[0]; | |||
| } | |||
| else | |||
| { | |||
| // assert tensor.int32_data().size() == 1 | |||
| i32 = tensor.int32_data().at(0); | |||
| } | |||
| onnx::AttributeProto* attr = node->add_attribute(); | |||
| attr->set_name(std::string(attr_name)); | |||
| attr->set_type(onnx::AttributeProto::INT); | |||
| attr->set_i(i32); | |||
| } | |||
| else if (tensor.data_type() == onnx::TensorProto::INT64) | |||
| { | |||
| int64_t i64; | |||
| if (tensor.has_raw_data()) | |||
| { | |||
| // assert tensor.raw_data().size() == 8 | |||
| i64 = ((int64_t*)tensor.raw_data().data())[0]; | |||
| } | |||
| else | |||
| { | |||
| // assert tensor.int64_data().size() == 1 | |||
| i64 = tensor.int64_data().at(0); | |||
| } | |||
| if (i64 == std::numeric_limits<int64_t>::max()) i64 = INT_MAX; | |||
| if (i64 == std::numeric_limits<int64_t>::min()) i64 = INT_MIN; | |||
| onnx::AttributeProto* attr = node->add_attribute(); | |||
| attr->set_name(std::string(attr_name)); | |||
| attr->set_type(onnx::AttributeProto::INT); | |||
| attr->set_i((int)i64); | |||
| } | |||
| else if (tensor.data_type() == onnx::TensorProto::FLOAT) | |||
| { | |||
| float f32; | |||
| if (tensor.has_raw_data()) | |||
| { | |||
| // assert tensor.raw_data().size() == 4 | |||
| f32 = ((float*)tensor.raw_data().data())[0]; | |||
| } | |||
| else | |||
| { | |||
| // assert tensor.float_data().size() == 1 | |||
| f32 = tensor.float_data().at(0); | |||
| } | |||
| onnx::AttributeProto* attr = node->add_attribute(); | |||
| attr->set_name(std::string(attr_name)); | |||
| attr->set_type(onnx::AttributeProto::FLOAT); | |||
| attr->set_f(f32); | |||
| } | |||
| else if (tensor.data_type() == onnx::TensorProto::BOOL) | |||
| { | |||
| bool bb; | |||
| if (tensor.has_raw_data()) | |||
| { | |||
| // assert tensor.raw_data().size() == 2 | |||
| bb = ((uint16_t*)tensor.raw_data().data())[0] ? true : false; | |||
| } | |||
| else | |||
| { | |||
| // assert tensor.int32_data().size() == 1 | |||
| bb = tensor.int32_data().at(0) ? true : false; | |||
| } | |||
| onnx::AttributeProto* attr = node->add_attribute(); | |||
| attr->set_name(std::string(attr_name)); | |||
| attr->set_type(onnx::AttributeProto::INT); | |||
| attr->set_i(bb ? 1 : 0); | |||
| } | |||
| else | |||
| { | |||
| fprintf(stderr, "unknown constant scalar type %d\n", (int)tensor.data_type()); | |||
| continue; | |||
| } | |||
| } | |||
| else if (tensor.dims_size() == 1) | |||
| { | |||
| // int list | |||
| const int list_size = tensor.dims(0); | |||
| if (tensor.data_type() == onnx::TensorProto::INT32) | |||
| { | |||
| std::vector<int> ai(list_size); | |||
| if (tensor.has_raw_data()) | |||
| { | |||
| // assert tensor.raw_data().size() == 4 * list_size | |||
| memcpy((void*)ai.data(), (int*)tensor.raw_data().data(), sizeof(int) * list_size); | |||
| } | |||
| else | |||
| { | |||
| // assert tensor.int32_data().size() == list_size | |||
| memcpy((void*)ai.data(), tensor.int32_data().data(), sizeof(int) * list_size); | |||
| } | |||
| onnx::AttributeProto* attr = node->add_attribute(); | |||
| attr->set_name(std::string(attr_name)); | |||
| attr->set_type(onnx::AttributeProto::INTS); | |||
| for (auto i32 : ai) | |||
| { | |||
| attr->add_ints(i32); | |||
| } | |||
| } | |||
| else if (tensor.data_type() == onnx::TensorProto::INT64) | |||
| { | |||
| std::vector<int64_t> ai(list_size); | |||
| if (tensor.has_raw_data()) | |||
| { | |||
| // assert tensor.raw_data().size() == 8 * list_size | |||
| memcpy((void*)ai.data(), (int64_t*)tensor.raw_data().data(), sizeof(int64_t) * list_size); | |||
| } | |||
| else | |||
| { | |||
| // assert tensor.int64_data().size() == list_size | |||
| memcpy((void*)ai.data(), tensor.int64_data().data(), sizeof(int64_t) * list_size); | |||
| } | |||
| onnx::AttributeProto* attr = node->add_attribute(); | |||
| attr->set_name(std::string(attr_name)); | |||
| attr->set_type(onnx::AttributeProto::INTS); | |||
| for (auto i64 : ai) | |||
| { | |||
| if (i64 == std::numeric_limits<int64_t>::max()) i64 = INT_MAX; | |||
| if (i64 == std::numeric_limits<int64_t>::min()) i64 = INT_MIN; | |||
| attr->add_ints((int)i64); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| fprintf(stderr, "unknown constant list type %d\n", (int)tensor.data_type()); | |||
| continue; | |||
| } | |||
| } | |||
| fused_input_indexes.push_back(j); | |||
| } | |||
| // drop inputs | |||
| for (size_t j = 0; j < fused_input_indexes.size(); j++) | |||
| { | |||
| const int fused_input_index = fused_input_indexes[j]; | |||
| // ..... fii ....... | |||
| const int node_input_size = node->input_size(); | |||
| for (int k = fused_input_index; k < node_input_size - 1; k++) | |||
| { | |||
| node->mutable_input()->SwapElements(k, k + 1); | |||
| } | |||
| // ..... ....... fii | |||
| node->mutable_input()->RemoveLast(); | |||
| } | |||
| } | |||
| } | |||
| } // namespace onnx2pnnx | |||
| } // namespace pnnx | |||
| @@ -0,0 +1,25 @@ | |||
| // Tencent is pleased to support the open source community by making ncnn available. | |||
| // | |||
| // Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| // | |||
| // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| // in compliance with the License. You may obtain a copy of the License at | |||
| // | |||
| // https://opensource.org/licenses/BSD-3-Clause | |||
| // | |||
| // 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. | |||
| #include "onnx.pb.h" | |||
| namespace pnnx { | |||
| namespace onnx2pnnx { | |||
| void fuse_constant_as_attribute(onnx::ModelProto& model); | |||
| } // namespace onnx2pnnx | |||
| } // namespace pnnx | |||
| @@ -5,8 +5,23 @@ macro(pnnx_onnx_add_test name) | |||
| add_test(NAME test_onnx_${name} COMMAND ${CMAKE_COMMAND} -DPYTHON_EXECUTABLE=${Python3_EXECUTABLE} -DPYTHON_SCRIPT=${CMAKE_CURRENT_SOURCE_DIR}/test_${name}.py -P ${CMAKE_CURRENT_SOURCE_DIR}/../run_test.cmake) | |||
| endmacro() | |||
| pnnx_onnx_add_test(F_conv_transpose1d) | |||
| pnnx_onnx_add_test(F_conv_transpose2d) | |||
| pnnx_onnx_add_test(F_conv_transpose3d) | |||
| pnnx_onnx_add_test(F_conv1d) | |||
| pnnx_onnx_add_test(F_conv2d) | |||
| pnnx_onnx_add_test(F_conv3d) | |||
| pnnx_onnx_add_test(F_pad) | |||
| pnnx_onnx_add_test(F_relu) | |||
| pnnx_onnx_add_test(nn_Conv1d) | |||
| pnnx_onnx_add_test(nn_Conv2d) | |||
| pnnx_onnx_add_test(nn_Conv3d) | |||
| pnnx_onnx_add_test(nn_ConvTranspose1d) | |||
| pnnx_onnx_add_test(nn_ConvTranspose2d) | |||
| pnnx_onnx_add_test(nn_ConvTranspose3d) | |||
| # pnnx_onnx_add_test(nn_ReLU) | |||
| pnnx_onnx_add_test(convnext_tiny) | |||
| pnnx_onnx_add_test(mobilenet_v2) | |||
| pnnx_onnx_add_test(mobilenet_v3_small) | |||
| @@ -0,0 +1,66 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| from packaging import version | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.w2 = nn.Parameter(torch.rand(12, 6, 4)) | |||
| self.b2 = nn.Parameter(torch.rand(12)) | |||
| self.w3 = nn.Parameter(torch.rand(6, 4, 3)) | |||
| def forward(self, x, w0, w1, b1, y): | |||
| x = F.conv1d(x, w0, None, stride=2, padding=1) | |||
| x = F.conv1d(x, w1, b1, stride=1, padding=1, dilation=2, groups=2) | |||
| # x = F.conv1d(x, w1, b1, stride=1, padding='same', dilation=2, groups=2) | |||
| y = F.conv1d(y, self.w2, self.b2, stride=2, padding=2) | |||
| y = F.conv1d(y, self.w3, None, stride=2, padding=1, groups=3) | |||
| return x, y | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 52) | |||
| w0 = torch.rand(16, 12, 3) | |||
| w1 = torch.rand(16, 8, 5) | |||
| b1 = torch.rand(16) | |||
| y = torch.rand(1, 6, 25) | |||
| a0, a1 = net(x, w0, w1, b1, y) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, w0, w1, b1, y), "test_F_conv1d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_conv1d.onnx inputshape=[1,12,52],[16,12,3],[16,8,5],[16],[1,6,25]") | |||
| # pnnx inference | |||
| import test_F_conv1d_pnnx | |||
| b0, b1 = test_F_conv1d_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,66 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| from packaging import version | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.w2 = nn.Parameter(torch.rand(12, 6, 4, 4)) | |||
| self.b2 = nn.Parameter(torch.rand(12)) | |||
| self.w3 = nn.Parameter(torch.rand(6, 4, 3, 3)) | |||
| def forward(self, x, w0, w1, b1, y): | |||
| x = F.conv2d(x, w0, None, stride=(2,2), padding=(1,1)) | |||
| x = F.conv2d(x, w1, b1, stride=(1,1), padding=(1,1), dilation=(2,1), groups=2) | |||
| # x = F.conv2d(x, w1, b1, stride=(1,1), padding='same', dilation=(2,1), groups=2) | |||
| y = F.conv2d(y, self.w2, self.b2, stride=(2,2), padding=(2,2)) | |||
| y = F.conv2d(y, self.w3, None, stride=(2,2), padding=(1,1), groups=3) | |||
| return x, y | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 52, 64) | |||
| w0 = torch.rand(16, 12, 3, 3) | |||
| w1 = torch.rand(16, 8, 5, 5) | |||
| b1 = torch.rand(16) | |||
| y = torch.rand(1, 6, 32, 25) | |||
| a0, a1 = net(x, w0, w1, b1, y) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, w0, w1, b1, y), "test_F_conv2d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_conv2d.onnx inputshape=[1,12,52,64],[16,12,3,3],[16,8,5,5],[16],[1,6,32,25]") | |||
| # pnnx inference | |||
| import test_F_conv2d_pnnx | |||
| b0, b1 = test_F_conv2d_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,66 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| from packaging import version | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.w2 = nn.Parameter(torch.rand(12, 6, 4, 4, 4)) | |||
| self.b2 = nn.Parameter(torch.rand(12)) | |||
| self.w3 = nn.Parameter(torch.rand(6, 4, 3, 3, 3)) | |||
| def forward(self, x, w0, w1, b1, y): | |||
| x = F.conv3d(x, w0, None, stride=(2,2,2), padding=(1,0,1)) | |||
| x = F.conv3d(x, w1, b1, stride=(1,1,1), padding=(1,1,1), dilation=(2,2,1), groups=2) | |||
| # x = F.conv3d(x, w1, b1, stride=(1,1,1), padding='same', dilation=(2,2,1), groups=2) | |||
| y = F.conv3d(y, self.w2, self.b2, stride=(2,2,2), padding=(2,2,2)) | |||
| y = F.conv3d(y, self.w3, None, stride=(2,2,2), padding=(1,1,1), groups=3) | |||
| return x, y | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 20, 32, 40) | |||
| w0 = torch.rand(16, 12, 3, 2, 3) | |||
| w1 = torch.rand(16, 8, 5, 4, 5) | |||
| b1 = torch.rand(16) | |||
| y = torch.rand(1, 6, 12, 11, 10) | |||
| a0, a1 = net(x, w0, w1, b1, y) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, w0, w1, b1, y), "test_F_conv3d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_conv3d.onnx inputshape=[1,12,20,32,40],[16,12,3,2,3],[16,8,5,4,5],[16],[1,6,12,11,10]") | |||
| # pnnx inference | |||
| import test_F_conv3d_pnnx | |||
| b0, b1 = test_F_conv3d_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,65 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.w2 = nn.Parameter(torch.rand(6, 12, 4)) | |||
| self.b2 = nn.Parameter(torch.rand(12)) | |||
| self.w3 = nn.Parameter(torch.rand(12, 2, 3)) | |||
| def forward(self, x, w0, w1, b1, y): | |||
| x = F.conv_transpose1d(x, w0, None, stride=2, padding=1, output_padding=1) | |||
| x = F.conv_transpose1d(x, w1, b1, stride=1, padding=2, dilation=2, groups=2) | |||
| y = F.conv_transpose1d(y, self.w2, self.b2, stride=2, padding=1, output_padding=1) | |||
| y = F.conv_transpose1d(y, self.w3, None, stride=1, padding=2, dilation=2, groups=3) | |||
| return x, y | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 22) | |||
| w0 = torch.rand(12, 16, 3) | |||
| w1 = torch.rand(16, 8, 5) | |||
| b1 = torch.rand(16) | |||
| y = torch.rand(1, 6, 5) | |||
| a0, a1 = net(x, w0, w1, b1, y) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, w0, w1, b1, y), "test_F_conv_transpose1d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_conv_transpose1d.onnx inputshape=[1,12,22],[12,16,3],[16,8,5],[16],[1,6,5]") | |||
| # pnnx inference | |||
| import test_F_conv_transpose1d_pnnx | |||
| b0, b1 = test_F_conv_transpose1d_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,65 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.w2 = nn.Parameter(torch.rand(6, 12, 4, 4)) | |||
| self.b2 = nn.Parameter(torch.rand(12)) | |||
| self.w3 = nn.Parameter(torch.rand(12, 2, 3, 3)) | |||
| def forward(self, x, w0, w1, b1, y): | |||
| x = F.conv_transpose2d(x, w0, None, stride=(2,2), padding=(1,1), output_padding=(1,1)) | |||
| x = F.conv_transpose2d(x, w1, b1, stride=(1,2), padding=(2,1), dilation=(2,1), groups=2) | |||
| y = F.conv_transpose2d(y, self.w2, self.b2, stride=(2,2), padding=(1,1), output_padding=(1,1)) | |||
| y = F.conv_transpose2d(y, self.w3, None, stride=(1,2), padding=(2,1), dilation=(2,1), groups=3) | |||
| return x, y | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 22, 32) | |||
| w0 = torch.rand(12, 16, 3, 3) | |||
| w1 = torch.rand(16, 8, 5, 5) | |||
| b1 = torch.rand(16) | |||
| y = torch.rand(1, 6, 5, 6) | |||
| a0, a1 = net(x, w0, w1, b1, y) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, w0, w1, b1, y), "test_F_conv_transpose2d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_conv_transpose2d.onnx inputshape=[1,12,22,32],[12,16,3,3],[16,8,5,5],[16],[1,6,5,6]") | |||
| # pnnx inference | |||
| import test_F_conv_transpose2d_pnnx | |||
| b0, b1 = test_F_conv_transpose2d_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,65 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.w2 = nn.Parameter(torch.rand(6, 12, 4, 4, 4)) | |||
| self.b2 = nn.Parameter(torch.rand(12)) | |||
| self.w3 = nn.Parameter(torch.rand(12, 2, 3, 3, 3)) | |||
| def forward(self, x, w0, w1, b1, y): | |||
| x = F.conv_transpose3d(x, w0, None, stride=(2,2,2), padding=(1,0,1), output_padding=(1,1,0)) | |||
| x = F.conv_transpose3d(x, w1, b1, stride=(1,1,2), padding=(2,2,1), dilation=(2,2,1), groups=2) | |||
| y = F.conv_transpose3d(y, self.w2, self.b2, stride=(2,2,2), padding=(1,0,1), output_padding=(1,1,0)) | |||
| y = F.conv_transpose3d(y, self.w3, None, stride=(1,1,2), padding=(2,2,1), dilation=(2,2,1), groups=3) | |||
| return x, y | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 10, 12, 14) | |||
| w0 = torch.rand(12, 16, 3, 2, 3) | |||
| w1 = torch.rand(16, 8, 5, 4, 5) | |||
| b1 = torch.rand(16) | |||
| y = torch.rand(1, 6, 4, 5, 6) | |||
| a0, a1 = net(x, w0, w1, b1, y) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, w0, w1, b1, y), "test_F_conv_transpose3d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_conv_transpose3d.onnx inputshape=[1,12,10,12,14],[12,16,3,2,3],[16,8,5,4,5],[16],[1,6,4,5,6]") | |||
| # pnnx inference | |||
| import test_F_conv_transpose3d_pnnx | |||
| b0, b1 = test_F_conv_transpose3d_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,73 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| def forward(self, x, y, z, w): | |||
| x = F.pad(x, (3,4), mode='constant', value=1.3) | |||
| x = F.pad(x, (2,2)) | |||
| y = F.pad(y, (5,6), mode='reflect') | |||
| y = F.pad(y, (2,1), mode='replicate') | |||
| y = F.pad(y, (3,4), mode='constant', value=1.3) | |||
| y = F.pad(y, (1,1)) | |||
| z = F.pad(z, (3,4,3,4), mode='reflect') | |||
| z = F.pad(z, (2,1,2,0), mode='replicate') | |||
| z = F.pad(z, (1,0,2,0), mode='constant', value=1.3) | |||
| z = F.pad(z, (3,3,3,3)) | |||
| #w = F.pad(w, (1,2,3,4,5,6), mode='reflect') | |||
| w = F.pad(w, (5,0,1,2,0,2), mode='replicate') | |||
| w = F.pad(w, (0,2,2,1,3,4), mode='constant', value=1.3) | |||
| w = F.pad(w, (2,2,2,2,2,2)) | |||
| return x, y, z, w | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 16) | |||
| y = torch.rand(12, 2, 16) | |||
| z = torch.rand(1, 3, 12, 16) | |||
| w = torch.rand(1, 5, 7, 9, 11) | |||
| a0, a1, a2, a3 = net(x, y, z, w) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, y, z, w), "test_F_pad.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_F_pad.onnx inputshape=[1,16],[12,2,16],[1,3,12,16],[1,5,7,9,11]") | |||
| # pnnx inference | |||
| import test_F_pad_pnnx | |||
| b0, b1, b2, b3 = test_F_pad_pnnx.test_inference() | |||
| return torch.equal(a0, b0) and torch.equal(a1, b1) and torch.equal(a2, b2) and torch.equal(a3, b3) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,73 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| from packaging import version | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.conv_0 = nn.Conv1d(in_channels=12, out_channels=16, kernel_size=3) | |||
| self.conv_1 = nn.Conv1d(in_channels=16, out_channels=20, kernel_size=2, stride=2, padding=2, dilation=1) | |||
| self.conv_2 = nn.Conv1d(in_channels=20, out_channels=24, kernel_size=3, stride=1, padding=(4), dilation=1, groups=1, bias=False) | |||
| self.conv_3 = nn.Conv1d(in_channels=24, out_channels=28, kernel_size=5, stride=1, padding=0, dilation=1, groups=4, bias=True) | |||
| self.conv_4 = nn.Conv1d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding=1, dilation=2, groups=2, bias=False, padding_mode='zeros') | |||
| # self.conv_3 = nn.Conv1d(in_channels=24, out_channels=28, kernel_size=5, stride=1, padding='valid', dilation=1, groups=4, bias=True) | |||
| # self.conv_4 = nn.Conv1d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding='same', dilation=2, groups=2, bias=False, padding_mode='zeros') | |||
| self.conv_5 = nn.Conv1d(in_channels=32, out_channels=32, kernel_size=2, stride=2, padding=3, dilation=1, groups=32, bias=True, padding_mode='reflect') | |||
| self.conv_6 = nn.Conv1d(in_channels=32, out_channels=28, kernel_size=2, stride=1, padding=2, dilation=1, groups=1, bias=False, padding_mode='replicate') | |||
| #self.conv_7 = nn.Conv1d(in_channels=28, out_channels=24, kernel_size=3, stride=2, padding=(5,6), dilation=2, groups=1, bias=True, padding_mode='circular') | |||
| def forward(self, x): | |||
| x = self.conv_0(x) | |||
| x = self.conv_1(x) | |||
| x = self.conv_2(x) | |||
| x = self.conv_3(x) | |||
| x = self.conv_4(x) | |||
| x = self.conv_5(x) | |||
| x = self.conv_6(x) | |||
| #x = self.conv_7(x) | |||
| return x | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 64) | |||
| a = net(x) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, ), "test_nn_Conv1d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_nn_Conv1d.onnx inputshape=[1,12,64]") | |||
| # pnnx inference | |||
| import test_nn_Conv1d_pnnx | |||
| b = test_nn_Conv1d_pnnx.test_inference() | |||
| return torch.equal(a, b) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,73 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| from packaging import version | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.conv_0 = nn.Conv2d(in_channels=12, out_channels=16, kernel_size=3) | |||
| self.conv_1 = nn.Conv2d(in_channels=16, out_channels=20, kernel_size=(2,4), stride=(2,1), padding=2, dilation=1) | |||
| self.conv_2 = nn.Conv2d(in_channels=20, out_channels=24, kernel_size=(1,3), stride=1, padding=(2,4), dilation=1, groups=1, bias=False) | |||
| self.conv_3 = nn.Conv2d(in_channels=24, out_channels=28, kernel_size=(5,4), stride=1, padding=0, dilation=1, groups=4, bias=True) | |||
| self.conv_4 = nn.Conv2d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding=1, dilation=(1,2), groups=2, bias=False, padding_mode='zeros') | |||
| # self.conv_3 = nn.Conv2d(in_channels=24, out_channels=28, kernel_size=(5,4), stride=1, padding='valid', dilation=1, groups=4, bias=True) | |||
| # self.conv_4 = nn.Conv2d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding='same', dilation=(1,2), groups=2, bias=False, padding_mode='zeros') | |||
| self.conv_5 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=2, stride=2, padding=3, dilation=1, groups=32, bias=True, padding_mode='reflect') | |||
| self.conv_6 = nn.Conv2d(in_channels=32, out_channels=28, kernel_size=2, stride=1, padding=2, dilation=1, groups=1, bias=False, padding_mode='replicate') | |||
| #self.conv_7 = nn.Conv2d(in_channels=28, out_channels=24, kernel_size=3, stride=2, padding=(5,6), dilation=2, groups=1, bias=True, padding_mode='circular') | |||
| def forward(self, x): | |||
| x = self.conv_0(x) | |||
| x = self.conv_1(x) | |||
| x = self.conv_2(x) | |||
| x = self.conv_3(x) | |||
| x = self.conv_4(x) | |||
| x = self.conv_5(x) | |||
| x = self.conv_6(x) | |||
| #x = self.conv_7(x) | |||
| return x | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 64, 64) | |||
| a = net(x) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, ), "test_nn_Conv2d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_nn_Conv2d.onnx inputshape=[1,12,64,64]") | |||
| # pnnx inference | |||
| import test_nn_Conv2d_pnnx | |||
| b = test_nn_Conv2d_pnnx.test_inference() | |||
| return torch.equal(a, b) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,77 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| from packaging import version | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.conv_0 = nn.Conv3d(in_channels=12, out_channels=16, kernel_size=3) | |||
| self.conv_1 = nn.Conv3d(in_channels=16, out_channels=20, kernel_size=(2,3,4), stride=(2,2,1), padding=2, dilation=1) | |||
| self.conv_2 = nn.Conv3d(in_channels=20, out_channels=24, kernel_size=(1,2,3), stride=1, padding=(2,4,1), dilation=1, groups=1, bias=False) | |||
| self.conv_3 = nn.Conv3d(in_channels=24, out_channels=28, kernel_size=(5,4,3), stride=1, padding=0, dilation=1, groups=4, bias=True) | |||
| self.conv_4 = nn.Conv3d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding=1, dilation=(1,2,2), groups=2, bias=False, padding_mode='zeros') | |||
| # self.conv_3 = nn.Conv3d(in_channels=24, out_channels=28, kernel_size=(5,4,3), stride=1, padding='valid', dilation=1, groups=4, bias=True) | |||
| # self.conv_4 = nn.Conv3d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding='same', dilation=(1,2,2), groups=2, bias=False, padding_mode='zeros') | |||
| if version.parse(torch.__version__) >= version.parse('1.10'): | |||
| self.conv_5 = nn.Conv3d(in_channels=32, out_channels=32, kernel_size=2, stride=2, padding=3, dilation=1, groups=32, bias=True, padding_mode='reflect') | |||
| self.conv_6 = nn.Conv3d(in_channels=32, out_channels=28, kernel_size=2, stride=1, padding=2, dilation=1, groups=1, bias=False, padding_mode='replicate') | |||
| # self.conv_7 = nn.Conv3d(in_channels=28, out_channels=24, kernel_size=3, stride=2, padding=(5,6), dilation=2, groups=1, bias=True, padding_mode='circular') | |||
| def forward(self, x): | |||
| x = self.conv_0(x) | |||
| x = self.conv_1(x) | |||
| x = self.conv_2(x) | |||
| x = self.conv_3(x) | |||
| x = self.conv_4(x) | |||
| if version.parse(torch.__version__) < version.parse('1.10'): | |||
| return x | |||
| x = self.conv_5(x) | |||
| x = self.conv_6(x) | |||
| #x = self.conv_7(x) | |||
| return x | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 48, 48, 64) | |||
| a = net(x) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, ), "test_nn_Conv3d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_nn_Conv3d.onnx inputshape=[1,12,48,48,64]") | |||
| # pnnx inference | |||
| import test_nn_Conv3d_pnnx | |||
| b = test_nn_Conv3d_pnnx.test_inference() | |||
| return torch.equal(a, b) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,76 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.deconv_0 = nn.ConvTranspose1d(in_channels=12, out_channels=16, kernel_size=3) | |||
| self.deconv_1 = nn.ConvTranspose1d(in_channels=16, out_channels=20, kernel_size=2, stride=2, padding=2, output_padding=0) | |||
| self.deconv_2 = nn.ConvTranspose1d(in_channels=20, out_channels=24, kernel_size=3, stride=1, padding=(2), output_padding=(0), dilation=1, groups=1, bias=False) | |||
| self.deconv_3 = nn.ConvTranspose1d(in_channels=24, out_channels=28, kernel_size=5, stride=2, padding=0, output_padding=(1), dilation=1, groups=4, bias=True) | |||
| self.deconv_4 = nn.ConvTranspose1d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding=1, output_padding=0, dilation=2, groups=2, bias=False) | |||
| self.deconv_5 = nn.ConvTranspose1d(in_channels=32, out_channels=32, kernel_size=2, stride=2, padding=3, output_padding=1, dilation=1, groups=32, bias=True) | |||
| self.deconv_6 = nn.ConvTranspose1d(in_channels=32, out_channels=28, kernel_size=2, stride=1, padding=2, output_padding=0, dilation=1, groups=1, bias=False) | |||
| self.deconv_7 = nn.ConvTranspose1d(in_channels=28, out_channels=24, kernel_size=3, stride=2, padding=(6), output_padding=(1), dilation=2, groups=1, bias=True) | |||
| self.downsample = nn.Conv1d(24, 16, 3, stride=2, padding=1) | |||
| self.upsample = nn.ConvTranspose1d(16, 24, 3, stride=2, padding=1) | |||
| def forward(self, x): | |||
| x = self.deconv_0(x) | |||
| x = self.deconv_1(x) | |||
| x = self.deconv_2(x) | |||
| x = self.deconv_3(x) | |||
| x = self.deconv_4(x) | |||
| x = self.deconv_5(x) | |||
| x = self.deconv_6(x) | |||
| x = self.deconv_7(x) | |||
| y = self.downsample(x) | |||
| x = self.upsample(y, output_size=x.size()) | |||
| return x | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 10) | |||
| a = net(x) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, ), "test_nn_ConvTranspose1d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_nn_ConvTranspose1d.onnx inputshape=[1,12,10]") | |||
| # pnnx inference | |||
| import test_nn_ConvTranspose1d_pnnx | |||
| b = test_nn_ConvTranspose1d_pnnx.test_inference() | |||
| return torch.equal(a, b) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,76 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.deconv_0 = nn.ConvTranspose2d(in_channels=12, out_channels=16, kernel_size=3) | |||
| self.deconv_1 = nn.ConvTranspose2d(in_channels=16, out_channels=20, kernel_size=(2,4), stride=(2,1), padding=2, output_padding=0) | |||
| self.deconv_2 = nn.ConvTranspose2d(in_channels=20, out_channels=24, kernel_size=(1,3), stride=1, padding=(2,4), output_padding=(0,0), dilation=1, groups=1, bias=False) | |||
| self.deconv_3 = nn.ConvTranspose2d(in_channels=24, out_channels=28, kernel_size=(5,4), stride=2, padding=0, output_padding=(0,1), dilation=1, groups=4, bias=True) | |||
| self.deconv_4 = nn.ConvTranspose2d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding=1, output_padding=0, dilation=(1,2), groups=2, bias=False) | |||
| self.deconv_5 = nn.ConvTranspose2d(in_channels=32, out_channels=32, kernel_size=2, stride=2, padding=3, output_padding=1, dilation=1, groups=32, bias=True) | |||
| self.deconv_6 = nn.ConvTranspose2d(in_channels=32, out_channels=28, kernel_size=2, stride=1, padding=2, output_padding=0, dilation=1, groups=1, bias=False) | |||
| self.deconv_7 = nn.ConvTranspose2d(in_channels=28, out_channels=24, kernel_size=3, stride=2, padding=(5,6), output_padding=(1,0), dilation=2, groups=1, bias=True) | |||
| self.downsample = nn.Conv2d(24, 16, 3, stride=2, padding=1) | |||
| self.upsample = nn.ConvTranspose2d(16, 24, 3, stride=2, padding=1) | |||
| def forward(self, x): | |||
| x = self.deconv_0(x) | |||
| x = self.deconv_1(x) | |||
| x = self.deconv_2(x) | |||
| x = self.deconv_3(x) | |||
| x = self.deconv_4(x) | |||
| x = self.deconv_5(x) | |||
| x = self.deconv_6(x) | |||
| x = self.deconv_7(x) | |||
| y = self.downsample(x) | |||
| x = self.upsample(y, output_size=x.size()) | |||
| return x | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 10, 10) | |||
| a = net(x) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, ), "test_nn_ConvTranspose2d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_nn_ConvTranspose2d.onnx inputshape=[1,12,10,10]") | |||
| # pnnx inference | |||
| import test_nn_ConvTranspose2d_pnnx | |||
| b = test_nn_ConvTranspose2d_pnnx.test_inference() | |||
| return torch.equal(a, b) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||
| @@ -0,0 +1,76 @@ | |||
| # Tencent is pleased to support the open source community by making ncnn available. | |||
| # | |||
| # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | |||
| # | |||
| # Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | |||
| # in compliance with the License. You may obtain a copy of the License at | |||
| # | |||
| # https://opensource.org/licenses/BSD-3-Clause | |||
| # | |||
| # 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. | |||
| import torch | |||
| import torch.nn as nn | |||
| import torch.nn.functional as F | |||
| class Model(nn.Module): | |||
| def __init__(self): | |||
| super(Model, self).__init__() | |||
| self.deconv_0 = nn.ConvTranspose3d(in_channels=12, out_channels=16, kernel_size=3) | |||
| self.deconv_1 = nn.ConvTranspose3d(in_channels=16, out_channels=20, kernel_size=(2,3,4), stride=(2,2,1), padding=2, output_padding=0) | |||
| self.deconv_2 = nn.ConvTranspose3d(in_channels=20, out_channels=24, kernel_size=(1,2,3), stride=1, padding=(2,3,4), output_padding=(0,0,0), dilation=1, groups=1, bias=False) | |||
| self.deconv_3 = nn.ConvTranspose3d(in_channels=24, out_channels=28, kernel_size=(5,4,3), stride=2, padding=0, output_padding=(0,1,1), dilation=1, groups=4, bias=True) | |||
| self.deconv_4 = nn.ConvTranspose3d(in_channels=28, out_channels=32, kernel_size=3, stride=1, padding=1, output_padding=0, dilation=(1,2,2), groups=2, bias=False) | |||
| self.deconv_5 = nn.ConvTranspose3d(in_channels=32, out_channels=32, kernel_size=2, stride=2, padding=3, output_padding=1, dilation=1, groups=32, bias=True) | |||
| self.deconv_6 = nn.ConvTranspose3d(in_channels=32, out_channels=28, kernel_size=2, stride=1, padding=2, output_padding=0, dilation=1, groups=1, bias=False) | |||
| self.deconv_7 = nn.ConvTranspose3d(in_channels=28, out_channels=24, kernel_size=3, stride=2, padding=(5,6,7), output_padding=(1,0,1), dilation=2, groups=1, bias=True) | |||
| self.downsample = nn.Conv3d(24, 16, 3, stride=2, padding=1) | |||
| self.upsample = nn.ConvTranspose3d(16, 24, 3, stride=2, padding=1) | |||
| def forward(self, x): | |||
| x = self.deconv_0(x) | |||
| x = self.deconv_1(x) | |||
| x = self.deconv_2(x) | |||
| x = self.deconv_3(x) | |||
| x = self.deconv_4(x) | |||
| x = self.deconv_5(x) | |||
| x = self.deconv_6(x) | |||
| x = self.deconv_7(x) | |||
| y = self.downsample(x) | |||
| x = self.upsample(y, output_size=x.size()) | |||
| return x | |||
| def test(): | |||
| net = Model() | |||
| net.eval() | |||
| torch.manual_seed(0) | |||
| x = torch.rand(1, 12, 7, 7, 10) | |||
| a = net(x) | |||
| # export onnx | |||
| torch.onnx.export(net, (x, ), "test_nn_ConvTranspose3d.onnx") | |||
| # onnx to pnnx | |||
| import os | |||
| os.system("../../src/pnnx test_nn_ConvTranspose3d.onnx inputshape=[1,12,7,7,10]") | |||
| # pnnx inference | |||
| import test_nn_ConvTranspose3d_pnnx | |||
| b = test_nn_ConvTranspose3d_pnnx.test_inference() | |||
| return torch.equal(a, b) | |||
| if __name__ == "__main__": | |||
| if test(): | |||
| exit(0) | |||
| else: | |||
| exit(1) | |||