他の質問に対するユーザーの回答について質問したかったのですが、何らかの理由でコメント ボックスが表示されません。私が何か間違ったことをしているなら、ごめんなさい。
いずれにせよ、この返信に関して: https://stackoverflow.com/a/11507723/1950164
次の質問があります。このコードを使用して、さまざまなデータをさまざまな関数に適合させるにはどうすればよいですか? 私は彼が解決したものと同様の問題を抱えています.累積分布に適合させたいと思っています. そこで、コードを一般化しようと始めました。私は3つの変更を行いました:
a)ヒストグラムが計算される行の後に、追加しました
hist = numpy.cumsum(hist)
これにより、分布が累積分布に変換されます
b) 例のガウス関数の代わりに、新しい関数を定義しました
def myerf(x, *p):
A, mu, sigma = p
return A/2. * (1+math.erf((x-mu)/(math.sqrt(2)*sigma)))
これは、ガウスの累積分布がどうあるべきかです。
c) もちろん最後に、curve_fit 行を変更して関数を呼び出します。
coeff, var_matrix = curve_fit(myerf, bin_centres, hist, p0=p0)
これは、うまくいかないことを除いて、簡単な演習です。プログラムは次のエラー メッセージを返すようになりました。
bash-3.2$ python fitting.py
Traceback (most recent call last):
File "fitting.py", line 27, in <module>
coeff, var_matrix = curve_fit(myerf, bin_centres, hist, p0=p0)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 506, in curve_fit
res = leastsq(func, p0, args=args, full_output=1, **kw)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 348, in leastsq
m = _check_func('leastsq', 'func', func, x0, args, n)[0]
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 14, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 418, in _general_function
return function(xdata, *params) - ydata
File "fitting.py", line 22, in myerf
return A/2. * (1+math.erf((x-mu)/(math.sqrt(2)*sigma)))
TypeError: only length-1 arrays can be converted to Python scalars
それで、私は何を間違っていますか?
おまけ: 関数の引数に *p が含まれていることを説明する参考文献を教えてください。
ありがとう!
編集:累積分布データを使用してプログラムを実行しようとしましたが、まだガウス関数を呼び出しています。それはうまくいきます、あなたはちょうど悪いフィット感を得ます. したがって、間違いは myerf 関数のどこかにあるはずです。
EDIT2: myerf 関数の戻り値をより単純なものに置き換えようとすると、
return A + mu*x + sigma*x**2
それは動作します。したがって、その見返りには、本来のことをしていない何かがあるに違いありません。
EDIT3:だから、数学の代わりにscipyのエラー関数を使ってみたところ、今はうまくいきます。なぜ以前は機能しなかったのかわかりませんが、現在は機能しています。したがって、コードは次のとおりです。
import matplotlib
matplotlib.use('Agg')
import numpy, math
import pylab as pl
from scipy.optimize import curve_fit
from scipy.special import erf
# Define some test data which is close to Gaussian
data = numpy.random.normal(size=10000)
hist, bin_edges = numpy.histogram(data, density=True)
bin_centres = (bin_edges[:-1] + bin_edges[1:])/2
hist = numpy.cumsum(hist)
def myerf(x, *p):
A, mu, sigma = p
return A/2. * ( 1+erf(((x-mu)/(math.sqrt(2)*sigma))) )
# p0 is the initial guess for the fitting coefficients (A, mu and sigma above)
p0 = [1., 0., 1.]
coeff, var_matrix = curve_fit(myerf, bin_centres, hist, p0=p0)
# Get the fitted curve
hist_fit = myerf(bin_centres, *coeff)
pl.plot(bin_centres, hist, label='Test data')
pl.plot(bin_centres, hist_fit, label='Fitted data')
# Finally, lets get the fitting parameters, i.e. the mean and standard deviation:
print 'Fitted mean = ', coeff[1]
print 'Fitted standard deviation = ', coeff[2]
pl.savefig('fitting.png')
pl.show()