| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "pass_level1.h" |
| |
|
| | |
| |
|
| | #include "../utils.h" |
| |
|
| | namespace pnnx { |
| |
|
| | class Conv2d : public FuseModulePass |
| | { |
| | public: |
| | const char* match_type_str() const |
| | { |
| | return "__torch__.torch.nn.modules.conv.Conv2d"; |
| | } |
| |
|
| | const char* type_str() const |
| | { |
| | return "nn.Conv2d"; |
| | } |
| |
|
| | void write(Operator* op, const std::shared_ptr<torch::jit::Graph>& graph, const torch::jit::Module& mod) const |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | const torch::jit::Node* convolution = find_node_by_kind(graph, "aten::_convolution"); |
| | const torch::jit::Node* convolution_mode = find_node_by_kind(graph, "aten::_convolution_mode"); |
| | const torch::jit::Node* pad = find_node_by_kind(graph, "aten::pad"); |
| | const torch::jit::Node* reflection_pad2d = find_node_by_kind(graph, "aten::reflection_pad2d"); |
| | const torch::jit::Node* replication_pad2d = find_node_by_kind(graph, "aten::replication_pad2d"); |
| |
|
| | if (convolution_mode) |
| | { |
| | convolution = convolution_mode; |
| | } |
| |
|
| | const auto& weight = mod.attr("weight").toTensor(); |
| |
|
| | op->params["groups"] = convolution->namedInput("groups"); |
| | op->params["in_channels"] = weight.size(1) * op->params["groups"].i; |
| | op->params["out_channels"] = weight.size(0); |
| | op->params["kernel_size"] = Parameter{weight.size(2), weight.size(3)}; |
| | op->params["stride"] = convolution->namedInput("stride"); |
| | if (pad) |
| | { |
| | op->params["padding_mode"] = pad->namedInput("mode"); |
| | op->params["padding"] = pad->namedInput("pad"); |
| | std::vector<int>& padding = op->params["padding"].ai; |
| | if (padding.size() == 4) |
| | { |
| | |
| | if (padding[0] == padding[1] && padding[1] == padding[2] && padding[2] == padding[3]) |
| | { |
| | padding.resize(2); |
| | } |
| | else if (padding[0] == padding[2] && padding[1] == padding[3] && padding[0] != padding[1]) |
| | { |
| | padding.resize(0); |
| | op->params["padding"].s = "same"; |
| | } |
| | } |
| | } |
| | else if (reflection_pad2d) |
| | { |
| | op->params["padding_mode"] = "reflect"; |
| | op->params["padding"] = reflection_pad2d->namedInput("padding"); |
| | std::vector<int>& padding = op->params["padding"].ai; |
| | if (padding.size() == 4) |
| | { |
| | |
| | if (padding[0] == padding[1] && padding[1] == padding[2] && padding[2] == padding[3]) |
| | { |
| | padding.resize(2); |
| | } |
| | else if (padding[0] == padding[2] && padding[1] == padding[3] && padding[0] != padding[1]) |
| | { |
| | padding.resize(0); |
| | op->params["padding"].s = "same"; |
| | } |
| | } |
| | } |
| | else if (replication_pad2d) |
| | { |
| | op->params["padding_mode"] = "replicate"; |
| | op->params["padding"] = replication_pad2d->namedInput("padding"); |
| | std::vector<int>& padding = op->params["padding"].ai; |
| | if (padding.size() == 4) |
| | { |
| | |
| | if (padding[0] == padding[1] && padding[1] == padding[2] && padding[2] == padding[3]) |
| | { |
| | padding.resize(2); |
| | } |
| | else if (padding[0] == padding[2] && padding[1] == padding[3] && padding[0] != padding[1]) |
| | { |
| | padding.resize(0); |
| | op->params["padding"].s = "same"; |
| | } |
| | } |
| | } |
| | else |
| | { |
| | op->params["padding_mode"] = "zeros"; |
| | op->params["padding"] = convolution->namedInput("padding"); |
| | } |
| | op->params["dilation"] = convolution->namedInput("dilation"); |
| | op->params["bias"] = mod.hasattr("bias"); |
| |
|
| | op->attrs["weight"] = weight; |
| | if (mod.hasattr("bias")) |
| | { |
| | op->attrs["bias"] = mod.attr("bias").toTensor(); |
| | } |
| | } |
| | }; |
| |
|
| | REGISTER_GLOBAL_PNNX_FUSE_MODULE_PASS(Conv2d) |
| |
|
| | } |
| |
|