Преобразование (нормализация) очень малых значений вероятности в вероятность

21

Я пишу алгоритм, в котором, учитывая модель, я вычисляю вероятности для списка наборов данных, а затем должен нормализовать (для вероятности) каждый из вероятностей. Таким образом, что-то вроде [0.00043, 0.00004, 0.00321] может быть преобразовано в что-то вроде [0.2, 0.03, 0.77].

Моя проблема заключается в том, что вероятность журналов, с которыми я работаю, довольно мала (например, в пространстве журналов значения равны -269647.432, -231444.981 и т. Д.). В моем коде C ++, когда я пытаюсь добавить два из них (взяв их показатель степени), я получаю ответ «Inf». Я попытался добавить их в пространство журнала (Суммирование / Вычитание журнала) , но снова наткнулся на ту же проблему.

Кто-нибудь может поделиться своим мнением по этому поводу?

Икрам
источник
Когда вы использовали функции, которые вы указали, включая , вы использовали эту функцию на своем языке? Это использует расширение Тейлора около 1.log(1+)log1p
Нил Г
1
Смотрите также некоторые ранее, связанные обсуждения здесь
Glen_b

Ответы:

30

Вычтите максимальный логарифм из всех журналов. Отбросьте все результаты, которые настолько отрицательны, что потеряют экспоненциальный результат. (Их вероятность для всех практических целей равна нулю.)

Действительно, если вам нужна относительная точность (например, для цифр точности) и у вас вероятностей, отбросьте любой результат, меньший логарифма . Затем продолжайте как обычно, чтобы возвести в степень полученные значения и разделите каждое из них на сумму всех экспонент.ϵ = 10 - д д н ϵ / нϵϵ=10ddnϵ/n

Для тех, кто любит формулы, пусть логарифмы будут с . Для логарифмов к основанию определитеλ n = max ( λ i ) b > 1λ1,λ2,,λnλn=max(λi)b>1

αi={bλiλn,λiλnlog(ϵ)log(n)0otherwise.

Нормализованные вероятности равны , Это работает, потому что замена всех остальных заниженных на ноль приводит к общей ошибке не более тогда как и все неотрицательны, знаменатель , откуда общая относительная ошибка, обусловленная правилом замены нуля, строго меньше , по желанию. i = 1 , 2 , , n . α i ( n - 1 ) ϵ / n < ϵ α n = b λ n - λ n = b 0 = 1 α i A = j α j1 ( ( n - 1αi/j=1nαji=1,2,,n.αi(n1)ϵ/n<ϵαn=bλnλn=b0=1αiA=jαj1((n1)ϵ/n)/A<ϵ

Чтобы избежать слишком большой ошибки округления, вычислите сумму, начиная с наименьших значений . Это будет сделано автоматически при первой сортировке в порядке возрастания. Это соображение только для очень больших .λ i nαiλin

Кстати, этот рецепт предполагал, что база журналов больше . Для баз меньших , сначала сверните все журналы и продолжайте, как если бы база была равна .б 1 1 / б1b11/b


пример

Пусть будет три значения с логарифмами (скажем, натуральными), равными и Последний самый большой; вычитание его из каждого значения дает и- 231444,981 , - 231444,699. - 38202,733 , - 0,282 , 0.269647.432, 231444.981,231444.699.38202.733, 0.282,0.

Предположим, вы хотите, чтобы точность была сопоставима с двойными значениями IEEE (около 16 десятичных цифр), чтобы и . (Вы не можете на самом деле достичь этой точности, потому что задается только тремя значащими цифрами, но это нормально: мы отбрасываем только те значения, которые гарантированно не повлияют на лучшую точность, которую вы хотите, и точность, которую вы на самом деле иметь.) Вычислить = = Первое из трех различий, меньше, чем это, поэтому отбросьте его, оставив только и их дает n = 3 - 0,282 log ( ϵ / n ) log ( 10 -ϵ=1016n=30.282log(ϵ/n)-37,93997. -38202.733,-0,2820.ехр(-0,282)=0,754ехр(0)=100,754 / (1+0,754)=log(1016)log(3)37.93997.38202.733,0.2820.exp(0.282)=0.754 и (конечно). Нормализованные значения - по порядку - для того, что вы выбросили, и .exp(0)=101 / ( 1 + 0,754 ) = 0,5700.754/(1+0.754)=0.4301/(1+0.754)=0.570

Whuber
источник
Это блестяще - так просто и так задним числом. @ Икрам, пожалуйста, отметьте это как правильный ответ! (если, конечно, у вас нет чего-то лучшего, в таком случае, пожалуйста, поделитесь)
zelanix
2
@whuber мы вообще должны выбросить ? Экспонирование, которое в любом случае дает нам ноль, и, следовательно, не вносит вклад в сумму. 38202.733
Тейлор