| 2747 | } |
| 2748 | |
| 2749 | void pooling::get_gradient( |
| 2750 | const tensor& gradient_input, |
| 2751 | const tensor& dest, |
| 2752 | const tensor& src, |
| 2753 | tensor& grad |
| 2754 | ) |
| 2755 | { |
| 2756 | DLIB_CASSERT(have_same_dimensions(gradient_input,dest)); |
| 2757 | DLIB_CASSERT(have_same_dimensions(src,grad)); |
| 2758 | |
| 2759 | |
| 2760 | if (src.size() == 0) |
| 2761 | { |
| 2762 | return; |
| 2763 | } |
| 2764 | |
| 2765 | |
| 2766 | auto gi = gradient_input.host(); |
| 2767 | auto g = grad.host(); |
| 2768 | const long x_offset = window_width/2 - padding_x; |
| 2769 | const long y_offset = window_height/2 - padding_y; |
| 2770 | if (does_max_pooling()) |
| 2771 | { |
| 2772 | for (long n = 0; n < dest.num_samples(); ++n) |
| 2773 | { |
| 2774 | for (long k = 0; k < dest.k(); ++k) |
| 2775 | { |
| 2776 | auto simg = image_plane(src,n,k); |
| 2777 | auto gimg = g + (n*grad.k() + k)*grad.nr()*grad.nc(); |
| 2778 | auto giimg = gi + (n*dest.k() + k)*dest.nr()*dest.nc(); |
| 2779 | auto imgbox = get_rect(simg); |
| 2780 | |
| 2781 | for (long r = 0; r < dest.nr(); ++r) |
| 2782 | { |
| 2783 | for (long c = 0; c < dest.nc(); ++c) |
| 2784 | { |
| 2785 | auto win = centered_rect(c*stride_x+x_offset, |
| 2786 | r*stride_y+y_offset, |
| 2787 | window_width, |
| 2788 | window_height).intersect(imgbox); |
| 2789 | auto p = max_point(subm(simg,win))+win.tl_corner(); |
| 2790 | gimg[p.y()*grad.nc()+p.x()] += giimg[r*dest.nc()+c]; |
| 2791 | } |
| 2792 | } |
| 2793 | } |
| 2794 | } |
| 2795 | } |
| 2796 | else |
| 2797 | { |
| 2798 | for (long n = 0; n < dest.num_samples(); ++n) |
| 2799 | { |
| 2800 | for (long k = 0; k < dest.k(); ++k) |
| 2801 | { |
| 2802 | auto simg = image_plane(src,n,k); |
| 2803 | auto gimg = g + (n*grad.k() + k)*grad.nr()*grad.nc(); |
| 2804 | auto giimg = gi + (n*dest.k() + k)*dest.nr()*dest.nc(); |
| 2805 | auto imgbox = get_rect(simg); |
| 2806 |
no test coverage detected