问题
I'm trying to do an exponential fit with a set of data:
import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as opt
def func(x, a, b, c):
return a * np.exp(x / -b) + c
epr_data = np.loadtxt('T2_text', skiprows=1)
time = epr_data[:, 1]
intensity = epr_data[:, 2]
optimizedParameters, pcov = opt.curve_fit(func, time, intensity)
print(optimizedParameters)
plt.plot(time, intensity, func(time, *optimizedParameters), label="fit")
plt.show()
but i just get this step function and these parameters:
[1.88476367e+05 1.00000000e+00 6.49563230e+03]
the plot with "fit"
as well as this error message:
OptimizeWarning: Covariance of the parameters could not be estimated
warnings.warn('Covariance of the parameters could not be estimated'
EDIT:
https://pastebin.com/GTTGf0ed
i want to plot the time and first row with intensity
the graph after your suggestion
edit 2:
import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as opt
def func(x, a, b, c):
return a * np.exp(x / -b) + c
epr_data = np.loadtxt('T2_text', skiprows=1)
time = epr_data[:, 1]
intensity = epr_data[:, 2]
c0 = np.mean(intensity[-10:])
a0 = intensity[0]-c0
th = time[np.searchsorted(-intensity+c0, -0.5*a0)]
b0 = th / np.log(2)
optimizedParameters, pcov = opt.curve_fit(func, time, intensity, p0=(a0, b0, c0))
print(optimizedParameters)
plt.plot(time, intensity, label='data')
plt.plot(time, func(time, *optimizedParameters), label="fit")
plt.legend()
plt.show()
回答1:
First, fix your plot
function call. To plot two curves with one call, you have to give the x
and y
values for each curve:
plt.plot(time, intensity, time, func(time, *optimizedParameters), label="fit")
For labeling, it might be simpler to call plot
twice:
plt.plot(time, intensity, label="data")
plt.plot(time, func(time, *optimizedParameters), label="fit")
It would be easier to address the warning generated by curve_fit
if we had your data. Experience shows, however, that it is most likely that the default initial guess of the parameters used by curve_fit
(which is all 1s) is just a really bad guess.
Try helping curve_fit
by giving it a better starting point for its numerical optimization routine. The following bit of code shows how you can compute rough guesses for a
, b
and c
. Pass these to curve_fit
with the argument p0=(a0, b0, c0)
.
# Assume that the time series is long enough that the tail
# has flattened out to approximately random noise around c.
c0 = np.mean(intensity[-10:])
# This assumes time[0] is 0.
a0 = intensity[0] - c0
# Rough guess of the half-life.
th = time[np.searchsorted(-intensity+c0, -0.5*a0)]
b0 = th / np.log(2)
来源:https://stackoverflow.com/questions/65671927/exponential-decay-with-scipy-just-gives-step-function