首页 > 解决方案 > 无法使用 Python 拟合正态分布。scipy包缺陷?

问题描述

import numpy as np
from astropy import modeling
import matplotlib.pyplot as plt
from scipy import optimize

def gaussian(x, amplitude, mean, stddev):
    return amplitude * np.exp(-((x - mean)/4/stddev)**2)

# the data
m = modeling.models.Gaussian1D(amplitude=10, mean=100, stddev=10)
x = np.linspace(0, 400, 400)
data = m(x)

# fitting
popt, _ = optimize.curve_fit(gaussian, x, data)

plt.figure(0)
plt.plot(x, data)

plt.plot(x, gaussian(x, *popt))

plt.show()

我运行它来进行正态分布拟合。但它给了我一条线。想不通为什么。

在此处输入图像描述

但是,如果我将平均值降低到 45 以下,它将给出一个很好的拟合。这是 scipy 包的设计缺陷吗?

标签: python-3.xscipynormal-distributionscipy-optimize

解决方案


当您使用 scipy.optimize.curve_fit 时,模型参数的初始估计(在这种情况下是幅度、平均值和标准差)会产生很大的不同。您没有提供任何初步猜测。提供猜测(带有实际值),那么拟合是完美的(因为高斯是完美的高斯,没有添加噪声):

import numpy as np
from astropy import modeling
import matplotlib.pyplot as plt
from scipy import optimize

def gaussian(x, amplitude, mean, stddev):
    return amplitude * np.exp(-((x - mean)/4/stddev)**2)

# the data
m = modeling.models.Gaussian1D(amplitude=10, mean=100, stddev=10)
x = np.linspace(0, 400, 400)
data = m(x)

# fitting
popt, _ = optimize.curve_fit(gaussian, x, data, p0 = [10, 100, 10])

plt.figure(0)
plt.plot(x, data)

plt.plot(x, gaussian(x, *popt))

plt.show()

你得到:高斯拟合

您可以通过向数据添加一些噪音来确保拟合有效,例如:

from astropy import modeling
import matplotlib.pyplot as plt
from scipy import optimize
import numpy as np

def gaussian(x, amplitude, mean, stddev):
    return amplitude * np.exp(-((x - mean)/4/stddev)**2)

# the data
m = modeling.models.Gaussian1D(amplitude=10, mean=100, stddev=10)
x = np.linspace(0, 400, 400)
data = m(x)
noise = np.random.normal(len(m))
data = data + noise

# fitting
popt, _ = optimize.curve_fit(gaussian, x, data, p0 = [10, 100, 10])

plt.figure(0)
plt.plot(x, data, 'o', label = 'data')

plt.plot(x, gaussian(x, *popt), label = 'fit')

plt.legend()

plt.show()

你得到:适合嘈杂的高斯


推荐阅读