Scipy's Curve Fit Can't Find Optimal Parameters

71 views Asked by At

I'm currently trying to give a Gaussian fit to some data files of LEDs using scipy's curve_fit tool. The method I've used for the first 3 out of 5 LEDs produces working curves, but the last 2 give similar errors.

I've added a screenshot of what one of the graphs looks like (one of the two that does not seem to work with curve_fit) as well as the cell of code where I try the fit itself.

error472 = data472y ** 0.5 
error505 = data505y ** 0.5 
error525 = data525y ** 0.5 
error588 = data588y ** 0.5 
error611 = data611y ** 0.5 

def GausFunc(x,a,b,c,d,f):
    return(a*np.exp(-(x-b)**2 / (2*c**2))+(d*x)+f)

popt472, pcov472 = curve_fit(GausFunc, data472x, data472y, [0.8,470,50,-10,6], error472, True)
popt505, pcov505 = curve_fit(GausFunc, data505x, data505y, [0.8,470,50,-10,6], error505, True)
popt525, pcov525 = curve_fit(GausFunc, data525x, data525y, [0.8,470,50,-10,6], error525, True)
popt588, pcov588 = curve_fit(GausFunc, data588x, data588y, [0.387,589,5,1,1], error588, True)
#popt611, pcov611 = curve_fit(GausFunc, data611x, data611y, [0.8,470,50,-10,6], error611, True)

The error message I am receiving:

RuntimeError                              Traceback (most recent call last)
Cell In[91], line 13
     11 popt505, pcov505 = curve_fit(GausFunc, data505x, data505y, [0.8,470,50,-10,6], error505, True)
     12 popt525, pcov525 = curve_fit(GausFunc, data525x, data525y, [0.8,470,50,-10,6], error525, True)
---> 13 popt588, pcov588 = curve_fit(GausFunc, data588x, data588y, [0.387,589,5,1,1], error588, True)

File ~\anaconda3\Lib\site-packages\scipy\optimize\_minpack_py.py:864, in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, full_output, **kwargs)
    862     cost = np.sum(infodict['fvec'] ** 2)
    863     if ier not in [1, 2, 3, 4]:
--> 864         raise RuntimeError("Optimal parameters not found: " + errmsg)
    865 else:
    866     # Rename maxfev (leastsq) to max_nfev (least_squares), if specified.
    867     if 'max_nfev' not in kwargs:

RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 1200.

I tried adjusting the initial guesses as much as I could, trying to narrow in on what would work, but none seem to do so (and the same initial guesses for the first 3 LEDs seemed to work just fine). I also tried increasing maxfev by quite a lot and it would produce the same error each time. It just seems to be the LED data at 588 nm and 611 nm that produce this error.

I also tried going with a base Gaussian function by removing anything involving the variables "d" and "f" in the function, which resulted in the same error of "RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 1200."

This is my first post here, so if I've forgotten any information I apologize; feel free to ask for any other needed information.

plot

1

There are 1 answers

0
jlandercy On

The following MCVE performs the regression without error for all your files:

import pathlib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import optimize, stats

def model(x, loc, scale, height):
    law = stats.norm(loc=loc, scale=scale)
    return height * law.pdf(x) / law.pdf(loc)

files = list(pathlib.Path("led").glob("*.txt"))

for file in files:
    
    data = pd.read_csv(file, sep="\t", header=None, names=["x", "y"])
    popt, pcov = optimize.curve_fit(model, data.x, data.y, p0=[600., 20., 0.8])
    
    fig, axe = plt.subplots()
    axe.plot(data.x, data.y)
    axe.plot(data.x, model(data.x, *popt))
    axe.grid()

It makes use of x and y and an educated initial guess. Fit are poor because your data are far from normality.

enter image description here