np.bincount 1行,矢量化多维平均

佩尔马托

我正在尝试使用numpy对操作进行矢量化,该操作已在我已分析的python脚本中使用,并且发现此操作是瓶颈,因此需要进行优化,因为我将多次运行它。

该操作是由两部分组成的数据集。首先,创建一个n不同长度(最大长度为)的一维向量的大集合(),Lmax其元素是1到的整数maxvalue向量集按2D数组排列,data大小为2D,(num_samples,Lmax)每行中的尾随元素清零。第二部分是一组标量浮点数,每个向量都有一个标量浮点数,我对其进行了计算,并且取决于标量浮点数的长度和每个位置的整数值。标量集合被制成Y大小为的一维数组num_samples

所需的操作是形成平均的Yn采样,如的函数 (value,position along length,length)

可以使用以下accumarray功能在matlab中对整个操作进行矢量化:使用3个大小与相同的2D数组data,其元素是所需最终数组的相应值,位置和长度索引:

sz_Y = num_samples;
sz_len = Lmax 
sz_pos = Lmax 
sz_val = maxvalue
ind_len = repmat( 1:sz_len      ,1         ,sz_samples);
ind_pos = repmat( 1:sz_pos      ,sz_samples,1         );
ind_val = data
ind_Y   = repmat((1:sz_Y)',1         ,Lmax      );
copiedY=Y(ind_Y);
mask = data>0; 
finalarr=accumarray({ind_val(mask),ind_pos(mask),ind_len(mask)},copiedY(mask), [sz_val sz_pos sz_len])/sz_val;

我希望使用来模拟此实现np.bincounts但是,在以下两个相关方面np.bincounts有所不同accumarray

    两个参数必须具有相同的一维大小,并且
    没有选择输出数组形状的选项。

在以上的用法中accumarray,索引的列表{ind_val(mask),ind_pos(mask),ind_len(mask)}是用作索引元组的1x3数组的1D单元数组,而np.bincounts据我所知它必须是1D标量。我希望它np.ravel可能有用,但不确定如何在这里使用它来做我想做的事情。我是从matlab转到python的,有些东西不能直接翻译,例如冒号运算符,它以与反序相反的顺序移动。所以我的问题是我应该如何使用np.bincount或其他任何numpy方法来实现此操作的高效python实现

编辑:为避免浪费时间:对于具有复杂索引操作的这些multiD索引问题,是否建议仅使用cython来显式实现循环的途径?

EDIT2:我刚想到的替代Python实现。
这是一个沉重的ram解决方案:

首先进行预计算:
使用索引单位表示长度(即长度1 = 0),制作4D bool数组,大小(num_samples,Lmax+1,Lmax+1,maxvalue),并保持满足条件中每个值的条件Y

ALLcond=np.zeros((num_samples,Lmax+1,Lmax+1,maxvalue+1),dtype='bool')
for l in range(Lmax+1):
    for i in range(Lmax+1):
        for v in range(maxvalue+!):
            ALLcond[:,l,i,v]=(data[:,i]==v) & (Lvec==l)`

在哪里Lvec=[len(row) for row in data]然后使用获取这些索引,np.where并初始化一个4D浮点数组,您将在其中分配Y的值:

[indY,ind_len,ind_pos,ind_val]=np.where(ALLcond)
Yval=np.zeros(np.shape(ALLcond),dtype='float')

现在,在必须执行操作的循环中,我用两行代码对其进行计算:

Yval[ind_Y,ind_len,ind_pos,ind_val]=Y[ind_Y]
Y_avg=sum(Yval)/num_samples

与直接循环实施相比,这可以提高4倍左右的速度。我期待更多。也许,对于Python头来说,这是一个更切实的实现。任何更快的建议,欢迎:)

用户名

一种方法是将3个“索引”转换为线性索引,然后应用bincountNumpy的ravel_multi_index本质与MATLAB的相同sub2ind因此,移植的代码可能类似于:

shape = (Lmax+1, Lmax+1, maxvalue+1)
posvec = np.arange(1, Lmax+1)

ind_len  = np.tile(Lvec[:,None], [1, Lmax])
ind_pos  = np.tile(posvec,       [n,    1])
ind_val  = data
Y_copied = np.tile(Y[:,None],    [1, Lmax])

mask = posvec <= Lvec[:,None]  # fill-value independent
lin_idx = np.ravel_multi_index((ind_len[mask], ind_pos[mask], ind_val[mask]), shape)
Y_avg = np.bincount(lin_idx, weights=Y_copied[mask], minlength=np.prod(shape)) / n
Y_avg.shape = shape

这是假设data具有shape (n, Lmax)LvecNumpy数组等。您可能需要稍微修改一下代码,以消除一对一的错误。

有人可能会说这些tile操作不是很有效,也不是很“ numpythonic”。有一些broadcast_arrays可能是好的,但我想我更喜欢这种方式:

shape = (Lmax+1, Lmax+1, maxvalue+1)
posvec = np.arange(1, Lmax+1)

len_idx  = np.repeat(Lvec, Lvec)
pos_idx  = np.broadcast_to(posvec, data.shape)[mask]
val_idx  = data[mask]
Y_copied = np.repeat(Y, Lvec)

mask = posvec <= Lvec[:,None]  # fill-value independent
lin_idx = np.ravel_multi_index((len_idx, pos_idx, val_idx), shape)
Y_avg = np.bincount(lin_idx, weights=Y_copied, minlength=np.prod(shape)) / n
Y_avg.shape = shape

注意broadcast_to已在Numpy 1.10.0中添加。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

MATLAB bsxfun或矢量化

来自分类Dev

numpy的bincount函数的反函数

来自分类Dev

Matlab效率-矢量化

来自分类Dev

在python中忽略numpy bincount中的NaN

来自分类Dev

通过矢量化提高np.irr函数的性能

来自分类Dev

Julia:矢量化与反矢量化代码

来自分类Dev

NumPy:按np.array过滤行

来自分类Dev

矢量化Elseif循环

来自分类Dev

向量化np.arange或等效

来自分类Dev

numpy矢量化错误

来自分类Dev

numpy矢量化

来自分类Dev

查找连续元素之间差异的矢量化方法?也许是np.diff()的变体?

来自分类Dev

Numpy进行循环矢量化:使用np.all广播和测试唯一元素

来自分类Dev

2D ID数组和1D权重的加权numpy bincount

来自分类Dev

np选择与Edning匹配的行

来自分类Dev

在矢量化函数中调用矢量化函数

来自分类Dev

有矢量化的方法来使用np.random.choice()将p设为p的倍数吗?

来自分类Dev

熊猫矢量化

来自分类Dev

从np数组中删除随机行

来自分类Dev

忽略python中的numpy bincount中的NaN

来自分类Dev

删除np.array中的选定行

来自分类Dev

多维数组上的Numpy np.dot()

来自分类Dev

使用 np.einsum 进行光线投射的矢量化范围

来自分类Dev

矢量化算法

来自分类Dev

矢量化列表

来自分类Dev

在计算距离和 np.sum 上优化 numpy 矢量化

来自分类Dev

在for循环中删除np数组中的行

来自分类Dev

具有类属性的 numpy bincount

来自分类Dev

np.reshape(-1) 做什么