нейронная сеть — Необычная причина NaN в C ++? Причины, приближающиеся к нулю, вызывают NaN?

Работая над проектом C ++, включающим нейронные сети, мне мешали результаты NaN. После долгого отслеживания (пытаясь найти происхождение NaN) я понял, что его источником была моя производная сигмоидальной функции, показанная ниже.

double sigDer(double n){
return 2*exp(-n) / pow(1 + exp(-n), 2);
}

Хотя он имеет домен всех действительных чисел, такие значения, как -1008,3, вызвали результат NaN. Согласно Mathematica, правильный результат должен быть очень близок к нулю — 2,522 * 10 ^ -438. Я предотвратил проблему следующим образом:

double sigDer(double n){
double res = 2*exp(-n) / pow(1 + exp(-n), 2);
if( isnan(res) ){
return 0;
} else{
return res;
}
}

С этим простым предположением мой код функционирует как ожидалось; Тем не менее, я до сих пор не понимаю, почему SigDer (<# с большой величиной>) не возвращает ~ 0. Может кто-нибудь сообщить мне о причинах NaN в C ++ (Xcode IDE), кроме деления на ноль и получения четного корня отрицательного числа?

Заранее спасибо! Я также хотел бы знать, почему подписывающее лицо (-1008.3) возвращает NaN и как лучше / более эффективно отслеживать источник значений NaN.

3

Решение

рампа

Знаменатель в каждом случае пытается достичь бесконечности (что означает, что целая дробь пытается достичь 0). Это, однако, означает, что вы определяете где-то деление на бесконечность (в сочетании с ограниченным двойным диапазоном).

Объяснение этому заключается в функция C ++ Exp который возвращает + -HUGE_VAL, если возвращаемое значение не может быть представлено как double.

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

Кстати, если вы хотите работать с большими числами, вы можете реализовать класс, который хранит числа, например, в строке и операторах перегрузки.

2

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

Что ж, если числитель и знаменатель в конечном итоге равны 0, то вы делаете 0/0, то есть NaN.

Я не сделал расчет, но я представляю exp(-1008) меньше чем 2E-308т.е. наименьшее представимое значение в double,

Может кто-нибудь, пожалуйста, сообщите мне о причинах NaN

Википедия это покрыла.

3

Если ваш вклад n большой отрицательный число

exp(-n) -> inf

pow(1 + exp(-n), 2) -> pow(1 + inf, 2) -> inf

inf / inf -> nan

Если ваш вклад n большой положительный номер, который вы никогда не получите нан 0/0

pow(1 + exp(-n), 2) -> pow(1 + 0, 2) != 0
1
По вопросам рекламы [email protected]