Question
Je sais ce que Java est Double.NaN
. J'ai un code Java qui produit NaN
.
// calculate errors
delta = m1 + m2 - M;
eta = f1 + f2 - F;
for (int i = 0; i < numChildren; i++) {
epsilon[i] = p[i]*m1+(1-p[i])*m2+q[i]*f1+(1-q[i])*f2-C[i];
}
// use errors in gradient descent
// set aside differences for the p's and q's
float mDiff = m1 - m2;
float fDiff = f1 - f2;
// first update m's and f's
m1 -= rate*delta;
m2 -= rate*delta;
f1 -= rate*eta;
f2 -= rate*eta;
for (int i = 0; i < numChildren; i++) {
m1 -= rate*epsilon[i]*p[i];
m2 -= rate*epsilon[i]*(1-p[i]);
f1 -= rate*epsilon[i]*q[i];
f2 -= rate*epsilon[i]*(1-q[i]);
}
// now update the p's and q's
for (int i = 0; i < numChildren; i++) {
p[i] -= rate*epsilon[i]*mDiff;
q[i] -= rate*epsilon[i]*fDiff;
}
Dans quelles circonstances Java produire une valeur NaN?
La solution
Étant donné ce que je sais descente de gradient, vous êtes le plus probablement sauter à l'infini parce que vous n'avez pas rate
adaptatif (à savoir votre rate
est trop grand).
Autres conseils
NaN
est déclenché par les événements suivants:
-
résultats
- qui sont des valeurs complexes
- vx où x est négatif
- log (x) où x est négatif
- tan (x) où x mod 180 est 90
- asin (x) ou acos (x) où x est à l'extérieur [-1..1]
- 0/0
- 8 / 8
- 8 / -8
- -8 / 8
- -8 / -8
- 0 × 8
- 0 × -8
- 1 8
- 8 + (-8)
- (- 8) + 8
Désolé pour cette réponse générale, mais je l'espère qui a aidé.
Selon Wikipedia:
Il existe trois types d'opération
NaN
de retour:
- Opérations avec un
NaN
au moins un opérande- formes Indéterminée
- Les divisions 0/0, 8 / 8, 8 / -8, -8 / 8 et -8 / -8
- Les multiplications 0 × 8 et 0 × -8
- La puissance 1 8
- Les additions 8 + (-8), (-8) + 8 et soustractions équivalents.
- Les opérations réelles avec des résultats complexes:
- La racine carrée d'un nombre négatif
- Le logarithme d'un nombre négatif
- La tangente d'un multiple impair de 90 degrés (ou n / 2 radians)
- Le sinus inverse ou cosinus d'un nombre qui est inférieur à -1 ou supérieure à 1.
Java extrait illustre tout ce qui précède, à l'exception d'une tangente (je soupçonne en raison de la précision limitée de double
):
import java.util.*;
import static java.lang.Double.NaN;
import static java.lang.Double.POSITIVE_INFINITY;
import static java.lang.Double.NEGATIVE_INFINITY;
public class NaN {
public static void main(String args[]) {
double[] allNaNs = {
0D/0D,
POSITIVE_INFINITY / POSITIVE_INFINITY,
POSITIVE_INFINITY / NEGATIVE_INFINITY,
NEGATIVE_INFINITY / POSITIVE_INFINITY,
NEGATIVE_INFINITY / NEGATIVE_INFINITY,
0 * POSITIVE_INFINITY,
0 * NEGATIVE_INFINITY,
Math.pow(1, POSITIVE_INFINITY),
POSITIVE_INFINITY + NEGATIVE_INFINITY,
NEGATIVE_INFINITY + POSITIVE_INFINITY,
POSITIVE_INFINITY - POSITIVE_INFINITY,
NEGATIVE_INFINITY - NEGATIVE_INFINITY,
Math.sqrt(-1),
Math.log(-1),
Math.asin(-2),
Math.acos(+2),
};
System.out.println(Arrays.toString(allNaNs));
// prints "[NaN, NaN...]"
System.out.println(NaN == NaN); // prints "false"
System.out.println(Double.isNaN(NaN)); // prints "true"
}
}
Références
- Wikipedia / NaN
- JLS 15.21.1 numérique égalité opérateurs == et! =
Si l'un des opérandes est
NaN
, alors le résultat de==
estfalse
mais le résultat de!=
esttrue
. En effet, lex!=x
test esttrue
si et seulement si la valeur dex
estNaN
. (Les méthodesFloat.isNaN
etDouble.isNaN
peuvent également être utilisées pour tester si une valeur estNaN
.)
Avez-vous essayé asperger votre code avec des instructions System.out.println
pour déterminer exactement où commencer NaN se produisant?