web-dev-qa-db-ja.com

curve_fitを使用して曲線をべき乗分布に適合させることが機能しない

私は視覚的にべき乗則分布を持っているように見える私のデータに適合する曲線を見つけようとしています。

enter image description here

私は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.
9
kpax

トレースバックが示すように、(アルゴリズムを終了するために)静止点を見つけることなく、関数評価の最大数に達しました。オプションmaxfevを使用して最大数を増やすことができます。この例では、maxfev=2000は、アルゴリズムを正常に終了させるのに十分な大きさです。

しかし、解決策は満足のいくものではありません。これは、アルゴリズムが変数の(デフォルト)初期推定値を選択するためです。この例では、これは適切ではありません(必要な反復の数が多いことを示しています)。 (単純な試行錯誤によって発見された)別の初期化ポイントを提供すると、maxfevを増やす必要なく、適切に適合します。

2つの近似とデータとの視覚的な比較を以下に示します。

x = np.asarray([ 1000, 3250, 5500, 10000, 32500, 55000, 77500, 100000, 200000 ])
y = np.asarray([ 1100, 500, 288, 200, 113, 67, 52, 44, 5 ])

sol1 = curve_fit(func_powerlaw, x, y, maxfev=2000 )
sol2 = curve_fit(func_powerlaw, x, y, p0 = np.asarray([-1,10**5,0]))

enter image description here

14
Stelios