26 votos

Conversión (normalización) de valores de probabilidad muy pequeños en probabilidad

Estoy escribiendo un algoritmo en el que, dado un modelo, calculo probabilidades para una lista de conjuntos de datos y luego necesito normalizar (a probabilidad) cada una de las probabilidades. Así que algo como [0,00043, 0,00004, 0,00321] podría convertirse en algo como [0,2, 0,03, 0,77].

Mi problema es que las probabilidades logarítmicas con las que trabajo son bastante pequeñas (por ejemplo, en el espacio logarítmico, los valores son -269647,432, -231444,981, etc.). En mi código C++, cuando intento sumar dos de ellos (tomando su exponente) obtengo una respuesta de "Inf". He intentado sumarlos en espacio logarítmico (Suma/resta de logaritmos) , pero de nuevo tropezó con el mismo problema.

¿Alguien puede compartir su opinión experta al respecto?

38voto

jldugger Puntos 7490

Resta el logaritmo máximo de todos los logaritmos. Desecha todos los resultados que sean tan negativos que desborden por debajo de la exponencial. (Sus probabilidades son, a efectos prácticos, cero).

En efecto, si desea una precisión relativa de $\epsilon$ (como $\epsilon = 10^{-d}$ para $d$ dígitos de precisión) y tiene $n$ probabilidades, desechar cualquier resultado inferior al logaritmo de $\epsilon/n$ . A continuación, proceda como de costumbre a exponenciar los valores resultantes y divida cada uno de ellos por la suma de todos los exponenciales.

Para los que les gusten las fórmulas, que los logaritmos sean $\lambda_1, \lambda_2, \ldots, \lambda_n$ con $\lambda_n = \max(\lambda_i)$ . Para logaritmos de base $b\gt 1$ define

$$\alpha_i = \cases{ b^{\lambda_i - \lambda_n}, \lambda_i - \lambda_n \ge \log(\epsilon)-\log(n) \\ 0\quad \text{otherwise}.}$$

Las probabilidades normalizadas son iguales a $\alpha_i / \sum_{j=1}^n \alpha_j$ , $i = 1, 2, \ldots, n.$ Esto funciona porque la sustitución de todo el desbordamiento de otra manera $\alpha_i$ por cero comete un error total de como máximo $(n-1)\epsilon/n\lt \epsilon$ Considerando que $\alpha_n=b^{\lambda_n-\lambda_n}=b^0=1$ y todos $\alpha_i$ son no negativos, el denominador $A = \sum_j \alpha_j \ge 1$ por lo que el total relativa error debido a la regla de sustitución por cero es estrictamente menor que $\left((n-1)\epsilon/n \right) / A \lt \epsilon$ según se desee.

Para evitar un error de redondeo excesivo, calcule la suma empezando por los valores más pequeños del $\alpha_i$ . Esto se hará automáticamente cuando el $\lambda_i$ se ordenan primero en orden creciente. Esto sólo debe tenerse en cuenta en el caso de $n$ .

BTW, esta receta supone que la base de los troncos es mayor que $1$ . Para las bases $b$ menos de $1$ primero niega todos los registros y procede como si la base fuera igual a $1/b$ .


Ejemplo

Sean tres valores con logaritmos (logaritmos naturales, digamos) iguales a $-269647.432,$ $-231444.981,$ y $-231444.699.$ El último es el mayor; restándolo de cada valor se obtiene $-38202.733,$ $-0.282,$ y $0.$

Supongamos que desea una precisión comparable a la de los dobles IEEE (unos 16 dígitos decimales), de modo que $\epsilon=10^{-16}$ y $n=3$ . (En realidad no se puede lograr esta precisión, porque $-0.282$ se da sólo con tres cifras significativas, pero no pasa nada: sólo estamos desechando valores que está garantizado que no afectarán a la mejor entre la precisión que quieres y la que realmente tienes). Calcule $\log(\epsilon/n)$ = $\log(10^{-16}) - \log(3)$ = $-37.93997.$ La primera de las tres diferencias, $-38202.733,$ es menor que esto, así que tíralo, dejando sólo $-0.282$ y $0.$ Exponenciándolos se obtiene $\exp(-0.282) = 0.754$ y $\exp(0)=1$ (por supuesto). Los valores normalizados son, por orden $0$ por el que tiraste, $0.754 / (1 + 0.754) = 0.430$ y $1/(1+0.754)=0.570$ .

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X