27 #ifndef LBANN_LAYER_UNPOOLING_HPP_INCLUDED 28 #define LBANN_LAYER_UNPOOLING_HPP_INCLUDED 45 template <
typename TensorDataType,
48 class unpooling_layer :
public data_type_layer<TensorDataType>
51 "unpooling only supports DATA_PARALLEL");
52 static_assert(Dev == El::Device::CPU,
"unpooling only supports CPU");
66 template <
typename ArchiveT>
71 std::string
get_type()
const override {
return "unpooling"; }
82 const auto* hint_layer =
84 if (hint_layer ==
nullptr) {
89 "does not have a valid pooling layer as a hint layer");
93 LBANN_ERROR(
"unpooling layer is only supported with max pooling");
95 if (hint_layer->using_gpus()) {
96 LBANN_ERROR(
"unpooling layer is not supported on GPUs");
107 const auto& pool_output_dims = hint_layer->get_output_dims();
108 if (input_dims != pool_output_dims) {
109 std::stringstream err;
111 <<
"expects input tensors with dimensions ";
112 for (
size_t i = 0; i < pool_output_dims.size(); ++i) {
113 err << (i > 0 ?
" x " :
"") << pool_output_dims[i];
115 err <<
", but parent layer " 117 <<
"outputs with dimensions ";
118 for (
size_t i = 0; i < input_dims.size(); ++i) {
119 err << (i > 0 ?
" x " :
"") << input_dims[i];
138 throw lbann_exception(
"unpooling_layer: GPU version not yet implemented");
148 throw lbann_exception(
"unpooling_layer: GPU version not yet implemented");
160 using DMatDT = El::Matrix<TensorDataType, Dev>;
163 const auto& hint_layer =
171 const int local_width = prev_activations_local.Width();
173 const int num_channels = output_dims[0];
174 const int num_per_input_channel = this->
get_input_size() / num_channels;
175 const int pool_size = hint_layer.m_pool_size;
178 DMatDT im2col_mat(pool_size * num_channels, num_per_input_channel);
181 for (
int sample = 0; sample < local_width; ++sample) {
184 El::Zero(im2col_mat);
187 const TensorDataType* prev_activations_buffer =
188 prev_activations_local.LockedBuffer(0, sample);
189 const int* indices_buffer =
192 for (
int channel = 0; channel < num_channels; ++channel) {
193 for (
int j = 0; j < num_per_input_channel; ++j) {
194 const int input_index = j + channel * num_per_input_channel;
195 const int max_index = indices_buffer[input_index];
196 TensorDataType* im2col_buffer =
197 im2col_mat.Buffer(channel * pool_size, j);
198 im2col_buffer[max_index] = prev_activations_buffer[input_index];
203 DMatDT output_mat = El::View(activations_local, El::ALL, El::IR(sample));
204 col2im<TensorDataType>(
208 output_dims.size() - 1,
210 hint_layer.m_pads.data(),
211 hint_layer.m_pool_dims.data(),
212 hint_layer.m_strides.data(),
213 [](TensorDataType
const& a, TensorDataType
const& b) {
214 return std::max(a, b);
223 using DMatDT = El::Matrix<TensorDataType, Dev>;
226 const auto& hint_layer =
230 const DMatDT& prev_error_signal_local =
235 const int local_width = prev_error_signal_local.Width();
237 const int num_channels = output_dims[0];
238 const int num_per_output_channel = this->
get_input_size() / num_channels;
239 const int pool_size = hint_layer.m_pool_size;
242 DMatDT im2col_mat(pool_size * num_channels, num_per_output_channel);
245 for (
int sample = 0; sample < local_width; ++sample) {
248 const DMatDT& input_mat =
249 El::LockedView(prev_error_signal_local, El::ALL, El::IR(sample));
250 im2col<TensorDataType>(input_mat,
253 output_dims.size() - 1,
255 hint_layer.m_pads.data(),
256 hint_layer.m_pool_dims.data(),
257 hint_layer.m_strides.data());
260 TensorDataType* output_buffer = error_signal_local.Buffer(0, sample);
261 const int* indices_buffer =
264 for (
int channel = 0; channel < num_channels; ++channel) {
265 for (
int j = 0; j < num_per_output_channel; ++j) {
266 const int output_index = j + channel * num_per_output_channel;
267 const int max_index = indices_buffer[output_index];
268 TensorDataType* im2col_buffer =
269 im2col_mat.Buffer(channel * pool_size, j);
270 output_buffer[output_index] = im2col_buffer[max_index];
277 #ifndef LBANN_UNPOOLING_LAYER_INSTANTIATE 279 extern template class unpooling_layer<T, \ 280 data_layout::DATA_PARALLEL, \ 283 #define LBANN_INSTANTIATE_CPU_HALF 286 #undef LBANN_INSTANTIATE_CPU_HALF 287 #endif // LBANN_UNPOOLING_LAYER_INSTANTIATE 291 #endif // LBANN_LAYER_UNPOOLING_HPP_INCLUDED virtual void setup_dims()
Setup tensor dimensions Called by the 'setup' function. If there are any input tensors, the base method sets all uninitialized output tensor dimensions equal to the first input tensor dimensions.
int get_backprop_requirements() const override
Returns the necessary tensors for computing backpropagation.
const Layer * get_hint_layer() const
Get hint layer.
friend class cereal::access
void fp_compute() override
Apply layer operation. Called by the 'forward_prop' function. Given the input tensors, the output tensors are populated with computed values.
std::vector< int > get_input_dims(size_t input_index=0) const
Get input tensor dimensions.
const InputAbsMatrixType & get_local_prev_activations(int parent_index=0) const
unpooling_layer * copy() const override
Copy function. This function dynamically allocates memory for a layer instance and instantiates a cop...
const OutputAbsMatrixType & get_local_prev_error_signals(int child_index=0) const
void write_specific_proto(lbann_data::Layer &proto) const final
void bp_compute() override
Compute objective funciton gradients. Called by the 'back_prop' function. Given the input...
constexpr El::Device Device
OutputAbsMatrixType & get_local_activations(int child_index=0)
void fp_compute_im2col()
Unpooling forward propagation with im2col.
int get_input_size(size_t input_index=0) const
Get input tensor size.
void set_output_dims(std::vector< int > dims, size_t output_index=0)
Set output tensor dimensions.
#define LBANN_OMP_PARALLEL_FOR
std::vector< const Layer * > get_parent_layers() const
exception lbann_exception
bool can_run_inplace() const override
If True, the computation can run in-place (feeding each input activations tensor as the corresponding...
data_layout get_data_layout() const override
Get data layout of the data tensors. We assume that the data layouts of the previous activations...
void setup_dims() override
Setup tensor dimensions Called by the 'setup' function. If there are any input tensors, the base method sets all uninitialized output tensor dimensions equal to the first input tensor dimensions.
std::string get_name() const
Get the layer instance's name.
void serialize(ArchiveT &ar)
El::Device get_device_allocation() const override
Get the device allocation for the data tensors. We assume that the decice allocation of the previous ...
data_layout
Data layout that is optimized for different modes of parallelism.
unpooling_layer(lbann_comm *comm)
InputAbsMatrixType & get_local_error_signals(int parent_index=0)
Transpose of pooling layer.
bool using_gpus() const noexcept
Whether the layer is using a GPU implementation.
std::string get_type() const override
Get the layer type's name.
virtual void setup_pointers()
Setup layer pointers. Called by the 'setup' function. Pointers to parent/child layers are assumed to ...
std::vector< int > get_output_dims(size_t output_index=0) const
Get output tensor dimensions.
void bp_compute_im2col()
Unpooling backward propagation with im2col.
void setup_pointers() override
Setup layer pointers. Called by the 'setup' function. Pointers to parent/child layers are assumed to ...