Как оценить параметры экспоненциального усеченного степенного закона с помощью Python?

В статье ниже есть уравнение экспоненциального усеченного степенного закона:

Гонсалес, М.К., Идальго, К.А., и Барабаси, А.Л. (2008). Понимание моделей индивидуальной мобильности человека. Природа, 453 (7196), 779-782.

так:

картинка уравнения

Это экспоненциальный усеченный степенной закон. Нужно оценить три параметра: rg0, beta и K. Теперь у нас есть радиус вращения (rg) нескольких пользователей, и мы загрузили его на Github: радиус gyrations.txt

Следующие коды могут использоваться для чтения данных и вычисления P(rg):

import numpy as np
# read radius of gyration from file
rg = []
with open('/path-to-the-data/radius of gyrations.txt', 'r') as f:
    for i in f:
        rg.append(float(i.strip('\n')))
# calculate P(rg)
rg = sorted(rg, reverse=True)
rg = np.array(rg)
prg = np.arange(len(sorted_data)) / float(len(sorted_data)-1)

или вы можете напрямую получить данные rg и prg следующим образом:

rg = np.array([ 20.7863444 ,   9.40547933,   8.70934714,   8.62690145,
     7.16978087,   7.02575052,   6.45280959,   6.44755478,
     5.16630287,   5.16092884,   5.15618737,   5.05610068,
     4.87023561,   4.66753197,   4.41807645,   4.2635671 ,
     3.54454372,   2.7087178 ,   2.39016885,   1.9483156 ,
     1.78393238,   1.75432688,   1.12789787,   1.02098332,
     0.92653501,   0.32586582,   0.1514813 ,   0.09722761,
     0.        ,   0.        ])

 prg = np.array([ 0.        ,  0.03448276,  0.06896552,  0.10344828,  0.13793103,
    0.17241379,  0.20689655,  0.24137931,  0.27586207,  0.31034483,
    0.34482759,  0.37931034,  0.4137931 ,  0.44827586,  0.48275862,
    0.51724138,  0.55172414,  0.5862069 ,  0.62068966,  0.65517241,
    0.68965517,  0.72413793,  0.75862069,  0.79310345,  0.82758621,
    0.86206897,  0.89655172,  0.93103448,  0.96551724,  1.        ])

Я могу построить P(r_g) и r_g, используя следующий скрипт Python:

import matplotlib.pyplot as plt
%matplotlib inline

plt.plot(rg, prg, 'bs', alpha = 0.3)
# roughly estimated params:
# rg0=1.8, beta=0.15, K=5
plt.plot(rg, (rg+1.8)**-.15*np.exp(-rg/5))
plt.yscale('log')
plt.xscale('log')
plt.xlabel('$r_g$', fontsize = 20)
plt.ylabel('$P(r_g)$', fontsize = 20)
plt.show()

введите здесь описание изображения

Как я могу использовать эти данные rgs для оценки трех указанных выше параметров? Я надеюсь решить это с помощью python.


person Daniel Chen    schedule 17.04.2017    source источник
comment
Пожалуйста, дайте скрипт python для чтения данных и укажите, что вы хотите решить проблему с помощью python.   -  person Frank Wang    schedule 17.04.2017
comment
Кажется, нам нужны два столбца переменных: rg и p(rg) для оценки параметров, пока вы дали только один столбец данных. Можете ли вы предоставить больше информации об этом?   -  person Frank Wang    schedule 17.04.2017
comment
Также добавьте дополнительные теги, например python.   -  person Frank Wang    schedule 17.04.2017
comment
Когда вы предоставили второй столбец, как предложил @Frank Wang, вам, вероятно, следует взглянуть на scipy.optimize.curve_fit.   -  person Michael H.    schedule 17.04.2017
comment
Это нелинейная регрессия, которую вы пытаетесь использовать для определения параметров en.wikipedia.org/wiki/Nonlinear_regression   -  person Guillaume Jacquenot    schedule 18.04.2017
comment
@Майкл Спасибо большое! Это работает!   -  person Daniel Chen    schedule 18.04.2017


Ответы (1)


Согласно предложению @Michael, мы можем решить проблему, используя scipy.optimize.curve_fit.

def func(rg, rg0, beta, K):
    return (rg + rg0) ** (-beta) * np.exp(-rg / K)

from scipy import optimize
popt, pcov = optimize.curve_fit(func, rg, prg, p0=[1.8, 0.15, 5])
print popt
print pcov

Результаты приведены ниже:

[  1.04303608e+03   3.02058550e-03   4.85784945e+00]

[[  1.38243336e+18  -6.14278286e+11  -1.14784675e+11]
 [ -6.14278286e+11   2.72951900e+05   5.10040746e+04]
 [ -1.14784675e+11   5.10040746e+04   9.53072925e+03]]

Затем мы можем проверить результаты, построив подогнанную кривую.

%matplotlib inline
import matplotlib.pyplot as plt

plt.plot(rg, prg, 'bs', alpha = 0.3)
plt.plot(rg, (rg+popt[0])**-(popt[1])*np.exp(-rg/popt[2]) )
plt.yscale('log')
plt.xscale('log')
plt.xlabel('$r_g$', fontsize = 20)
plt.ylabel('$P(r_g)$', fontsize = 20)
plt.show()

введите здесь описание изображения

person Frank Wang    schedule 18.04.2017