使用 curve_fit (python) 和高斯函数,它给你均值和方差

using curve_fit (python) with a gaussian function which gives you mean and variance

我在使用 scipy 中的 curve_fit 时遇到问题。或者至少它没有按照我期望的方式工作。

我有某种来自直方图的数据集,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].

正态分布是连续分布,因此您不能对直方图的总和进行归一化,而是对积分进行归一化。

这是适合我的代码版本。我唯一改变的是将直方图除以 bin 宽度。它returns [ 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()