我们如何在 Python 中拟合 sigmoid 函数?

Posted

技术标签:

【中文标题】我们如何在 Python 中拟合 sigmoid 函数?【英文标题】:How do we fit a sigmoid function in Python? 【发布时间】:2019-08-01 19:17:00 【问题描述】:

出于可重复性的原因,我正在分享我正在使用的简单数据集here。

为了清楚我在做什么 - 从第 2 列开始,我正在读取当前行并将其与前一行的值进行比较。如果它更大,我会继续比较。如果当前值小于前一行的值,我想将当前值(较小)除以前一个值(较大)。因此,下面是我的源代码。

import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import beta

protocols = 

types = "data_v": "data_v.csv"

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = 
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    
    plt.figure(); plt.clf()
    plt.plot(quotient_times, quotient, ".", label=protname, color="blue")
    plt.ylim(0, 1.0001)
    plt.title(protname)
    plt.xlabel("quotient_times")
    plt.ylabel("quotient")
    plt.legend()
    plt.show()
    sns.distplot(quotient, hist=False, label=protname)

这给出了以下图。

从图中我们可以看出

quotient_times 小于 3 时,Data-V 的商为 0.8,如果 quotient_times 为 大于 3。

我还使用以下代码将其安装到 beta 发行版中

xt = plt.xticks()[0]  
xmin, xmax = min(xt), max(xt)  
lnspc = np.linspace(xmin, xmax, len(quotient))

alpha,beta,loc,scale = stats.beta.fit(quotient)  
pdf_beta = stats.beta.pdf(lnspc, alpha, beta,loc, scale)  
plt.plot(lnspc, pdf_beta, label="Data-V", color="darkblue", alpha=0.9)
plt.xlabel('$quotient$')
#plt.ylabel(r'$p(x|\alpha,\beta)$')
plt.title('Beta Distribution')
plt.legend(loc="best", frameon=False)

我们如何将quotient(如上定义)放入一个 sigmoid 函数中,以得到如下图?

【问题讨论】:

我向您推荐 lmfit 软件包。在那里你有一个简单的方法来实现你自己的拟合功能。 (希望我正确理解了您的问题) lmfit 用于 sigmoid 函数?我以前没有使用过它,但你可以尝试使用我共享的数据集吗,Richard?谢谢。 将数据集拟合到 sigmoid 与使用 sigmoid 分类器不同吗?您只需要提取参数。 Scikit learn 具有非常易于使用的 sigmoid 分类器。 我在 R 中做了一些非常相似的事情,如果我分享一下会有帮助吗? @MedImage,谢谢,但我想要它在 Python 中。如果您可以分享您在 Python 中使用我分享的相同数据回答您的答案,那就太好了,我会将其标记为已接受的答案。 【参考方案1】:

您想匹配sigmoid,或者实际上是logistic function。这可以通过多种方式进行更改,例如斜率、中点、幅度和偏移量。

这是定义 sigmoid 函数并利用 scipy.optimize.curve_fit 函数通过调整参数来最小化错误的代码。

from scipy.optimize import curve_fit

def sigmoid (x, A, h, slope, C):
    return 1 / (1 + np.exp ((x - h) / slope)) *  A + C

# Fits the function sigmoid with the x and y data
#   Note, we are using the cumulative sum of your beta distribution!
p, _ = curve_fit(sigmoid, lnspc, pdf_beta.cumsum())

# Plots the data
plt.plot(lnspc, pdf_beta.cumsum(), label='original')
plt.plot(lnspc, sigmoid(lnspc, *p), label='sigmoid fit')
plt.legend()

# Show parameters for the fit
print(p)

这为您提供了以下情节:

以及下面的参数空间(对于上面用到的函数):

[-1.82910694e+01  4.88870236e-01  6.15103201e-03  1.82895890e+01]

如果要拟合变量 quotient_timequotient,只需更改变量即可。

...
p, _ = curve_fit(sigmoid, quotient_times, quotient)
...

并绘制它:

【讨论】:

我仍然不确定这是否是你真正“想要”的(科学上),但这就是你所要求的 ;-) 是的,这正是我所要求的,但你能用我共享的数据集试试吗? @Brown,这是你的数据集!这是 beta 分布的累积和。 真的吗?那么你在哪里传递数据的 beta 拟合呢?我可以喝咖啡吗:-D @Brown,它是 pdf_beta.cumsum() 命令,pdf_beta 是您在示例代码中提供的。我现在还提供了quotientquotient_times 的匹配(作为你的第一个情节)。希望能帮助到你。而当数据如此异质分布时,拟合很可能不太好。

以上是关于我们如何在 Python 中拟合 sigmoid 函数?的主要内容,如果未能解决你的问题,请参考以下文章

scikits.learn 曲线拟合参数的聚类方法

softmax sigmoid

拟合和比较 R 中的多个 sigmoid 曲线

用 ggplot 将 sigmoidal 曲线拟合到点

神经网络中为啥要用sigmoid函数?

为python中的列表定义数值稳定的sigmoid函数的最佳方法