212 return params_.weight.width_ *
213 params_.weight.height_ *
219 return (params_.weight.width_ * params_.w_stride) *
220 (params_.weight.height_ * params_.h_stride) *
225 std::vector<tensor_t*>&
out_data)
override {
242 const std::vector<tensor_t*>&
out_data,
244 std::vector<tensor_t*>&
in_grad)
override {
248 std::vector<index3d<serial_size_t>>
in_shape()
const override {
249 if (params_.has_bias) {
250 return { params_.in, params_.weight,
253 return { params_.in, params_.weight };
257 std::vector<index3d<serial_size_t>>
out_shape()
const override {
258 return {params_.out_unpadded, params_.out_unpadded};
263 image<> weightto_image()
const {
272 img.resize(width, height);
275 auto minmax = std::minmax_element(
W.begin(),
W.end());
277 for (serial_size_t
r = 0;
r < params_.in.depth_; ++
r) {
278 for (serial_size_t
c = 0;
c < params_.out.depth_; ++
c) {
279 if (!params_.tbl.is_connected(
c,
r))
continue;
284 serial_size_t
idx = 0;
286 for (serial_size_t
y = 0;
y < params_.weight.height_; ++
y) {
287 for (serial_size_t
x = 0;
x < params_.weight.width_; ++
x) {
288 idx = params_.weight.get_index(
x,
y,
c * params_.in.depth_ +
r);
303 void init_backend(
const backend_t backend_type) {
304 std::shared_ptr<core::backend>
backend =
nullptr;
307 if (backend_type == backend_t::internal) {
308 backend = std::make_shared<core::tiny_backend>(¶ms_,
309 [
this](
const tensor_t& in) {
310 return copy_and_unpad_output(in);
312 [
this](
const tensor_t&
delta, tensor_t&
dst) {
313 return copy_and_pad_delta(
delta,
dst);
315 [
this](
const tensor_t&
p_delta,
316 const tensor_t& out, tensor_t&
c_delta) {
319 &deconv_layer_worker_storage_);
320 }
else if (backend_type == backend_t::nnpack) {
321 backend = std::make_shared<core::nnp_backend>();
322 }
else if (backend_type == backend_t::libdnn) {
323 backend = std::make_shared<core::dnn_backend>();
325 }
else if (backend_type == backend_t::avx) {
326 backend = std::make_shared<core::avx_backend>(¶ms_,
327 [
this](
const tensor_t& in) {
328 return copy_and_unpad_output(in);
330 [
this](
const tensor_t&
delta, tensor_t&
dst) {
331 return copy_and_pad_delta(
delta,
dst);
333 [
this](
const tensor_t&
p_delta,
334 const tensor_t& out, tensor_t&
c_delta) {
337 &deconv_layer_worker_storage_);
340 throw nn_error(
"Not supported backend type.");
345 Base::backend_->set_layer(
this);
347 throw nn_error(
"Could not allocate the backend.");
351 void deconv_set_params(
const shape3d& in,
357 serial_size_t w_stride,
358 serial_size_t h_stride,
363 deconv_out_length(in.height_,
w_height, h_stride),
365 params_.out_unpadded =
367 deconv_out_unpadded_length(in.height_,
w_height, h_stride,
ptype),
370 params_.has_bias = has_bias;
371 params_.pad_type =
ptype;
372 params_.w_stride = w_stride;
373 params_.h_stride = h_stride;
380 if (params_.pad_type == padding::same) {
385 dws.curr_out_buf_.clear();
390 serial_size_t in_length(serial_size_t in_length,
391 serial_size_t
window_size, padding pad_type)
const {
395 static serial_size_t deconv_out_length(serial_size_t in_length,
401 static serial_size_t deconv_out_unpadded_length(serial_size_t in_length,
403 serial_size_t
stride, padding pad_type) {
404 return pad_type == padding::same ?
409 static serial_size_t deconv_out_dim(serial_size_t
in_width,
412 serial_size_t w_stride,
413 serial_size_t h_stride, padding pad_type) {
418 serial_size_t deconv_out_dim(serial_size_t
in_width,
422 serial_size_t w_stride,
423 serial_size_t h_stride, padding pad_type)
const {
429 if (params_.pad_type == padding::valid) {
437 for (serial_size_t
c = 0;
c < params_.in.depth_;
c++) {
441 for (serial_size_t
y = 0;
y < params_.in.height_;
y++,
pdst +=
442 params_.in.width_,
pin += params_.in.width_) {
443 std::copy(
pin,
pin + params_.in.width_,
pdst);
450 void copy_and_unpad_output(
const tensor_t& out) {
452 deconv_layer_worker_storage_;
454 dws.curr_out_buf_ = tensor_t(out.size(), vec_t(params_.out_unpadded.width_*
455 params_.out_unpadded.height_*
456 params_.out_unpadded.depth_,0));
459 if (params_.pad_type == padding::valid) {
460 dws.curr_out_unpadded_ = &out;
464 serial_size_t
idx = 0;
469 for (serial_size_t
c = 0;
c < params_.out_unpadded.depth_;
c++) {
477 pout += params_.out.width_,
478 pimg += params_.out_unpadded.width_) {
480 pout + params_.out_unpadded.width_,
486 dws.curr_out_unpadded_ = &
dws.curr_out_buf_;
494 backend_t backend_type_;