tiny_dnn  1.0.0
A header only, dependency-free deep learning framework in C++11
average_unpooling_layer.h
1 /*
2  Copyright (c) 2013, 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/util/util.h"
34 #include "tiny_dnn/util/image.h"
35 #include "tiny_dnn/layers/partial_connected_layer.h"
36 #include "tiny_dnn/activations/activation_function.h"
37 
38 namespace tiny_dnn {
39 
40 // forward_propagation
41 template <typename Activation>
42 void tiny_average_unpooling_kernel(bool parallelize,
43  const std::vector<tensor_t*>& in_data,
44  std::vector<tensor_t*>& out_data,
45  const shape3d& out_dim,
46  float_t scale_factor,
47  std::vector<typename partial_connected_layer<Activation>::wi_connections>& out2wi,
48  Activation& h) {
49  for (size_t sample = 0; sample < in_data[0]->size(); sample++) {
50  const vec_t& in = (*in_data[0])[sample];
51  const vec_t& W = (*in_data[1])[0];
52  const vec_t& b = (*in_data[2])[0];
53  vec_t& out = (*out_data[0])[sample];
54  vec_t& a = (*out_data[1])[sample];
55 
56  auto oarea = out_dim.area();
57  size_t idx = 0;
58  for (size_t d = 0; d < out_dim.depth_; ++d) {
59  float_t weight = W[d];// * scale_factor;
60  float_t bias = b[d];
61  for (size_t i = 0; i < oarea; ++i, ++idx) {
62  const auto& connections = out2wi[idx];
63  float_t value = float_t(0);
64  for (auto connection : connections)// 13.1%
65  value += in[connection.second]; // 3.2%
66  value *= weight;
67  value += bias;
68  a[idx] = value;
69  }
70  }
71 
72  assert(out.size() == out2wi.size());
73  for_i(parallelize, out2wi.size(), [&](int i) {
74  out[i] = h.f(a, i);
75  });
76  }
77 }
78 
79 // back_propagation
80 template<typename Activation>
81 void tiny_average_unpooling_back_kernel(const std::vector<tensor_t*>& in_data,
82  const std::vector<tensor_t*>& out_data,
83  std::vector<tensor_t*>& out_grad,
84  std::vector<tensor_t*>& in_grad,
85  const shape3d& in_dim,
86  float_t scale_factor,
87  std::vector<typename partial_connected_layer<Activation>::io_connections>& weight2io,
88  std::vector<typename partial_connected_layer<Activation>::wo_connections>& in2wo,
89  std::vector<std::vector<serial_size_t>>& bias2out) {
90 
91  for (size_t sample = 0; sample < in_data[0]->size(); sample++) {
92  const vec_t& prev_out = (*in_data[0])[sample];
93  const vec_t& W = (*in_data[1])[0];
94  vec_t& dW = (*in_grad[1])[sample];
95  vec_t& db = (*in_grad[2])[sample];
96  vec_t& prev_delta = (*in_grad[0])[sample];
97  vec_t& curr_delta = (*out_grad[0])[sample];
98 
99  auto inarea = in_dim.area();
100  size_t idx = 0;
101  for (size_t i = 0; i < in_dim.depth_; ++i) {
102  float_t weight = W[i];// * scale_factor;
103  for (size_t j = 0; j < inarea; ++j, ++idx) {
104  prev_delta[idx] = weight * curr_delta[in2wo[idx][0].second];
105  }
106  }
107 
108  for (size_t i = 0; i < weight2io.size(); ++i) {
109  const auto& connections = weight2io[i];
110  float_t diff = float_t(0);
111 
112  for (auto connection : connections)
113  diff += prev_out[connection.first] * curr_delta[connection.second];
114 
115  dW[i] += diff;// * scale_factor;
116  }
117 
118  for (size_t i = 0; i < bias2out.size(); i++) {
119  const std::vector<serial_size_t>& outs = bias2out[i];
120  float_t diff = float_t(0);
121 
122  for (auto o : outs)
123  diff += curr_delta[o];
124 
125  db[i] += diff;
126  }
127  }
128 }
129 
133 template<typename Activation = activation::identity>
135  public:
137  CNN_USE_LAYER_MEMBERS;
138 
145  average_unpooling_layer(serial_size_t in_width,
146  serial_size_t in_height,
147  serial_size_t in_channels,
148  serial_size_t pooling_size)
149  : Base(in_width * in_height * in_channels,
150  in_width * in_height * in_channels * sqr(pooling_size),
151  in_channels, in_channels, float_t(1) * sqr(pooling_size)),
152  stride_(pooling_size),
153  in_(in_width, in_height, in_channels),
154  out_(in_width*pooling_size, in_height*pooling_size, in_channels),
155  w_(pooling_size, pooling_size, in_channels) {
156 
157  init_connection(pooling_size);
158  }
159 
167  average_unpooling_layer(serial_size_t in_width,
168  serial_size_t in_height,
169  serial_size_t in_channels,
170  serial_size_t pooling_size,
171  serial_size_t stride)
172  : Base(in_width * in_height * in_channels,
173  unpool_out_dim(in_width, pooling_size, stride) *
174  unpool_out_dim(in_height, pooling_size, stride) * in_channels,
175  in_channels, in_channels, float_t(1) * sqr(pooling_size)),
176  stride_(stride),
177  in_(in_width, in_height, in_channels),
178  out_(unpool_out_dim(in_width, pooling_size, stride),
179  unpool_out_dim(in_height, pooling_size, stride), in_channels),
180  w_(pooling_size, pooling_size, in_channels) {
181 
182  init_connection(pooling_size);
183  }
184 
185  std::vector<index3d<serial_size_t>> in_shape() const override {
186  return { in_, w_, index3d<serial_size_t>(1, 1, out_.depth_) };
187  }
188 
189  std::vector<index3d<serial_size_t>> out_shape() const override {
190  return { out_, out_ };
191  }
192 
193  std::string layer_type() const override { return "ave-unpool"; }
194 
195  void forward_propagation(const std::vector<tensor_t*>& in_data,
196  std::vector<tensor_t*>& out_data) override {
197 
198  tiny_average_unpooling_kernel<Activation>(
199  parallelize_,
200  in_data,
201  out_data,
202  out_,
203  Base::scale_factor_,
204  Base::out2wi_,
205  Base::h_);
206 
207  }
208 
209  void back_propagation(const std::vector<tensor_t*>& in_data,
210  const std::vector<tensor_t*>& out_data,
211  std::vector<tensor_t*>& out_grad,
212  std::vector<tensor_t*>& in_grad) override {
213  tensor_t& curr_delta = *out_grad[0];
214  this->backward_activation(*out_grad[0], *out_data[0], curr_delta);
215 
216  tiny_average_unpooling_back_kernel<Activation>(
217  in_data,
218  out_data,
219  out_grad,
220  in_grad,
221  in_,
222  Base::scale_factor_,
223  Base::weight2io_,
224  Base::in2wo_,
225  Base::bias2out_);
226  }
227 
228  private:
229  serial_size_t stride_;
230  shape3d in_;
231  shape3d out_;
232  shape3d w_;
233 
234  static serial_size_t unpool_out_dim(serial_size_t in_size,
235  serial_size_t pooling_size,
236  serial_size_t stride) {
237  return static_cast<int>((in_size-1) * stride + pooling_size);
238  }
239 
240  void init_connection(serial_size_t pooling_size) {
241  for (serial_size_t c = 0; c < in_.depth_; ++c) {
242  for (serial_size_t y = 0; y < in_.height_; ++y) {
243  for (serial_size_t x = 0; x < in_.width_; ++x) {
244  connect_kernel(pooling_size, x, y, c);
245  }
246  }
247  }
248 
249  for (serial_size_t c = 0; c < in_.depth_; ++c) {
250  for (serial_size_t y = 0; y < out_.height_; ++y) {
251  for (serial_size_t x = 0; x < out_.width_; ++x) {
252  this->connect_bias(c, out_.get_index(x, y, c));
253  }
254  }
255  }
256  }
257 
258  void connect_kernel(serial_size_t pooling_size,
259  serial_size_t x,
260  serial_size_t y,
261  serial_size_t inc) {
262  serial_size_t dymax = std::min(pooling_size, out_.height_ - y);
263  serial_size_t dxmax = std::min(pooling_size, out_.width_ - x);
264  serial_size_t dstx = x * stride_;
265  serial_size_t dsty = y * stride_;
266  serial_size_t inidx = in_.get_index(x, y, inc);
267  for (serial_size_t dy = 0; dy < dymax; ++dy) {
268  for (serial_size_t dx = 0; dx < dxmax; ++dx) {
269  this->connect_weight(
270  inidx,
271  out_.get_index(dstx + dx, dsty + dy, inc),
272  inc);
273  }
274  }
275  }
276 };
277 
278 } // namespace tiny_dnn
average pooling with trainable weights
Definition: average_unpooling_layer.h:134
std::vector< index3d< serial_size_t > > in_shape() const override
array of input shapes (width x height x depth)
Definition: average_unpooling_layer.h:185
std::string layer_type() const override
name of layer, should be unique for each concrete class
Definition: average_unpooling_layer.h:193
average_unpooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pooling_size, serial_size_t stride)
Definition: average_unpooling_layer.h:167
average_unpooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pooling_size)
Definition: average_unpooling_layer.h:145
void forward_propagation(const std::vector< tensor_t * > &in_data, std::vector< tensor_t * > &out_data) override
Definition: average_unpooling_layer.h:195
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: average_unpooling_layer.h:209
std::vector< index3d< serial_size_t > > out_shape() const override
array of output shapes (width x height x depth)
Definition: average_unpooling_layer.h:189
serial_size_t in_size() const
!
Definition: layer.h:176
bool parallelize_
Flag indicating whether the layer/node operations ara paralellized.
Definition: layer.h:696
serial_size_t in_channels() const
number of outgoing edges in this layer
Definition: layer.h:146
Definition: partial_connected_layer.h:34