2012-06-17 4 views
9

Ein Freund von mir entdeckte ein seltsames Verhalten in gnuplot in Bezug auf eine einfache polynomische Anpassung Kann jemand das erklären? HierGnuplot verhält sich in polynomischer Anpassung merkwürdig. Warum das?

ist die Datei:

#!/usr/bin/gnuplot -p 

f(x) = B*(x**4) + A 
fit f(x) "data.txt" using ($1+273.14):2 via A, B 

plot "data.txt" using ($1+273.14):2 notitle,\ 
     f(x) notitle 

Die Daten sind:

# content of data.txt 
350 3.856 
330 3.242 
290 2.391 
250 1.713 
210 1.181 
170 0.763 
130 0.437 

Das resultierende Diagramm ist die grüne Linie. Die blaue Linie zeigt eine weitaus bessere Übereinstimmung mit einer anderen Funktion von im Wesentlichen der gleichen Form. A Für die grüne Linie durch einen konstanten Wert ersetzt wurde (A = 0,2123, die über * B 300^4)

odd fitting behavior gnuplot

So ist die grüne Linie eindeutig nicht die beste Lösung hier seit f(x) = B*(x**4) - 0.2123 weit betterresults ergibt und hat auch die Form B * x 4 + A. In der grünen Anpassung wird der Parameter ** A einfach von gnuplot ignoriert und bleibt durch den Anpassungsalgorithmus unverändert. Die Einstellung verschiedener Anfangswerte für A und B scheint nicht viel zu helfen - der Wert von A ändert sich nie für seinen Anfangswert. Mein Freund und ich verwenden die Standard-Gnuplot-Version, die mit Ubuntu geliefert wird: gnuplot 4.4 Patchlevel 3.

Antwort

7

Dies ist eine sehr gute (und beteiligten) Fragen, für die ich keine vollständige Antwort habe, aber das folgende wird hoffentlich erleuchtend sein.

Fit verwendet eine Anpassungsroutine der kleinsten Quadrate (Levenberg–Marquardt). welches iterativ gegen eine "gute" Lösung konvergiert. Wie gut eine Lösung benötigt wird, wird durch die Variable FIT_LIMIT bestimmt. Standardmäßig ist FIT_LIMIT auf (eine konservative) 1.e-5 festgelegt. Offensichtlich konvergieren Ihre Daten viel schneller, indem Sie den Wert von B im iterativen Routing im Vergleich zu A ändern. Tatsächlich können Sie, wie Sie bemerkt haben, unter die Fehlerschwelle gelangen, ohne die Variable A zu berühren. Wenn Sie jedoch ankurbeln Ihre Erwartungen (Sie erwarten eine bessere Anpassung, also setzen Sie FIT_LIMIT auf einen niedrigeren Wert - ich setze es auf 1.e-14), Sie erhalten ein viel besseres Ergebnis. Der Preis, den Sie hier zahlen, ist, dass die Anpassung viel länger dauern kann, um zu konvergieren (oder es kann sogar auseinander gehen - ich bin kein Experte in der Anpassung). Ein Take-away hier ist, dass Funktionsmontage mehr eine Kunst als eine Wissenschaft ist - und es gibt keine solche Sache wie eine beste Passform, nur eine gut genug passen.

Beachten Sie auch, dass der Algorithmus nach einer lokalen Minimierung der Quadrate der Residuen sucht (die der von Ihnen angegebenen Toleranz entspricht). Es garantiert nicht, dass es ein globales Minimum findet.

#!/usr/bin/gnuplot -p 

FIT_LIMIT=1.e-14 
f(x) =A + B*(x**4) 
fit f(x) "data.txt" using ($1+273.14):2 via A, B 

plot  "data.txt" using ($1+273.14):2 notitle,\ 
     f(x) notitle 

Beachten Sie auch, dass, wenn Sie, dass gnuplot finden auf dem falschen Minimum konvergiert, können Sie „Samen“ der Anpassungsroutine, indem Sie:

FIT_LIMIT=1.e-14 
f(x) =A + B*(x**4) 
A=1.3 #initial guess for A 
fit f(x) "data.txt" using ($1+273.14):2 via A, B 

plot  "data.txt" using ($1+273.14):2 notitle,\ 
     f(x) notitle 
+0

Tanks viel. Als Physiker kenne ich die Anpassung im Allgemeinen sehr gut. Ich dachte nicht, Gnuplot wäre so schlimm. Es gibt eine geschlossene mathematische Theorie für polynomische Fits und ihre Konvergenz, die ideale Ergebnisse liefern würde.Gnuplot sollte keine Probleme mit einem einfachen Polynom haben, aber ich verstehe, dass die Kleinste-Quadrate-Anpassung mit einer schwachen Grenze für den Fehler die Ursache meines Problems sein sollte. Danke noch einmal. –

+0

@ con-f-use Ja, du könntest besser mit polynomischen Passungen umgehen, aber die Anpassungsroutine in gnuplot ist dazu gedacht, alles zu handhaben, also denke ich (zur Vereinfachung), dass sie nicht versuchen, herauszufinden, ob du ein passendes bist Polynom anstelle einiger nichtlinearer Funktionen. – mgilson

+0

Ja, nur zu sagen, vielleicht sollten sie ;-) –

5

Versuchen Sie einfach den Code unten. Der Trick besteht darin, sicherzustellen, dass der Bereich der Variablen x und y in derselben Größenordnung liegt.

reset; 
plot 'data.txt' u ($1+273.14):2 w p; 
f(x, a, b) = a*(1e-2*x)**4 + b; # note the 1e-2 multiplicative factor 
a = 1; b = 1; # initial parmeters 
fit f(x,a,b) 'data.txt' u (($1+273.14)):2 via a, b 
#plot 'data.txt' u (($1+273.14)):2 w p, f(x, a, b) w l 
plot 'data.txt' u (($1+273.14)):2 w p, (a*(1e-2)**4)*x**4+b w l 
print sprintf("Fit parameters for the fit function a*x^4 + b are :\n\ta = %e, \n\tb = %f", a*(1e-2)**4, b) 

Image of the graph

+1

gnuplot version> 5.0 hat eine Option "Prescale anpassen", die die Startwerte automatisch vorskaliert. Sie müssen natürlich sicherstellen, dass sie sich bereits in der richtigen Region befinden. – Karl