scipy.optimize.curve_fit 无法适应颠倒的高斯分布

scipy.optimize.curve_fit can't fit an upside down gaussian

我正在尝试使用 scipy.optimize.curve_fit 将直线拟合到倒置的高斯分布。它非常适合传统的高斯分布,但不适合符号翻转的高斯分布,而是始终输出一条直线。

我也试过约束我的高斯函数,使变量 'a' 始终为负,但这并不能解决问题。指定 -max(y) 而不是 max(y) 似乎也没有帮助。

import scipy
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from scipy import asarray as ar,exp

def fitdata(x, y):
    mean = sum(x * y) / sum(y)
    sigma = np.sqrt(sum(y * (x - mean) ** 2) / sum(y))

    def guassianfunc(xVar, a, b, c):
        return a * exp(-(xVar - b) ** 2 / (2 * c ** 2))

    popt, _ = scipy.optimize.curve_fit(guassianfunc, x, y, p0=[max(y), mean,         sigma])
    return guassianfunc(np.arange(1, 6, 1), *popt)


x = np.array((1,2,3,4,5))
f, ((ax1, ax2)) = plt.subplots(2, sharex='col', sharey='row')
y = np.array((1, 2, 3, 2, 1))
ax1.plot(x, y, color='black')
ax1.plot(x, fitdata(x, y), linewidth=2, label='Fit')
y = np.array((3, 2, 1, 2, 3))
ax2.plot(x, y, color='black')
ax2.plot(x, fitdata(x, y), linewidth=2, label='Fit')
plt.legend()

我认为这是因为您的第二行可能需要偏移参数?也就是说,您的 guassianfunc 可以制作一个倒置的钟形曲线,前提是它低于 x 轴。例如:

y = np.array((3, 2, 1, 2, 3))-4
ax2.plot(x, y, color='black')
ax2.plot(x, fitdata(x, y), linewidth=2, label='Fit')

尝试像这样添加第 4 个参数

def fitdata(x, y):
    mean = sum(x * y) / sum(y)
    sigma = np.sqrt(sum(y * (x - mean) ** 2) / sum(y))

    def guassianfunc(xVar, a, b, c, d):
        return a * exp(-(xVar - b) ** 2 / (2 * c ** 2)) + d

    popt, _ = scipy.optimize.curve_fit(guassianfunc, x, y, p0=[max(y), mean,         sigma,0])
    return guassianfunc(x, *popt)

这也大大减少了您的错误。