web-dev-qa-db-ja.com

xのエラーを含むscipy curve_fitでの正しいフィッティング?

scipy.optimize.curve_fitを使用して、データにヒストグラムを適合させようとしています。 yにエラーを追加したい場合は、weightを当てはめに適用するだけで簡単に追加できます。しかし、xのエラーを適用する方法(つまり、ヒストグラムの場合のビニングによるエラー)

私の質問は、curve_fitまたはxで線形回帰を行う場合のpolyfitのエラーにも適用されます。 yではなくxでエラーを追加する方法を知っています。

ここに例があります(一部は matplotlibドキュメント から):

import numpy as np
import pylab as P
from scipy.optimize import curve_fit

# create the data histogram
mu, sigma = 200, 25
x = mu + sigma*P.randn(10000)

# define fit function
def gauss(x, *p):
    A, mu, sigma = p
    return A*np.exp(-(x-mu)**2/(2*sigma**2))

# the histogram of the data
n, bins, patches = P.hist(x, 50, histtype='step')
sigma_n = np.sqrt(n)  # Adding Poisson errors in y
bin_centres = (bins[:-1] + bins[1:])/2
sigma_x = (bins[1] - bins[0])/np.sqrt(12)  # Binning error in x
P.setp(patches, 'facecolor', 'g', 'alpha', 0.75)

# fitting and plotting
p0 = [700, 200, 25]
popt, pcov = curve_fit(gauss, bin_centres, n, p0=p0, sigma=sigma_n, absolute_sigma=True)
x = np.arange(100, 300, 0.5)
fit = gauss(x, *popt)
P.plot(x, fit, 'r--')

現在、この適合(失敗しない場合)はyエラーsigma_nを考慮していますが、sigma_xを考慮させる方法が見つかりませんでした。私はscipyメーリングリストでいくつかのスレッドをスキャンし、absolute_sigma値の使用方法と 非対称エラー に関するStackoverflowの投稿を見つけましたが、双方向のエラーについては何もありませんでした。達成することは可能ですか?

16
Zollern

scipy.optmize.curve_fitは標準の非線形最小二乗最適化を使用するため、応答変数の偏差のみを最小化します。考慮される独立変数にエラーがある場合は、scipy.odr直交距離回帰を使用します。その名前が示すように、独立変数と従属変数の両方で最小化されます。

以下のサンプルをご覧ください。 fit_typeパラメータは、scipy.odrは完全なODR(fit_type=0)または最小二乗最適化(fit_type=2)。

[〜#〜]編集[〜#〜]

この例は機能しましたが、yデータがノイズのあるxデータに基づいて計算されたため、不等間隔の独立変数が生成されるため、あまり意味がありませんでした。重みの代わりにデータの標準誤差を指定できるRealDataの使用方法も示すサンプルを更新しました。

from scipy.odr import ODR, Model, Data, RealData
import numpy as np
from pylab import *

def func(beta, x):
    y = beta[0]+beta[1]*x+beta[2]*x**3
    return y

#generate data
x = np.linspace(-3,2,100)
y = func([-2.3,7.0,-4.0], x)

# add some noise
x += np.random.normal(scale=0.3, size=100)
y += np.random.normal(scale=0.1, size=100)

data = RealData(x, y, 0.3, 0.1)
model = Model(func)

odr = ODR(data, model, [1,0,0])
odr.set_job(fit_type=2)
output = odr.run()

xn = np.linspace(-3,2,50)
yn = func(output.beta, xn)
hold(True)
plot(x,y,'ro')
plot(xn,yn,'k-',label='leastsq')
odr.set_job(fit_type=0)
output = odr.run()
yn = func(output.beta, xn)
plot(xn,yn,'g-',label='odr')
legend(loc=0)

fit to noisy data

23
Christian K.