Normalmente estos valores no se calculan solos: toda la colección de $v_i$ y $\log(1 - \exp(v_i))$ es necesario. Eso cambia el análisis del esfuerzo computacional.
Para ello
$$\bar x = \log\left(\sum_{j} e^{x_j}\right) = x_k + \log\left(1 + \sum_{j\ne k} e^{x_j-x_k}\right)$$
para cualquier índice $k.$ La expresión de la derecha muestra cómo $\bar x - x_k$ puede calcularse de forma numéricamente estable cuando $k$ es el índice del argumento mayor, pues entonces el argumento del logaritmo está entre $1$ y $n$ (el número del $x_i$ ) y la suma puede calcularse con precisión utilizando exp
(especialmente cuando el $x_j$ se ordenan de menor a mayor en la suma).
La relación
$$\eqalign{ \log\left(1 - \frac{e^{x_i}}{\sum_{j} e^{x_j}}\right) &= \log\left(\frac{\sum_{j\ne i} e^{x_j}}{\sum_{j} e^{x_j}}\right) \\ &= \log\left(\sum_{j\ne i} e^{x_j}\right) - x_k + \log\left(\frac{e^{x_k}}{\sum_{j} e^{x_j}}\right) \\ &= \log\left(-e^{x_i} + \sum_{j} e^{x_j}\right) - x_k + v_k \\ &= \log\left(1 - e^{x_i - \bar x}\right) + (\bar x - x_k) + v_k }$$
reduce el problema a encontrar ese último logaritmo, lo que se consigue aplicando un log1mexp
a la diferencia $x_i - \bar x.$
Para $n$ argumentos $x_i,$ $i=1,2,\ldots, n,$ el esfuerzo total para calcular todos $2n$ es
-
$n$ cálculos del $v_i$ utilizando logsoftmax
.
-
Un cálculo de $\bar x - x_k$ (utilizando $n-1$ exponenciales y un logaritmo).
-
$n$ invocaciones de log1mexp
.