将索引和数据放入dict

时间:2013-10-23 09:08:03

标签: python numpy nearest-neighbor knn

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个最近的向量)。

怎么做?我需要使用dict吗?

更新

我无法堆叠data1和data2,因为它不适合RAM。我使用块的numpy.memmap读取我的大数组(1 chunk = data)。

例如,这可行,但仅适用于小尺寸。所以我需要通过块迭代地处理数据。

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:object is alighn

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]

3 个答案:

答案 0 :(得分:3)

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

如果data1data2至少有一个维度相等,您可以堆叠verticallyhorizontally d1d2然后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]

我还没有对代码进行测试,因此可能会出错,但我希望它足够清晰并且可以满足您的需求

答案 1 :(得分: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

答案 2 :(得分: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))

您需要预先知道data1data2的大小,以分配d数组,但您不需要同时将向量保留在内存中,您可以删除在加载data1之前填充d的第一部分后data2 {。}}。我计算距离的方式,如(a-b)**2 = a*a + b*b -2*a*b,比你的方法更有效,特别是cols很大。

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