我试图找到一个曲线拟合我的数据,视觉上似乎有一个幂律分布。
我希望使用scipy.optimize.curve_fit,但是无论我尝试什么函数或数据规范化,我都会得到RuntimeError(参数未找到或溢出)或一条不适合我的数据的曲线,即使是远程的。请帮助我找出我在这里做错了什么。
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
df = pd.DataFrame({
'x': [ 1000, 3250, 5500, 10000, 32500, 55000, 77500, 100000, 200000 ],
'y': [ 1100, 500, 288, 200, 113, 67, 52, 44, 5 ]
})
df.plot(x='x', y='y', kind='line', style='--ro', figsize=(10, 5))
def func_powerlaw(x, m, c, c0):
return c0 + x**m * c
target_func = func_powerlaw
X = df['x']
y = df['y']
popt, pcov = curve_fit(target_func, X, y)
plt.figure(figsize=(10, 5))
plt.plot(X, target_func(X, *popt), '--')
plt.plot(X, y, 'ro')
plt.legend()
plt.show()
输出量
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-243-17421b6b0c14> in <module>()
18 y = df['y']
19
---> 20 popt, pcov = curve_fit(target_func, X, y)
21
22 plt.figure(figsize=(10, 5))
/Users/evgenyp/.virtualenvs/kindle-dev/lib/python2.7/site-packages/scipy/optimize/minpack.pyc in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method,**kwargs)
653 cost = np.sum(infodict['fvec']**2)
654 if ier not in [1, 2, 3, 4]:
--> 655 raise RuntimeError("Optimal parameters not found: " + errmsg)
656 else:
657 res = least_squares(func, p0, args=args, bounds=bounds, method=method,
RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 800.
2条答案
按热度按时间xhv8bpkk1#
如回溯所述,已达到函数评估的最大数目,但未找到驻点(以终止算法)。您可以使用选项
maxfev
来增加最大数目。在此范例中,maxfev=2000
的设定值足以成功终止算法。然而,该解决方案并不令人满意。这是由于算法为变量选择了(默认)初始估计,对于该示例,这是不好的(所需的大量迭代是这一点的指示)。提供另一个初始化点(通过简单的试错法找到)导致良好的拟合,而不需要增加
maxfev
。两次拟合和与数据的视觉比较如下所示。
kiz8lqtg2#
严格来说,
func_powerlaw
并不是幂律,因为它有一个加性常数。一般来说,如果你想快速直观地评估幂律关系,你可以
或
这两种方法都应该给予一条直线,尽管它们之间有细微的差别(特别是在曲线拟合方面)。
所有这一切都没有加常数,它弄乱了幂律关系。
如果你想拟合一个幂律,根据对数-对数尺度来衡量数据(通常是理想的),你可以使用下面的代码。