我在curve_fit
使用scipy
时遇到问题。或者至少它不会像我期望的那样工作。
我有直方图中的某种数据集,而x值是直方图中的大小为numpy数组。如果需要,我稍后会添加我的数据。直方图几乎有一个高斯形状,我想只用两个自由参数来拟合高斯函数,但它不起作用。
使用三个参数,代码可以正常工作:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
hist=np.load('Rinnen.npy')
faktor = np.sum(hist)
norm_hist=hist/faktor # values from the histogram are normed
ref_werte = np.arange(0,1,0.001)
def gauss(x, *p):
a, b, c = p
y = a*np.exp(-0.5*((x - b)/c)**2.)
return y
p_initial = [0.1, 0.0, 0.1]
popt, pcov = curve_fit(gauss, ref_werte, norm_hist, p0=p_initial)
print(popt) #zeigen der koeffizienten
plt.figure()
plt.plot(ref_werte, norm_hist, linewidth=2.0, color='b')
plt.plot(ref_werte, gauss(ref_werte, *popt), 'b-', linewidth=2.0, color='r')
plt.xlabel('Reflektanzen')
plt.ylabel('normierte Häufigkeit')
plt.show()
但我的目标是使用高斯分布,这是普通分布的PDF(见wikipedia)。但是当我改变我的代码并使用像下面这样的函数的新定义时,它会弄乱一切而根本不起作用。
def gauss(x, *p):
b, c = p
kons = np.sqrt(2.*np.pi)
y = (1./(c*kons))*np.exp(-0.5*((x - b)/c)**2.)
return y
即使我使用的p_initial
值非常接近直方图,例如p_initial = [0.08 , 0.02]
也没有用,我真的不明白为什么。
如果有人可以帮助我真的很开心。
编辑:代码示例
hist
的一个示例数组是:
array([ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4,
30, 224, 2257, 3603, 2029, 2412, 1391, 2269, 3789,
8279, 9091, 6617, 7087, 5071, 2316, 2675, 2273, 3913,
2299, 3573, 1761, 2445, 2426, 3261, 5881, 8408, 11659,
15174, 21250, 19644, 32068, 25315, 19329, 23333, 17168, 15748,
15744, 15045, 14274, 11566, 13887, 10144, 8532, 10696, 8531,
9687, 9493, 9424, 10294, 8869, 9509, 8445, 7723, 8515,
7137, 7464, 8006, 6440, 6457, 4999, 5364, 4519, 4361,
3976, 3366, 3352, 2833, 2475, 2332, 1881, 1905, 1639,
1568, 1318, 1141, 1130, 1010, 907, 906, 823, 789,
745, 726, 674, 692, 630, 610, 568, 575, 589,
535, 538, 522, 511, 513, 534, 467, 446, 445,
337, 441, 454, 451, 438, 417, 388, 456, 405,
408, 399, 356, 404, 371, 412, 404, 401, 389,
354, 342, 358, 317, 306, 303, 295, 303, 294,
288, 251, 256, 226, 178, 241, 213, 196, 215,
210, 184, 165, 208, 200, 181, 171, 136, 156,
147, 137, 102, 119, 116, 89, 117, 104, 85,
77, 74, 52, 69, 34, 47, 44, 50, 32,
27, 34, 38, 24, 21, 28, 24, 22, 25,
19, 17, 15, 17, 18, 14, 11, 12, 5,
9, 9, 9, 6, 5, 5, 8, 7, 4,
4, 2, 1, 4, 0, 2, 2, 2, 3,
2, 3, 1, 1, 2, 1, 2, 2, 0,
1, 1, 2, 1, 1, 2, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
使用这个数组,我的代码可以使用带有三个参数的版本,结果我得到[ 0.02697915 0.08060284 0.01334016]
。如果我将我的代码更改为具有相同数组的两个参数版本,并且所有内容都以相同的方式...那么它根本不适合并且可以工作。我使用了p_initial = [0.08 , 0.02]
的其他版本,它使用均值和标准派生,结果不是真的:[-1.62281493 0.53329897]
。
答案 0 :(得分:1)
正态分布是连续分布,因此您不能将直方图的总和归一化,而是积分。
以下是适用于我的代码版本。我唯一改变的是将直方图除以箱宽。它返回[ 0.08083458 0.01470529]
:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
hist = np.array([ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4,
30, 224, 2257, 3603, 2029, 2412, 1391, 2269, 3789,
8279, 9091, 6617, 7087, 5071, 2316, 2675, 2273, 3913,
2299, 3573, 1761, 2445, 2426, 3261, 5881, 8408, 11659,
15174, 21250, 19644, 32068, 25315, 19329, 23333, 17168, 15748,
15744, 15045, 14274, 11566, 13887, 10144, 8532, 10696, 8531,
9687, 9493, 9424, 10294, 8869, 9509, 8445, 7723, 8515,
7137, 7464, 8006, 6440, 6457, 4999, 5364, 4519, 4361,
3976, 3366, 3352, 2833, 2475, 2332, 1881, 1905, 1639,
1568, 1318, 1141, 1130, 1010, 907, 906, 823, 789,
745, 726, 674, 692, 630, 610, 568, 575, 589,
535, 538, 522, 511, 513, 534, 467, 446, 445,
337, 441, 454, 451, 438, 417, 388, 456, 405,
408, 399, 356, 404, 371, 412, 404, 401, 389,
354, 342, 358, 317, 306, 303, 295, 303, 294,
288, 251, 256, 226, 178, 241, 213, 196, 215,
210, 184, 165, 208, 200, 181, 171, 136, 156,
147, 137, 102, 119, 116, 89, 117, 104, 85,
77, 74, 52, 69, 34, 47, 44, 50, 32,
27, 34, 38, 24, 21, 28, 24, 22, 25,
19, 17, 15, 17, 18, 14, 11, 12, 5,
9, 9, 9, 6, 5, 5, 8, 7, 4,
4, 2, 1, 4, 0, 2, 2, 2, 3,
2, 3, 1, 1, 2, 1, 2, 2, 0,
1, 1, 2, 1, 1, 2, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
faktor = np.sum(hist)
ref_werte = np.arange(0,1,0.001)
bin_width = 0.001
norm_hist=hist/(bin_width*faktor) # values from the histogram are normed
def gauss(x, *p):
b, c = p
kons = np.sqrt(2.*np.pi)
y = (1./(c*kons))*np.exp(-0.5*((x - b)/c)**2.)
return y
p_initial = [0, 1]
popt, pcov = curve_fit(gauss, ref_werte, norm_hist, p0=p_initial)
print(popt) #zeigen der koeffizienten
plt.figure()
plt.plot(ref_werte, norm_hist, linewidth=2.0, color='b')
plt.plot(ref_werte, gauss(ref_werte, *popt), 'b-', linewidth=2.0, color='r')
plt.xlabel('Reflektanzen')
plt.ylabel('normierte Häufigkeit')
plt.show()