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)
这也大大减少了您的错误。
我正在尝试使用 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)
这也大大减少了您的错误。