1 #ifndef LAYER_CONVOLUTIONAL_H_ 2 #define LAYER_CONVOLUTIONAL_H_ 9 #include "../Utils/Convolution.h" 10 #include "../Utils/Convolution_DHT.h" 11 #include "../Utils/Random.h" 23 template <
typename Activation>
24 class Convolutional:
public Layer
27 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
28 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;
29 typedef Matrix::ConstAlignedMapType ConstAlignedMapMat;
30 typedef Vector::ConstAlignedMapType ConstAlignedMapVec;
31 typedef Vector::AlignedMapType AlignedMapVec;
33 const internal::ConvDims m_dim;
48 internal::DHT2D m_dht;
65 const int in_channels,
const int out_channels,
66 const int window_width,
const int window_height) :
67 Layer(in_width * in_height * in_channels,
68 (in_width - window_width + 1) * (in_height - window_height + 1) * out_channels),
69 m_dim(in_channels, out_channels, in_height, in_width, window_height, window_width),
70 m_dht(in_height, in_width)
73 void init(
const Scalar& mu,
const Scalar& sigma,
RNG& rng)
76 const int filter_data_size = m_dim.in_channels * m_dim.out_channels * m_dim.filter_rows * m_dim.filter_cols;
77 m_filter_data.resize(filter_data_size);
78 m_df_data.resize(filter_data_size);
81 internal::set_normal_random(m_filter_data.data(), filter_data_size, rng, mu, sigma);
84 m_bias.resize(m_dim.out_channels);
85 m_db.resize(m_dim.out_channels);
86 internal::set_normal_random(m_bias.data(), m_dim.out_channels, rng, mu, sigma);
90 void forward(
const Matrix& prev_layer_data)
93 const int nobs = prev_layer_data.cols();
96 m_z.resize(this->m_out_size, nobs);
98 const int in_dht_depth = m_dim.in_channels * nobs;
99 m_dht.pseudo_transform(
100 ConstAlignedMapMat(prev_layer_data.data(), m_dim.channel_rows, m_dim.channel_cols * in_dht_depth),
104 const int filter_dht_depth = m_dim.in_channels * m_dim.out_channels;
105 m_dht.pseudo_transform_padding(
106 ConstAlignedMapMat(m_filter_data.data(), m_dim.filter_rows, m_dim.filter_cols * filter_dht_depth),
107 filter_dht_depth,
true,
110 internal::convolve_valid_dht(m_dim, m_dht,
111 m_in_dht, m_filter_dht,
true, nobs, m_z.data());
115 int channel_start_row = 0;
116 const int channel_nelem = m_dim.conv_rows * m_dim.conv_cols;
117 for(
int i = 0; i < m_dim.out_channels; i++, channel_start_row += channel_nelem)
119 m_z.block(channel_start_row, 0, channel_nelem, nobs).array() += m_bias[i];
123 m_a.resize(this->m_out_size, nobs);
124 Activation::activate(m_z, m_a);
135 void backprop(
const Matrix& prev_layer_data,
const Matrix& next_layer_data)
137 const int nobs = prev_layer_data.cols();
144 Activation::apply_jacobian(m_z, m_a, next_layer_data, dLz);
160 internal::ConvDims back_conv_dim(nobs, m_dim.out_channels, m_dim.channel_rows, m_dim.channel_cols,
161 m_dim.conv_rows, m_dim.conv_cols);
162 const int dLz_dht_depth = back_conv_dim.in_channels * back_conv_dim.out_channels;
163 m_dht.pseudo_transform_padding(
164 ConstAlignedMapMat(dLz.data(), back_conv_dim.filter_rows, back_conv_dim.filter_cols * dLz_dht_depth),
168 internal::convolve_valid_dht(back_conv_dim, m_dht,
169 m_in_dht, m_dLz_dht,
false, m_dim.in_channels, m_df_data.data());
174 ConstAlignedMapMat dLz_by_channel(dLz.data(), m_dim.conv_rows * m_dim.conv_cols, m_dim.out_channels * nobs);
175 Vector dLb = dLz_by_channel.colwise().sum();
177 ConstAlignedMapMat dLb_by_obs(dLb.data(), m_dim.out_channels, nobs);
178 m_db.noalias() = dLb_by_obs.rowwise().mean();
181 m_din.resize(this->m_in_size, nobs);
182 internal::ConvDims conv_full_dim(m_dim.out_channels, m_dim.in_channels, m_dim.conv_rows, m_dim.conv_cols, m_dim.filter_rows, m_dim.filter_cols);
183 const int filter_dht_depth = m_dim.in_channels * m_dim.out_channels;
184 m_dht.pseudo_transform_padding(
185 ConstAlignedMapMat(m_filter_data.data(), m_dim.filter_rows, m_dim.filter_cols * filter_dht_depth),
186 filter_dht_depth,
false,
189 internal::convolve_full_dht(conv_full_dim, m_dht,
190 m_dLz_dht, m_filter_dht, nobs, m_din.data());
200 ConstAlignedMapVec dw(m_df_data.data(), m_df_data.size());
201 ConstAlignedMapVec db(m_db.data(), m_db.size());
202 AlignedMapVec w(m_filter_data.data(), m_filter_data.size());
203 AlignedMapVec b(m_bias.data(), m_bias.size());
211 std::vector<Scalar> res(m_filter_data.size() + m_bias.size());
213 std::copy(m_filter_data.data(), m_filter_data.data() + m_filter_data.size(), res.begin());
214 std::copy(m_bias.data(), m_bias.data() + m_bias.size(), res.begin() + m_filter_data.size());
221 if(static_cast<int>(param.size()) != m_filter_data.size() + m_bias.size())
222 throw std::invalid_argument(
"Parameter size does not match");
224 std::copy(param.begin(), param.begin() + m_filter_data.size(), m_filter_data.data());
225 std::copy(param.begin() + m_filter_data.size(), param.end(), m_bias.data());
230 std::vector<Scalar> res(m_df_data.size() + m_db.size());
232 std::copy(m_df_data.data(), m_df_data.data() + m_df_data.size(), res.begin());
233 std::copy(m_db.data(), m_db.data() + m_db.size(), res.begin() + m_df_data.size());
void init(const Scalar &mu, const Scalar &sigma, RNG &rng)
std::vector< Scalar > get_parameters() const
void set_parameters(const std::vector< Scalar > ¶m)
const Matrix & output() const
void update(Optimizer &opt)
Convolutional(const int in_width, const int in_height, const int in_channels, const int out_channels, const int window_width, const int window_height)
std::vector< Scalar > get_derivatives() const
void backprop(const Matrix &prev_layer_data, const Matrix &next_layer_data)
const Matrix & backprop_data() const
virtual void update(ConstAlignedMapVec &dvec, AlignedMapVec &vec)=0
void forward(const Matrix &prev_layer_data)