rec/fdeep/layers/max_pooling_2d_layer.hpp
2020-03-18 14:42:46 +08:00

91 lines
3.1 KiB
C++
Executable File

// Copyright 2016, Tobias Hermann.
// https://github.com/Dobiasd/frugally-deep
// Distributed under the MIT License.
// (See accompanying LICENSE file or at
// https://opensource.org/licenses/MIT)
#pragma once
#include "fdeep/layers/pooling_2d_layer.hpp"
#include <algorithm>
#include <limits>
#include <string>
namespace fdeep { namespace internal
{
FDEEP_FORCE_INLINE tensor5 max_pool_2d(
std::size_t pool_height, std::size_t pool_width,
std::size_t strides_y, std::size_t strides_x,
padding pad_type,
bool use_offset,
const tensor5& in)
{
const float_type invalid = std::numeric_limits<float_type>::lowest();
const auto conv_cfg = preprocess_convolution(
shape2(pool_height, pool_width),
shape2(strides_y, strides_x),
pad_type, use_offset, in.shape());
int pad_top_int = static_cast<int>(conv_cfg.pad_top_);
int pad_left_int = static_cast<int>(conv_cfg.pad_left_);
const std::size_t offset_y = conv_cfg.offset_y_;
const std::size_t offset_x = conv_cfg.offset_x_;
const std::size_t out_height = conv_cfg.out_height_;
const std::size_t out_width = conv_cfg.out_width_;
tensor5 out(shape5(1, 1, out_height, out_width, in.shape().depth_), 0);
for (std::size_t y = 0; y < out.shape().height_; ++y)
{
for (std::size_t x = 0; x < out.shape().width_; ++x)
{
for (std::size_t z = 0; z < out.shape().depth_; ++z)
{
float_type val = std::numeric_limits<float_type>::lowest();
for (std::size_t yf = 0; yf < pool_height; ++yf)
{
int in_get_y = static_cast<int>(offset_y + strides_y * y + yf) - pad_top_int;
for (std::size_t xf = 0; xf < pool_width; ++xf)
{
int in_get_x = static_cast<int>(offset_x + strides_x * x + xf) - pad_left_int;
const auto current = in.get_x_y_padded(invalid,
in_get_y, in_get_x, z);
val = std::max(val, current);
}
}
out.set(0, 0, y, x, z, val);
}
}
}
return out;
}
class max_pooling_2d_layer : public pooling_2d_layer
{
public:
explicit max_pooling_2d_layer(const std::string& name,
const shape2& pool_size, const shape2& strides, padding p,
bool padding_valid_uses_offset, bool padding_same_uses_offset) :
pooling_2d_layer(name, pool_size, strides, p,
padding_valid_uses_offset, padding_same_uses_offset)
{
}
protected:
tensor5 pool(const tensor5& in) const override
{
if (pool_size_ == shape2(2, 2) && strides_ == shape2(2, 2))
return max_pool_2d(2, 2, 2, 2, padding_, use_offset(), in);
else if (pool_size_ == shape2(4, 4) && strides_ == shape2(4, 4))
return max_pool_2d(4, 4, 4, 4, padding_, use_offset(), in);
else
return max_pool_2d(
pool_size_.height_, pool_size_.width_,
strides_.height_, strides_.width_,
padding_, use_offset(), in);
}
};
} } // namespace fdeep, namespace internal