1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include <builders/ie_deconvolution_layer.hpp>
6 #include <ie_cnn_layer_builder.h>
11 using namespace InferenceEngine;
13 Builder::DeconvolutionLayer::DeconvolutionLayer(const std::string& name): ConvolutionLayer(name) {
14 getLayer()->setType("Deconvolution");
16 Builder::DeconvolutionLayer::DeconvolutionLayer(const Layer::Ptr& layer): ConvolutionLayer(layer->getName()) {
17 this->getLayer() = layer;
18 checkType("Deconvolution");
20 Builder::DeconvolutionLayer::DeconvolutionLayer(const Layer::CPtr& layer): ConvolutionLayer(layer->getName()) {
21 this->getLayer().reset();
23 checkType("Deconvolution");
26 REG_VALIDATOR_FOR(Deconvolution, [] (const InferenceEngine::Builder::Layer::CPtr& layer, bool partial) {
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())
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();
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);
48 if (l_kernel.empty()) {
49 THROW_IE_EXCEPTION << "Kernel is empty!";
52 if (l_paddingBegin.size() != l_paddingEnd.size()) {
53 THROW_IE_EXCEPTION << "Padding_begin dimension is not equal to padding_end dimension";
56 if (!l_paddingBegin.empty() && l_kernel.size() != l_paddingBegin.size()) {
57 THROW_IE_EXCEPTION << "Padding dimension is not equal to kernel dimension";
60 if (l_kernel.size() != l_strides.size()) {
61 THROW_IE_EXCEPTION << "Stride dimension is not equal to kernel dimension";
64 if (!l_dilation.empty() && l_kernel.size() != l_dilation.size()) {
65 THROW_IE_EXCEPTION << "Dilation dimension is not equal to kernel dimension";
68 if (deconvBuilder.getOutDepth() == 0) {
69 THROW_IE_EXCEPTION << "OutDepth parameter should be more than 0";
72 for (size_t kernel_dim : l_kernel) {
73 if (kernel_dim == 0) {
74 THROW_IE_EXCEPTION << "Kernel dimensions should be more than 0";
78 for (size_t i_stride : l_strides) {
80 THROW_IE_EXCEPTION << "Strides should be more than 0";
84 for (size_t dil : l_dilation) {
86 THROW_IE_EXCEPTION << "Dilation should be more than 0";
89 if (!deconvBuilder.getGroup())
90 THROW_IE_EXCEPTION << "Group should be more than 0";
92 if (deconvBuilder.getInputPort().shape().empty())
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() << ")";
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";
105 weight_size *= kernel_dim;
111 const auto weights = layer->getInputPorts()[1].getData()->getData();
112 if (weights->size() != weight_size) {
113 THROW_IE_EXCEPTION << "Weight size is not correct!";
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!";
121 REG_CONVERTER_FOR(Deconvolution, [](const CNNLayerPtr& cnnLayer, Builder::Layer& layer) {
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())
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]);
132 layer.getParameters()["kernel"] = cur;
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]);
139 layer.getParameters()["strides"] = cur;
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]);
146 layer.getParameters()["dilations"] = cur;
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]);
153 layer.getParameters()["pads_begin"] = cur;
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]);
160 layer.getParameters()["pads_end"] = cur;
162 layer.getParameters()["group"] = static_cast<size_t>(cnnLayer->GetParamAsUInt("group"));
163 layer.getParameters()["output"] = static_cast<size_t>(cnnLayer->GetParamAsUInt("output"));