如果我正确理解了这个问题,您可以考虑使用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]]
要找到最接近每个观察值的 7 值行code_book
,可以使用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
code_book
请注意,与简单的穷举搜索相比,您的( N
)中的点数必须大于数据的维度(例如N >> 2**7
),以便 KDTree 更快。
使用vq.vq
orKDTree.query
可能会也可能不会比穷举搜索更快,具体取决于数据的大小(code_book
和observations
)。要找出哪个更快,请务必对这些与使用timeit的详尽搜索进行基准测试。