Estou escrevendo um algoritmo no qual, dado um modelo, calculo as probabilidades para uma lista de conjuntos de dados e, em seguida, preciso normalizar (com probabilidade) cada uma das probabilidades. Então, algo como [0,00043, 0,00004, 0,00321] pode ser convertido em [0,2, 0,03, 0,77].
Meu problema é que as probabilidades de log, com as quais estou trabalhando, são muito pequenas (por exemplo, no espaço de log, os valores são como -269647.432, -231444.981 etc.). No meu código C ++, quando tento adicionar dois deles (usando o expoente), recebo uma resposta de "Inf". Tentei adicioná-los no espaço de log (soma / subtração de log) , mas novamente deparei com o mesmo problema.
Alguém pode compartilhar sua opinião de especialista sobre isso?
log1p
Respostas:
Subtraia o logaritmo máximo de todos os logs. Jogue fora todos os resultados que são tão negativos que irão prejudicar o exponencial. (Suas probabilidades são, para todos os efeitos práticos, zero.)
De fato, se você deseja uma precisão relativa de (como para dígitos de precisão) e tem probabilidades, jogue fora qualquer resultado menor que o logaritmo de . Em seguida, proceda como de costume para exponenciar os valores resultantes e divida cada um pela soma de todos os exponenciais.ϵ = 10 - d d n ϵ / nϵ ϵ=10−d d n ϵ/n
Para quem gosta de fórmulas, os logaritmos devem ser com . Para logaritmos na base b \ gt 1 , definaλ n = máx ( λ i ) b > 1λ1,λ2,…,λn λn=max(λi) b>1
As probabilidades normalizadas são iguais a , Isso funciona porque a substituição de todos os por outro lado, com fluxo , um erro total de no máximo , enquanto que, porque e todos não são negativos, o denominador , de onde o erro relativo total devido à regra de substituição zero é estritamente menor que , conforme desejado. 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 muitos erros de arredondamento, calcule a soma começando com os menores valores de . Isso será feito automaticamente quando os forem classificados pela primeira vez em ordem crescente. Essa é uma consideração apenas para muito grande .λ i nαi λi n
BTW, essa prescrição assumiu que a base dos logs é maior que . Para bases menores que , primeiro negue todos os logs e proceda como se a base fosse igual a .b 1 1 / b1 b 1 1/b
Exemplo
três valores com logaritmos (logs naturais, digamos) iguais a e O último é o maior; subtraindo-o de cada valor, obtém e- 231444.981 , - 231444.699. - 38202,733 , - 0,282 , 0.−269647.432, −231444.981, −231444.699. −38202.733, −0.282, 0.
Suponha que você gostaria de precisão comparável ao IEEE duplos (cerca de 16 dígitos decimais), de modo que e . (Na verdade, você não pode atingir essa precisão, porque é dado apenas a três números significativos, mas tudo bem: estamos apenas descartando valores que são garantidos para não afetar o melhor da precisão desejada e da precisão que você realmente Calcule = = A primeira das três diferenças, é menor que isso, então jogue fora, deixando apenas e Exponencia-las dá n = 3 - 0,282 log ( ϵ / n ) log ( 10 - 16 ) - log ( 3 ) - 37,93997. - 38202.733 , - 0,282 0. exp ( - 0,282 ) = 0,754 exp ( 0 ) = 1 0 0,754 / ( 1 + 0,754 ) =ϵ=10−16 n=3 −0.282 log(ϵ/n) log(10−16)−log(3) −37.93997. −38202.733, −0.282 0. exp(−0.282)=0.754 e (é claro). Os valores normalizados são - em ordem - para o que você jogou fora, e .exp(0)=1 0 0.754/(1+0.754)=0.430 1/(1+0.754)=0.570
fonte