1

我一直在使用 [Simmetrics][1] Java 库成功地比较两个字符串,并取得了很好的成功。但似乎有两种方法,我需要将两者结合起来用于我的场景。

目前我正在使用 CosineSimilarity(我确实使用了一些简化器,但这里省略了以保持代码简单)

StringMetric metric = with(new CosineSimilarity<String>())
                .tokenize(Tokenizers.whitespace()).build();
 score = metric.compare(string1, string2);

这工作得很好,除非我有一个简单的拼写错误我会期望一个比我得到的更高的分数

例如比较mony honeymoney honey只返回0.5(分数从0.0到1.0,1.0是完美匹配),我本来期望更高。

使用 Levenshtein 它返回更好的0.9090909

但是我在阅读文档时注意到的一件事是,这是一个MultiSet指标,并且 whitespace() 实际上需要将输入分成几部分,而像Levenshtein这样的StringMetric则不需要

 StringMetric metric = with(new Levenshtein())
                .build();

这意味着 Levenshtein 没有特别考虑空格,这是一个问题,因为我想匹配单词并且基本上忽略空格或顺序。

因此,例如使用 CosineSimilarity 它在比较蜂蜜陷阱陷阱蜂蜜时返回 1.0,但 Levenshtein 返回 0.0,这对我没有好处。

我理想地想要的是词序不重要,然后如果单词中只有轻微的变化,例如money/mony,那么单个单词就可以很好地匹配

字符串可以是任何语言,但最常见的是英文,它们是歌曲标题,因此通常少于十个单词,通常大约 5 个单词长。

Simmetrics 是否提供另一种可以同时提供这两个部分的算法?

有诸如RefinedSoundex 之类的简化器可以应用于输入,但由于该语言可能不是英语,因此认为这不会很好。

你认为最好的算法是什么?

4

1 回答 1

0

Simmetrics 包含用于比较字符串、列表、集合和多重集合的指标。

两个单词之间的 Levenshtein 距离是单个字符编辑的最小数量。空格也是一个字符,因此空格的差异会导致相似性的差异。

余弦相似度是两个零向量之间的相似度(为方便起见,将其表示为多集)。因此,如果没有某种形式的处理余弦相似度,根本不适合比较字符串。

根据您拆分字符串的方式,您最终可能会比较完全不同的事物。如果您在空格上拆分字符串,您最终将通过它们在单词使用方面的相似性来比较文档。如果您在 n-gram 上拆分字符串,您将比较其字母对上的字符串,这往往可以很好地防止拼写错误。

对于您的特定用例,您可能希望研究对空格进行标记,然后在 q-gram 上进行标记。然后尝试 CosineSimilarity、Tanimoto、Dice、SimonWhite、Jaccard。

例如:

/**
 * Tokenizers can also be chained.
 * 
 * `chilperic ii son of childeric ii`
 * 
 * By splitting on whitespace is tokenized into:
 * 
 * `[chilperic, ii, son, of, childeric, ii]`
 * 
 * After using a q-gram with a q of 2:
 * 
 * `[ch,hi,il,il,lp,pe,er,ri,ic, ii, so,on, of, ch,hi,il,ld,de,er,ri,ic,
 * ii]`
 * 
 */
public static float example04() {

    String a = "A quirky thing it is. This is a sentence.";
    String b = "This sentence is similar; a quirky thing it is.";

    StringMetric metric = 
            with(new CosineSimilarity<String>())
            .tokenize(Tokenizers.whitespace())
            .tokenize(Tokenizers.qGram(3))
            .build();

    return metric.compare(a, b); // 0.8292
}

为了做出决定,您可以进行一些有代表性的查询,并通过其精确度和召回率来比较结果。然后,您可以就使用哪个指标做出正确的决定。

全面披露:我是 Simmetrics 项目的当前维护者。

于 2016-11-22T19:26:52.227 回答