2012-06-17 22 views
9

Un amigo mío descubrió un comportamiento extraño en gnuplot con respecto a un simple ajuste polinómico. ¿Puede explicar esto?Gnuplot se comporta de forma extraña en un ajuste polinómico. ¿Porqué es eso?

Aquí está el archivo:

#!/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 

Los datos son:

# 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 

El gráfico resultante es la línea verde. La línea azul muestra un ajuste mucho mejor usando otra función de básicamente la misma forma. Para la línea verde A se sustituye por un valor constante (A = 0,2123, que es sobre B * 300^4)

odd fitting behavior gnuplot

Así la línea verde no es claramente el mejor ajuste aquí desde f(x) = B*(x**4) - 0.2123 produce betterresults FAR y también tiene la forma B * x 4 + A. En el ajuste verde, el parámetro ** A simplemente se ignora por gnuplot y el algoritmo de ajuste no lo modifica. Establecer diferentes valores iniciales para A y B no parece ayudar mucho; el valor de A nunca cambia para su valor inicial. Mi amigo y yo estamos usando la versión estándar de Gnuplot que viene con Ubuntu: gnuplot 4.4 patchlevel 3.

Respuesta

7

Esta es una muy buena (y complicada) pregunta para la que no tengo una respuesta completa, pero espero que la siguiente ser iluminador.

El ajuste usa una rutina de ajuste de mínimos cuadrados (Levenberg–Marquardt). que converge iterativamente en una "buena" solución. La buena solución que se requiere está determinada por la variable FIT_LIMIT. De forma predeterminada, FIT_LIMIT está configurado como (un conservador) 1.e-5. Aparentemente, tus datos convergen mucho más rápido al cambiar el valor de B en el enrutamiento iterativo en comparación con el cambio A. De hecho, como habrás notado, puedes obtener el umbral de error sin siquiera tocar la variable A. Sin embargo, si te mueves hacia arriba sus expectativas (Espera obtener un mejor ajuste, por lo que establece FIT_LIMIT a un valor inferior - Lo ajusto a 1.e-14), obtendrá un resultado mucho mejor. El precio que paga aquí es que el ajuste puede tardar mucho más tiempo en converger (o incluso puede divergir; no soy un experto en ajuste). Lo más llamativo es que el ajuste de función es más un arte que una ciencia, y no existe , no existe el mejor ajuste, solo un ajuste suficientemente bueno.

También tenga en cuenta que el algoritmo busca una minimización local de los cuadrados de los residuos (que cumple con la tolerancia que ha otorgado). No garantiza que encuentre un mínimo global.

#!/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 

También tenga en cuenta que si usted encuentra que gnuplot está convergiendo en el mínimo mal, puede "semilla" de la rutina en forma haciendo:

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

tanques mucho. Como físico, estoy bastante familiarizado con la adaptación en general. No pensé que gnuplot fuera tan malo. Existe una teoría matemática cerrada para los ajustes polinomiales y su convergencia que produciría resultados ideales.Gnuplot no debería tener problemas con un polinomio simple, pero entiendo que la adaptación de mínimos cuadrados con un límite débil en el error debería ser la causa de mi problema. Gracias de nuevo. –

+0

@ con-f-use Sí, podría ser mejor con ajustes polinómicos, pero la rutina de ajuste en gnuplot está diseñada para manejar cualquier cosa, así que supongo que (por simplicidad) no intentan averiguar si está ajustando un polinomio en lugar de alguna función no lineal. – mgilson

+0

Sí, simplemente diciendo que tal vez deberían ;-) –

5

Sólo trate el código de abajo. El truco consiste en garantizar que el rango de las variables x e y sea del mismo orden de magnitud.

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 tiene una opción "set fit precale" que automáticamente prescalcea los valores iniciales. Debes asegurarte de que ya estén en la región correcta, por supuesto. – Karl

Cuestiones relacionadas