統計の双曲線近似のためのシンプルなPythonプログラム

なぜそれが必要ですか



Zipfの法則は、任意の自然言語でテキスト内の単語の頻度分布の法則を説明しています[1]。 言語学に加えて、これらの法律は経済学にも適用されます[2]。 Zipfの法則に従うオブジェクトの統計データを近似するには、次の形式の双曲線関数が使用されます。



(1)



ここで、abは定数係数です。xは関数引数の統計データ(リスト形式)です。yは、最小二乗法で得られた実データに対する関数の値の近似値です[3]。



通常、双曲線関数を対数法で近似するには、線形化され、係数a、bが決定され、逆変換が行われます[4]。 直接変換および逆変換により、追加の近似誤差が生じます。 したがって、最小二乗法の古典的な実装のための単純なPythonプログラムを提供しています。



アルゴリズム





ソースデータは2つのリストで設定されます。 ここで、 nはリスト内のデータの量です。



係数を決定する関数を取得します



次の連立方程式から係数a、bを見つけます。 (3)



このようなシステムの解決策は特に難しくありません:



(4)

(5)。



平均近似誤差 式によって: (6)



Pythonコード



#!/usr/bin/python # -*- coding: utf-8 -* import matplotlib.pyplot as plt import matplotlib as mpl mpl.rcParams['font.family'] = 'fantasy' def mnkGP(x,y): #       n=len(x) #     s=sum(y) #   y s1=sum([1/x[i] for i in range(0,n)]) #  1/x s2=sum([(1/x[i])**2 for i in range(0,n)]) #  (1/x)**2 s3=sum([y[i]/x[i] for i in range(0,n)]) #  y/xa= round((s*s2-s1*s3)/(n*s2-s1**2),3) #       b=round((n*s3-s1*s)/(n*s2-s1**2),3)#  b     s4=[a+b/x[i] for i in range(0,n)] #     so=round(sum([abs(y[i] -s4[i]) for i in range(0,n)])/(n*sum(y))*100,3) #    plt.title('  Y='+str(a)+'+'+str(b)+'/x\n  --'+str(so)+'%',size=14) plt.xlabel(' X', size=14) plt.ylabel(' Y', size=14) plt.plot(x, y, color='r', linestyle=' ', marker='o', label='Data(x,y)') plt.plot(x, s4, color='g', linewidth=2, label='Data(x,f(x)=a+b/x') plt.legend(loc='best') plt.grid(True) plt.show() x=[10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86] y=[0.1, 0.0714, 0.0556, 0.0455, 0.0385, 0.0333, 0.0294, 0.0263, 0.0238, 0.0217, 0.02, 0.0185, 0.0172, 0.0161, 0.0152, 0.0143, 0.0135, 0.0128, 0.0122, 0.0116] #      y=1/x mnkGP(x,y)
      
      





結果







等辺双曲線の関数からデータを取得したため、a = 0、b = 10、絶対誤差0.004%を取得しました。 したがって、関数mnkGP(x、y)は正しく機能し、アプリケーションプログラムに挿入できます。



べき関数の近似



Pythonにはこのためのscipyモジュールがありますが、多項式の負の次数dはサポートしていません。 多項式によるデータ近似を実装するコードを考えます。



 #!/usr/bin/python # coding: utf8 import scipy as sp import matplotlib.pyplot as plt def mnkGP(x,y): d=2 #   fp, residuals, rank, sv, rcond = sp.polyfit(x, y, d, full=True) #  f = sp.poly1d(fp) #   print(' -- a %s '%round(fp[0],4)) print('-- b %s '%round(fp[1],4)) print(' -- c %s '%round(fp[2],4)) y1=[fp[0]*x[i]**2+fp[1]*x[i]+fp[2] for i in range(0,len(x))] #   a*x**2+b*x+c so=round(sum([abs(y[i]-y1[i]) for i in range(0,len(x))])/(len(x)*sum(y))*100,4) #   print('Average quadratic deviation '+str(so)) fx = sp.linspace(x[0], x[-1] + 1, len(x)) #    len(x)     plt.plot(x, y, 'o', label='Original data', markersize=10) plt.plot(fx, f(fx), linewidth=2) plt.grid(True) plt.show() x=[10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86] y=[0.1, 0.0714, 0.0556, 0.0455, 0.0385, 0.0333, 0.0294, 0.0263, 0.0238, 0.0217, 0.02, 0.0185, 0.0172, 0.0161, 0.0152, 0.0143, 0.0135, 0.0128, 0.0122, 0.0116] #      y=1/x mnkGP(x,y)
      
      





結果







グラフからわかるように、放物線が双曲線に沿って変化するデータを近似すると、平均誤差が増加し、二次方程式の自由項が消滅します。



取得した関数は、Zipfの法則(Zipf)の分析に使用されますが、これは次の記事で行われます。



参照:



1. Zipfの法則(Zipf) tpl-it.wikispaces.com/Laws+ Zipf +%28Zipf%29

2. Zipfの法則はこれです。 dic.academic.ru/dic.nsf/ruwiki/24105

3. Zipfの法律。 wiki.webimho.ru/zipfaの法律

4.講義5.最小二乗法による関数の近似。 mvm-math.narod.ru/Lec_PM5.pdf

5.平均近似誤差。 math.semestr.ru/corel/zadacha.php



All Articles