2016-06-23 10 views
2

問題:私は物理的な文脈からピーク(固定)の距離を知っているバイモーダル正規分布に経験的データを適合させたいと思います。同じ標準偏差。いくつかのパラメータを固定したバイモーダルガウス分布をフィッティングする

私は(以下のコードを参照してください)scipy.stats.rv_continousで独自の分布を作成しようとしていたが、パラメータは常に1に装着されている誰かが何が起こっているか理解している、または問題を解決するために異なるアプローチに私を指すことができますか?

詳細:私はlocscaleパラメータを避け、ピーク距離deltascaleの影響を受けてはならないので、直接_pdf -methodにmsとしてそれらを実装しました。それを補うために、私はfit -methodにfloc=0fscale=1にそれらを固定し、実際に私は、サンプルデータに期待するものmためのフィットパラメータ、sとピークw

の重みたいのは周りのピークを持つ分布でありますx=-450およびx=450(=>m=0)。標準sは約100または200でなければなりませんが、1.0ではなく、重量wは約1でなければなりません。 0.5

from __future__ import division 
from scipy.stats import rv_continuous 
import numpy as np 


class norm2_gen(rv_continuous): 
    def _argcheck(self, *args): 
     return True 

    def _pdf(self, x, m, s, w, delta): 
     return np.exp(-(x-m+delta/2)**2/(2. * s**2))/np.sqrt(2. * np.pi * s**2) * w + \ 
       np.exp(-(x-m-delta/2)**2/(2. * s**2))/np.sqrt(2. * np.pi * s**2) * (1 - w) 


norm2 = norm2_gen(name='norm2') 

data = [487.0, -325.5, -159.0, 326.5, 538.0, 552.0, 563.0, -156.0, 545.5, 341.0, 530.0, -156.0, 473.0, 328.0, -319.5, -287.0, -294.5, 153.5, -512.0, 386.0, -129.0, -432.5, -382.0, -346.5, 349.0, 391.0, 299.0, 364.0, -283.0, 562.5, -42.0, 214.0, -389.0, 42.5, 259.5, -302.5, 330.5, -338.0, 508.5, 319.5, -356.5, 421.5, 543.0] 

m, s, w, delta, loc, scale = norm2.fit(data, fdelta=900, floc=0, fscale=1) 
print m, s, w, delta, loc, scale 

>>> 1.0 1.0 1.0 900 0 1 

答えて

3

私はカップルの微調整を行った後のデータを合わせて、あなたのディストリビューションを取得することができた:

  • wを使用して、あなたが行ったように、あなたは暗黙の制約を持っている0 < = w < = 1というfit()メソッドで使用されるソルバーはこの制約を認識していないため、wが不合理な値になる可能性があります。このタイプの制約を処理する1つの方法は、wを任意の実際の値にすることですが、PDFの式では、phi = 0.5 + arctan(w)/piを使用してwを0と1の間の分数phiに変換します。
  • 一般的なfit()メソッドは数値最適化ルーチンを使用して最尤推定を検索します。ほとんどのこのようなルーチンと同様に、最適化の出発点が必要です。デフォルトの開始点はすべて1ですが、これは必ずしもうまく機能しません。データの後ろにfit()の定位置引数として値を指定することで、異なる開始点を選択することができます。スクリプトで使用した値は機能しました。私は結果がこれらの出発価値にどの程度敏感であったかを調べなかった。

2つの見積もりを行いました。最初に、私はdeltaは自由パラメータで聞かせて、第二に、私は以下のスクリプトは、次のプロットを生成900

deltaを固定:

plot

ここではスクリプトです:

from __future__ import division 
from scipy.stats import rv_continuous 
import numpy as np 
import matplotlib.pyplot as plt 


class norm2_gen(rv_continuous): 
    def _argcheck(self, *args): 
     return True 

    def _pdf(self, x, m, s, w, delta): 
     phi = 0.5 + np.arctan(w)/np.pi 
     return np.exp(-(x-m+delta/2)**2/(2. * s**2))/np.sqrt(2. * np.pi * s**2) * phi + \ 
       np.exp(-(x-m-delta/2)**2/(2. * s**2))/np.sqrt(2. * np.pi * s**2) * (1 - phi) 

norm2 = norm2_gen(name='norm2') 


data = [487.0, -325.5, -159.0, 326.5, 538.0, 552.0, 563.0, -156.0, 545.5, 
     341.0, 530.0, -156.0, 473.0, 328.0, -319.5, -287.0, -294.5, 153.5, 
     -512.0, 386.0, -129.0, -432.5, -382.0, -346.5, 349.0, 391.0, 299.0, 
     364.0, -283.0, 562.5, -42.0, 214.0, -389.0, 42.5, 259.5, -302.5, 
     330.5, -338.0, 508.5, 319.5, -356.5, 421.5, 543.0] 

# In the fit method, the positional arguments after data are the initial 
# guesses that are passed to the optimization routine that computes the MLE. 
# First let's see what we get if delta is not fixed. 
m, s, w, delta, loc, scale = norm2.fit(data, 1.0, 1.0, 0.0, 900.0, floc=0, fscale=1) 

# Fit the disribution with delta fixed. 
fdelta = 900 
m1, s1, w1, delta1, loc, scale = norm2.fit(data, 1.0, 1.0, 0.0, fdelta=fdelta, floc=0, fscale=1) 

plt.hist(data, bins=12, normed=True, color='c', alpha=0.65) 
q = np.linspace(-800, 800, 1000) 
p = norm2.pdf(q, m, s, w, delta) 
p1 = norm2.pdf(q, m1, s1, w1, fdelta) 
plt.plot(q, p, 'k', linewidth=2.5, label='delta=%6.2f (fit)' % delta) 
plt.plot(q, p1, 'k--', linewidth=2.5, label='delta=%6.2f (fixed)' % fdelta) 
plt.legend(loc='best') 
plt.show() 
+0

これだけです。重量変換はこの問題を解決しました。ありがとうございました! – ascripter

関連する問題