Эта функция переводится с внутренней функции logspace_add
в исходном коде R здесь
logspace_add <- function(logx,logy) {
pmax(logx,logy) + log1p(exp(-abs(logx - logy)))
}
Не обязательно самая эффективная, но вы должны быть в состоянии сделать это для > 2 элемента с помощью Reduce()
:
logspace_add_mult <- function(x) {
Reduce(logspace_add, x)
}
Быстрый тест (с использованием значений, которые достаточно велики , а не , чтобы потерять значение, чтобы мы могли сравнить результаты регулярных вычислений и вычислений в лог-пространстве ).
x <- c(1e-4,1e-5,1e-6)
logspace_add_mult(log(x))
## [1] -9.10598
log(sum(x))
## [1] -9.10598
Насколько я знаю, это более или менее стандартный подход к добавлению пространства журналов. Преимущество использования чего-то другого, кроме этой домашней реализации, будет: (1) зрелость кода и тестирование и (2) скорость (по крайней мере, для версии logspace_add_mult
; я сомневаюсь, что было бы много преимуществ от нативной C (или что угодно) реализация logspace_add
). Пакет Brobdingnag использует аналогичные представления:
library(Brobdingnag)
brob(log(x))
## [1] +exp(-9.2103) +exp(-11.513) +exp(-13.816)
sum(brob(log(x)))
## [1] +exp(-9.106)
log(as.numeric(sum(brob(log(x)))))
## [1] -9.10598
В Python, numpy имеет logaddexp , но это работает только попарно: вы можете использовать functools.reduce()
обобщить, как указано выше.
import numpy as np
import functools as f
x = np.array([1e-4,1e-5,1e-6])
f.reduce(np.logaddexp,np.log(x))
Это, вероятно, немного быстрее, чем Reduce()
в R.