Python 优化邻接矩阵计算

Python 优化邻接矩阵计算,python,optimization,adjacency-matrix,Python,Optimization,Adjacency Matrix,X是一个包含100000等大小(500个元素)位向量的文本文件(即每行是500个元素的向量)。我正在使用下面的代码生成一个邻接矩阵(100000 X 100000),但它没有经过优化,而且非常耗时。我该如何改进这一点 import numpy as np import scipy.spatial.distance readFrom = "vector.txt" fout = open("adjacencymatrix.txt","a") X = np.genfromtxt(readF

X是一个包含
100000
等大小(500个元素)位向量的文本文件(即每行是500个元素的向量)。我正在使用下面的代码生成一个邻接矩阵(100000 X 100000),但它没有经过优化,而且非常耗时。我该如何改进这一点

import numpy as np
import scipy.spatial.distance


 readFrom = "vector.txt"
 fout = open("adjacencymatrix.txt","a")

 X = np.genfromtxt(readFrom, dtype=None) 

 for outer in range(0,100000):
    for inner in range(0,100000):
        dis = scipy.spatial.distance.euclidean(X[outer],X[inner])
        tmp += str(dis)+" "
    tmp += "\n"        
    fout.write(tmp)
 fout.close()
谢谢。

(如果您使用的是Python2.x,请使用
xrange
而不是
range

要进行计算,您可以使用:

diff_matrix = numpy.subtract.outer(X, X)
result = numpy.sqrt(numpy.abs(diff_matrix))
# output the result.

请注意,要存储一个100000×100000的
double
矩阵,您需要74.5GB的内存,对于文本输出的文件大小,可能需要加倍的内存。你真的需要整个矩阵吗?(您也可以将计算并行化,但这需要的不仅仅是numpy。)

对代码进行一些小优化(我假设您使用的是Python 2.x):

我不建议在编写之前预先计算整个矩阵——尽管这样做可以让我们利用问题的复杂性,只迭代一半的元素,但会消耗大量内存。我坚持你所拥有的——每一行都是计算出来的


这里真正的问题是输入数据庞大,距离计算将执行100000 x 100000=10000'000000次,再多的微优化也不会改变这一点。你确定要计算整个矩阵吗?

我有一个预感,距离矩阵可能是在不使用显式python循环的情况下,通过使用矩阵运算来计算的

带转置的
X
的外积似乎很有希望,因为它执行每对向量的内积,并将结果保留在生成的100.000 X 100.000矩阵的每个单元格中,而内积与欧氏距离(或其平方)密切相关

所以我想这是一个调整的问题,得到两个向量之间的欧几里德距离,而不是内积。我的直觉告诉我,复数在这里可能有用


也许一些更聪明的人可以给我们带来一些启发。

编辑:在更好地理解问题后,完全重写。考虑到数据的大小等因素,这个问题很棘手。到目前为止,我在加速方面取得了最好的成绩:

import time
import numpy as np
from scipy import spatial
import multiprocessing as mp

pool = mp.Pool(4)

test_data = np.random.random(100000*500).reshape([100000,500])

outfile = open('/tmp/test.out','w')

def split(data,size):
    for i in xrange(0, len(data), size):
        yield data[i:i+size]

def distance(vecs):
    return spatial.distance.cdist(vecs,test_data)

chunks = list(split(test_data,100))
for chunk in chunks:
    t0 = time.time()
    distances = spatial.distance.cdist(chunk,test_data)
    outfile.write(' '.join([str(x) for x in distances]))
    print 'estimated: %.2f secs'%((time.time()-t0)*len(chunks))

所以我试着平衡数据集每个块的大小和内存开销。这使我估计要完成的时间减少到6600秒,或大约110分钟。您可以看到,我也开始考虑是否可以使用多处理池进行并行化。我的策略是异步处理每个块并将它们保存到不同的文本文件中,然后向下连接文件,但我必须继续工作。

矩阵是对称的,所以实际上只需要计算一半的元素。非常感谢您的回答。它工作得非常好。我正在尝试多处理部分,但我对此完全陌生…让我们看看它是如何进行的。。。再次感谢:)python的多处理池在工作时非常棒,但在如何实现序列化函数以传递给池线程方面,我经常遇到限制。例如,传递给池的函数需要声明为全局函数。。。讨厌。使用默认的多处理池可能是一条死胡同。。。此外,我还建议,如果您追求并行化,您可以在连接之前将结果单独写回磁盘,或者使用memmapped数组,numpy具有非常好的memmap支持。
import time
import numpy as np
from scipy import spatial
import multiprocessing as mp

pool = mp.Pool(4)

test_data = np.random.random(100000*500).reshape([100000,500])

outfile = open('/tmp/test.out','w')

def split(data,size):
    for i in xrange(0, len(data), size):
        yield data[i:i+size]

def distance(vecs):
    return spatial.distance.cdist(vecs,test_data)

chunks = list(split(test_data,100))
for chunk in chunks:
    t0 = time.time()
    distances = spatial.distance.cdist(chunk,test_data)
    outfile.write(' '.join([str(x) for x in distances]))
    print 'estimated: %.2f secs'%((time.time()-t0)*len(chunks))