J'essaie d'implémenter la fonction suivante en virgule flottante double précision avec une faible erreur relative :
Ceci est largement utilisé dans les applications statistiques pour ajouter des probabilités ou des densités de probabilité qui sont représentées dans l'espace logarithmique. Bien sûr, ou pourrait facilement déborder ou déborder, ce qui serait mauvais car l'espace de journal est utilisé pour éviter tout débordement en premier lieu. C'est la solution typique:
L'annulation de se produit, mais est atténuée par . Le pire est de loin lorsque et sont proches. Voici un graphique d'erreur relative:exp x l o g 1 p ( exp ( y - x ) )
Le tracé est coupé à pour souligner la forme de la courbe , autour de laquelle l'annulation se produit. J'ai vu des erreurs jusqu'à et je soupçonne que cela empire. (FWIW, la fonction "vérité au sol" est implémentée à l'aide de flotteurs de précision arbitraire MPFR avec une précision de 128 bits.) l o g s u m ( x , y ) = 0 10 - 11
J'ai essayé d'autres reformulations, toutes avec le même résultat. Avec comme expression externe, la même erreur se produit en prenant un journal de quelque chose près de 1. Avec comme expression externe, l'annulation se produit dans l'expression interne.l o g 1 p
Maintenant, l' erreur absolue est très petite, donc a une très petite erreur relative (dans un epsilon). On pourrait soutenir que, parce qu'un utilisateur de est vraiment intéressé par les probabilités (pas les probabilités de journalisation), cette terrible erreur relative n'est pas un problème. Il est probable que ce ne soit généralement pas le cas, mais j'écris une fonction de bibliothèque, et j'aimerais que ses clients puissent compter sur une erreur relative pas bien pire qu'une erreur d'arrondi.l o g s u m
Il semble que j'ai besoin d'une nouvelle approche. Qu'est-ce que ça pourrait être?
la source
Réponses:
La formule doit être numériquement stable. Elle se généralise en numérique calcul stable de log ∑ i e x i = ξ + log ∑ i e x
Dans le cas où la somme des journaux est très proche de zéro et que vous souhaitez une précision relative élevée, vous pouvez probablement utiliser utilisant une précision (c'est-à-dire plus que la double précision) implémentation de qui est presque linéaire pour les petits .l e x p ( z ) : = log ( 1 + e - | z | ) z
la source