在集合中查找最相似的匹配

时间:2012-11-01 22:44:45

标签: database algorithm search

我有一个动物数据库,每个都有许多属性,范围从0到1--这些属性是大小,速度,毛羽等等。给定一组输入属性,以及每种属性的权重,我需要在动物组中找到“最接近”的匹配。有没有一种算法可以比O(n)时间更好地完成这项工作?

我特别想要做的是在游戏中通过遗传算法为“动物”找到合适的纹理,将它们与已经存在的动物相匹配。 “最接近”是指动物的属性差异的加权和最小。数据库和权重在应用程序启动时已知,因此可以投入大量时间来准备数据。

我已经根据用户偏好找到了字符串匹配和产品匹配的算法,但要么我找不到我正在寻找的东西,要么我不理解如何将这些概念重新应用到我的困境中。也许图论的世界有什么东西可以帮助我?

非常感谢任何帮助!

4 个答案:

答案 0 :(得分:2)

您可以将项目视为高维空间中的点,并将它们全部插入到BSP树中,例如k-d tree。要使用属性权重,只需将它们乘以相应的坐标:(w1*x, w2*y, ...)

准备:(来自wikipedia,python代码)

def kdtree(point_list, depth=0):

    if not point_list:
        return None

    # Select axis based on depth so that axis cycles through all valid values
    k = len(point_list[0]) # assumes all points have the same dimension
    axis = depth % k

    # Sort point list and choose median as pivot element
    point_list.sort(key=lambda point: point[axis])
    median = len(point_list) // 2 # choose median

    # Create node and construct subtrees
    node = Node()
    node.location = point_list[median]
    node.left_child = kdtree(point_list[:median], depth + 1)
    node.right_child = kdtree(point_list[median + 1:], depth + 1)
    return node

搜索(来自gist,基于wikipedia algorithm

# method of the Node-class

def closest_point(self, target, point, best=None):
    if target is None:
        return best

    if best is None:
        best = target

    # consider the current node
    if distance(target, point) < distance(best, point):
        best = target

    # search the near branch
    best = self.child_near(point).closest_point(point, best)

    # search the away branch - maybe
    if self.distance_axis(point) < distance(best, point):
        best = self.child_away(point).closest_point(target, point, best)

    return best

了解详情:

答案 1 :(得分:1)

如果您可以花时间安排数据,则可以按分数对您的动物进行排序<(O(nlogn)时间,但只进行一次),然后对分数应用二分搜索以在O(logn)时间内找到最接近的匹配。

如果从SQL数据库中获取动物列表,则可以使用查询中的ASCDESC关键字获取排序列表。

答案 2 :(得分:1)

您可以将此框架设置为最大权重匹配问题,但找到最小匹配的复杂性的下限将远远大于O(n)。更像是O(n^3)

如果我必须尝试解决此问题,我会考虑根据权重成对匹配相同类型的属性(即,在输入'毛茸茸'属性和数据中的每个其他'毛茸茸'属性之间创建加权边缘设置,使用输入权重的某个因子和查询“毛茸茸”值与匹配的“毛茸茸”值之间的差异的倒数。此时,您可以将所有边缘合并到特定动物,并将边缘权重的总和作为匹配分数。

例如:

Monkey:  
A1: 0.5 
B1: 0.25
C1: 1.0

Giraffe:
A2: 0.2
C2: 0.9
D2: 0.1

Input query:
Ai: 0.4 with weight 0.8
Di: 0.2 with weight 0.25

所以我们创建了以下图表:

Ai --> A1 with weight 0.8 * 1/abs(0.5-0.4) (i.e., 8.0)
Ai --> A2 with weight 0.8 * 1/abs(0.2-0.4) (i.e., 4.0)

Di --> D2 with weight 0.25 * 1/abs(0.1-0.2) (i.e., 2.5)

然后我们用同一目标动物中的属性折叠所有边缘,以获得我们的候选人:

Monkey: 8.0
Giraffe: 4.0 + 2.5

它不漂亮,而且比O(n)更糟糕(可能是m的某个因素,其中m是您要匹配的属性数量),但它可能是开始优化更好解决方案的起点。

答案 3 :(得分:0)

如何找到线性反转的数量?所以你有2个动物的线性数据集,你想通过对它们进行排序来找出它们有多么相似或不同。复杂性与合并排序相同。对于'n'个动物,你将计算nC2反转。