tiny_dnn 1.0.0
A header only, dependency-free deep learning framework in C++11
Loading...
Searching...
No Matches
max_pooling_layer.h
1/*
2 Copyright (c) 2015, Taiga Nomi
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the <organization> nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
17 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#pragma once
28
29#include <string>
30#include <vector>
31#include <algorithm>
32
33#include "tiny_dnn/core/backend_tiny.h"
34#include "tiny_dnn/core/backend_nnp.h"
35#include "tiny_dnn/core/backend_dnn.h"
36#ifdef CNN_USE_AVX
37#include "tiny_dnn/core/backend_avx.h"
38#endif
39
40#include "tiny_dnn/core/kernels/maxpool_op.h"
41#include "tiny_dnn/core/kernels/maxpool_grad_op.h"
42
43#include "tiny_dnn/util/util.h"
44#include "tiny_dnn/util/image.h"
45#include "tiny_dnn/activations/activation_function.h"
46
47namespace tiny_dnn {
48
52template <typename Activation = activation::identity>
53class max_pooling_layer : public feedforward_layer<Activation> {
54 public:
55 CNN_USE_LAYER_MEMBERS;
57
65 serial_size_t in_height,
66 serial_size_t in_channels,
67 serial_size_t pooling_size,
68 backend_t backend_type = core::default_engine())
70 pooling_size, backend_type) {}
71
73 serial_size_t pooling_size,
74 serial_size_t stride,
75 backend_t backend_type = core::default_engine())
76 : max_pooling_layer(in_shape.width_, in_shape.height_, in_shape.depth_,
77 pooling_size, stride, backend_type) {}
78
79 max_pooling_layer(serial_size_t in_width,
80 serial_size_t in_height,
81 serial_size_t in_channels,
82 serial_size_t pooling_size,
83 serial_size_t stride,
84 backend_t backend_type = core::default_engine())
85 : max_pooling_layer(in_width, in_height, in_channels, pooling_size,
86 pooling_size, stride, stride, padding::valid,
87 backend_type) {}
88
97 serial_size_t in_height,
98 serial_size_t in_channels,
99 serial_size_t pooling_size_x,
100 serial_size_t pooling_size_y,
101 serial_size_t stride_x,
102 serial_size_t stride_y,
103 padding pad_type = padding::valid,
104 backend_t backend_type = core::default_engine())
105 : Base({ vector_type::data }) {
106 set_maxpool_params(
108 shape3d(conv_out_length(in_width, pooling_size_x, stride_x, pad_type),
109 conv_out_length(in_height, pooling_size_y, stride_y, pad_type),
111 pooling_size_x, pooling_size_y, stride_x, stride_y, pad_type);
112
113 init_connection();
114 init_backend(backend_type);
115 Base::set_backend_type(backend_type);
116 }
117
118 // move constructor
119 max_pooling_layer(max_pooling_layer&& other) // NOLINT
120 : Base(std::move(other))
121 , params_(std::move(other.params_)) {
122 init_connection();
123 init_backend(std::move(Base::engine()));
124 }
125
126 serial_size_t fan_in_size() const override {
127 return static_cast<serial_size_t>(params_.out2in[0].size());
128 }
129
130 serial_size_t fan_out_size() const override {
131 return 1;
132 }
133
134 void forward_propagation(const std::vector<tensor_t*>& in_data,
135 std::vector<tensor_t*>& out_data) override {
136 // forward convolutional op context
137 auto ctx = OpKernelContext(in_data, out_data);
138 ctx.setParallelize(layer::parallelize());
139 ctx.setEngine(layer::engine());
140
141 // launch convolutional kernel
142 kernel_fwd_->compute(ctx);
143
144 // activations
145 this->forward_activation(*out_data[0], *out_data[1]);
146 }
147
148 void back_propagation(const std::vector<tensor_t*>& in_data,
149 const std::vector<tensor_t*>& out_data,
150 std::vector<tensor_t*>& out_grad,
151 std::vector<tensor_t*>& in_grad) override {
152 // activations
153 // TODO(edgar/nyanp): refactor and move activations outside
154 this->backward_activation(*out_grad[0], *out_data[0], *out_grad[1]);
155
156 // backward convolutional op context
157 auto ctx = OpKernelContext(in_data, out_data, out_grad, in_grad);
158 ctx.setParallelize(layer::parallelize());
159 ctx.setEngine(layer::engine());
160
161 // launch convolutional kernel
162 kernel_back_->compute(ctx);
163 }
164
165 std::vector<index3d<serial_size_t>>
166 in_shape() const override { return { params_.in }; }
167
168 std::vector<index3d<serial_size_t>>
169 out_shape() const override { return { params_.out, params_.out }; }
170
171 std::string layer_type() const override {
172 return std::string("max-pool");
173 }
174
175 std::string kernel_file() const override {
176 return std::string("../tiny_cnn/core/kernels/cl_kernels/pooling.cl");
177 }
178
179 std::pair<serial_size_t, serial_size_t> pool_size() const {
180 return std::make_pair(params_.pool_size_x, params_.pool_size_y);
181 }
182
183 void set_sample_count(serial_size_t sample_count) override {
184 Base::set_sample_count(sample_count);
185 params_.out2inmax.resize(
186 sample_count, std::vector<serial_size_t>(params_.out.size()));
187 }
188
189
190 template <class Archive>
191 static void
192 load_and_construct(Archive & ar,
193 cereal::construct<max_pooling_layer> & construct) {
194 shape3d in;
195 serial_size_t stride_x, stride_y, pool_size_x, pool_size_y;
196 padding pad_type;
197
198 ar(cereal::make_nvp("in_size", in),
199 cereal::make_nvp("pool_size_x", pool_size_x),
200 cereal::make_nvp("pool_size_y", pool_size_y),
201 cereal::make_nvp("stride_x", stride_x),
202 cereal::make_nvp("stride_y", stride_y),
203 cereal::make_nvp("pad_type", pad_type));
204 construct(in.width_, in.height_, in.depth_, pool_size_x, pool_size_y,
205 stride_x, stride_y, pad_type);
206 }
207
208 template <class Archive>
209 void serialize(Archive & ar) {
210 layer::serialize_prolog(ar);
211 ar(cereal::make_nvp("in_size", params_.in),
212 cereal::make_nvp("pool_size_x", params_.pool_size_x),
213 cereal::make_nvp("pool_size_y", params_.pool_size_y),
214 cereal::make_nvp("stride_x", params_.stride_x),
215 cereal::make_nvp("stride_y", params_.stride_y),
216 cereal::make_nvp("pad_type", params_.pad_type));
217 }
218
219private:
220 /* The Max Poling operation params */
221 maxpool_params params_;
222
223 /* Forward and backward ops */
224 std::shared_ptr<core::OpKernel> kernel_fwd_;
225 std::shared_ptr<core::OpKernel> kernel_back_;
226
227 void connect_kernel(serial_size_t pooling_size_x,
228 serial_size_t pooling_size_y,
229 serial_size_t outx,
230 serial_size_t outy,
231 serial_size_t c) {
232 serial_size_t dxmax = static_cast<serial_size_t>(
233 std::min(static_cast<serial_size_t>(pooling_size_x),
234 params_.in.width_ - outx * params_.stride_x));
235
236 serial_size_t dymax = static_cast<serial_size_t>(
237 std::min(static_cast<serial_size_t>(pooling_size_y),
238 params_.in.height_ - outy * params_.stride_y));
239
240 for (serial_size_t dy = 0; dy < dymax; dy++) {
241 for (serial_size_t dx = 0; dx < dxmax; dx++) {
242 serial_size_t in_index = params_.in.get_index(
243 static_cast<serial_size_t>(outx * params_.stride_x + dx),
244 static_cast<serial_size_t>(outy * params_.stride_y + dy), c);
245 serial_size_t out_index = params_.out.get_index(outx, outy, c);
246
247 if (in_index >= params_.in2out.size()) {
248 throw nn_error("index overflow");
249 }
250 if (out_index >= params_.out2in.size()) {
251 throw nn_error("index overflow");
252 }
253 params_.in2out[in_index] = out_index;
254 params_.out2in[out_index].push_back(in_index);
255 }
256 }
257 }
258
259 void init_connection() {
260 params_.in2out.resize(params_.in.size());
261 params_.out2in.resize(params_.out.size());
262
263 for (serial_size_t c = 0; c < params_.in.depth_; ++c) {
264 for (serial_size_t y = 0; y < params_.out.height_; ++y) {
265 for (serial_size_t x = 0; x < params_.out.width_; ++x) {
266 connect_kernel(params_.pool_size_x,
267 params_.pool_size_y,
268 x, y, c);
269 }
270 }
271 }
272 }
273
274 void init_backend(backend_t backend_type) {
275 core::OpKernelConstruction ctx =
276 core::OpKernelConstruction(layer::device(), &params_);
277
278 if (backend_type == backend_t::internal ||
279 backend_type == backend_t::nnpack ||
280 backend_type == backend_t::avx) {
281
282 kernel_fwd_.reset(new MaxPoolOp(ctx));
283 kernel_back_.reset(new MaxPoolGradOp(ctx));
284 return;
285 }
286 else {
287 throw nn_error("Not supported engine: " + to_string(backend_type));
288 }
289
290 }
291
292 void set_maxpool_params(const shape3d& in,
293 const shape3d& out,
294 serial_size_t pooling_size_x,
295 serial_size_t pooling_size_y,
296 serial_size_t stride_x,
297 serial_size_t stride_y,
298 padding pad_type) {
299 params_.in = in;
300 params_.out = out;
301 params_.pool_size_x = pooling_size_x;
302 params_.pool_size_y = pooling_size_y;
303 params_.stride_x = stride_x;
304 params_.stride_y = stride_y;
305 params_.pad_type = pad_type;
306 }
307};
308
309} // namespace tiny_dnn
310
single-input, single-output network with activation function
Definition feedforward_layer.h:37
Simple image utility class.
Definition image.h:94
serial_size_t in_channels() const
number of outgoing edges in this layer
Definition layer.h:146
applies max-pooing operaton to the spatial data
Definition max_pooling_layer.h:53
max_pooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pooling_size, backend_t backend_type=core::default_engine())
Definition max_pooling_layer.h:64
serial_size_t fan_out_size() const override
number of outgoing connections for each input unit used only for weight/bias initialization methods w...
Definition max_pooling_layer.h:130
std::string layer_type() const override
name of layer, should be unique for each concrete class
Definition max_pooling_layer.h:171
void back_propagation(const std::vector< tensor_t * > &in_data, const std::vector< tensor_t * > &out_data, std::vector< tensor_t * > &out_grad, std::vector< tensor_t * > &in_grad) override
return delta of previous layer (delta=\frac{dE}{da}, a=wx in fully-connected layer)
Definition max_pooling_layer.h:148
std::vector< index3d< serial_size_t > > out_shape() const override
array of output shapes (width x height x depth)
Definition max_pooling_layer.h:169
max_pooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pooling_size_x, serial_size_t pooling_size_y, serial_size_t stride_x, serial_size_t stride_y, padding pad_type=padding::valid, backend_t backend_type=core::default_engine())
Definition max_pooling_layer.h:96
std::vector< index3d< serial_size_t > > in_shape() const override
array of input shapes (width x height x depth)
Definition max_pooling_layer.h:166
serial_size_t fan_in_size() const override
number of incoming connections for each output unit used only for weight/bias initialization methods ...
Definition max_pooling_layer.h:126
void forward_propagation(const std::vector< tensor_t * > &in_data, std::vector< tensor_t * > &out_data) override
Definition max_pooling_layer.h:134