对稀疏矩阵行求和的最快方法

2024-03-16

我有一个大的 csr_matrix(1M*1K),我想添加行并获得一个具有相同列数但行数减少的新 csr_matrix。其实我的问题和这个完全一样对 scipy.sparse.csr_matrix 中的行求和 https://stackoverflow.com/questions/29629821/sum-over-rows-in-scipy-sparse-csr-matrix。唯一的问题是我发现接受的解决方案对于我的目的来说很慢。让我陈述一下我所拥有的

map_fn = np.random.randint(0, 10000, 1000000)

map_fn这里告诉我如何将输入行(1M)映射到输出行(10K)。例如,第 i 个输入行被添加到map_fn[i]输出行。我尝试了上面问题中提到的两种方法, 即形成稀疏矩阵并使用稀疏和。虽然稀疏矩阵方法看起来比稀疏求和方法好得多,但我发现它对于我的目的来说很慢。这是比较两种方法的代码:

import scipy.sparse
import numpy as np 
import time

print "Setting up input"
s=10000
n=1000000
d=1000
density=1.0/500

X=scipy.sparse.rand(n,d,density=density,format="csr")
map_fn=np.random.randint(0, s, n)

# Approach 1
start_time=time.time()
col = scipy.arange(n)
val = np.ones(n)
S = scipy.sparse.csr_matrix( (val, (map_fn, col)), shape = (s,n))
print "Approach 1 Creation time : ",time.time()-start_time
SX = S.dot(X)
print "Approach 1 Total time : ",time.time()-start_time

#Approach 2
start_time=time.time()
SX = np.zeros((s,X.shape[1]))
for i in range(SX.shape[0]):
    SX[i,:] = X[np.where(map_fn==i)[0],:].sum(axis=0)

print "Approach 2 Total time : ",time.time()-start_time

给出以下数字:

Approach 1 Creation time :  0.187678098679
Approach 1 Total time :  0.286989927292
Approach 2 Total time :  10.208632946

所以我的问题是有更好的方法吗?我发现形成稀疏矩阵是一种矫枉过正的行为,因为它花费了一半以上的时间。还有更好的选择吗?非常感谢任何建议。谢谢


起始方法

适应sparse solution from this post https://stackoverflow.com/a/46457039/3293881 -

def sparse_matrix_mult_sparseX_mod1(X, rows):   
    nrows = rows.max()+1
    ncols = X.shape[1]
    nelem = nrows * ncols

    a,b = X.nonzero()
    ids = rows[a] + b*nrows
    sums = np.bincount(ids, X[a,b].A1, minlength=nelem)
    out = sums.reshape(ncols,-1).T
    return out

标杆管理

原始方法#1 -

def app1(X, map_fn):
    col = scipy.arange(n)
    val = np.ones(n)
    S = scipy.sparse.csr_matrix( (val, (map_fn, col)), shape = (s,n))
    SX = S.dot(X)
    return SX

时间安排和验证 -

In [209]: # Inputs setup
     ...: s=10000
     ...: n=1000000
     ...: d=1000
     ...: density=1.0/500
     ...: 
     ...: X=scipy.sparse.rand(n,d,density=density,format="csr")
     ...: map_fn=np.random.randint(0, s, n)
     ...: 

In [210]: out1 = app1(X, map_fn)
     ...: out2 = sparse_matrix_mult_sparseX_mod1(X, map_fn)
     ...: print np.allclose(out1.toarray(), out2)
     ...: 
True

In [211]: %timeit app1(X, map_fn)
1 loop, best of 3: 517 ms per loop

In [212]: %timeit sparse_matrix_mult_sparseX_mod1(X, map_fn)
10 loops, best of 3: 147 ms per loop

公平地说,我们应该对最终的密集数组版本进行计时app1 -

In [214]: %timeit app1(X, map_fn).toarray()
1 loop, best of 3: 584 ms per loop

移植到 Numba

我们可以将分箱计数步骤转换为 numba,这可能有利于更密集的输入矩阵。这样做的方法之一是 -

from numba import njit

@njit
def bincount_mod2(out, rows, r, C, V):
    N = len(V)
    for i in range(N):
        out[rows[r[i]], C[i]] += V[i]
    return out

def sparse_matrix_mult_sparseX_mod2(X, rows):
    nrows = rows.max()+1
    ncols = X.shape[1]
    r,C = X.nonzero()

    V = X[r,C].A1
    out = np.zeros((nrows, ncols))
    return bincount_mod2(out, rows, r, C, V)

时间安排 -

In [373]: # Inputs setup
     ...: s=10000
     ...: n=1000000
     ...: d=1000
     ...: density=1.0/100 # Denser now!
     ...: 
     ...: X=scipy.sparse.rand(n,d,density=density,format="csr")
     ...: map_fn=np.random.randint(0, s, n)
     ...: 

In [374]: %timeit app1(X, map_fn)
1 loop, best of 3: 787 ms per loop

In [375]: %timeit sparse_matrix_mult_sparseX_mod1(X, map_fn)
1 loop, best of 3: 906 ms per loop

In [376]: %timeit sparse_matrix_mult_sparseX_mod2(X, map_fn)
1 loop, best of 3: 705 ms per loop

随着密集输出app1 -

In [379]: %timeit app1(X, map_fn).toarray()
1 loop, best of 3: 910 ms per loop
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对稀疏矩阵行求和的最快方法 的相关文章

随机推荐

  • 如何将垂直线的表格图像分成三张图像?

    我想将垂直线上的表格图像分成三个图像 如下所示 是否可以 每列的宽度是可变的 可悲的是 如您所见 左侧垂直线是从标题向下绘制的 输入图像 input png 输出图像 output1 png 输出图像 output2 png 输出图像 ou
  • 如何学习阿格达

    我正在努力学习agda 但是 我遇到了一个问题 我在 agda wiki 上找到的所有教程对我来说都太复杂了 并且涵盖了编程的不同方面 在并行阅读了 3 个关于 agda 的教程后 我能够编写简单的证明 但我仍然没有足够的知识来使用它来实现
  • 调用随机函数 Javascript,但不能调用同一函数两次

    我使用一个随机选择另一个有效函数的函数 但有时它会连续运行相同的函数两次甚至更频繁 有办法防止这种情况吗 我当前的代码 window setInterval function var arr func1 func2 func3 rand M
  • Node.js - 异步模块加载

    是否可以异步加载 Node js 模块 这是标准代码 var foo require foo js waiting for I O foo bar 但我想写这样的东西 require foo js function foo foo bar
  • 如何以编程方式获取 Google Cloud 定价详细信息?

    谁能告诉我如何以编程方式从 Google Cloud 网站获取 Google Cloud 定价详细信息 例如 Google Compute Engine Google Cloud Storage Google Cloud SQL 等的定价
  • Android 中的多屏幕 xml

    我正在开发2 2版本的android xml是根据这个版本设计的 模拟器规格 2 2版 内置 HVGA 内存 1024 现在我需要将此应用程序转换为4 0版本的三星galaxy s3 但屏幕非常拉伸 看起来不太好 如果有任何帮助 请提前致谢
  • Cloudinary - 上传预设必须位于未签名上传的白名单中

    我想将图像上传到 Cloudinary 使用 cordova 相机插件直接从 Ionic 中的相机拍摄 我收到代码 1 的错误 并显示消息 上传预设必须位于未签名上传的白名单中 如何解决这个错误 请帮忙 我编辑的js代码是 scope ca
  • 打印词性以及单词的同义词

    我有以下代码 用于从输入文本文件中获取单词并使用 WordNet 打印该单词的同义词 定义和例句 它根据词性将同义词与同义词集分开 即动词的同义词和形容词的同义词分别打印 例如 flabbergasted 一词的同义词有 1 flabber
  • Junit - Spring boot:测试时@Value始终为null

    有一个 Value注释的常量 在运行测试时没有被初始化 当构造函数中需要它时 它会抛出NullPointerException 要测试的示例类 class TestClass Value test value1 private String
  • laravel 中的 Auth::login($user) 无法登录用户

    我在用拉拉维尔 5 4 and 验证 登录 用户 显示类型错误 传递给 Illuminate Auth SessionGuard login 的参数 1 必须 实现接口 Illuminate Contracts Auth Authentic
  • 无需访问服务器或 phpMyADMIN 即可导出 SQL 表的简单方法

    我需要一种方法来轻松地将 MySQL 表中的数据从远程服务器导出然后导入到我的家庭服务器 我无法直接访问服务器 也没有安装 phpMyAdmin 等实用程序 不过 我确实有能力将 PHP 脚本放在服务器上 我如何获取数据 我问这个问题纯粹是
  • 什么是具有强度 1 边缘矩阵的设备互连 StreamExecutor

    我有四个 NVIDIA GTX 1080 显卡 当我初始化会话时 我看到以下控制台输出 Adding visible gpu devices 0 1 2 3 Device interconnect StreamExecutor with s
  • 函数的侦听器无法启动。 Azure.Storage.Blobs:服务请求失败

    我有一个包含普通函数和计时器函数的 Azure Function 项目 计时器功能突然停止工作并出现错误 The listener for function Function1 was unable to start Azure Stora
  • Eclipse 中有重新运行最近启动的程序的快捷方式吗?

    我使用 Eclipse 最常做的事情之一就是重新运行上一个程序 我这样做是为了运行 gt 运行历史记录 gt 最上面的项目 有没有快捷键可以做到这一点 I know of CTRL F11 but this does not work fo
  • Laravel 5.2 中应用于 API 路由的 Web 中间件

    我有以下路线 Route group prefix gt api v1 middleware gt api function Route resource authenticate AuthenticateController only g
  • 为什么DFS和BFS的时间复杂度都是O( V + E )

    BFS的基本算法 set start vertex to visited load it into queue while queue not empty for each edge incident to vertex if its no
  • 替换 Haskell 中的单个列表元素?

    我有一个元素列表 我希望更新它们 由此 Off Off Off Off 对此 Off Off On Off 由于我对 Haskell 有点陌生 所以我一直在使用 x xs y使用以下函数提取和更新各个组件 replace y z repla
  • 如何将具有多个“from”的 LINQ 表达式从查询语法转换为方法语法? [复制]

    这个问题在这里已经有答案了 我正在使用实体框架 我如何在 Lambda C 中编写以下 Linq 代码 var users from u in context Users ToList from e in u Events where e
  • FFMpeg 连续实时图像到视频编码

    我正在尝试使用 FFMpeg 获取图像文件流并将其转换为视频 现在 我已经成功地做到了这一点 但前提是我已经捕获了所有我想要的图像 我想做的是将图像保存到磁盘 实时录像机 时将其转换为视频 目前 当我在仍在抓取帧的情况下调用 FFMpeg
  • 对稀疏矩阵行求和的最快方法

    我有一个大的 csr matrix 1M 1K 我想添加行并获得一个具有相同列数但行数减少的新 csr matrix 其实我的问题和这个完全一样对 scipy sparse csr matrix 中的行求和 https stackoverf