我对Scipy很陌生。我有一个数据文件(https://www.dropbox.com/s/mwz8s2kap2mnwo0/data.dat?dl=0),想要适合函数a exp(b x ^ c)。问题是当我手动给出c的值(例如c = 0.75)时,代码可以正常工作,但是如果我想从拟合中找到'a','b'和'c',则代码将无法工作并产生一条扁线对不起,如果问题太傻了。该代码显示为:
import numpy as np
from scipy.optimize import curve_fit
import sys
import matplotlib.pyplot as plt
import math as math
filename = sys.argv[1]
data = np.loadtxt(filename)
x = np.array(data[:,0])
y = np.array(data[:,1])
def func(x, a, b, c):
return a*np.exp(b*x**c)
params = curve_fit(func, x, y)
[a, b, c] = params[0]
perr = np.sqrt(np.diag(params[1]))
x_new = []
y_new = []
for i in np.linspace(1.00003e-05, 0.10303175629999914, num=1000):
j = func(i, a, b, c)
x_new.append(i)
y_new.append(j)
x1 = np.array(x_new)
y1 = np.array(y_new)
print ("a = ", a, "error = ", perr[0], "error % = ", (perr[0]/a)*100, '\t' "b = ", b, "error = ", perr[1], "error % = ", (perr[1]/b)*100), '\t' "c = ", c, "error = ", perr[2], "error % = ", (perr[2]/c)*100,
#np.savetxt('fit.dat', np.c_[x1, y1])
plt.plot(x, y, label='data')
plt.plot(x1, y1, label = 'a*np.exp(b*x**c)')
plt.xlabel('Time(s)')
plt.ylabel('SRO')
plt.legend()
plt.show()
答案 0 :(得分:1)
指数方程对非线性求解器的初始参数估计可能非常敏感。默认情况下,如果未提供任何初始值估计,许多非线性求解器(包括scipy的curve_fit)都将默认初始值1.0用作这些初始参数估计值,在这种情况下,这些值对于数据和方程的组合而言并不是很好的初始估计值。 Scipy确实包含一种遗传算法,可用于确定初始参数估计值,并且其实现需要在搜索范围内进行。这是一个使用scipydifferential_evolution遗传算法模块的图形解算器示例,请注意我在其中使用遗传算法进行搜索的范围。用这种方法给参数范围而不是显式值要容易得多,尽管这并不总是正确的。您将需要更改用于加载数据的文件路径。
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |order|
csv << order.attributes.values_at(*column_names)
end
end
end