tinyopt
700
Tinyopt, a lightweight, header only optimization library
Toggle main menu visibility
Loading...
Searching...
No Matches
classif.h
1
// Copyright 2026 Julien Michot.
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include <tinyopt/math.h>
7
#include <tinyopt/traits.h>
8
9
namespace
tinyopt::losses
{
10
16
template
<
typename
T,
typename
ExportJ = std::
nullptr
_t>
17
auto
Softmax
(
const
T &x,
const
ExportJ &Jx_or_bool =
nullptr
) {
18
constexpr
bool
IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
19
if
constexpr
(traits::is_pair_v<T>) {
// pair
20
return
Softmax
(x.first, x.second);
21
}
else
if
constexpr
(!IsMatrix) {
// scalar
22
if
constexpr
(std::is_null_pointer_v<ExportJ>)
23
return
1;
24
else
if
constexpr
(traits::is_matrix_or_array_v<ExportJ>)
25
return
std::make_pair(1, Jx_or_bool);
26
else
27
return
std::make_pair(1, 1);
28
}
else
{
// Matrix
29
using
std::exp;
30
using
Scalar =
typename
T::Scalar;
31
constexpr
Index Dims = T::RowsAtCompileTime;
32
const
auto
si = x.array().exp().matrix().eval();
33
const
Scalar sum = si.sum();
34
const
T out = x.unaryExpr([sum](Scalar v) {
return
exp(v) / sum; }).eval();
35
if
constexpr
(std::is_null_pointer_v<ExportJ>) {
36
return
out;
37
}
else
{
38
Matrix<Scalar, Dims, Dims> Jo(x.rows(), x.rows());
39
Jo.setZero();
40
for
(
int
c = 0; c < Jo.cols(); ++c) {
41
for
(
int
r = c; r < Jo.rows(); ++r) {
42
Jo(r, c) = r == c ? out[c] * (1.0 - out[c]) : -out[r] * out[c];
43
}
44
}
45
Jo.template triangularView<Upper>() = Jo.template triangularView<Lower>().transpose();
46
return
std::make_pair(out, (Jo * Jx_or_bool).eval());
47
}
48
}
49
}
50
52
template
<
typename
T,
typename
ExportJ = std::
nullptr
_t>
53
auto
SafeSoftmax
(
const
T &x,
const
ExportJ &Jx_or_bool =
nullptr
) {
54
constexpr
bool
IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
55
if
constexpr
(traits::is_pair_v<T>) {
// pair
56
return
SafeSoftmax
(x.first, x.second);
57
}
else
if
constexpr
(!IsMatrix) {
// scalar
58
if
constexpr
(std::is_null_pointer_v<ExportJ>)
59
return
std::make_pair(1, 1);
60
else
if
constexpr
(traits::is_matrix_or_array_v<ExportJ>)
61
return
std::make_pair(1, Jx_or_bool);
62
else
63
return
1;
64
}
else
{
// Matrix
65
using
std::exp;
66
using
Scalar =
typename
T::Scalar;
67
constexpr
Index Dims = T::RowsAtCompileTime;
68
const
Scalar mx = x.maxCoeff();
69
const
auto
si = (x.array() - mx).exp().matrix().eval();
70
const
Scalar sum = si.sum();
71
const
T out = x.unaryExpr([mx, sum](Scalar v) {
return
exp(v - mx) / sum; });
72
if
constexpr
(std::is_null_pointer_v<ExportJ>) {
73
return
out;
74
}
else
{
75
Matrix<Scalar, Dims, Dims> Jo(x.rows(), x.rows());
76
Jo.setZero();
77
for
(
int
c = 0; c < Jo.cols(); ++c) {
78
for
(
int
r = c; r < Jo.rows(); ++r) {
79
Jo(r, c) = r == c ? out[c] * (1.0 - out[c]) : -out[r] * out[c];
80
}
81
}
82
Jo.template triangularView<Upper>() = Jo.template triangularView<Lower>().transpose();
83
return
std::make_pair(out, (Jo * Jx_or_bool).eval());
84
}
85
}
86
}
87
89
}
// namespace tinyopt::losses
tinyopt::losses
Definition
activations.h:8
tinyopt::losses::Softmax
auto Softmax(const T &x, const ExportJ &Jx_or_bool=nullptr)
Softmax = e^xi / sum(e^x), jacobian = {i=j: si(x)*(1-si(x)) , i!=j: -si(x)*sj(x)}.
Definition
classif.h:17
tinyopt::losses::SafeSoftmax
auto SafeSoftmax(const T &x, const ExportJ &Jx_or_bool=nullptr)
Safe Softmax = e^(xi-max(xi)) / sum(e^(x-max(xi)).
Definition
classif.h:53
include
tinyopt
losses
classif.h
Generated by
1.18.0