c ++ 11 — Расчет функции log-sum-exp в переполнении стека

Существуют ли какие-либо функции в стандартной библиотеке c ++, которые вычисляют лог суммы экспонент? Если нет, то как мне написать свой собственный? Есть ли у вас какие-либо предложения, не упомянутые в эта статья вики?

Меня особенно беспокоит возможность того, что слагаемые опустошения. Это ситуация, когда вы возводите в степень отрицательные числа, которые имеют большое абсолютное значение. Я использую C ++ 11.

2

Решение

(C ++ 11 вариант кода Шувро с использованием стандартной библиотеки в соответствии с вопросом.)

template <typename Iter>
std::iterator_traits<Iter>::value_type
log_sum_exp(Iter begin, Iter end)
{
using VT = std::iterator_traits<Iter>::value_type{};
if (begin==end) return VT{};
using std::exp;
using std::log;
auto max_elem = *std::max_element(begin, end);
auto sum = std::accumulate(begin, end, VT{},
[max_elem](VT a, VT b) { return a + exp(b - max_elem); });
return max_elem + log(sum);
}

Эта версия является более общей — она ​​будет работать с любым типом значения, в любом типе контейнера, если она имеет соответствующие операторы. В частности, он будет использовать std::exp а также std::log если тип значения не имеет своих собственных перегрузок.

Чтобы быть действительно устойчивым к недопущению, даже для неизвестных числовых типов, вероятно, было бы полезно отсортировать значения. Если вы сортируете входные данные, самое первое значение будет max_elemИтак, первый срок sum будет exp(VT{0} который предположительно VT{1}, Это явно без недостатка.

4

Другие решения

Если вы хотите меньший код, эта реализация может сделать работу:

double log_sum_exp(double arr[], int count)
{
if(count > 0 ){
double maxVal = arr[0];
double sum = 0;

for (int i = 1 ; i < count ; i++){
if (arr[i] > maxVal){
maxVal = arr[i];
}
}

for (int i = 0; i < count ; i++){
sum += exp(arr[i] - maxVal);
}
return log(sum) + maxVal;

}
else
{
return 0.0;
}
}

Вы можете увидеть более надежную реализацию на Блог Takeda 25 (японский) (или посмотри на английском, через Google Translate).

3

По вопросам рекламы [email protected]