2014-05-14 5 views
7

Ich muss ein normalisiertes Exponential eines Vektors in Matlab berechnen.Numerisch stabile Implementierung

einfach

res = exp(V)/sum(exp(V)) 

Überlauf in einem Element V Schreiben größer ist als log (Realmax) = 709,7827. (Ich bin mir nicht sicher über Unterlaufbedingungen.)

Wie sollte ich es implementieren, um numerische Instabilität zu vermeiden?

Update: Ich habe ausgezeichnete Antworten erhalten, wie man Überlauf vermeiden kann. Ich bin jedoch immer noch glücklich, Ihre Gedanken über die Möglichkeit des Unterlaufs im Code zu hören.

Antwort

6

Der folgende Ansatz der Überlauf durch vermeidet die Exponenten subtrahiert und dann die exponentielle nehmen, anstatt die Exponentialgrößen des Teilens:

res = 1./sum(exp(bsxfun(@minus, V(:), V(:).'))) 

Als allgemeine Regel gilt, Überlauf kann durch die Arbeit in der Log-Domäne vermieden werden so lange wie möglich und nur am Ende exponentiell.

+0

Dank. Ich bin neu bei bsxfun. Was ist, wenn V eine Matrix ist und wir möchten, dass dies entlang der Dimension dim gilt? – user25004

+0

@ user25004 Wie wäre das? 'exp (V)' wäre dann eine Matrix und 'sum (exp (V), dim)' wäre ein Vektor. Wie definiert man 'exp (V)/sum (exp (V, dim))' in diesem Fall? –

+0

Ich meine, wenn die Variable Dim 1 ist, möchte ich Ihren vorherigen Code auf jede Spalte angewendet werden. Wenn dim 2 ist, wird der Code zeilenweise angewendet. – user25004

2

Die Antwort ist Ihrer vorherigen Frage ziemlich ähnlich. Benutze Mathematik!

exp(V)=exp(V-max(V))*exp(max(V)) 
sum(exp(V))=sum(exp(V-max(V))*exp(max(V)))=exp(max(V)*sum(exp(V-max(V)))) 

Putting beide zusammen:

res=exp(V-max(V))*exp(max(V))/exp(max(V)*sum(exp(V-max(V)))=exp(V-max(V))/sum(exp(V-max(V))) 

Ein Code, der auf den Eingangsbereich robust ist:

res=exp(V-max(V))/sum(exp(V-max(V))) 
+0

Schöne Idee! Subtrahiere das Maximum –