| 1696 | } |
| 1697 | |
| 1698 | void softmax_gradient( |
| 1699 | const long num_locations, |
| 1700 | const long num_channels, |
| 1701 | tensor& grad, |
| 1702 | const tensor& dest, |
| 1703 | const tensor& gradient_input, |
| 1704 | operation_mode mode = operation_mode::CHANNEL_WISE |
| 1705 | ) |
| 1706 | { |
| 1707 | DLIB_ASSERT(num_channels * num_locations == grad.nr() * grad.nc() * grad.k()); |
| 1708 | DLIB_CASSERT(have_same_dimensions(grad, dest)); |
| 1709 | DLIB_CASSERT(have_same_dimensions(grad, gradient_input)); |
| 1710 | |
| 1711 | const auto d = dest.host(); |
| 1712 | const auto g = grad.host(); |
| 1713 | const auto in = gradient_input.host(); |
| 1714 | for (long n = 0; n < grad.num_samples(); ++n) |
| 1715 | { |
| 1716 | const auto d2 = d + num_locations * num_channels * n; |
| 1717 | const auto g2 = g + num_locations * num_channels * n; |
| 1718 | const auto in2 = in + num_locations * num_channels * n; |
| 1719 | |
| 1720 | if (mode == operation_mode::CHANNEL_WISE) |
| 1721 | { |
| 1722 | for (long i = 0; i < num_locations; ++i) |
| 1723 | { |
| 1724 | const auto d3 = d2 + i; |
| 1725 | const auto g3 = g2 + i; |
| 1726 | const auto in3 = in2 + i; |
| 1727 | float sum = 0.0f; |
| 1728 | for (long k = 0; k < num_channels; ++k) |
| 1729 | sum += -d3[k * num_locations] * in3[k * num_locations]; |
| 1730 | if (is_same_object(gradient_input, grad)) |
| 1731 | { |
| 1732 | for (long k = 0; k < num_channels; ++k) |
| 1733 | g3[k * num_locations] = d3[k * num_locations] * (sum + in3[k * num_locations]); |
| 1734 | } |
| 1735 | else |
| 1736 | { |
| 1737 | for (long k = 0; k < num_channels; ++k) |
| 1738 | g3[k * num_locations] += d3[k * num_locations] * (sum + in3[k * num_locations]); |
| 1739 | } |
| 1740 | } |
| 1741 | } |
| 1742 | else if (mode == operation_mode::PLANE_WISE) |
| 1743 | { |
| 1744 | for (long k = 0; k < num_channels; ++k) |
| 1745 | { |
| 1746 | const auto d_channel = d2 + k * num_locations; |
| 1747 | const auto g_channel = g2 + k * num_locations; |
| 1748 | const auto in_channel = in2 + k * num_locations; |
| 1749 | for (long r = 0; r < grad.nr(); ++r) |
| 1750 | { |
| 1751 | float sum = 0.0f; |
| 1752 | for (long c = 0, idx = r * grad.nc(); c < grad.nc(); ++c, ++idx) |
| 1753 | sum += -d_channel[idx] * in_channel[idx]; |
| 1754 | if (is_same_object(gradient_input, grad)) |
| 1755 | { |