【问题标题】:Client-side predictive search relevance calculation with multiple parameters多参数的客户端预测搜索相关性计算
【发布时间】:2011-06-17 05:51:56
【问题描述】:

我正在编写一个预测搜索,为了满足服务器性能要求(所有内容都已缓存),它必须在客户端浏览器上运行。这些项目是电视节目和电影,并与标题、演员和导演姓名相匹配。执行搜索后,它会返回一个匹配项列表,每个结果有两个值:

  1. 匹配词数 (n):用户可以输入 4 个词,但其中只有 2 个词匹配一个项目。越多越好。

  2. Levenshtein Edit Distance 加法 (ld)。用户可以键入 3 个单词,但其中 2 个单词与索引单词有拼写错误或其他小的差异。我使用编辑距离来查找最近的索引词。所有 Levenshtein 距离的相加作为邻近指标返回。越少越好。

要求

  1. 客户端。没有 Sphinx、Lucene 或任何其他服务器端解决方案。

  2. 速度超过准确性。该算法在每次击键时运行,我们不想让用户感到厌烦。保持big O不要那么big

  3. 非递归。每个项目相关性的计算不应依赖于其他项目的计算。我不想打败谷歌,只提供小集合中最好的结果。

  4. 有界形式 0 到 1、0 到 100 或类似的形式。不是必需的,但能够显示“相关百分比”是加分项。

  5. 想法优于实现。我正在寻找比特定实现更好的算法/公式。

我的方法

根据指数衰减(如放射性半衰期分解),我提出了这个公式。

地点:

  • T 是用户提供的字数。
  • n 是匹配词的数量。
  • ld 是这个匹配词的 Levenshtein 距离加法。

在伪代码中。

function lambda(n, ld) {
    lambda = (n/T) * e^(-ld * 1/n);
    return lambda;
}

一点解释:

  • -ld * 1/n 是相关性度量核心。如果ld 较低且n 较大,则它接近于零(-0 边),表明此结果更相关。

  • n/T 是一个准确率。匹配词与所有词。通过考虑总用户输入来优化先前的相关性。

对于负幂,指数函数将结果限制在 0 和 1 之间。

最后是问题

我想要的不是改进搜索算法,基于this response 进行额外的编辑距离计算,而是通过为每个元素分配一个相关性值来改进返回元素的相关性排序。如果需要除nld 之外的任何参数并且易于计算,则可以使用。在我的解决方案中,我添加了T,即用户提供的字数。

【问题讨论】:

  • ld 是否介于 0 和 1 之间?
  • @ffriend 不,不是。是介于 0 和 T*MAX_LD 之间的整数值,其中 MAX_LD 是设置的阈值。 'color' 和 'colour' 之间的 LD 为 1,'house' 和 'noses' 之间的 LD 为 3。
  • 我明白了,你不使用词干,所以'house'和'houses'是两个不同的词,使用Levenshtein距离来解决这个问题?
  • 对,由于客户端限制,没有词干

标签: javascript algorithm search client-side relevance


【解决方案1】:

总的来说,我认为您必须简化您的公式。事实上,像tf-idf 这样的大多数基本相关性公式都非常简单,只使用产生式或部分参数,可能具有“加强”或“削弱”功能。例如,tf-idf 只是词频乘以对数逆文档频率“弱化”。首先我会快速分析一下你的公式,然后提出一些建议。

分析

让我们重写你的公式:

首先,请注意,n/T 未标准化:可能有更多结果 (n) 然后搜索字词 (T)。考虑这样的例子:用户输入查询“John Malkovich”,您的数据库中有电影Being John Malkovich。用户输入了 2 个词,即 T = 2,但电影在电影名称和演员表中都有这些词,所以 n = 2 * 2 = 4。鉴于此,最终相关性将大于 1。缺乏规范化本身并不是问题,但在实践中它可能会在未来导致许多错误。

现在让我们看一下公式的第二部分 - 1 / e^(ld/n)。让我们将ld/n 表示为x。在这种情况下,公式的第二部分将如下所示:

所以对于x 的高值,它会大大削弱最终的相关性。虽然我不明白为什么它必须是指数的,但它仍然是有道理的。但是x 不是自变量,它本身是两个变量的函数:x = x(ld, n)。此外,ld 也是一个函数:ld = ld(MAX_LD, T),所以x 取决于 3 个不同的独立变量/参数:x = x(MAX_LD, T, n)。在这种情况下,很难预测所有可能情况下x 的行为(以及最终相关性)。

建议

1.简化 x()。 如果您希望公式的第二部分仅跟踪 Levenshtein 距离,则让它仅取决于此距离,而不是所有 3 个自变量。例如,您的公式可能如下所示:

甚至:

其中distance 是实际的Levenshtein 编辑距离,而不是TMAX_LD 的函数。

2。使用词干。 我知道,我知道,你说过,你不能使用服务器端编程。但是你确定它不能在客户端执行吗?词干比看起来要容易得多。大多数词干只是截断后缀和结尾,如“-s”、“-ing”、“-ment”等。这并不理想,但我相信它会产生更好的结果,然后是 Levenshtein 距离。这里唯一的强限制是:词干必须同时用于索引和搜索

有关更精确的词干算法,请参阅 Lucene sources 的 PorterStemmer 类。

3。使用逆记录频率。回忆查询“John Malkovich”的示例。可能有很多电影都带有“约翰”一词,但只有几部电影带有“马尔科维奇”。很自然地假设,第二个词在搜索结果中的权重必须大于第一个。 tf-idf 在其 idf(逆文档频率)部分中涉及到这一事实。您可以通过计算逆记录频率来做同样的事情:

irf = number-of-all-found-records / number-of-records-with-current-term

并添加到您的相关性公式第三部分:

当然,请记住:只有在真实数据上进行测试之前,没有公式是好的

【讨论】:

  • 关于分析 n/T 是标准化的,因为匹配索引是唯一的,不考虑标题中的重复单词(指环王:回归国王),也没有两者,标题和演员(成为约翰马尔科维奇)。起初,指数函数是将输出绑定在 0 和 1 之间的简单方法(我忘记了 1/(1+x) 选项)。在那之后,我意识到指数衰减是有意义的,正如你所说,与相关性的概念
  • 关于提案 从我的角度来看,我更喜欢没有词干提取而不是糟糕的词干提取。我会尝试一些x() 的简化和一些带有真实语料库的 tf-idf 想法,但它真的很小,而且所有单词都很少见。也许对于弱化通常的嫌疑人('the''and''of'...)很有用。我会及时通知你。
  • 在对真实数据进行了一些测试后,几乎所有的修改都显示出相似的结果(语料库规模小)。最后我决定添加tf-idf 作为第三部分,并用1/(1+x) 替换de 1/e^x 以获得最平滑的衰减。另一方面,由于增加了相关性,我留在ld/n。非常感谢。
猜你喜欢
  • 2011-11-26
  • 2011-03-24
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
相关资源
最近更新 更多