池化层正向都是求区域最大值,反向有两种方法:1、记住最大值位置,将回传值赋值到该位置;2、平均值平均分配到区域中。下面就是实现啦,实现了这两种方法:
#ifndef _POOL_LAYER_HPP_
#define _POOL_LAYER_HPP_
#include "base_logic.hpp"
/* 池化层,对区域内取最大值 */
template<template<int,int,int,int,typename> class update_method_tpl, int input_row, int input_col, int tpl_row, int tpl_col, typename val_t = double>
struct pool_layer
{
using input_type = mat<input_row, input_col, val_t>;
using ret_type = mat<get_ceil_div(input_row, tpl_row), get_ceil_div(input_col, tpl_col), val_t>;
update_method_tpl<input_row, input_col, tpl_row, tpl_col, val_t> um; // 更新算法
ret_type forward(const input_type& mt)
{
return um.forward(mt);
}
input_type backward(const ret_type& mt)
{
return um.backward(mt);
}
};
template<int r, int c, int tpl_row, int tpl_col>
struct region_max_cal
{
template<int row_num, int col_num, typename val_t, typename omat_p_t>
inline static val_t cal(const mat<row_num, col_num, val_t>& mt, omat_p_t& p_omt_r, omat_p_t& p_omt_c)
{
int i_max_r = 0, i_max_c = 0;
val_t ret = mt.region_max<r*tpl_row, c*tpl_col, tpl_row, tpl_col>(i_max_r, i_max_c);
(*p_omt_r).get_val<r, c>() = (i_max_r);
(*p_omt_c).get_val<r, c>() = (i_max_c);
return ret;
}
};
template<int input_row, int input_col, int tpl_row, int tpl_col, typename val_t = double>
struct pool_layer_max
{
using input_type = mat<input_row, input_col, val_t>;
using ret_type = mat<get_ceil_div(input_row, tpl_row), get_ceil_div(input_col, tpl_col), val_t>;
template<int r, int c>
struct region_max_local
{
template<int row_num, int col_num, typename val_t, typename omat_p_t>
inline static val_t cal(const mat<row_num, col_num, val_t>& mt, omat_p_t& p_omt_r, omat_p_t& p_omt_c)
{
return region_max_cal<r, c, tpl_row, tpl_col>::cal(mt, p_omt_r, p_omt_c);
}
};
mat<get_ceil_div(input_row, tpl_row), get_ceil_div(input_col, tpl_col), int> mt_max_row, mt_max_col;
ret_type forward(const input_type& mt)
{
ret_type ret;
col_loop<ret_type::c - 1, region_max_local>(ret, mt, &mt_max_row, &mt_max_col);
return ret;
}
input_type backward(const ret_type& mt)
{
input_type ret;
for (int r = 0; r < ret_type::r; ++r)
{
for (int c = 0; c < ret_type::c; ++c)
{
ret.get(mt_max_row.get(r, c), mt_max_col.get(r, c)) = mt.get(r, c);
}
}
return ret;
}
};
template<int input_row, int input_col, int tpl_row, int tpl_col, typename val_t = double>
struct pool_layer_average
{
using input_type = mat<input_row, input_col, val_t>;
using ret_type = mat<get_ceil_div(input_row, tpl_row), get_ceil_div(input_col, tpl_col), val_t>;
template<int r, int c>
struct region_max_local
{
template<int row_num, int col_num, typename val_t, typename omat_p_t>
inline static val_t cal(const mat<row_num, col_num, val_t>& mt, omat_p_t& p_omt_r, omat_p_t& p_omt_c)
{
return region_max_cal<r, c, tpl_row, tpl_col>::cal(mt, p_omt_r, p_omt_c);
}
};
ret_type forward(const input_type& mt)
{
ret_type ret;
mat<get_ceil_div(input_row, tpl_row), get_ceil_div(input_col, tpl_col), int> mt_max_row, mt_max_col;
col_loop<ret_type::c - 1, region_max_local>(ret, mt, &mt_max_row, &mt_max_col);
return ret;
}
input_type backward(const ret_type& mt)
{
input_type ret;
for (int r = 0; r < input_type::r; ++r)
{
for (int c = 0; c < input_type::c; ++c)
{
ret.get(r, c) = mt.get(r/tpl_row, c/tpl_col)/(tpl_row*tpl_col);
}
}
return ret;
}
};
#endif