我有一个大的,对称的,2D距离数组。我想得到最接近的N对观测值。
该数组被存储为numpy压缩数组,并且具有1亿个观测值的数量级。
这里有一个例子,在一个较小的数组上获得100个最近的距离(~ 500 k个观察值),但它比我想要的要慢得多。
import numpy as np
import random
import sklearn.metrics.pairwise
import scipy.spatial.distance
N = 100
r = np.array([random.randrange(1, 1000) for _ in range(0, 1000)])
c = r[:, None]
dists = scipy.spatial.distance.pdist(c, 'cityblock')
# these are the indices of the closest N observations
closest = dists.argsort()[:N]
# but it's really slow to get out the pairs of observations
def condensed_to_square_index(n, c):
# converts an index in a condensed array to the
# pair of observations it represents
# modified from here: http://stackoverflow.com/questions/5323818/condensed-matrix-function-to-find-pairs
ti = np.triu_indices(n, 1)
return ti[0][c]+ 1, ti[1][c]+ 1
r = []
n = np.ceil(np.sqrt(2* len(dists)))
for i in closest:
pair = condensed_to_square_index(n, i)
r.append(pair)
字符串
在我看来,用标准的numpy或scipy函数一定有更快的方法来做到这一点,但我被难倒了。
如果很多对是等距的,那是可以的,在这种情况下,我不关心它们的顺序。
4条答案
按热度按时间tyg4sfes1#
您不需要在每次调用
condensed_to_square_index
时计算ti
。这里有一个基本的修改,只计算一次:字符串
您还可以矢量化
r
的创建:型
或者是
型
fcipmucu2#
如果使用numpy 1.8和
np.partition
,可以显著加快最小值的定位速度:字符串
一旦你有了最小的索引,你就不需要一个循环来提取索引,只需一次:
型
k75qkfdt3#
最佳解决方案可能无法生成所有距离。
提案:
1.创建一个最大大小为100的堆(如果堆变大,请将其减小)。
1.使用“最近对”算法查找最近对。
1.将对添加到堆(优先级队列)。
1.从那对中选一个。将其99个最近的邻居添加到堆中。
1.从列表中删除所选点。
1.找到下一个最接近的配对,然后重复。添加的相邻点的数量为100减去运行“最接近对”算法的次数。
qrjkbowd4#
您可以使用pandas DataFrame。首先,您将相似性矩阵(例如使用sklearn中的pairwise_distances())声明为DataFrame,添加源数据中的列名和索引名。然后按名称选择任何列(这是您感兴趣的列),然后使用pandas.DataFrame.sort_values(),然后选择top5或top10。就是这样