【发布时间】:2011-10-19 09:45:31
【问题描述】:
我使用邻接矩阵来表示朋友网络,可以直观地解释为
Mary 0 1 1 1
Joe 1 0 1 1
Bob 1 1 0 1
Susan 1 1 1 0
Mary Joe Bob Susan
使用这个矩阵,我想编译一个所有可能的友谊三角形的列表,条件是用户 1 是用户 2 的朋友,用户 2 是用户 3 的朋友。对于我的列表,不需要用户 1是用户 3 的朋友。
(joe, mary, bob)
(joe, mary, susan)
(bob, mary, susan)
(bob, joe, susan)
我有一些代码可以很好地处理小三角形,但我需要它来扩展非常大的稀疏矩阵。
from numpy import *
from scipy import *
def buildTriangles(G):
# G is a sparse adjacency matrix
start = time.time()
ctr = 0
G = G + G.T # I do this to make sure it is symmetric
triples = []
for i in arange(G.shape[0] - 1): # for each row but the last one
J,J = G[i,:].nonzero() # J: primary friends of user i
# I do J,J because I do not care about the row values
J = J[ J < i ] # only computer the lower triangle to avoid repetition
for j in J:
K, buff = G[:,j].nonzero() # K: secondary friends of user i
K = K[ K > i ] # only compute below i to avoid repetition
for k in K:
ctr = ctr + 1
triples.append( (i,j,k) )
print("total number of triples: %d" % ctr)
print("run time is %.2f" % (time.time() - start())
return triples
我能够在大约 21 分钟内在 csr_matrix 上运行代码。该矩阵为 1032570 x 1032570,包含 88910 个存储元素。总共生成了 2178893 个三元组。
我需要能够对 1968654 x 1968654 稀疏矩阵和 9428596 个存储元素做类似的事情。
我对 python 非常陌生(不到一个月的经验),并且在线性代数方面不是最出色的,这就是为什么我的代码没有利用矩阵运算的原因。 任何人都可以提出任何改进建议或让我知道我的目标是否现实吗?
【问题讨论】:
-
我认为在一条语句 (
J,J=) 中两次分配相同的值在 Python 中没有任何保证的意义。从你的评论来看,我觉得这很令人困惑,你也是,所以你可能想摆脱它。 -
@larsmans 我很抱歉。 nonzero() 将矩阵的索引作为二维数组返回。或者我可以先完成
row, col = G[i,:].nonzero(),然后再完成J = col。我使用了J,J=方法,因为我担心内存使用情况并想吃掉行数组,因为它不需要。 -
别道歉,我不是故意的。这不是 Pythonic 的习惯用法,我认为 Guido 在 lib 中可以改变 Python 版本之间该构造的含义,因此您不能依赖它来工作。如果它真的很重要,最好使用
del一个变量,尽管在这种情况下J = G[i, :].nonzero()[1]也可以工作。 -
感谢您的建议。它确实清理了一些代码。你对维基百科文章所做的工作正是我想要做的。我将更多地研究解决问题的线性代数方法。
标签: python numpy data-mining scipy adjacency-matrix