Как надежно добавить большие экспоненциальные термины без ошибок переполнения?


24

Очень распространенная проблема в цепочке Маркова Монте-Карло включает вычисление вероятностей, которые являются суммой больших экспоненциальных членов,

еa1+еa2+,,,

aКзнак равноМаксимумя(aя)

е 'е в 1 + Ē в 2 + . , ,

a'знак равноК+Lог(еa1-К+еa2-К+,,,)
еa'еa1+еa2+,,,

Такой подход является разумным , если все элементы велики, но не такая хорошая идея , если они не являются. Конечно, меньшие элементы в любом случае не влияют на сумму с плавающей запятой, но я не уверен, как с ними надежно справиться. В коде R мой подход выглядит так:a

if ( max(abs(a)) > max(a) )
  K <-  min(a)
else
  K <- max(a)
ans <- log(sum(exp(a-K))) + K

Это кажется достаточно распространенной проблемой, что должно быть стандартное решение, но я не уверен, что это такое. Спасибо за любые предложения.


1
Это вещь. Google для 'logsumexp'.

Ответы:


15

Существует простое решение только с двумя проходами через данные:

Сначала вычислите

Кзнак равноМаксимумяaя,

который говорит вам, что, если есть терминов, то Σ я е яп е К .N

ΣяеaяNеК,

Так как вы, вероятно, не имеете столь же большого, как даже , вам не нужно беспокоиться о переполнении в вычислениях с двойной точностью ,N1020

τзнак равноΣяеaя-КN

Таким образом, вычислите и тогда ваше решение будет .τеКτ


Спасибо за четкую запись - но я считаю, что это, по сути, то, что я предложил (?). Если мне нужно избежать ошибок недостаточного значения, когда некоторые малы, я понял , что мне нужен подход суммирования Кахана, предложенный @gareth ? aя
cboettig

Ах, теперь я вижу, к чему вы клоните. На самом деле вам не нужно беспокоиться о недостаточном объеме, поскольку добавление в решение исключительно крошечных результатов не должно его менять. Если их было исключительно много, то сначала нужно сложить маленькие значения.
Джек Поулсон

Для downvoter: не могли бы вы дать мне знать, что не так с моим ответом?
Джек Полсон

еaя-К0


10

Чтобы сохранить точность при добавлении двойных чисел, вам необходимо использовать Kahan Summation , это программное обеспечение, эквивалентное наличию регистра переноса.

е709,783doubleMax - sumSoFar < valueToAddexponent > 709.783

vaLUе×2sчасяеT

#!/usr/bin/env python
from math import exp, log, ceil

doubleMAX = (1.0 + (1.0 - (2 ** -52))) * (2 ** (2 ** 10 - 1))

def KahanSumExp(expvalues):
  expvalues.sort() # gives precision improvement in certain cases 
  shift = 0 
  esum = 0.0 
  carry = 0.0 
  for exponent in expvalues:
    if exponent - shift * log(2) > 709.783:
      n = ceil((exponent - shift * log(2) - 709.783)/log(2))
      shift += n
      carry /= 2*n
      esum /= 2*n
    elif exponent - shift * log(2) < -708.396:
      n = floor((exponent - shift * log(2) - -708.396)/log(2))
      shift += n
      carry *= 2*n
      esum *= 2*n
    exponent -= shift * log(2)
    value = exp(exponent) - carry 
    if doubleMAX - esum < value:
      shift += 1
      esum /= 2
      value /= 2
    tmp = esum + value 
    carry = (tmp - esum) - value 
    esum = tmp
  return esum, shift

values = [10, 37, 34, 0.1, 0.0004, 34, 37.1, 37.2, 36.9, 709, 710, 711]
value, shift = KahanSumExp(values)
print "{0} x 2^{1}".format(value, shift)

Суммирование по Кахану - это всего лишь один из методов «компенсированного суммирования». Если по какой-то причине Кахан работает не совсем правильно, существует ряд других методов для правильного сложения терминов различных величин и противоположных знаков.
JM

@JM, не могли бы вы дать мне названия этих других методов, я бы очень заинтересовался, чтобы прочитать их. Спасибо.
Гарет А. Ллойд


0

Существует пакет R, который обеспечивает быструю и эффективную реализацию "трюка log-sum-exp"

http://www.inside-r.org/packages/cran/matrixStats/docs/logSumExp

Функция logSumExp принимает числовой вектор lX и выводит log (sum (exp (lX))), избегая при этом проблем переполнения и переполнения, используя описанный вами метод.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.