python - 完全矢量化 numpy polyfit

标签 python numpy

概览

我在使用 polyfit 时遇到了性能问题,因为它似乎无法接受广播数组。我知道from this post如果您使用 numpy.polynomial.polynomial.polyfit,相关数据 y 可以是多维的。但是,x 维度不能是多维的。有什么办法吗?

动机

我需要计算一些数据的变化率。为了与实验相匹配,我想使用以下方法:获取数据 yx,对于短部分数据拟合多项式,然后使用拟合系数作为估计的变化率。

插图

import numpy as np
import matplotlib.pyplot as plt

n = 100
x = np.linspace(0, 10, n)
y = np.sin(x)

window_length = 10
ydot = [np.polyfit(x[j:j+window_length], y[j:j+window_length], 1)[0] 
                                  for j in range(n - window_length)]
x_mids = [x[j+window_length/2] for j in range(n - window_length)]

plt.plot(x, y)
plt.plot(x_mids, ydot)

plt.show()

enter image description here

蓝线是原始数据(正弦曲线),而绿线是一阶微分(余弦曲线)。

问题

为了对其进行矢量化,我做了以下工作:

window_length = 10
vert_idx_list = np.arange(0, len(x) - window_length, 1)
hori_idx_list = np.arange(window_length)
A, B = np.meshgrid(hori_idx_list, vert_idx_list)
idx_array = A + B 

x_array = x[idx_array]
y_array = y[idx_array]

这会将两个一维向量广播为形状为 (n-window_length, window_length) 的二维向量。现在我希望 polyfit 有一个 axis 参数,这样我就可以并行计算,但没有这样的运气。

有没有人对如何做到这一点有任何建议?我愿意接受

最佳答案

polyfit 的工作方式是解决以下形式的最小二乘问题:

y = [X].a

y 是您的依赖坐标,[X]Vandermonde matrix对应的独立坐标,a是拟合系数向量。

在您的情况下,您总是在计算一次多项式近似值,并且实际上只对一次项的系数感兴趣。这有一个 well known closed form solution您可以在任何统计书籍中找到,或者通过创建一个 2x2 线性方程组来生成您自己的方程,将上述方程的两边预乘以 [X] 的转置。这一切加起来就是您要计算的值:

>>> n = 10
>>> x = np.random.random(n)
>>> y = np.random.random(n)
>>> np.polyfit(x, y, 1)[0]
-0.29207474654700277
>>> (n*(x*y).sum() - x.sum()*y.sum()) / (n*(x*x).sum() - x.sum()*x.sum())
-0.29207474654700216

最重要的是,你有一个滑动窗口运行在你的数据上,所以你可以使用类似于 1D summed area table 的东西。如下:

def sliding_fitted_slope(x, y, win):
    x = np.concatenate(([0], x))
    y = np.concatenate(([0], y))
    Sx = np.cumsum(x)
    Sy = np.cumsum(y)
    Sx2 = np.cumsum(x*x)
    Sxy = np.cumsum(x*y)

    Sx = Sx[win:] - Sx[:-win]
    Sy = Sy[win:] - Sy[:-win]
    Sx2 = Sx2[win:] - Sx2[:-win]
    Sxy = Sxy[win:] - Sxy[:-win]

    return (win*Sxy - Sx*Sy) / (win*Sx2 - Sx*Sx)

使用这段代码,您可以轻松检查(注意我将范围扩大了 1):

>>> np.allclose(sliding_fitted_slope(x, y, window_length),
                [np.polyfit(x[j:j+window_length], y[j:j+window_length], 1)[0]
                 for j in range(n - window_length + 1)])
True

和:

%timeit sliding_fitted_slope(x, y, window_length)
10000 loops, best of 3: 34.5 us per loop

%%timeit
[np.polyfit(x[j:j+window_length], y[j:j+window_length], 1)[0]
 for j in range(n - window_length + 1)]
100 loops, best of 3: 10.1 ms per loop

因此,您的示例数据的处理速度大约快 300 倍。

关于python - 完全矢量化 numpy polyfit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28237428/

相关文章:

python - Scrapy 输出格式化困难

python - 如何在 pandas 或 matplotlib 中绘制两个 y 轴上的数据?

numpy: 你如何对 "break"进行 numpy 操作?

python - Pandas,从一列中选择最大值,从另一列中选择最小值

具有更新值的python for循环

python - 通过从用户输入中获取键来从 python 字典中查找值

python - 为什么加载libc共享库有 "' LibraryLoader' object is not callable”错误?

Python:如何返回连接节点的列表

python - 循环邻域 - 最小 Numpy

python - 使用 pandas 绘图时,图例仅显示一个标签