Python+scipy中sigmoid回归的参数

2024-05-03 16:15:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Python数组,其中包含日期,表示某个现象在特定年份的出现次数。这个向量包含200个不同的日期,每个日期重复一定的次数。重复是指现象发生的次数。我成功地用matplotlib计算并绘制了累计和,代码片段如下:

counts = arange(0, len(list_of_dates))
# Add the cumulative sum to the plot (list_of_dates contains repetitions)
plt.plot(list_of_dates, counts, linewidth=3.0)   

Cumulative sum (in blue) per date

在蓝色,你可以看到曲线描绘累计和,在其他颜色的参数我想获得。但是,我需要蓝色曲线的数学表达式来获得这些参数。我知道这种类型的曲线可以使用logistic回归进行调整,但是,我不知道如何在Python中进行调整。在

  1. 首先,我尝试使用scikitlearn的LogisticRegression,但后来我意识到他们似乎在使用这个模型进行机器学习classification(和其他类似的东西),这不是我想要的

  2. 然后我想我可以直接去定义逻辑函数,并尝试自己构建它。我找到了this thread,建议使用scipy.special.expit来计算曲线。这个函数似乎已经实现了,所以我决定使用它。所以我这样做了:

    target_vector = dictionary.values() Y = expit(target_vector) plt.plot(list_of_dates, y, linewidth=3.0)

我得到了一个包含209个元素的向量(与target_vector)类似:[ 1. 0.98201379 0.95257413 0.73105858 ... 0.98201379 1. ]。然而,图形输出看起来像是孩子在抓纸,而不是像图片中那样漂亮的sigmoid曲线。在

我还检查了其他堆栈溢出线程(thisthis),但我想我需要做的只是一个比较它们的玩具示例。我只需要数学公式来计算一些简单快捷的参数。在

有没有一种方法可以得到这个函数的数学表达式?在

非常感谢!在


Tags: ofthe函数target参数plotthis次数
2条回答

使用this post和昨天发布的评论,我得出了以下代码:

from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import normalize # Added this new line

# This is how I normalized the vector. "ydata" looked like this:
# original_ ydata = [ 1, 3, 8, 14, 12, 27, 33, 36, 87, 136, 77, 57, 32, 31, 28, 24, 12, 2 ]
# The curve was NOT fitting using this values, so I found a function in 
# scikit-learn that normalizes (multidim) arrays: [normalize][2]

# m = []
# m.append(original_ydata)
# ydata = normalize(m, norm='l2') * 10

# Why 10? This function is converting my original values in a range 
# going from [0.00014, ..., 0.002 ] or something similar. So "curve_fit" 
# couldn't find anything but a horizontal line crossing y = 1. 
# I tried multiplying by 5, 6, ..., 12, and I realized that 10 is 
# the maximum value that lets the maximum value of my array below 1.00, like 0.97599. 

# Length of both arrays is 209
# Y-axis data has been normalized BUT then multiplied by 10
ydata = array([  5.09124776e-04,   1.01824955e-03, ... , 9.75992196e-01])
xdata = array(range(0,len(ydata),1))

def sigmoid(x, x0, k):
    y = 1 / (1+ np.exp(-k*(x-x0)))
    return y

popt, pcov = curve_fit(sigmoid, xdata, ydata)

x = np.linspace(0, 250, 250)
y = sigmoid(x, *popt)

plt.plot(xdata, ydata, 'o', label='data')
plt.plot(x,y, linewidth=3.0, label='fit')
plt.ylim(0, 1.25)
plt.legend(loc='best')

# This (m, b, C) parameters not sure on where they are... popt, pcov? 
# y = C * sigmoid(m*x + b)

此程序将创建您可以在下面看到的绘图。正如你所看到的,这是一个合理的调整,但是我想如果我改变sigmoid函数中Y的定义,加一个C乘以第一个1,我可能会得到更好的调整。还在那上面。在

Sigmoid curve fitting

似乎标准化数据(正如Ben Kuhn在评论中建议的那样)是一个必需的步骤,否则就不会创建曲线。但是,如果将值规格化为非常低的值(接近零),则曲线也不会绘制。所以我把标准化向量乘以10,把它放大到更大的单位。然后程序简单地找到了曲线。我无法解释为什么,因为我在这方面完全是个新手。请注意,这只是我的个人经历,我不说这是一个规则。在

如果我打印poptpcov,我得到:

^{pr2}$

并且documentation on curve_fit表示这些参数包含参数的“最佳值”,以便使平方误差和前一个参数的协方差最小。在

这6个值中有没有一个是表征sigmoid曲线的参数?因为如果是这样的话,那么这个问题就很难解决了!:-)

非常感谢!在

你提到的情节看起来不好有几个原因。在

第一个原因是dictionary.values()按未排序的顺序返回值。如果你做了类似(未经测试,因为我没有你的字典),会发生什么情况

target_pairs = sorted(dictionary.iteritems()) #should be a sorted list of (date, count)
target_vector = [count for (date, count) in target_pairs]

看看结果target_vector?现在应该会增加。在

从那里得到一个逻辑函数需要更多的工作:您需要规范化target_vector使值位于[0,1],然后应用scipy.special.logit(这将[0,1]上的sigmoid变成一条直线),然后您就可以找到最适合它的线。然后您可以恢复逻辑模型的参数:

^{pr2}$

其中m和{}是转换数据的线性回归的斜率和截距,C是归一化数据时除以的值。在

相关问题 更多 >