使用 numpy 计算双端队列的加权平均值

Computing weighted average on a deque using numpy

我有一个双端队列对象,我想找到它的加权平均值。 deque 对象是 (60 * 60 * 3) 个 NumPy 数组的集合(它们实际上是存储在 deque 对象中的图像)。我想找到双端队列对象中所有元素(即图像)的加权平均值。

motion_buffer = deque(maxlen = 5)
motion_weights = [5./15, 4./15, 3./15, 2./15, 1./15]
# After adding few elements ( i.e images ) in motion_buffer. the following is done:
motion_avg = np.average(motion_buffer, weights=motion_weights)

I get the error:
    "Axis must be specified when shapes of a and weights "
    TypeError: Axis must be specified when shapes of a and weights differ.

我知道某处不匹配,但提供轴值(根据 docs)对我没有帮助。我已经通过以下方式对其进行了测试:

>>> A = np.random.randn(4,4)
>>> weights = [1 , 4 ,6 ,7]
>>> buf = deque(maxlen=5)
>>> buf.appendleft(A)
>>> c = np.average(buf, weights=weights)
Traceback (most recent call last):
    ...  
    "Axis must be specified when shapes of a and weights "
TypeError: Axis must be specified when shapes of a and weights differ.

我已经尝试将 np.average 用于具有 1d 元素的双端队列对象并且它有效。 我究竟应该如何修改我的代码,我试验过但它对我不起作用。

根据 np.average 文档

weights : array_like, optional
    An array of weights associated with the values in a. Each value in
    a contributes to the average according to its associated weight.
    The weights array can either be 1-D (in which case its length must be
    the size of a along the given axis) or of the same shape as a.

你不能。

您可以实施解决方法

av_average  = np.average(np.average(your_deque, axis=(1,2,3)), weights=(5,4,3,2,1))

首先(内部平均值)调解每个 60×60×3 矩阵,指定求和的轴,然后使用权重计算平均值的加权平均值。


OP 真的想要这个

average = np.average(the_deque, axis=0, weights=(…))

其中 (…) 是一个序列,其长度等于双端队列的当前长度。

一种可行的方法是将双端队列转换为 numpy 数组,然后

my_array = np.array(deque)
np.average(deque, axis=0, weights=weights) 

帮助解决了唯一增加计算时间的问题。

In [1]: from collections import deque                                                                
In [2]: >>> A = np.random.randn(4,4) 
   ...: >>> weights = [1 , 4 ,6 ,7] 
   ...: >>> buf = deque(maxlen=5) 
   ...: >>> buf.appendleft(A)                                                                        
In [3]: buf                                                                                          
Out[3]: 
deque([array([[ 1.10651806, -0.50125715, -0.35877456,  1.31969932],
              [-0.4674734 ,  0.25144544, -1.5392525 ,  0.09607722],
              [ 2.24245413, -1.09636901,  1.97502862, -0.90069983],
              [ 0.61917197, -0.13276115, -0.1103521 ,  0.56556319]])])
In [4]: np.array(buf)                                                                                
Out[4]: 
array([[[ 1.10651806, -0.50125715, -0.35877456,  1.31969932],
        [-0.4674734 ,  0.25144544, -1.5392525 ,  0.09607722],
        [ 2.24245413, -1.09636901,  1.97502862, -0.90069983],
        [ 0.61917197, -0.13276115, -0.1103521 ,  0.56556319]]])
In [5]: np.average(buf, weights=weights, axis=0)                                                     
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-8a8c3dba2415> in <module>
----> 1 np.average(buf, weights=weights, axis=0)

<__array_function__ internals> in average(*args, **kwargs)

/usr/local/lib/python3.6/dist-packages/numpy/lib/function_base.py in average(a, axis, weights, returned)
    399             if wgt.shape[0] != a.shape[axis]:
    400                 raise ValueError(
--> 401                     "Length of weights not compatible with specified axis.")
    402 
    403             # setup wgt to broadcast along axis

ValueError: Length of weights not compatible with specified axis.
In [6]: _4.shape                                                                                     
Out[6]: (1, 4, 4)

糟糕,我应该检查数组的形状。出于某种原因,我不会深入研究 Out[4] 的初始尺寸为 1 维。

In [7]: np.average(buf, weights=weights, axis=1)                                                     
Out[7]: array([[ 0.94586406, -0.38905653,  0.25344014,  0.01437508]])