Estoy escribiendo un algoritmo donde, dado un modelo, calculo las probabilidades para una lista de conjuntos de datos y luego necesito normalizar (a la probabilidad) cada una de las probabilidades. Por lo tanto, algo como [0.00043, 0.00004, 0.00321] podría convertirse como [0.2, 0.03, 0.77].
Mi problema es que las probabilidades de registro, con las que estoy trabajando, son bastante pequeñas (por ejemplo, en el espacio de registro, los valores son como -269647.432, -231444.981, etc.). En mi código C ++, cuando trato de agregar dos de ellos (tomando su exponente) obtengo una respuesta de "Inf". Traté de agregarlos en el espacio de registro (Suma / resta del registro) , pero nuevamente tropecé con el mismo problema.
¿Alguien puede compartir su opinión experta sobre esto?
log1p
Respuestas:
Reste el logaritmo máximo de todos los registros. Deseche todos los resultados que sean tan negativos que desbordarán lo exponencial. (Sus posibilidades son, a todos los efectos prácticos, cero).
De hecho, si desea una precisión relativa de (como para dígitos de precisión) y tiene probabilidades, deseche cualquier resultado menor que el logaritmo de . Luego proceda como de costumbre para exponer los valores resultantes y divida cada uno entre la suma de todos los exponenciales.ϵ = 10 - d d n ϵ / nϵ ϵ=10−d d n ϵ/n
Para quienes gustan de las fórmulas, dejemos que los logaritmos sean con . Para logaritmos a la base b \ gt 1 , definaλ n = max ( λ i ) b > 1λ1,λ2,…,λn λn=max(λi) b>1
Las probabilidades normalizadas son iguales a , Esto funciona porque al reemplazar todos los otra manera se desbordan por cero, se produce un error total de como máximo mientras que, porque y todos no son negativos, el denominador , por lo que el error relativo total debido a la regla de reemplazo cero es estrictamente menor que , según se desee. i = 1 , 2 , ... , n . α i ( n - 1 ) ϵ / n < ϵ α n = b λ n - λ n = b 0 = 1 α i A = ∑ j α j ≥ 1 ( ( n - 1αi/∑nj=1αj i=1,2,…,n. αi (n−1)ϵ/n<ϵ αn=bλn−λn=b0=1 αi A=∑jαj≥1 ((n−1)ϵ/n)/A<ϵ
Para evitar demasiados errores de redondeo, calcule la suma comenzando con los valores más pequeños de . Esto se hará automáticamente cuando los se primera vez en orden creciente. Esta es una consideración solo para muy grandes .λ i nαi λi n
Por cierto, esta receta asumió que la base de los registros es mayor que . Para bases menores que , primero niegue todos los registros y proceda como si la base fuera igual a .b 1 1 / b1 b 1 1/b
Ejemplo
Deje que haya tres valores con logaritmos (registros naturales, por ejemplo) igual a y El último es el más grande; restarlo de cada valor da y- 231444.981 , - 231444.699. - 38202.733 , - 0.282 , 0.−269647.432, −231444.981, −231444.699. −38202.733, −0.282, 0.
Supongamos que desea una precisión comparable a IEEE dobles (cerca de 16 dígitos decimales), por lo que y . (En realidad, no puede lograr esta precisión, porque se da solo a tres cifras significativas, pero está bien: solo estamos descartando valores que están garantizados para no afectar la mejor precisión que desea y la precisión que realmente tener.) Calcular = = La primera de las tres diferencias, es menor que esta, así que tírela, dejando solo y da n = 3 - 0.282 log ( ϵ / n ) log ( 10 - 16 ) - log ( 3 ) - 37.93997. - 38202.733 , - 0.282 0. exp ( - 0.282 ) = 0.754ϵ=10−16 n=3 - 0.282 Iniciar sesión( ϵ / n ) Iniciar sesión( 10- 16) - iniciar sesión( 3 ) - 37.93997. - 38202.733 , - 0.282 0. exp( - 0.282 ) = 0.754 y (por supuesto). Los valores normalizados son, en orden, para el que tiró, y .exp( 0 ) = 1 0 0 0.754 / ( 1 + 0.754 ) = 0.430 1 / ( 1 + 0.754 ) = 0.570
fuente