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"
41 template <
typename Activation>
42 void tiny_average_pooling_kernel(
bool parallelize,
43 const std::vector<tensor_t*>& in_data,
44 std::vector<tensor_t*>& out_data,
45 const shape3d& out_dim,
47 std::vector<
typename partial_connected_layer<Activation>::wi_connections>& out2wi,
50 for_i(in_data[0]->size(), [&](
size_t sample) {
51 const vec_t& in = (*in_data[0])[sample];
52 const vec_t& W = (*in_data[1])[0];
53 const vec_t& b = (*in_data[2])[0];
54 vec_t& out = (*out_data[0])[sample];
55 vec_t& a = (*out_data[1])[sample];
57 auto oarea = out_dim.area();
59 for (serial_size_t d = 0; d < out_dim.depth_; ++d) {
60 float_t weight = W[d] * scale_factor;
62 for (serial_size_t i = 0; i < oarea; ++i, ++idx) {
63 const auto& connections = out2wi[idx];
64 float_t value = float_t(0);
65 for (
auto connection : connections)
66 value += in[connection.second];
73 assert(out.size() == out2wi.size());
74 for (serial_size_t i = 0; i < static_cast<serial_size_t>(out2wi.size()); i++) {
81 template<
typename Activation>
82 void tiny_average_pooling_back_kernel(
const std::vector<tensor_t*>& in_data,
83 const std::vector<tensor_t*>& out_data,
84 std::vector<tensor_t*>& out_grad,
85 std::vector<tensor_t*>& in_grad,
86 const shape3d& in_dim,
88 std::vector<
typename partial_connected_layer<Activation>::io_connections>& weight2io,
89 std::vector<
typename partial_connected_layer<Activation>::wo_connections>& in2wo,
90 std::vector<std::vector<serial_size_t>>& bias2out) {
92 for_i(in_data[0]->size(), [&](
size_t sample) {
93 const vec_t& prev_out = (*in_data[0])[sample];
94 const vec_t& W = (*in_data[1])[0];
95 vec_t& dW = (*in_grad[1])[sample];
96 vec_t& db = (*in_grad[2])[sample];
97 vec_t& prev_delta = (*in_grad[0])[sample];
98 vec_t& curr_delta = (*out_grad[0])[sample];
100 auto inarea = in_dim.area();
102 for (
size_t i = 0; i < in_dim.depth_; ++i) {
103 float_t weight = W[i] * scale_factor;
104 for (
size_t j = 0; j < inarea; ++j, ++idx) {
105 prev_delta[idx] = weight * curr_delta[in2wo[idx][0].second];
109 for (
size_t i = 0; i < weight2io.size(); ++i) {
110 const auto& connections = weight2io[i];
111 float_t diff = float_t(0);
113 for (
auto connection : connections)
114 diff += prev_out[connection.first] * curr_delta[connection.second];
116 dW[i] += diff * scale_factor;
119 for (
size_t i = 0; i < bias2out.size(); i++) {
120 const std::vector<serial_size_t>& outs = bias2out[i];
121 float_t diff = float_t(0);
124 diff += curr_delta[o];
135 template<
typename Activation = activation::
identity>
139 CNN_USE_LAYER_MEMBERS;
148 serial_size_t in_height,
150 serial_size_t pool_size)
155 serial_size_t pool_size,
156 serial_size_t stride)
168 serial_size_t in_height,
170 serial_size_t pool_size,
171 serial_size_t stride)
186 serial_size_t in_height,
188 serial_size_t pool_size_x,
189 serial_size_t pool_size_y,
190 serial_size_t stride_x,
191 serial_size_t stride_y,
192 padding pad_type = padding::valid)
194 conv_out_length(in_width, pool_size_x, stride_x, pad_type) *
195 conv_out_length(in_height, pool_size_y, stride_y, pad_type) *
in_channels,
199 pool_size_x_(pool_size_x),
200 pool_size_y_(pool_size_y),
203 out_(conv_out_length(in_width, pool_size_x, stride_x, pad_type),
204 conv_out_length(in_height, pool_size_y, stride_y, pad_type),
in_channels),
206 if ((in_width % pool_size_x) || (in_height % pool_size_y)) {
207 pooling_size_mismatch(in_width, in_height, pool_size_x, pool_size_y);
210 init_connection(pool_size_x, pool_size_y);
212 std::vector<index3d<serial_size_t>>
in_shape()
const override {
216 std::vector<index3d<serial_size_t>>
out_shape()
const override {
217 return { out_, out_ };
220 std::string
layer_type()
const override {
return "ave-pool"; }
223 std::vector<tensor_t*>& out_data)
override {
225 tiny_average_pooling_kernel<Activation>(
237 const std::vector<tensor_t*>& out_data,
238 std::vector<tensor_t*>& out_grad,
239 std::vector<tensor_t*>& in_grad)
override {
241 tensor_t& curr_delta = *out_grad[0];
242 this->backward_activation(*out_grad[0], *out_data[0], curr_delta);
244 tiny_average_pooling_back_kernel<Activation>(
256 template <
class Archive>
257 static void load_and_construct(Archive & ar, cereal::construct<average_pooling_layer> & construct) {
259 serial_size_t stride_x, stride_y, pool_size_x, pool_size_y;
262 ar(cereal::make_nvp(
"in_size", in),
263 cereal::make_nvp(
"pool_size_x", pool_size_x),
264 cereal::make_nvp(
"pool_size_y", pool_size_y),
265 cereal::make_nvp(
"stride_x", stride_x),
266 cereal::make_nvp(
"stride_y", stride_y),
267 cereal::make_nvp(
"pad_type", pad_type)
269 construct(in.width_, in.height_, in.depth_, pool_size_x, pool_size_y, stride_x, stride_y, pad_type);
272 template <
class Archive>
273 void serialize(Archive & ar) {
274 layer::serialize_prolog(ar);
275 ar(cereal::make_nvp(
"in_size", in_),
276 cereal::make_nvp(
"pool_size_x", pool_size_x_),
277 cereal::make_nvp(
"pool_size_y", pool_size_y_),
278 cereal::make_nvp(
"stride_x", stride_x_),
279 cereal::make_nvp(
"stride_y", stride_y_),
280 cereal::make_nvp(
"pad_type", pad_type_)
284 std::pair<serial_size_t, serial_size_t> pool_size()
const {
return std::make_pair(pool_size_x_, pool_size_y_); }
287 serial_size_t stride_x_;
288 serial_size_t stride_y_;
289 serial_size_t pool_size_x_;
290 serial_size_t pool_size_y_;
296 static serial_size_t pool_out_dim(serial_size_t
in_size,
297 serial_size_t pooling_size,
298 serial_size_t stride) {
299 return static_cast<int>(std::ceil((
300 static_cast<float_t
>(
in_size) - pooling_size) / stride) + 1);
303 void init_connection(serial_size_t pooling_size_x, serial_size_t pooling_size_y) {
304 for (serial_size_t c = 0; c < in_.depth_; ++c) {
305 for (serial_size_t y = 0; y < in_.height_ - pooling_size_y + 1; y += stride_y_) {
306 for (serial_size_t x = 0; x < in_.width_ - pooling_size_x + 1; x += stride_x_) {
307 connect_kernel(pooling_size_x, pooling_size_y, x, y, c);
312 for (serial_size_t c = 0; c < in_.depth_; ++c) {
313 for (serial_size_t y = 0; y < out_.height_; ++y) {
314 for (serial_size_t x = 0; x < out_.width_; ++x) {
315 this->connect_bias(c, out_.get_index(x, y, c));
321 void connect_kernel(serial_size_t pooling_size_x,
322 serial_size_t pooling_size_y,
326 serial_size_t dymax = std::min(pooling_size_y, in_.height_ - y);
327 serial_size_t dxmax = std::min(pooling_size_x, in_.width_ - x);
328 serial_size_t dstx = x / stride_x_;
329 serial_size_t dsty = y / stride_y_;
330 serial_size_t outidx = out_.get_index(dstx, dsty, inc);
331 for (serial_size_t dy = 0; dy < dymax; ++dy) {
332 for (serial_size_t dx = 0; dx < dxmax; ++dx) {
333 this->connect_weight(
334 in_.get_index(x + dx, y + dy, inc),
average pooling with trainable weights
Definition: average_pooling_layer.h:136
std::vector< index3d< serial_size_t > > out_shape() const override
array of output shapes (width x height x depth)
Definition: average_pooling_layer.h:216
std::string layer_type() const override
name of layer, should be unique for each concrete class
Definition: average_pooling_layer.h:220
std::vector< index3d< serial_size_t > > in_shape() const override
array of input shapes (width x height x depth)
Definition: average_pooling_layer.h:212
average_pooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pool_size, serial_size_t stride)
Definition: average_pooling_layer.h:167
average_pooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pool_size_x, serial_size_t pool_size_y, serial_size_t stride_x, serial_size_t stride_y, padding pad_type=padding::valid)
Definition: average_pooling_layer.h:185
average_pooling_layer(serial_size_t in_width, serial_size_t in_height, serial_size_t in_channels, serial_size_t pool_size)
Definition: average_pooling_layer.h:147
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_pooling_layer.h:236
void forward_propagation(const std::vector< tensor_t * > &in_data, std::vector< tensor_t * > &out_data) override
Definition: average_pooling_layer.h:222
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