Python:精确定位斜率的线性部分

use*_*716 15 python graph

我有几个看起来如下的情节:

在此输入图像描述

我想知道在x轴上找到大约5.5到8之间的斜率可能有什么样的方法.如果有这样的几个图,我更想知道是否有办法自动找到斜率值.

有什么建议?

我在想ployfit(),或者是线性回归.问题是我不确定如何自动查找值.

Han*_*ann 28

在数据集中查找线性部分的一般方法是计算函数的二阶导数,并查看它的位置(接近)为零.解决方案的方法有几点需要考虑:

  • 如何计算噪声数据的二阶导数?一种快速简单的方法,可以很容易地适应不同的噪声水平,数据集大小和线性贴片的预期长度,是将数据卷积为等于高斯二阶导数的卷积核.可调部分是内核的宽度.

  • 在您的背景下,"接近于零"意味着什么?要回答这个问题,您必须试验您的数据.

  • 该方法的结果可以用作上述chi ^ 2方法的输入,以识别数据集中的候选区域.

这里有一些源代码可以帮助您入门:

from matplotlib import pyplot as plt

import numpy as np

# create theoretical data
x_a = np.linspace(-8,0, 60)
y_a = np.sin(x_a)
x_b = np.linspace(0,4,30)[1:]
y_b = x_b[:]
x_c = np.linspace(4,6,15)[1:]
y_c = np.sin((x_c - 4)/4*np.pi)/np.pi*4. + 4
x_d = np.linspace(6,14,120)[1:]
y_d = np.zeros(len(x_d)) + 4 + (4/np.pi)

x = np.concatenate((x_a, x_b, x_c, x_d))
y = np.concatenate((y_a, y_b, y_c, y_d))


# make noisy data from theoretical data
y_n = y + np.random.normal(0, 0.27, len(x))

# create convolution kernel for calculating
# the smoothed second order derivative
smooth_width = 59
x1 = np.linspace(-3,3,smooth_width)
norm = np.sum(np.exp(-x1**2)) * (x1[1]-x1[0]) # ad hoc normalization
y1 = (4*x1**2 - 2) * np.exp(-x1**2) / smooth_width *8#norm*(x1[1]-x1[0])



# calculate second order deriv.
y_conv = np.convolve(y_n, y1, mode="same")

# plot data
plt.plot(x,y_conv, label = "second deriv")
plt.plot(x, y_n,"o", label = "noisy data")
plt.plot(x, y, label="theory")
plt.plot(x, x, "0.3", label = "linear data")
plt.hlines([0],-10, 20)
plt.axvspan(0,4, color="y", alpha=0.2)
plt.axvspan(6,14, color="y", alpha=0.2)
plt.axhspan(-1,1, color="b", alpha=0.2)
plt.vlines([0, 4, 6],-10, 10)
plt.xlim(-2.5,12)
plt.ylim(-2.5,6)
plt.legend(loc=0)
plt.show()
Run Code Online (Sandbox Code Playgroud)

这是结果: 在此输入图像描述

smooth_width是卷积核的宽度.为了调整噪声量,0.27请将random.normal中的值更改为不同的值.请注意,此方法不能很好地靠近数据空间的边界.

如您所见,对于黄色部分,二阶导数(蓝线)的"接近零"要求非常好,其中数据是线性的.


unu*_*tbu 5

您可以使用Ramer Douglas Peucker 算法将数据简化为一组较小的线段。该算法允许您指定一个epsilon使得每个数据点都不会比epsilon某个线段更远的地方。线段的斜率可以粗略估计曲线的斜率。

这里有RDP 算法Python 实现。


YXD*_*YXD 0

如果您的数据“模型”由大部分符合直线的数据组成,最后有一些异常值或波动位,您可以尝试RANSAC算法。

这里的(非常罗嗦,抱歉)伪代码是:

choose a small threshold distance D

for N iterations:
    pick two random points from your data, a and b
    fit a straight line, L, to a and b
    count the inliers: data points within a distance D of the line L
    save the parameters of the line with the most inliers so far

estimate the final line using ALL the inliers of the best line
Run Code Online (Sandbox Code Playgroud)