1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include <builders/ie_convolution_layer.hpp>
6 #include <ie_cnn_layer_builder.h>
12 using namespace InferenceEngine;
14 Builder::ConvolutionLayer::ConvolutionLayer(const std::string& name): LayerDecorator("Convolution", name) {
15 getLayer()->getInputPorts().resize(3);
16 getLayer()->getInputPorts()[1].setParameter("type", "weights");
17 getLayer()->getInputPorts()[2].setParameter("type", "biases");
18 getLayer()->getOutputPorts().resize(1);
28 Builder::ConvolutionLayer::ConvolutionLayer(const Layer::Ptr& layer): LayerDecorator(layer) {
29 checkType("Convolution");
32 Builder::ConvolutionLayer::ConvolutionLayer(const Layer::CPtr& layer): LayerDecorator(layer) {
33 checkType("Convolution");
36 Builder::ConvolutionLayer &Builder::ConvolutionLayer::setName(const std::string &name) {
37 getLayer()->setName(name);
41 const Port& Builder::ConvolutionLayer::getInputPort() const {
42 return getLayer()->getInputPorts()[0];
45 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setInputPort(const Port& port) {
46 getLayer()->getInputPorts()[0] = port;
50 const Port& Builder::ConvolutionLayer::getOutputPort() const {
51 return getLayer()->getOutputPorts()[0];
54 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setOutputPort(const Port& port) {
55 getLayer()->getOutputPorts()[0] = port;
59 const std::vector<size_t> Builder::ConvolutionLayer::getKernel() const {
60 return getLayer()->getParameters().at("kernel");
62 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setKernel(const std::vector<size_t>& kernel) {
63 getLayer()->getParameters()["kernel"] = kernel;
67 const std::vector<size_t> Builder::ConvolutionLayer::getStrides() const {
68 return getLayer()->getParameters().at("strides");
70 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setStrides(const std::vector<size_t>& strides) {
71 getLayer()->getParameters()["strides"] = strides;
75 const std::vector<size_t> Builder::ConvolutionLayer::getDilation() const {
76 return getLayer()->getParameters().at("dilations");
78 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setDilation(const std::vector<size_t>& dilation) {
79 getLayer()->getParameters()["dilations"] = dilation;
83 const std::vector<size_t> Builder::ConvolutionLayer::getPaddingsBegin() const {
84 return getLayer()->getParameters().at("pads_begin");
86 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setPaddingsBegin(const std::vector<size_t>& paddings) {
87 getLayer()->getParameters()["pads_begin"] = paddings;
91 const std::vector<size_t> Builder::ConvolutionLayer::getPaddingsEnd() const {
92 return getLayer()->getParameters().at("pads_end");
94 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setPaddingsEnd(const std::vector<size_t>& paddings) {
95 getLayer()->getParameters()["pads_end"] = paddings;
99 size_t Builder::ConvolutionLayer::getGroup() const {
100 return getLayer()->getParameters().at("group");
102 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setGroup(size_t group) {
103 getLayer()->getParameters()["group"] = group;
107 size_t Builder::ConvolutionLayer::getOutDepth() const {
108 return getLayer()->getParameters().at("output");
110 Builder::ConvolutionLayer& Builder::ConvolutionLayer::setOutDepth(size_t outDepth) {
111 getLayer()->getParameters()["output"] = outDepth;
115 REG_VALIDATOR_FOR(Convolution, [] (const InferenceEngine::Builder::Layer::CPtr& layer, bool partial) {
117 if (layer->getParameters().find("kernel") == layer->getParameters().end() &&
118 layer->getParameters().find("kernel-x") != layer->getParameters().end() &&
119 layer->getParameters().find("kernel-y") != layer->getParameters().end())
122 Builder::ConvolutionLayer convBuilder(layer);
123 std::vector<size_t> l_kernel = convBuilder.getKernel();
124 std::vector<size_t> l_dilation = convBuilder.getDilation();
125 std::vector<size_t> l_paddingBegin = convBuilder.getPaddingsBegin();
126 std::vector<size_t> l_paddingEnd = convBuilder.getPaddingsEnd();
127 std::vector<size_t> l_strides = convBuilder.getStrides();
129 if (l_paddingBegin.empty() && !l_kernel.empty())
130 l_paddingBegin.resize(l_kernel.size(), 0);
131 if (l_paddingEnd.empty() && !l_kernel.empty())
132 l_paddingEnd.resize(l_kernel.size(), 0);
133 if (l_dilation.empty() && !l_kernel.empty())
134 l_dilation.resize(l_kernel.size(), 1);
135 if (l_strides.empty() && !l_kernel.empty())
136 l_strides.resize(l_kernel.size(), 1);
138 if (l_kernel.empty()) {
139 THROW_IE_EXCEPTION << "Kernel is empty!";
142 if (l_paddingBegin.size() != l_paddingEnd.size()) {
143 THROW_IE_EXCEPTION << "Padding_begin dimension is not equal to padding_end dimension";
146 if (!l_paddingBegin.empty() && l_kernel.size() != l_paddingBegin.size()) {
147 THROW_IE_EXCEPTION << "Padding dimension is not equal to kernel dimension";
150 if (l_kernel.size() != l_strides.size()) {
151 THROW_IE_EXCEPTION << "Stride dimension is not equal to kernel dimension";
154 if (!l_dilation.empty() && l_kernel.size() != l_dilation.size()) {
155 THROW_IE_EXCEPTION << "Dilation dimension is not equal to kernel dimension";
158 if (convBuilder.getOutDepth() == 0) {
159 THROW_IE_EXCEPTION << "OutDepth parameter should be more than 0";
162 for (size_t kernel_dim : l_kernel) {
163 if (kernel_dim == 0) {
164 THROW_IE_EXCEPTION << "Kernel dimensions should be more than 0";
168 for (size_t i_stride : l_strides) {
170 THROW_IE_EXCEPTION << "Strides should be more than 0";
174 for (size_t dil : l_dilation) {
176 THROW_IE_EXCEPTION << "Dilation should be more than 0";
179 if (!convBuilder.getGroup())
180 THROW_IE_EXCEPTION << "Group should be more than 0";
182 if (convBuilder.getInputPort().shape().empty())
185 const size_t IC = convBuilder.getInputPort().shape()[1];
186 if (IC % convBuilder.getGroup())
187 THROW_IE_EXCEPTION << "Number of input channels (" << IC <<
188 ") is not divided by group number (" << convBuilder.getGroup() << ")";
190 size_t weight_size = convBuilder.getOutDepth() * IC / convBuilder.getGroup();
191 for (size_t kernel_dim : l_kernel) {
192 if (static_cast<double>(weight_size) * kernel_dim > std::numeric_limits<size_t>::max()) {
193 THROW_IE_EXCEPTION << "Weight size exceeds the size_t max";
195 weight_size *= kernel_dim;
201 const auto weights = layer->getInputPorts()[1].getData()->getData();
202 if (weights->size() != weight_size) {
203 THROW_IE_EXCEPTION << "Weight size is not correct!";
206 const auto biases = layer->getInputPorts()[2].getData()->getData();
207 if (biases && biases->cbuffer() && biases->size() != convBuilder.getOutDepth())
208 THROW_IE_EXCEPTION << "Biases size is incorrect!";
211 REG_CONVERTER_FOR(Convolution, [](const CNNLayerPtr& cnnLayer, Builder::Layer& layer) {
213 if (cnnLayer->params.find("kernel") == cnnLayer->params.end() &&
214 cnnLayer->params.find("kernel-x") != cnnLayer->params.end() &&
215 cnnLayer->params.find("kernel-y") != cnnLayer->params.end())
218 std::vector<unsigned int> tmp = cnnLayer->GetParamAsUInts("kernel");
219 std::vector<size_t> cur(tmp.size());
220 for (size_t i = 0; i < tmp.size(); ++i) {
221 cur[i] = static_cast<size_t>(tmp[i]);
223 layer.getParameters()["kernel"] = cur;
225 tmp = cnnLayer->GetParamAsUInts("strides");
226 cur.resize(tmp.size());
227 for (size_t i = 0; i < tmp.size(); ++i) {
228 cur[i] = static_cast<size_t>(tmp[i]);
230 layer.getParameters()["strides"] = cur;
232 tmp = cnnLayer->GetParamAsUInts("dilations");
233 cur.resize(tmp.size());
234 for (size_t i = 0; i < tmp.size(); ++i) {
235 cur[i] = static_cast<size_t>(tmp[i]);
237 layer.getParameters()["dilations"] = cur;
239 tmp = cnnLayer->GetParamAsUInts("pads_begin");
240 cur.resize(tmp.size());
241 for (size_t i = 0; i < tmp.size(); ++i) {
242 cur[i] = static_cast<size_t>(tmp[i]);
244 layer.getParameters()["pads_begin"] = cur;
246 tmp = cnnLayer->GetParamAsUInts("pads_end");
247 cur.resize(tmp.size());
248 for (size_t i = 0; i < tmp.size(); ++i) {
249 cur[i] = static_cast<size_t>(tmp[i]);
251 layer.getParameters()["pads_end"] = cur;
253 layer.getParameters()["group"] = static_cast<size_t>(cnnLayer->GetParamAsUInt("group"));
254 layer.getParameters()["output"] = static_cast<size_t>(cnnLayer->GetParamAsUInt("output"));