2013-10-31 6 views
7

Ho un set di punti dati, (xey nel codice qui sotto) e sto cercando di creare una linea lineare di miglior adattamento attraverso i miei punti. Sto usando scipy.optimize.curve_fit. Il mio codice produce una linea, ma non una linea di miglior adattamento. Ho provato a fornire i parametri del modello di funzione da utilizzare per il mio gradiente e per la mia intercettazione, ma ogni volta produce la stessa identica linea che non si adatta ai miei punti dati.Perché scipy.optimize.curve_fit non produce una linea di miglior adattamento per i miei punti?

I punti blu sono i miei punti di dati la linea rossa dovrebbero essere montati:

enter image description here

Se qualcuno potesse precisare dove sto andando male sarei estremamente grato:

import numpy as np 
import matplotlib.pyplot as mpl 
import scipy as sp 
import scipy.optimize as opt 

x=[1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7] 
y=[6.008,15.722,27.130,33.772,5.257,9.549,11.098,28.828] 
trialX = np.linspace(1.0,4.0,1000)       #Trial values of x 

def f(x,m,c):          #Defining the function y(x)=(m*x)+c 
    return (x*m)+c 

popt,pcov=opt.curve_fit(f,x,y)      #Returning popt and pcov 
ynew=f(trialX,*popt)             

mpl.plot(x,y,'bo') 
mpl.plot(trialX,ynew,'r-') 
mpl.show() 
+0

Sono riuscito a capire il problema da solo. x era definito come una lista, non come una matrice. L'ho risolto semplicemente mettendo np.array nella parte anteriore degli array x e y definiti. –

+0

Sono arrivato alla stessa conclusione Lizi, avrei dovuto vedere prima questo commento! La prossima volta che succede, sentiti libero di postarlo come una risposta alla tua stessa domanda e accettarlo. – Hooked

+0

Si noti che questo è stato corretto: https://github.com/scipy/scipy/issues/3037 – Hooked

risposta

4

In alternativa è possibile utilizzare numpy.polyfit per ottenere la linea migliore:

import numpy as np 
import matplotlib.pyplot as mpl 

x=[1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7] 
y=[6.008,15.722,27.130,33.772,5.257,9.549,11.098,28.828] 
trialX = np.linspace(1.0,4.0,1000)       #Trial values of x 

#get the first order coefficients 
fit = np.polyfit(x, y, 1) 

#apply 
ynew = trialX * fit[0] + fit[1]            

mpl.plot(x,y,'bo') 
mpl.plot(trialX,ynew,'r-') 
mpl.show() 

Ecco l'output: enter image description here

+0

È possibile ridimensionare questa risposta modificando le linee di adattamento in qualcosa del tipo: 'fit_poly = np.poly1d (np.polyfit (x , y, 1)) 'e' ynew = fit_poly (trialX) '. Questo rende più facile passare a un quadratico se lo si desidera in seguito. – Hooked

+2

Ti ho dato un altro upvote, questo dovrebbe essere sufficiente per aggiungere immagini ai post successivi (e modificare questo). Benvenuto in Stack Overflow! Non è necessario aggiungere cose come "spero che questo aiuti", se lo fa, otterrete voti, se non otterrete downvotes o commenti che richiedono chiarimenti. Cerchiamo di mantenere pulite le risposte qui! – Hooked

2

EDIT: Questo comportamento è stato ora patchato nella versione corrente di SciPy per fare .curve_fit un po 'più infallibile:

https://github.com/scipy/scipy/issues/3037


Per alcuni il motivo, .curve_fit vuole davvero che l'input sia un array numpy e ti darà risultati errati se lo passi in una lista regolare (IMHO questo è un comportamento inaspettato e potrebbe essere un bug). Modificare la definizione di x a:

x=np.array([1.0,2.5,3.5,4.0,1.1,1.8,2.2,3.7]) 

E si ottiene:

enter image description here

Sto indovinando che il accade poiché m*x dove m un intero e x è una lista produrrà m copie quella lista, chiaramente non il risultato che stavi cercando!

+0

mi sembra un errore in curva_fit: potresti presentare un problema su https://github.com/scipy/scipy? –

+0

@Zhenya Ci stavo pensando, non è un bug, ma è inatteso per i nuovi utenti. In quanto tale, https://github.com/scipy/scipy/issues/3037 – Hooked

+0

Nota: f è ** la tua ** funzione, e curve_fit sta solo passando ** tuo ** x ad esso. Quindi, dovresti controllare che la tua funzione abbia il comportamento giusto per i tuoi dati. :) – user333700

Problemi correlati