new error in old code in numpy exp

穿精又带淫゛_ 提交于 2019-12-12 04:04:16

问题


Recently I was working on some data for which I was able to obtain a curve using curve_fit after saving the plot and the values obtained I returned to the same code later only to find it does not work.

#! python 3.5.2

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
from scipy.optimize import curve_fit

data= np.array([
    [24, 0.176644513],
    [27, 0.146382841],
    [30, 0.129891534],
    [33, 0.105370908],
    [38, 0.077820511],
    [50, 0.047407538]])
x, y = np.array([]), np.array([])

for val in data:
    x = np.append(x, val[0])
    y = np.append(y, (val[1]/(1-val[1])))

def f(x, a, b): 
    return (np.exp(-a*x)**b)

# The original a and b values obtained
a = -0.2 # after rounding
b = -0.32 # after rounding
plt.scatter(x, y)
Xcurve = np.linspace(x[0], x[-1], 500)
plt.plot(Xcurve, f(Xcurve,a,b), ls='--', color='k', lw=1)
plt.show()

# the original code to get the values
a = b = 1
popt, pcov = curve_fit(f, x, y, (a, b))

Whereas, previously curve_fit returned the values a, b = -0.2, -0.32 now returns: Warning (from warnings module): File "C:/Users ... line 22 return (np.exp(-a*x)**b) RuntimeWarning: overflow encountered in exp

The code as far as I am aware did not change. Thanks


回答1:


Without knowing what changed in the code, it is hard to say what changed between your state of "working" and "not working". It may be that changes in the version of scipy you used give different results: there have changes to the underlying implementation in curve_fit() over the past few years.

But also: curve_fit() (and the underlying python and Fortran code it uses) requires reasonably good initial guesses for the parameters for many problems to work at all. With bad guesses for the parameters, many problems will fail.

Exponential decay problems seem to be especially challenging for the Levenberg-Marquardt algorithm (and the implementations used by curve_fit(), and do require reasonable starting points. It's also easy to get into a part of parameter space where the function evaluates to zero, and changes in the parameter values have no effect.

If possible, if your problem involves exponential decay, it is helpful to work in log space. That is, model log(f), not f itself. For your problem in particular, your model function is exp(-a*x)**b. Is that really what you mean? a and bwill be exactly correlated.

In addition, you may find lmfit helpful. It has a Model class for curve-fitting, using similar underlying code, but allows fixing or setting bounds on any of the parameters. An example for your problem would be (approximately):

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
from scipy.optimize import curve_fit

import lmfit

data= np.array([
    [24, 0.176644513],
    [27, 0.146382841],
    [30, 0.129891534],
    [33, 0.105370908],
    [38, 0.077820511],
    [50, 0.047407538]])
x, y = np.array([]), np.array([])

for val in data:
    x = np.append(x, val[0])
    y = np.append(y, (val[1]/(1-val[1])))

def f(x, a, b):
    print("In f:  a, b =  " , a, b)
    return (np.exp(-a*x)**b)


fmod = lmfit.Model(f)
params = fmod.make_params(a=-0.2, b=-0.4)

# set bounds on parameters
params['a'].min = -2
params['a'].max =  0
params['b'].vary = False

out = fmod.fit(y, params, x=x)
print(out.fit_report())

plt.plot(x, y)
plt.plot(x, out.best_fit, '--')
plt.show()


来源:https://stackoverflow.com/questions/45312404/new-error-in-old-code-in-numpy-exp

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