-
19-09-2019 - |
题
我有大量的对象,我需要找出它们之间的相似之处。
确切地说:给定两个对象,我可以将它们的差异计算为数字,a 公制 - 值越高意味着相似度越低,0 意味着对象具有相同的内容。计算该数字的成本与较小对象的大小成正比(每个对象都有给定的大小)。
我需要能够在给定一个对象的情况下快速找到与其相似的一组对象。
确切地说:我需要生成一个数据结构,对于某些相异值 d,将任何对象 o 映射到与 o 不相似的对象集,这样列出集合中的对象不会比它们在数组中花费更多的时间或链表(也许它们实际上是)。通常,该集合将比对象总数小得多,因此执行此计算确实值得。如果数据结构假设一个固定的 d 就足够了,但如果它适用于任意 d,那就更好了。
您以前见过这个问题或类似的问题吗?什么是好的解决方案?
确切地说:一个简单的解决方案涉及计算所有对象对之间的差异,但这很慢 - O(n2) 其中 n 是对象的数量。有没有复杂度较低的通用解决方案?
解决方案
不知道度量的更多的细节,这是很难说。我没有为消除为O(n ^ 2)方面的任何想法,但有可能会降低所涉及的一些常量的一种方式。例如,如果你有一个欧几里德度量d(P,Q)= SQRT((P_1-Q_1)^ 2 + ... +(P_N-Q_N)^ 2),即可方的距离d,并比较它的部分(P_I-Q_I)^ 2,当你超过d ^ 2停止的总和。
这是否会真正节省您的时间取决于如何昂贵的比较是只计算被加数,以及如何你可以指望,以避免这样做,许多被加数计算(显然,小d是,越好)。
其他提示
我需要产生数据结构 任何对象映射O到组 对象没有更多不同的邻比 d,对于一些相异值d。
这可能是最快的,只是放弃相似度计算时的小计变得比d
大。例如,如果你的相似之处是基于余弦或豪斯多夫距离这很容易做到。
PS:如果这不能这样做,你的问题可能与第k近邻问题(或者更精确的最近邻问题阈值附近)。你应该寻找发现近距离的成员,而不计算所有的距离(可能使用三角不等式的东西)算法。维基百科应该帮助你去探索合适的算法。的
如果您的相似度是传递的,你没有来计算的相似性将所有对对象的自为对象,B,C:
similarity(a,c) = similarity(a,b) op similarity(b,c)
其中op
是一个二进制运算符例如乘法或加法。
我认为解决方案取决于有关问题性质的更多细节。
您是否需要多次查找同一对象的相似对象,还是只查找一次?如果多次,那么创建一个数据结构,在其中为每对计算一次差异,然后将对象连接到相似的对象,以便您可以快速检索列表而无需重新计算,这可能是非常有用的性能增强。
计算的本质是什么?在一种极端情况下,如果差异的性质是,例如,两个人之间的身高差异,那么维护按身高排序的列表可以让您非常快速地找到相似的对象。我假设真正的问题比这更复杂,但是按照这个逻辑,如果差异是几个线性量的总和,您可以创建一个多维数组,然后从概念上想象一组类似的对象在 n 维球体内(即以参考对象为中心的圆、球体、超球体等),然后再次直接找到它们。实际上,我想到如果半径计算太复杂或花费太多运行时间,一个好的近似方法是创建一个 n 维立方体(即围绕参考对象的正方形、立方体、超正方体等),检索位于该立方体内的所有对象作为“候选者”,然后对候选者进行实际计算。
例如,假设“差异”是三个属性(例如 a1、a2 和 a3)的差异的绝对值之和。您可以创建一个 3 维数组,并将数组每个节点的值设置为具有这些值的对象(如果有)。那么如果你想找到与对象 o 差异小于 d 的所有对象,你可以这样写:
for (x1=o.a1-d;x1<o.a1+d;++x1)
{
for (x2=o.a2-d;x1<o.a2+d;++x2)
{
for (x3=o.a3-d;x1<o.a3+d;++x3)
{
if (array[x1][x2][x3]!=null
&& (abs(x1-o.a1)+abs(x2-o.a2)+abs(x3-o.a3)<=d)
{
... found a match ...
}
}
}
}
我怀疑差异规则比这更复杂,但是很好,只需增加算法的复杂性以匹配规则的复杂性即可。重点是使用数组来限制您必须检查的对象集。
- 再次讨论计算的性质:如果构成差异的一个元素或某个小子集往往比其他元素更重要,那么创建一个数据结构,允许您在范围内快速比较。如果在范围内,则进行全面比较。如果没有,那你连看都不看。
时它不可能使用一ķ d-树?
这可能是必要的(如果可能的话)来归一化的尺寸。之后,你只需要填充树,并使用“最近的N个邻居”进行搜索,并试图找到一些范围内的任何物体。
对象的实施例: 图像,文档。当然,与这些对象的原始表示工作大多是没有用的。通常一个将预先处理原始形式并把它变成一些归一化形式(文档,说一个向量,其中每个条目表示的次某个词出现的数目/百分比,对于图像可以发现的视觉特征的表示在图像)。
如果d是固定的,并且一个N ^ 2预先计算是可行的,可以只使用一个图表示使用链表的每个对象,例如。 您可以使用近似最近邻算法对精确度的代价更有效的解决方案。
我们可以假设相似性是传递的,即。 diff(a,c) == diff(a,b) + diff(b,c)
?如果是这样,您可以尝试以下操作:
- 对对象集合进行排序。如果对象相似度度量没有合适的绝对值,您可以任意选择一个对象作为“零”,并根据与该对象的相似度对所有其他对象进行排序。
- 寻找相似的对象
s
到o
, , 寻找o
在排序列表中,向左和向右搜索,直到 diff 大于s
.
这样做的优点是排序可以完成一次,并且后续的集合构建与集合中的成员数量成正比。
听起来像BK-树。 这里是一个小例如的。基本上,你创建的树和检查应使用哪个分支类似对象的搜索和没有,所以你防止O(n2)