矢量化numpy polyfit移动窗口

时间:2017-11-22 16:58:33

标签: python numpy polynomials

我希望对以下功能进行矢量化

def nppolyfit(pnp_array, **kwargs):
  """ Moving polyfit 
  """
  win_size = kwargs['length']
  degree = kwargs['degree']

  xdata = range(win_size)
  res = np.zeros(pnp_array.shape)

  for i in range(win_size, len(pnp_array) + 1):
      res[i-1]  = np.poly1d(np.polyfit(xdata , pnp_array[i - win_size : i], deg = degree))(win_size)

  return res

到目前为止做了什么:

def rolling_window(a, window):
    shp = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shp, strides=strides)

def nppolyfitv(pnp_array, **kwargs):
  """ Moving polyfit 
  """
  win_size = kwargs['length']
  degree = kwargs['degree']

  xdata = np.arange(win_size)
  ydata = rolling_window(pnp_array, win_size).T
  fit = np.polyfit(xdata, ydata, deg = degree)
  res = np.zeros(len(pnp_array))
  res[win_size-1:] = np.polynomial.polynomial.polyval(np.zeros(len(pnp_array)), fit).T[len(pnp_array) - 1,:]

  return res

但看起来我错过了什么或做错了。你能纠正我吗?也许还有另一个更有效的解决方案?感谢。

测试用例:

import numpy as np
npd = np.arange(30)
win_size1 = 11
degree = 1
c1  =     nppolyfit(npd, length=win_size1, degree=degree)
c1v  =   nppolyfitv(npd, length=win_size1, degree=degree)
print(c1)
print(c1v)

结果是:

[  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.  11.  12.  13.  14.  15.
  16.  17.  18.  19.  20.  21.  22.  23.  24.  25.  26.  27.  28.  29.  30.]
[   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    1.   30.
   59.   88.  117.  146.  175.  204.  233.  262.  291.  320.  349.  378.
  407.  436.  465.  494.  523.  552.]

2 个答案:

答案 0 :(得分:2)

polyfit方法返回多项式系数,最高权力

polyval方法要求系数首先具有最低功率。将一种方法的输出提供给另一种方法时,请考虑到这一点。

此外,polyval的x参数不合逻辑:np.zeros(len(pnp_array))。为什么要求polyval在同一点0多次评估多项式?特别是因为你的非向量化函数在win_size处评估了多项式。为了与非矢量化方法保持一致,请替换

res[win_size-1:] = np.polynomial.polynomial.polyval(np.zeros(len(pnp_array)), fit).T[len(pnp_array) - 1,:]

res[win_size-1:] = np.polynomial.polynomial.polyval(win_size, fit[::-1])

然后测试用例的两个输出都是相同的。

(也就是说,我也不知道为什么你在窗口的右边缘评估多项式;中间是否会是更有代表性的值?但这是你可以决定的。)

答案 1 :(得分:0)

第一步是比较两种方法的中间值;

例如,我可以使用

跟踪polyfit步骤
In [304]: def nppolyfit(pnp_array, **kwargs):
     ...:   """ Moving polyfit 
     ...:   """
     ...:   win_size = kwargs['length']
     ...:   degree = kwargs['degree']
     ...: 
     ...:   xdata = np.arange(win_size)
     ...:   res = np.zeros(pnp_array.shape)
     ...:   fits = []
     ...:   for i in range(win_size, len(pnp_array) + 1):
     ...:       fit = np.polyfit(xdata , pnp_array[i - win_size : i], deg = degr
     ...: ee)
     ...:       res[i-1] = np.poly1d(fit)(win_size)
     ...:       fits.append(fit)
     ...:   return res, fits
     ...: 
     ...: 
In [305]: 
In [305]: nppolyfit(npd,length=win_size1, degree=degree)
Out[305]: 
(array([  0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,  11.,
         12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.,  21.,  22.,
         23.,  24.,  25.,  26.,  27.,  28.,  29.,  30.]),
 [array([  1.00000000e+00,   1.60677522e-15]),
  array([ 1.,  1.]),
  array([ 1.,  2.]),
  array([ 1.,  3.]),
  array([ 1.,  4.]),
  array([ 1.,  5.]),
  array([ 1.,  6.]),
  array([ 1.,  7.]),
  array([ 1.,  8.]),
  array([ 1.,  9.]),
  array([ 1., 10.]),
  array([  1.,  11.]),
  array([  1.,  12.]),
  array([  1.,  13.]),
  array([  1.,  14.]),
  array([  1.,  15.]),
  array([  1.,  16.]),
  array([  1.,  17.]),
  array([  1.,  18.]),
  array([  1.,  19.])])

然后我应该将它与多维polyfit案例中的fit变量进行比较。

更改上一个功能以返回fit以及res

In [308]: nppolyfitv(npd, length=win_size1, degree=degree)
Out[308]: 
(array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  1.,
         1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,
         1.,  1.,  1.,  1.]),
 array([[  1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
           1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
           1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
           1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
           1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
           1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
           1.00000000e+00,   1.00000000e+00],
        [  1.60677522e-15,   1.00000000e+00,   2.00000000e+00,
           3.00000000e+00,   4.00000000e+00,   5.00000000e+00,
           6.00000000e+00,   7.00000000e+00,   8.00000000e+00,
           9.00000000e+00,   1.00000000e+01,   1.10000000e+01,
           1.20000000e+01,   1.30000000e+01,   1.40000000e+01,
           1.50000000e+01,   1.60000000e+01,   1.70000000e+01,
           1.80000000e+01,   1.90000000e+01]]))

适合似乎匹配。所以问题可能在于poly1d步骤。