3

特定のデータ セットの最小二乗適合を見つけるのに問題があります。データが関数に従うことはわかっていますが、魔女はガウスと長方形の畳み込みです(広いスリットを通るX線)。私がこれまでに行ったことは、畳み込み積分を見て、それが次のようになることを発見すること ですここに画像の説明を入力ここに画像の説明を入力適合する関数は、幅パラメーター a で指定された積分境界を持つガウスの積分関数です。次に、積分も xt のシフトで実行されます。

これは、データの一部と手作りの適合です。from pylab import * from scipy.optimize import curve_fit from scipy.integrate import quad

# 1/10 of the Data to show the form.
xData = array([-0.1 , -0.09, -0.08, -0.07, -0.06, -0.05, -0.04, -0.03, -0.02,
       -0.01,  0.  ,  0.01,  0.02,  0.03,  0.04,  0.05,  0.06,  0.07,
        0.08,  0.09,  0.1 ])
yData = array([  18.      ,   22.      ,   22.      ,   34.000999,   54.002998,
        152.022995,  398.15799 ,  628.39502 ,  884.781982,  848.719971,
        854.72998 ,  842.710022,  762.580994,  660.435974,  346.119995,
        138.018997,   40.001999,    8.      ,    6.      ,    4.      ,
        6.      ])
yerr = 0.1*yData # uncertainty of the data

plt.scatter(xData, yData)
plt.show()

データのプロット

# functions
def gaus(x, *p):
    """ gaussian with p = A, mu, sigma """
    A, mu, sigma = p
    return A/(sqrt(2*pi)*sigma)*numpy.exp(-(x-mu)**2/(2.*sigma**2))

def func(x,*p):
    """ Convolution of gaussian and rectangle is a gaussian integral.
        Parameters: A, mu, sigma, a"""
    A, mu, sigma, a = p
    return quad(lambda t: gaus(x-t,A,mu,sigma),-a,a)
vfunc = vectorize(func)  # Probably this is a Problem but if I dont use it, func can only be evaluated at 1 point not an array

func が実際にデータを記述しており、私の計算が正しいことを確認するために、データと関数をいじり、それらを一致させるのに疲れました。次のことが実現可能であることがわかりました。

p0=[850,0,0.01, 0.04] # will be used as starting values for fitting
sample = linspace(-0.1,0.1,200) # just to make the plot smooth
y, dy = vfunc(sample,*p0)       

plt.plot(sample, y, label="Handmade Fit")
plt.scatter(xData, yData, label="Data")
plt.legend()
plt.show()

データと手作りフィット 取得したばかりの開始値を使用してデータを適合させようとすると、問題が発生します。

fp, Sfcov =  curve_fit(vfunc, xData, yData, p0=p0, sigma=yerr)
yf = vfunc(xData, fp)
plt.plot(x, yf, label="Fit")
plt.show()


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-83-6d362c4b9204> in <module>()
----> 1 fp, Sfcov =  curve_fit(vfunc, xData, yData, p0=p0, sigma=yerr)
      2 yf = vfunc(xData,fp)
      3 plt.plot(x,yf, label="Fit")

    /usr/lib/python3/dist-packages/scipy/optimize/minpack.py in curve_fit(f, xdata, ydata, p0, sigma, **kw)
    531     # Remove full_output from kw, otherwise we're passing it in twice.
    532     return_full = kw.pop('full_output', False)
--> 533     res = leastsq(func, p0, args=args, full_output=1, **kw)
    534     (popt, pcov, infodict, errmsg, ier) = res
    535 

/usr/lib/python3/dist-packages/scipy/optimize/minpack.py in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    369     m = shape[0]
    370     if n > m:
--> 371         raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
    372     if epsfcn is None:
    373         epsfcn = finfo(dtype).eps

TypeError: Improper input: N=4 must not exceed M=2

これは、フィットパラメータよりもデータポイントが少ないことを意味していると思います。それを見てみましょう:

print("Fit-Parameters: %i"%len(p0))
print("Datapoints: %i"%len(yData))

Fit-Parameters: 4
Datapoints: 21

実際には 210 のデータ ポイントがあります。

上記のように、積分関数 (func <> vfunc) に numpy の vectorize 関数を使用する必要がある理由がよくわかりませんが、使用しないことも役に立ちません。一般に、numpy 配列を関数に渡すことができますが、ここでは機能していないようです。一方、ここでは leas-square-fit の力を過大評価している可能性があり、この場合は使用できない可能性がありますが、ここで最尤法を使用するのは好きではありません。一般に、積分関数をデータに当てはめようとしたことがないので、これは私にとって新しいことです。おそらく問題はここにあります。クワッドに関する私の知識は限られており、より良い方法があるかもしれません。積分を分析的に実行することは私の知る限り不可能ですが、明らかに理想的な解決策です;)。

それで、このエラーがどこから来たのか、何か考えはありますか?

4

1 に答える 1

0

2 つの問題があります。1 つはquad値と誤差の推定値を含むタプルを返すことで、もう 1 つはベクトル化の方法にあります。ベクトル パラメーターでベクトル化したくありません。np.vectorizefor ループがあるため、自分で実行してもパフォーマンスは向上しません。

def func(x, p):
    """ Convolution of gaussian and rectangle is a gaussian integral.
        Parameters: A, mu, sigma, a"""
    A, mu, sigma, a = p
    return quad(lambda t: gaus(x-t,A,mu,sigma),-a,a)[0]

def vfunc(x, *p):
    evaluations = numpy.array([func(i, p) for i in x])
    return evaluations

からではなく、 *inを取り除いたことに注意してください。また、 の最初の出力を選択しています。funcgausquad

これで問題は解決しますが、畳み込みに合わせるには、フーリエ空間に行くことを検討してください。畳み込みのフーリエ変換は、関数の変換の結果であり、これはあなたの人生を大幅に簡素化します。さらに、フーリエ空間に入ると、ローパス フィルターを適用してノイズを減らすことを検討できます。210 データ ポイントは、良好な結果を得るのに十分な高さです。

また、より強力なアルゴリズムが必要な場合は、ROOT の長い実績のある Minuit を使用して、iminuit を検討する必要があります。

于 2014-06-15T14:23:27.637 に答える