2
data = np.random.rand(rows,cols)
vec= np.random.rand(1,cols)
d = ((data-vec)**2).sum(axis=1)  # compute distances
ndx = d.argsort()

比我能拿的第一个 k

ndx[:k]

但如果有

d1 = ((data1-vec)**2).sum(axis=1)  # compute distances
    ndx1 = d1.argsort()
d2 = ((data2-vec)**2).sum(axis=1)  # compute distances
    ndx2 = d2.argsort()

我需要连接 ndx1+ndx2 的值+索引并按值排序(从 2k 个向量中取 k 个最近的向量)。

怎么做到呢?我需要使用字典吗?

更新:

我不能堆叠 data1 和 data2 因为它不适合 RAM。我使用 numpy.memmap 按块读取我的大数组(1 个块 = 数据)。

例如,这有效,但仅适用于小尺寸。所以我需要按块迭代地处理数据。

import numpy as np
import time


rows = 10000
cols = 1000
batches = 5
k= 10
fp = np.memmap('C:/memmap_test', dtype='float32', mode='w+', shape=(rows*batches,cols))

vec= np.random.rand(1,cols)

t0= time.time()
d = ((fp-vec)**2).sum(axis=1)  # compute distances
ndx = d.argsort()
print (time.time()-t0)

print ndx[:k]

这种方法不起作用:

ValueError:对象不对齐

t0= time.time()
d = np.empty((rows*batches,))
for i in range(batches):
    d[i*rows:(i+1)*rows] = (np.einsum('ij,ij->i', fp[i*rows:(i+1)*rows], fp[i*rows:(i+1)*rows]) + np.dot(vec, vec) -
             2 * np.dot(fp[i*rows:(i+1)*rows], vec))
print (time.time()-t0)

这似乎有效

t0= time.time()
d = np.empty((rows*batches,))
for i in range(batches):
    d[i*rows:(i+1)*rows] = ((fp[i*rows:(i+1)*rows]-vec)**2).sum(axis=1)
ndx = d.argsort()
print (time.time()-t0)
print ndx[:k]
4

3 回答 3

3

希望能正确理解这个问题。

如果data1并且data2至少有一个维度相等,您可以垂直水平 d1堆叠,d2然后argsort堆叠阵列。

这样,将对两个数组的所有元素进行排序,但您不知道哪个是原始数组。

我不认为 dict 是要走的路,如果不是因为 dict 没有排序。

编辑:内存问题。

我想到的一种方法或多或少是这样的:

#read the first batch and compute distances
# save the first k indeces and values
masterindex = d.argsort()[:k]
mastervalue = d[masterindex]

for i in (all the other batches):
    #read the following batch and compute distances
    tempindex = d.argsort()[:k]
    tempvalue = d[tempindex]
    # get the tempindex as absolute position with respect to the whole file
    tempindex += n_rows_already_read # by previous batches

    #stack the indeces and value arrays
    masterindex = np.concatenate([masterindex,tempindex])
    mastervalue = np.concatenate([mastervalue,tempvalue])
    # argsort the concatenated values, then save the new sorted 
    # values and indeces
    indx = mastervalue.argsort()[:k]
    masterindex = masterindex[indx]
    mastervalue = mastervalue[indx]

我没有测试代码,所以可能有问题,但我希望它足够清楚,并且可以满足您的需求

于 2013-10-23T09:32:10.890 回答
2

如果您有内存问题,您可以执行以下操作:

data1 = np.random.rand(rows1, cols)
data2 = np.random.rand(rows2, cols)
vec = np.random.rand(cols)

d = np.empty((rows1 + rows2,))
d[:rows1] = (np.einsum('ij,ij->i', data1, data1) + np.dot(vec, vec) -
             2 * np.dot(data1, vec))
d[rows1:] = (np.einsum('ij,ij->i', data2, data2) + np.dot(vec, vec) -
             2 * np.dot(data2, vec))

您需要事先知道的大小data1和分配数组,但您不需要将向量同时保存在内存中,您可以在加载之前删除, 的第一部分。我在上面计算距离的方式比你的方法更节省内存,尤其是在很大的情况下。data2ddata1ddata2(a-b)**2 = a*a + b*b -2*a*bcols

您现在可以对数组进行排序d,并将其映射到两个数组的行,例如@Developer 的答案。

于 2013-10-23T11:30:39.300 回答
2

这是我们的解决方案:

import numpy as np

rows1,rows2,cols = 1000,600,7
data1 = np.random.rand(rows1,cols)
data2 = np.random.rand(rows2,cols)

data = np.vstack((data1,data2))     #stacking data

vec = np.random.rand(1,cols)
d = ((data-vec)**2).sum(axis=1)     #compute distances
ndx = d.argsort()

k = 30

sdx = ndx[:k]                       #selected k indices of nearest points

f = (sdx<rows1)                     #masking

idx1 = sdx[f]                       #indices from data1
idx2 = sdx[~f]-rows1                #indices from data2
于 2013-10-23T10:20:12.230 回答