有效合理的数字向量搜索索引?

时间:2013-06-17 13:01:55

标签: search math indexing numeric image-recognition

我有一个长数字表,其中7列是键,4列是要查找的值。

实际上我已经渲染了一个具有不同距离和透视角度的物体,并计算了它的轮廓的Hu矩。但这对问题来说并不重要,只是一个想象的样本。

所以,当我有7个值时,我需要扫描一个表,找到该7列中最接近的值并提取相应的4个值。

因此,需要考虑的任务方面如下:

1)数字有错误

2)功能域中的比例与功能值中的比例不同;即,与7维空间中的点的“距离”应该取决于4个值,它如何影响

3)搜索应该快速

所以问题如下:是不是有一些算法可以有效地解决这个问题,即在7列上执行一些索引,但这样做不像传统数据库那样,但考虑到上面的点。

2 个答案:

答案 0 :(得分:2)

如果我正确理解了问题,您可以考虑使用scipy.cluster.vq(矢量量化):

假设您的7个数字列看起来像这样(让我们调用数组code_book):

import scipy.cluster.vq as vq
import scipy.spatial as spatial
import numpy as np
np.random.seed(2013)
np.set_printoptions(precision=2)
code_book = np.random.random((3,7))
print(code_book)
# [[ 0.68  0.96  0.27  0.6   0.63  0.24  0.7 ]
#  [ 0.84  0.6   0.59  0.87  0.7   0.08  0.33]
#  [ 0.08  0.17  0.67  0.43  0.52  0.79  0.11]]

假设关联的4列值如下所示:

values = np.arange(12).reshape(3,4)
print(values)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

最后,假设我们对7列值有一些“观察”,如下所示:

observations = np.random.random((5,7))
print(observations)
# [[ 0.49  0.39  0.41  0.49  0.9   0.89  0.1 ]
#  [ 0.27  0.96  0.16  0.17  0.72  0.43  0.64]
#  [ 0.93  0.54  0.99  0.62  0.63  0.81  0.36]
#  [ 0.17  0.45  0.84  0.02  0.95  0.51  0.26]
#  [ 0.51  0.8   0.2   0.9   0.41  0.34  0.36]]

要找到最接近每个观察的code_book中的7值行,您可以使用vq.vq

index, dist = vq.vq(observations, code_book)
print(index)
# [2 0 1 2 0]

索引值是指code_book中的行。但是,如果values中的行的排序方式与code_book相同,我们可以使用values[index]“查找”相关值:

print(values[index])
# [[ 8  9 10 11]
#  [ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [ 0  1  2  3]]

以上假设您将所有观察结果排列在一个数组中。因此,要查找所有索引,您只需要拨打vq.vq一次。

但是,如果您一次获得一个观察结果,并且需要在进行下一次观察之前找到code_book中最近的行,那么每次调用vq.vq都是低效的。相反,生成一次KDTree ,然后在树中找到最近的邻居:

tree = spatial.KDTree(code_book)
for observation in observations:
    distances, indices = tree.query(observation)
    print(indices)
    # 2
    # 0
    # 1
    # 2
    # 0

请注意,与简单穷举搜索相比,KDTree的code_bookNmust be large compared to the dimension数据(例如N >> 2**7)的点数要快

使用vq.vqKDTree.query可能会或不会比穷举搜索更快,具体取决于您的数据大小(code_bookobservations)。要找出哪个更快,请务必使用timeit对这些进行基准测试与穷举搜索。

答案 1 :(得分:1)

我不知道我是否理解你的问题,但我会尝试给出答案。

表中每行K计算键与该行中键的距离:

((X1-K1)^ 2 +(X2-K2)^ 2 +(X3-K3)^ 2 +(X4-K4)^ 2 +(X5-K5)^ 2 +(X6- K6)^ 2 +(X7-K7)^ 2)^ 0.5

其中{X1,X2,X3,X4,X5,X6,X7}是键,{K1,K2,K3,K4,K5,K6,K7}是K行的关键

你可以使一个关键因素或多或少与其他关键因素相乘,同时计算距离,例如你可以用(X1-K1)^ 2 > 5 *(X1-K1)^ 2 使其更加流入。

并在变量中存储距离,在第二个变量中存储行号

对以下行执行相同操作,如果新距离低于您存储的距离,则替换距离和行号。

当您检查了表格中的所有行时,您使用的第二个变量将显示距离键最近的行

这里有一些伪代码:

int Row= 0
float Key[7] #suppose it is already filled with some values
float ClosestDistance= +infinity 
int ClosestRow= 0
while Row<NumberOfRows{
    NewDistance= Distance(Key,Table[Row][0:7])#suppose Distance is a function that outputs the distance and Table is the table you want to control Table[Row= NumberOfRows][Column= 7+4]
    if NewDistance<ClosestDistance{
        ClosestDistance= NewDistance
        ClosestRow= Row}
    increase row by 1}

ValueFound= Table[ClosestRow][7:11]#this should be the value you were looking for

我知道它并不快,但它是我能做的最好的,希望它有所帮助。

P.S。我知道,我没有考虑测量误差。