【问题标题】:Estimate the similarity of a curve to a gaussian distribution (in Python)估计曲线与高斯分布的相似度(在 Python 中)
【发布时间】:2020-04-21 02:48:45
【问题描述】:

我想用 Python 量化测量值曲线与高斯分布的相似度。

给出了两个值数组:

H=(0,5,10,15,20,25,30,35,40,50,70) 是以米为单位的高度

C(H)=(0,1,1,2,4,6,7,5,3,1,0) 是测量量(例如浓度)

在 Python 中有没有办法

a) 将高斯曲线拟合到 C(H)? 的值?

b) 得到某种描述曲线与高斯曲线的相似程度的相似系数?

提前致谢

【问题讨论】:

  • 这似乎更像是一道数学题而不是编程题。你能准确地说出一些曲线与另一条曲线“相似”的含义吗?你能写出一个数学公式来给你一个合适的度量吗?
  • 我投票结束这个问题,因为它似乎是一个数学问题,而不是一个编程问题。
  • 我也希望问题被详细说明,但至少它足够具体,可以提供相当精确的答案,您可能会争辩说“Python 中有没有办法”部分变成了它变成了一个编程问题。您也可以争辩说,这会将其归入“框架推荐”的题外话类别。
  • 很抱歉不够精确。这个问题来自我的一些科学工作。我没有衡量相似度的具体公式,但是 James Philips 提出的计算 RMSE 和 R 平方值的方法似乎是合理的。谢谢你没有关闭线程。我已经在一个数学论坛上问过同样的问题,但到目前为止没有人可以帮助我。

标签: python curve-fitting gaussian


【解决方案1】:

因为您专门要求提供 Python 代码,所以这里有一个图形 Python 曲线拟合器,它使用您的数据并拟合高斯峰值方程。 RMSE 和 R 平方值应该是衡量相似性的有用指标,因为它们共同描述了数据的高斯拟合质量。

import numpy, scipy, matplotlib
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

H=(0,5,10,15,20,25,30,35,40,50,70) 
C=(0,1,1,2,4,6,7,5,3,1,0)

xData = numpy.array(H, dtype=float)
yData = numpy.array(C, dtype=float)


def func(x, a, b, c): # Gaussian peak
    return  a * numpy.exp(-0.5 * numpy.power((x-b) / c, 2.0))


# estimate initial parameters from the data
a_est = max(C)
b_est = (max(H) + min(H)) / 2
c_est = max(C)
initialParameters = numpy.array([a_est, b_est, c_est], dtype=float)

# curve fit the test data
fittedParameters, pcov = curve_fit(func, xData, yData, initialParameters)

modelPredictions = func(xData, *fittedParameters) 

absError = modelPredictions - yData

SE = numpy.square(absError) # squared errors
MSE = numpy.mean(SE) # mean squared errors
RMSE = numpy.sqrt(MSE) # Root Mean Squared Error, RMSE
Rsquared = 1.0 - (numpy.var(absError) / numpy.var(yData))

print('Parameters:', fittedParameters)
print('RMSE:', RMSE)
print('R-squared:', Rsquared)

print()


##########################################################
# graphics output section
def ModelAndScatterPlot(graphWidth, graphHeight):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)
    axes = f.add_subplot(111)

    # first the raw data as a scatter plot
    axes.plot(xData, yData,  'D')

    # create data for the fitted equation plot
    xModel = numpy.linspace(min(xData), max(xData))
    yModel = func(xModel, *fittedParameters)

    # now the model as a line plot
    axes.plot(xModel, yModel)

    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label

    plt.show()
    plt.close('all') # clean up after using pyplot

graphWidth = 800
graphHeight = 600
ModelAndScatterPlot(graphWidth, graphHeight)

【讨论】:

  • 从统计/概率理论的角度来看,这个过程实现了什么,以及您正在计算什么估计量(当然它们不是 MLE)还不清楚。
  • @fuglede 这个过程实现了发布数据到高斯峰值方程的曲线拟合,并且单个估计量是最小的平方和误差。
  • 非常感谢。我将用我的真实数据尝试这个过程,并与我的主管讨论结果。
  • “全 0”拟合是由于我使用全 1.0 的默认初始参数估计,我编辑了代码以根据数据进行初始参数估计。请尝试更新的源代码。
  • 嘿。我已经删除了这个问题,因为我发现这是由初始参数引起的。我只是设置参数 b = 2 以避免“全 0”拟合,但您的解决方案可能更好。再次感谢:)
【解决方案2】:

对于第一个问题,您要问的是是否可以使用 Python 来估计描述您的数据的正常人群的参数。有无限多的估计器可供选择,但如果您要寻找的是最大似然估计,那么这些只是样本均值和样本标准差,您可以使用 vanilla Python 或 NumPy 之类的工具轻松找到:

In [22]: H = [0,5,10,15,20,25,30,35,40,50,70]

In [23]: C = [0,1,1,2,4,6,7,5,3,1,0]

In [24]: a = np.repeat(H, C)

In [25]: a
Out[25]:
array([ 5, 10, 15, 15, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 30, 30, 30,
       30, 30, 30, 30, 35, 35, 35, 35, 35, 40, 40, 40, 50])

In [26]: a.mean(), a.std()
Out[26]: (27.666666666666668, 9.46337971105226)

SciPy 中提供了许多常见分布的参数估计,也可以在这里使用:

In [27]: scipy.stats.norm.fit(a)
Out[27]: (27.666666666666668, 9.46337971105226)

第二个问题相当模糊,但足够具体,答案在于确定正常模型的“goodness of fit”,或者更笼统地说,为您的数据找到合适的“normality test”。维基百科文章列出了一旦您知道要检查的内容就适用的统计测试,但如果没有进一步的假设,就没有灵丹妙药。很有可能像Q–Q plot 这样的定性工具可能会告诉您您想知道什么;对于您给定的样本,这有点难以分辨,但我认为您的实际数据与您在此处提供的数据不同。

import matplotlib.pyplot as plt
import scipy.stats as st
st.probplot(a, dist=st.norm, plot=plt)
plt.show()

【讨论】:

  • 非常感谢。是的,我的实际数据与此不同,但我将尝试按照您向我展示的方式计算 Q-Q 图,以获得定性的想法。看起来很有希望。
猜你喜欢
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
相关资源
最近更新 更多