Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 全矢量numpy polyfit 概述_Python_Numpy - Fatal编程技术网

Python 全矢量numpy polyfit 概述

Python 全矢量numpy polyfit 概述,python,numpy,Python,Numpy,我在使用polyfit时遇到性能问题,因为它似乎无法接受广播阵列。我知道,如果使用numpy.polynomy.polynomy.polynomy.polyfit,依赖数据y可能是多维的。但是,x维度不能是多维的。这有什么关系吗 动机 我需要计算一些数据的变化率。为了与实验相匹配,我想使用以下方法:取数据y和x,对于短段数据拟合多项式,然后使用拟合系数作为变化率的估计值 插图 蓝线是原始数据(正弦曲线),而绿线是第一个微分(余弦曲线) 问题 为了将其矢量化,我执行了以下操作: window_l

我在使用polyfit时遇到性能问题,因为它似乎无法接受广播阵列。我知道,如果使用
numpy.polynomy.polynomy.polynomy.polyfit
,依赖数据
y
可能是多维的。但是,
x
维度不能是多维的。这有什么关系吗

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

插图

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

问题 为了将其矢量化,我执行了以下操作:

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]
这会将两个1D向量广播到形状
(n-window\u length,window\u length)
的2D向量。现在我希望
polyfit
会有一个
axis
参数,这样我就可以并行计算了,但没有这样的运气


有人对如何做到这一点有什么建议吗?很抱歉,我回答了自己的问题,但在20分钟的时间里,我有以下解决方案:

ydot = np.polynomial.polynomial.polyfit(x_array[0], y_array.T, 1)[-1]
一个令人困惑的部分是
np.polyfit
首先返回具有最高幂次的系数。在
np.polynomy.polynomy.polyfit
中,最高的幂次是last(因此
-1
而不是
0
索引)

另一个混淆是我们只使用
x
x\u数组[0]
)的第一个片段。我认为这是可以的,因为使用的不是独立向量x的绝对值,而是它们之间的差异。或者,它类似于更改参考
x


如果有更好的方法,我还是很高兴听到这个消息

使用另一种方法计算变化率可能是提高速度和精度的解决方案

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


def timingPolyfit(x,y):
    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]

    ydot = np.polynomial.polynomial.polyfit(x_array[0], y_array.T, 1)[-1]
    x_mids = [x[j+window_length/2] for j in range(n - window_length)]

    return ydot, x_mids

def timingSimple(x,y):
    dy = (y[2:] - y[:-2])/2
    dx =  x[1] - x[0]
    dydx = dy/dx
    return dydx, x[1:-1]

y1, x1 = timingPolyfit(x,y)
y2, x2 = timingSimple(x,y)

polyfitError = np.abs(y1 - np.cos(x1))
simpleError = np.abs(y2 - np.cos(x2))

print("polyfit average error: {:.2e}".format(np.average(polyfitError)))
print("simple average error: {:.2e}".format(np.average(simpleError)))

result = %timeit -o timingPolyfit(x,y)
result2 = %timeit -o timingSimple(x,y)

print("simple is {0} times faster".format(result.best / result2.best))

相对误差:

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

y = [X].a
其中,
y
是从属坐标,
[X]
是相应独立坐标的向量,
a
是拟合系数的向量

在你的例子中,你总是在计算一次多项式近似值,实际上你只对一次项的系数感兴趣。你可以在任何一本统计书中找到这一点,也可以创建一个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
最重要的是,您有一个滑动窗口运行在您的数据上,因此您可以使用类似于a的东西,如下所示:

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):

以及:


因此,对于您的样本数据,它大约快300倍。

计算一阶数值导数而不是使用polyfit应该会更快、更快accurate@M4rtini你是对的,但我这样做是为了和实验主义者使用的方法保持一致。这是在问题中,但我很感激有太多的文本让任何人都懒得去读。哦,错过了问题的那一部分。我想我的答案是完全不相关的,正如在问题的评论中所讨论的,我想解释的正是这些错误!虽然我真的很感激你在这里所做的努力,但实际上我还没有意识到这种方法有多么糟糕!因为这个原因,我会把这个留在这里!我似乎记得在数学课上,多项式天生就不适合拟合调和函数。因此,对于其他类型的数据,相对误差可能没有那么大。但是速度应该还是一样的。我将把这个留在这里,以备将来参考,即使它没有直接回答这个问题。
>>> 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
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)
>>> 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