【问题标题】:how to speed up the computation?如何加快计算速度?
【发布时间】:2017-02-09 15:06:44
【问题描述】:

我需要计算 100 万*100 万次计算来填充稀疏矩阵。但是当我使用循环逐行填充矩阵时,我发现只需 100*100 次计算就需要 6 分钟。所以任务无法解决。有什么方法可以加快进程吗?

import numpy as np
from scipy.sparse import lil_matrix
import pandas as pd  
tp = pd.read_csv('F:\\SogouDownload\\train.csv', iterator=True, chunksize=1000)  
data = pd.concat(tp, ignore_index=True) 
matrix=lil_matrix((1862220,1862220))
for i in range(1,1862220):
    for j in range(1,1862220):
        matrix[i-1,j-1]=np.sum(data[data['source_node']==i].destination_node.isin(data[data['source_node']==j].destination_node))

【问题讨论】:

  • 向我们展示您的代码将是一个好的开始。并且 10^12 的计算无条件地太高了。
  • 你的矩阵有多稀疏?通常一种使用字典的方法,其中键是矩阵坐标工作。
  • 这是 Python 2 还是 3?如果是 2,您应该使用 xrange 而不是 range。
  • 好吧,你可以从计算外循环中的表达式data[data['source_node']==i开始。
  • 这看起来像是稀疏矩阵乘法的工作,不是单独计算 3.5 万亿个大部分为零的矩阵条目。

标签: python numpy scipy sparse-matrix


【解决方案1】:

虽然不是构建稀疏矩阵的最快方法,但这也不是很慢,至少不是lil 分配步骤:

In [204]: N=100
In [205]: M=sparse.lil_matrix((N,N))
In [206]: for i in range(N):
     ...:     for j in range(N):
     ...:         M[i,j]=(i==j)
In [207]: M
Out[207]: 
<100x100 sparse matrix of type '<class 'numpy.float64'>'
    with 100 stored elements in LInked List format>

它只将非零值保存到M。我几乎没有看到循环期间的延迟。

所以我的猜测是大部分时间都花在了panadas索引表达式上:

np.sum(data[data['source_node']==i].destination_node.isin(data[data['source_node']==j].destination_node))

将数据(通常是文本数据)转换为 coocurance 计数稀疏矩阵经常出现。它们用于学习代码、模式搜索等。经常使用scikit-learn。还有tensorflow。


对于 N=1000

In [212]: %%timeit
     ...: M=sparse.lil_matrix((N,N))
     ...: for i in range(N):
     ...:       for j in range(N):
     ...:           M[i,j]=(i==j)
     ...: 
1 loop, best of 3: 7.31 s per loop

将这些值迭代地分配给密集数组会更快,即使我们在最后包含到稀疏的转换。

In [213]: %%timeit
     ...: M=np.zeros((N,N))
     ...: for i in range(N):
     ...:       for j in range(N):
     ...:           M[i,j]=(i==j)
     ...: 
1 loop, best of 3: 353 ms per loop

In [214]: %%timeit
     ...: M=np.zeros((N,N))
     ...: for i in range(N):
     ...:       for j in range(N):
     ...:           M[i,j]=(i==j)
     ...: M = sparse.lil_matrix(M)
     ...: 
1 loop, best of 3: 353 ms per loop

但是对于非常大的情况,创建中间密集数组可能会遇到内存问题。

【讨论】:

  • 感谢您的帮助。实际上我无法创建如此大的密集数组。实用的方法似乎可以减少尺寸。我同意这是索引表达式减慢了过程。
【解决方案2】:

这里使用的技术是稀疏矩阵乘法。但是对于该技术,您首先需要一个二进制矩阵将源节点映射到目标节点(节点标签将是非零条目的索引)。

from scipy.sparse import csr_matrix

I = data['source_node'] - 1
J = data['destination_node'] - 1
values = np.ones(len(data), int)
shape = (np.max(I) + 1, np.max(J) + 1)
mapping = csr_matrix((values, (I, J)), shape)

该技术本身只是该矩阵与其转置的矩阵乘法(另请参阅this question)。

cooccurrence = mapping.dot(mapping.T)

唯一的潜在问题是生成的矩阵可能不是稀疏的并且会消耗你所有的内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多