Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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:通过组合以前数组的子集来创建新数组_Python_Numpy_Scipy_Sparse Matrix - Fatal编程技术网

Python Numpy:通过组合以前数组的子集来创建新数组

Python Numpy:通过组合以前数组的子集来创建新数组,python,numpy,scipy,sparse-matrix,Python,Numpy,Scipy,Sparse Matrix,我有一个二进制稀疏CSR数组。我想通过合并原始数组中的列来创建一个新数组。也就是说,我有一个列组列表:[[1,10,3],[5,54202],[12199],[5],…] 对于这些列组中的每一个,我都希望将原始数组中的列与OR操作组合起来。np.max可用于此操作,并将组合后的列添加到新矩阵中 我目前的解决方案是使用hstack,但速度非常慢: for cg in column_groups: tmp = np.max(data_orig[:,cg].toarray(), axis=1,

我有一个二进制稀疏CSR数组。我想通过合并原始数组中的列来创建一个新数组。也就是说,我有一个列组列表:[[1,10,3],[5,54202],[12199],[5],…]

对于这些列组中的每一个,我都希望将原始数组中的列与OR操作组合起来。np.max可用于此操作,并将组合后的列添加到新矩阵中

我目前的解决方案是使用hstack,但速度非常慢:

for cg in column_groups:
    tmp = np.max(data_orig[:,cg].toarray(), axis=1, keepdims=True)
    data = np.hstack((data, tmp))

您基本上是在每次迭代中选择max列。所以,我们可以选择所有的列,然后使用来对最大列进行插值,从而为我们提供一个向量化的解决方案,如下所示-

def grouped_max(data_orig, column_groups):
    cols = np.hstack((column_groups))
    clens = np.hstack((0,np.cumsum(map(len,column_groups))[:-1]))
    all_data = data_orig[:,cols].toarray()
    return np.maximum.reduceat(all_data, clens,axis=1)
clens = np.hstack((0,np.cumsum(list(map(len,column_groups)))[:-1]))
对于Python3.x版本,我们需要计算clen,如下所示-

def grouped_max(data_orig, column_groups):
    cols = np.hstack((column_groups))
    clens = np.hstack((0,np.cumsum(map(len,column_groups))[:-1]))
    all_data = data_orig[:,cols].toarray()
    return np.maximum.reduceat(all_data, clens,axis=1)
clens = np.hstack((0,np.cumsum(list(map(len,column_groups)))[:-1]))
由于loopy版本是沿着组进行迭代的,因此当使用大量组时,这种矢量化解决方案将显示出其优势

样本运行-

In [303]: # Setup sample csr matrix
     ...: a = np.random.randint(0,3,(12,28))
     ...: data_orig = sparse.csr_matrix(a)
     ...: 
     ...: # Random column IDs
     ...: column_groups = [[1,10,3], [5,14],[2]]
     ...: 
     ...: data = np.empty((12,0),dtype=int)
     ...: for cg in column_groups:
     ...:     tmp = np.max(data_orig[:,cg].toarray(), axis=1, keepdims=True)
     ...:     data = np.hstack((data, tmp))
     ...:     

In [304]: out = grouped_max(data_orig, column_groups)

In [305]: # Verify results between original and propsed ones
     ...: print np.allclose(out, data)
True

您基本上是在每次迭代中选择max列。所以,我们可以选择所有的列,然后使用来对最大列进行插值,从而为我们提供一个向量化的解决方案,如下所示-

def grouped_max(data_orig, column_groups):
    cols = np.hstack((column_groups))
    clens = np.hstack((0,np.cumsum(map(len,column_groups))[:-1]))
    all_data = data_orig[:,cols].toarray()
    return np.maximum.reduceat(all_data, clens,axis=1)
clens = np.hstack((0,np.cumsum(list(map(len,column_groups)))[:-1]))
对于Python3.x版本,我们需要计算clen,如下所示-

def grouped_max(data_orig, column_groups):
    cols = np.hstack((column_groups))
    clens = np.hstack((0,np.cumsum(map(len,column_groups))[:-1]))
    all_data = data_orig[:,cols].toarray()
    return np.maximum.reduceat(all_data, clens,axis=1)
clens = np.hstack((0,np.cumsum(list(map(len,column_groups)))[:-1]))
由于loopy版本是沿着组进行迭代的,因此当使用大量组时,这种矢量化解决方案将显示出其优势

样本运行-

In [303]: # Setup sample csr matrix
     ...: a = np.random.randint(0,3,(12,28))
     ...: data_orig = sparse.csr_matrix(a)
     ...: 
     ...: # Random column IDs
     ...: column_groups = [[1,10,3], [5,14],[2]]
     ...: 
     ...: data = np.empty((12,0),dtype=int)
     ...: for cg in column_groups:
     ...:     tmp = np.max(data_orig[:,cg].toarray(), axis=1, keepdims=True)
     ...:     data = np.hstack((data, tmp))
     ...:     

In [304]: out = grouped_max(data_orig, column_groups)

In [305]: # Verify results between original and propsed ones
     ...: print np.allclose(out, data)
True

我想主要的问题是,hstack在每次迭代中都在构建一个新的矩阵——复制大量数据

我还没有使用过稀疏矩阵,所以可能有点离谱,但据我从文档中了解,可以将它们分割为普通的numpy数组。在这种情况下,最好预先分配数组,然后逐列添加结果:

rows = data_orig.shape[0]
cols = len(column_groups)
data = scipy.sparse.csr_matrix((rows, cols))
for cg in enumerate(column_groups):
    tmp = np.max(data_orig[:,cg[1]].toarray(), axis=1, keepdims=True)
    data[:, cg[0]] = tmp

我想主要的问题是,hstack在每次迭代中都在构建一个新的矩阵——复制大量数据

我还没有使用过稀疏矩阵,所以可能有点离谱,但据我从文档中了解,可以将它们分割为普通的numpy数组。在这种情况下,最好预先分配数组,然后逐列添加结果:

rows = data_orig.shape[0]
cols = len(column_groups)
data = scipy.sparse.csr_matrix((rows, cols))
for cg in enumerate(column_groups):
    tmp = np.max(data_orig[:,cg[1]].toarray(), axis=1, keepdims=True)
    data[:, cg[0]] = tmp
我可以将稀疏矩阵转换为稠密矩阵,得到相同的结果

In [431]: dataM=data_orig.todense()
In [432]: test1(dataM, cg)
我本可以使用data_orig.A,但是我必须在函数中省略.A

In [433]: timeit test1(data_orig, cg)
100 loops, best of 3: 2.52 ms per loop
In [434]: timeit test1(dataM, cg)
10000 loops, best of 3: 118 µs per loop
这些时间安排证实了我的猜测,即稀疏列索引相对较慢

使用Divakar的reduceat版本:

就我自己的Py3改编而言,差异只是风格上的:

def grouped_max(data_orig, column_groups):
    cols = np.hstack((column_groups))
    clens = np.hstack((0,np.cumsum([len(i) for i in cg])[:-1]))
    all_data = data_orig[:,cols].A
    return np.maximum.reduceat(all_data, clens,axis=1)
稀疏矩阵的速度显著加快。显然,一个较大的列选择比许多较小的列选择快。密集矩阵的加速效果并不显著

像这样的稀疏矩阵列选择实际上是通过矩阵乘法执行的。它为所需列构造另一个1的稀疏矩阵,并执行点积。行/列和也使用矩阵乘积执行

这是一个纯粹的稀疏版本:

def test2(data_orig, cg):
    data = []
    for g in cg:
        temp=data_orig[:,g].max(axis=1)
        data.append(temp)          # alt append(temp.A)
    return sparse.hstack(data)     #      np.hstack

In [465]: timeit test2(data_orig, cg).A
100 loops, best of 3: 3.21 ms per loop  (2.99 with np.hstack)
我可以将稀疏矩阵转换为稠密矩阵,得到相同的结果

In [431]: dataM=data_orig.todense()
In [432]: test1(dataM, cg)
我本可以使用data_orig.A,但是我必须在函数中省略.A

In [433]: timeit test1(data_orig, cg)
100 loops, best of 3: 2.52 ms per loop
In [434]: timeit test1(dataM, cg)
10000 loops, best of 3: 118 µs per loop
这些时间安排证实了我的猜测,即稀疏列索引相对较慢

使用Divakar的reduceat版本:

就我自己的Py3改编而言,差异只是风格上的:

def grouped_max(data_orig, column_groups):
    cols = np.hstack((column_groups))
    clens = np.hstack((0,np.cumsum([len(i) for i in cg])[:-1]))
    all_data = data_orig[:,cols].A
    return np.maximum.reduceat(all_data, clens,axis=1)
稀疏矩阵的速度显著加快。显然,一个较大的列选择比许多较小的列选择快。密集矩阵的加速效果并不显著

像这样的稀疏矩阵列选择实际上是通过矩阵乘法执行的。它为所需列构造另一个1的稀疏矩阵,并执行点积。行/列和也使用矩阵乘积执行

这是一个纯粹的稀疏版本:

def test2(data_orig, cg):
    data = []
    for g in cg:
        temp=data_orig[:,g].max(axis=1)
        data.append(temp)          # alt append(temp.A)
    return sparse.hstack(data)     #      np.hstack

In [465]: timeit test2(data_orig, cg).A
100 loops, best of 3: 3.21 ms per loop  (2.99 with np.hstack)

稀疏是指数组中只有很少的元素,还是使用scipy.sparse将其存储为稀疏结构?@JohanL它当前存储为scipy稀疏CSR矩阵我怀疑CSR列索引是一个缓慢的步骤。通过hstack收集tmp比list append慢。通过sparse,您的意思是数组中只有很少的元素,还是使用scipy.sparse将其存储为稀疏结构?@JohanL它当前存储为scipy sparse CSR矩阵我怀疑CSR列索引是一个缓慢的步骤。通过hstack收集tmp比列表附加慢。是的,意外地将枚举保留在中,只是将其删除。好吧,我刚才提出的解决方案需要它才能工作-我明白了,你建议先建造它。但是,重新分配一个列的时间不就和hstack一样长吗?我想我必须对它进行测试。对于稀疏阵列,可能需要的时间几乎相同。对于全尺寸阵列,这有很大的不同。顺便问一下,datasparse是您的初始解决方案吗?也可以在稀疏矩阵上使用np.hstack吗?你不需要做scip
y、 sparse.hstack?是的,意外地将枚举保留在中,只是将其删除。好吧,我刚才提出的解决方案需要它,如果它有效的话-我明白了,你建议先建造它。但是,重新分配一个列的时间不就和hstack一样长吗?我想我必须对它进行测试。对于稀疏阵列,可能需要的时间几乎相同。对于全尺寸阵列,这有很大的不同。顺便问一下,datasparse是您的初始解决方案吗?也可以在稀疏矩阵上使用np.hstack吗?你不需要做scipy.sparse.hstack吗?我在原来的帖子中犯了一个错误,包括了枚举并删除了它。这个想法就是抓取一组列cg是一组列号,将它们组合起来,然后将它们添加到新的数组中。有没有办法调整这个解决方案,使其不必转换为密集数组?我在原始帖子中犯了一个错误,将枚举包含在内,并将其删除。这个想法就是抓取一组列cg是一组列号,将它们组合起来,然后将它们添加到新的数组中。是否有任何方法可以调整此解决方案,使其不必转换为密集阵列?Is.a比.toarray快?a是相同的,只是更可爱而已。比如.T,那么我已经在我的帖子中介绍了我的矢量化解决方案的Py3版本。我看不出另一个Py3版本有什么意义,它用一个循环理解来替代clens是如何创建的,这不会对计时产生任何大的影响,正如你所说。a只是另一种放置。toarray的方式。当我第一次复制你的函数时,我没有注意到Py3的调整。不同之处在于风格。是。A比。toarray?快。A是一样的,只是更可爱。比如.T,那么我已经在我的帖子中介绍了我的矢量化解决方案的Py3版本。我看不出另一个Py3版本有什么意义,它用一个循环理解来替代clens是如何创建的,这不会对计时产生任何大的影响,正如你所说。a只是另一种放置。toarray的方式。当我第一次复制你的函数时,我没有注意到Py3的调整。这些差异只是风格上的差异。