Dimension issue with scipy's curve_fit function

一世执手 提交于 2019-12-23 17:09:32

问题


I'm new to curve fitting in python, as well as python in general. Currently, I'm trying to use the curve_fit module from scipy to fit 4 spectroscopic peaks.

In a few words, I have data in a text file that has two columns. So my first step was to import the data into two arrays, one containing the xdata, the other the y data. Then I tried to define the function that I was going to fit (four voigt peaks). Finally, when I tried to run the whole thing, I get the following error:

raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) TypeError: Improper input: N=11 must not exceed M=1

As far as I can tell from the curve_fit help page, this error says that I must have at least as many data points as fit parameters, which makes sense. The problem is that my data set has 250 points in it...

Here's my code

import numpy as n
import pyspec as p
from scipy.optimize import curve_fit

file = open('fileName', "r") #open the file
data = n.loadtxt(file) #load the file into an array
freq = n.array(data[:, 0] - n.median(data[:, 0])) #center data on zero. 
counts = n.array(data[:, 1])
error = n.array(data[:, 1]**0.5) #get the error on the counts. Standard poisson error. 

# Define a single voigt profile
def voigt(xdata, amp, cent, FWHM, ep) :
   x = xdata
   C = cent
   F = FWHM
   A = amp
   E = ep
   vmodel = A * ((1 - E)*n.exp(-2.77259 * (n.square(x - C))/n.square(F)) + E / (1 + (4 * n.square(x - C)/F**2)))
   return[vmodel]

   #Define the four peak function

def voigt4(xdata, amp1, amp2, amp3, amp4, pos1, pos2, pos3, pos4, FWHM, ep, Bg):
   voigtp1 = voigt(xdata, amp1, pos1, FWHM, ep)
   voigtp2 = voigt(xdata, amp2, pos2, FWHM, ep)
   voigtp3 = voigt(xdata, amp3, pos3, FWHM, ep)
   voigtp4 = voigt(xdata, amp4, pos3, FWHM, ep)

   voigt4 = (voigtp1 + voigtp2 + voigtp3 + voigtp4 + Bg) # include a background term
    return[voigt4]

   # give an initial guess. The *_in params are initial guesses made by the user. 
   guess =   n.array([amp1_in, amp2_in, amp3_in, amp4_in, pos1_in, pos2_in, pos3_in, pos4_in, 500, 0.5, bkgr_in])

   fit = curve_fit(voigt4, freq, counts, guess) # try to fit

I have no idea why that error comes up.


回答1:


As already written in the comments, you should remove the brackets in your return statements in your functions voigt and voigt4. The problem with the brackets is that you put your array which you want to return in a list and thereby you reduce the dimensions of your returned object. Consider the following example:

import numpy as np
ar = np.array([1, 2, 3, 4])

Then the command

len(ar)

would return 4 and

a[0]

returns 1 as expected. If you now do

b = [ar] 

as you did in your return statement

b

would be

[array([1, 2, 3, 4])]

and

b[0]

not a single value anymore but the entire original array:

array([1, 2, 3, 4])

which means that you you receive and error like

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-269-33e961e0e4ea> in <module>()
----> 1 b[1]

IndexError: list index out of range

if you tried to access b[1].

So it is then not a big surprise that you receive an error message regarding the dimensions since you reduce the multidimensional object to a one dimensional object.



来源:https://stackoverflow.com/questions/34864656/dimension-issue-with-scipys-curve-fit-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!