Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / inference_engine / builders / ie_deconvolution_layer.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <builders/ie_deconvolution_layer.hpp>
6 #include <ie_cnn_layer_builder.h>
7 #include <limits>
8 #include <vector>
9 #include <string>
10
11 using namespace InferenceEngine;
12
13 Builder::DeconvolutionLayer::DeconvolutionLayer(const std::string& name): ConvolutionLayer(name) {
14     getLayer()->setType("Deconvolution");
15 }
16 Builder::DeconvolutionLayer::DeconvolutionLayer(const Layer::Ptr& layer): ConvolutionLayer(layer->getName()) {
17     this->getLayer() = layer;
18     checkType("Deconvolution");
19 }
20 Builder::DeconvolutionLayer::DeconvolutionLayer(const Layer::CPtr& layer): ConvolutionLayer(layer->getName()) {
21     this->getLayer().reset();
22     cLayer = layer;
23     checkType("Deconvolution");
24 }
25
26 REG_VALIDATOR_FOR(Deconvolution, [] (const InferenceEngine::Builder::Layer::CPtr& layer, bool partial) {
27     // WA for old IRs
28     if (layer->getParameters().find("kernel") == layer->getParameters().end() &&
29         layer->getParameters().find("kernel-x") != layer->getParameters().end() &&
30         layer->getParameters().find("kernel-y") != layer->getParameters().end())
31         return;
32     Builder::DeconvolutionLayer deconvBuilder(layer);
33     std::vector<size_t> l_kernel = deconvBuilder.getKernel();
34     std::vector<size_t> l_dilation = deconvBuilder.getDilation();
35     std::vector<size_t> l_paddingBegin = deconvBuilder.getPaddingsBegin();
36     std::vector<size_t> l_paddingEnd = deconvBuilder.getPaddingsEnd();
37     std::vector<size_t> l_strides = deconvBuilder.getStrides();
38
39     if (l_paddingBegin.empty() && !l_kernel.empty())
40         l_paddingBegin.resize(l_kernel.size(), 0);
41     if (l_paddingEnd.empty() && !l_kernel.empty())
42         l_paddingEnd.resize(l_kernel.size(), 0);
43     if (l_dilation.empty() && !l_kernel.empty())
44         l_dilation.resize(l_kernel.size(), 1);
45     if (l_strides.empty() && !l_kernel.empty())
46         l_strides.resize(l_kernel.size(), 1);
47
48     if (l_kernel.empty()) {
49         THROW_IE_EXCEPTION << "Kernel is empty!";
50     }
51
52     if (l_paddingBegin.size() != l_paddingEnd.size()) {
53         THROW_IE_EXCEPTION << "Padding_begin dimension is not equal to padding_end dimension";
54     }
55
56     if (!l_paddingBegin.empty() && l_kernel.size() != l_paddingBegin.size()) {
57         THROW_IE_EXCEPTION << "Padding dimension is not equal to kernel dimension";
58     }
59
60     if (l_kernel.size() != l_strides.size()) {
61         THROW_IE_EXCEPTION << "Stride dimension is not equal to kernel dimension";
62     }
63
64     if (!l_dilation.empty() && l_kernel.size() != l_dilation.size()) {
65         THROW_IE_EXCEPTION << "Dilation dimension is not equal to kernel dimension";
66     }
67
68     if (deconvBuilder.getOutDepth() == 0) {
69         THROW_IE_EXCEPTION << "OutDepth parameter should be more than 0";
70     }
71
72     for (size_t kernel_dim : l_kernel) {
73         if (kernel_dim == 0) {
74             THROW_IE_EXCEPTION << "Kernel dimensions should be more than 0";
75         }
76     }
77
78     for (size_t i_stride : l_strides) {
79         if (i_stride == 0) {
80             THROW_IE_EXCEPTION << "Strides should be more than 0";
81         }
82     }
83
84     for (size_t dil : l_dilation) {
85         if (dil == 0)
86             THROW_IE_EXCEPTION << "Dilation should be more than 0";
87     }
88
89     if (!deconvBuilder.getGroup())
90         THROW_IE_EXCEPTION << "Group should be more than 0";
91
92     if (deconvBuilder.getInputPort().shape().empty())
93         return;
94
95     const size_t IC = deconvBuilder.getInputPort().shape()[1];
96     if (IC % deconvBuilder.getGroup())
97         THROW_IE_EXCEPTION << "Number of input channels (" << IC <<
98                            ") is not divided by group number (" << deconvBuilder.getGroup() << ")";
99
100     size_t weight_size = deconvBuilder.getOutDepth() * IC / deconvBuilder.getGroup();
101     for (size_t kernel_dim : l_kernel) {
102         if (static_cast<double>(weight_size) * kernel_dim > std::numeric_limits<size_t>::max()) {
103             THROW_IE_EXCEPTION << "Weight size exceeds the size_t max";
104         }
105         weight_size *= kernel_dim;
106     }
107
108     if (partial)
109         return;
110
111     const auto weights = layer->getInputPorts()[1].getData()->getData();
112     if (weights->size() != weight_size) {
113         THROW_IE_EXCEPTION << "Weight size is not correct!";
114     }
115
116     const auto biases = layer->getInputPorts()[2].getData()->getData();
117     if (biases && biases->cbuffer() && biases->size() != deconvBuilder.getOutDepth())
118         THROW_IE_EXCEPTION << "Biases size is incorrect!";
119 });
120
121 REG_CONVERTER_FOR(Deconvolution, [](const CNNLayerPtr& cnnLayer, Builder::Layer& layer) {
122     // WA for old IRs
123     if (cnnLayer->params.find("kernel") == cnnLayer->params.end() &&
124         cnnLayer->params.find("kernel-x") != cnnLayer->params.end() &&
125         cnnLayer->params.find("kernel-y") != cnnLayer->params.end())
126         return;
127     std::vector<unsigned int> tmp = cnnLayer->GetParamAsUInts("kernel");
128     std::vector<size_t> cur(tmp.size());
129     for (size_t i = 0; i < tmp.size(); ++i) {
130         cur[i] = static_cast<size_t>(tmp[i]);
131     }
132     layer.getParameters()["kernel"] = cur;
133
134     tmp = cnnLayer->GetParamAsUInts("strides");
135     cur.resize(tmp.size());
136     for (size_t i = 0; i < tmp.size(); ++i) {
137         cur[i] = static_cast<size_t>(tmp[i]);
138     }
139     layer.getParameters()["strides"] = cur;
140
141     tmp = cnnLayer->GetParamAsUInts("dilations");
142     cur.resize(tmp.size());
143     for (size_t i = 0; i < tmp.size(); ++i) {
144         cur[i] = static_cast<size_t>(tmp[i]);
145     }
146     layer.getParameters()["dilations"] = cur;
147
148     tmp = cnnLayer->GetParamAsUInts("pads_begin");
149     cur.resize(tmp.size());
150     for (size_t i = 0; i < tmp.size(); ++i) {
151         cur[i] = static_cast<size_t>(tmp[i]);
152     }
153     layer.getParameters()["pads_begin"] = cur;
154
155     tmp = cnnLayer->GetParamAsUInts("pads_end");
156     cur.resize(tmp.size());
157     for (size_t i = 0; i < tmp.size(); ++i) {
158         cur[i] = static_cast<size_t>(tmp[i]);
159     }
160     layer.getParameters()["pads_end"] = cur;
161
162     layer.getParameters()["group"] = static_cast<size_t>(cnnLayer->GetParamAsUInt("group"));
163     layer.getParameters()["output"] = static_cast<size_t>(cnnLayer->GetParamAsUInt("output"));
164 });