将加法向量化到另一个数组索引的数组中

托特

我正在尝试获取以下循环的快速矢量化版本:

for i in xrange(N1):
   A[y[i]] -= B[i,:]

在这里A.shape = (N2,N3)y.shape = (N1)y服用值[0,N2[B.shape = (N1,N3)您可以考虑将条目y索引为的行A这里N1很大,N2很小,N3也很小。

我以为干嘛

A[y] -= B

会工作,但问题是,有重复的条目y,这不会做正确的事(即,如果y=[1,1]A[1]只加一次,而不是两次)。而且,这似乎没有比未向量化的for循环更快。

有更好的方法吗?

编辑:YXD将此评论链接到最初似乎符合要求的评论中。看来您可以完全按照我的意愿去做

np.subtract.at(A, y, B)

并且确实可以,但是当我尝试运行它时,它比未向量化的版本要慢得多。因此,问题仍然存在:是否有更高效的方法可以做到这一点?

EDIT2:一个例子,使事情具体:

n1,n2,n3 = 10000, 10, 500
A = np.random.rand(n2,n3)
y = np.random.randint(n2, size=n1)
B = np.random.rand(n1,n3)

%timeit在ipython中运行时,for循环在我的机器上给出:

10 loops, best of 3: 19.4 ms per loop

subtract.at版本A最终会产生相同的值,但速度要慢得多:

  1 loops, best of 3: 444 ms per loop
迪卡卡(Divakar)

原始的基于for循环方法的代码如下所示:

def for_loop(A):
    N1 = B.shape[0]
    for i in xrange(N1):
       A[y[i]] -= B[i,:]
    return A

情况1

如果n2 >> n3,我建议采用这种向量化方法-

def bincount_vectorized(A):

    n3 = A.shape[1]
    nrows = y.max()+1
    id = y[:,None] + nrows*np.arange(n3)
    A[:nrows] -= np.bincount(id.ravel(),B.ravel()).reshape(n3,nrows).T
    return A

运行时测试-

In [203]: n1,n2,n3 = 10000, 500, 10
     ...: A = np.random.rand(n2,n3)
     ...: y = np.random.randint(n2, size=n1)
     ...: B = np.random.rand(n1,n3)
     ...: 
     ...: # Make copies
     ...: Acopy1 = A.copy()
     ...: Acopy2 = A.copy()
     ...: 

In [204]: %timeit for_loop(Acopy1)
10 loops, best of 3: 19 ms per loop

In [205]: %timeit bincount_vectorized(Acopy2)
1000 loops, best of 3: 779 µs per loop

情况#2

如果n2 << n3,则可以建议使用一种改进的for-loop方法,其循环复杂度要低一些-

def for_loop_v2(A):
    n2 = A.shape[0]
    for i in range(n2):
        A[i] -= np.einsum('ij->j',B[y==i]) # OR (B[y==i]).sum(0)
    return A

运行时测试-

In [206]: n1,n2,n3 = 10000, 10, 500
     ...: A = np.random.rand(n2,n3)
     ...: y = np.random.randint(n2, size=n1)
     ...: B = np.random.rand(n1,n3)
     ...: 
     ...: # Make copies
     ...: Acopy1 = A.copy()
     ...: Acopy2 = A.copy()
     ...: 

In [207]: %timeit for_loop(Acopy1)
10 loops, best of 3: 24.2 ms per loop

In [208]: %timeit for_loop_v2(Acopy2)
10 loops, best of 3: 20.3 ms per loop

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将一个数组的一些索引复制到另一个数组

将包含某个单词的数组的索引存储到Python中的另一个数组中

向量化为另一个数组中的每个元素在数组中找到最接近的值

使用另一个numpy数组元素作为索引的向量化更新numpy数组

将一个数组的索引(被随机挑选然后拼接)复制到另一个数组中,以便我知道它的拼接顺序

将多维数组中的值与另一个数组的索引进行比较

如何通过Java中的条件将一个数组的索引插入另一个数组

在numpy中索引另一个数组

将数组中的元素移除到另一个数组中 (Ruby)

在另一个数组中查找一个数组的匹配索引

根据对象的数据将单独的数组创建到另一个数组中

将数组项目复制到另一个数组中

将数组特定值分离到另一个数组中的正确方法

将数组字段更快地复制到另一个数组中

将数组存储到另一个数组中,是否得到意外结果?

将数组作为元素放置到C中的另一个数组

将数组解包到另一个数组 PHP 中

将一个数组的元素以相反的顺序存储到另一个数组中

将一个数组的元素复制到另一个数组中

向量化方法,用于提取包含另一个数组元素的端点数组的行

将数组的所有元素复制到指定索引处的另一个数组

另一个数组的数组返回索引

比较数组中的多个索引与另一个数组中的多个索引

向量化索引数组中元素的条件和以及要添加的另一个元素数组

将大于某个值的数字存储到另一个数组中

数组索引替换为另一个数组在php中相同的索引

php-将值从数组复制到多维数组中的另一个数组

将数组中的不同索引值转换为 php 中的另一个数组

使用PySpark数据帧时,根据索引从一个数组中定位值,然后复制到另一个数组中