| 1623 | namespace ttimpl |
| 1624 | { |
| 1625 | void softmax( |
| 1626 | const long num_locations, |
| 1627 | const long num_channels, |
| 1628 | tensor& dest, |
| 1629 | const tensor& src, |
| 1630 | operation_mode mode = operation_mode::CHANNEL_WISE |
| 1631 | ) |
| 1632 | { |
| 1633 | DLIB_ASSERT(num_channels * num_locations == src.nr() * src.nc() * src.k()); |
| 1634 | DLIB_CASSERT(have_same_dimensions(dest, src)); |
| 1635 | const auto d = dest.host(); |
| 1636 | const auto s = src.host(); |
| 1637 | |
| 1638 | for (long n = 0; n < src.num_samples(); ++n) |
| 1639 | { |
| 1640 | auto ss = s + num_locations * num_channels * n; |
| 1641 | auto dd = d + num_locations * num_channels * n; |
| 1642 | |
| 1643 | if (mode == operation_mode::CHANNEL_WISE) |
| 1644 | { |
| 1645 | for (long i = 0; i < num_locations; ++i) |
| 1646 | { |
| 1647 | float max_val = -std::numeric_limits<float>::infinity(); |
| 1648 | for (long k = 0; k < num_channels; ++k) |
| 1649 | max_val = std::max(max_val, ss[k * num_locations]); |
| 1650 | |
| 1651 | float sum = 0.0f; |
| 1652 | for (long k = 0; k < num_channels; ++k) |
| 1653 | { |
| 1654 | dd[k * num_locations] = std::exp(ss[k * num_locations] - max_val); |
| 1655 | sum += dd[k * num_locations]; |
| 1656 | } |
| 1657 | for (long k = 0; k < num_channels; ++k) |
| 1658 | dd[k * num_locations] /= sum; |
| 1659 | |
| 1660 | ++ss; |
| 1661 | ++dd; |
| 1662 | } |
| 1663 | } |
| 1664 | else if (mode == operation_mode::PLANE_WISE) |
| 1665 | { |
| 1666 | for (long k = 0; k < num_channels; ++k) |
| 1667 | { |
| 1668 | auto s_channel = ss + k * num_locations; |
| 1669 | auto d_channel = dd + k * num_locations; |
| 1670 | for (long r = 0; r < src.nr(); ++r) |
| 1671 | { |
| 1672 | float max_val = -std::numeric_limits<float>::infinity(); |
| 1673 | for (long c = 0, idx = r * src.nc(); c < src.nc(); ++c, ++idx) |
| 1674 | max_val = std::max(max_val, s_channel[idx]); |
| 1675 | |
| 1676 | if (max_val == -std::numeric_limits<float>::infinity()) |
| 1677 | { |
| 1678 | for (long c = 0, idx = r * src.nc(); c < src.nc(); ++c, ++idx) |
| 1679 | d_channel[idx] = 0.0f; |
| 1680 | } |
| 1681 | else |
| 1682 | { |