javascript - 如何衡量句子之间的字符串相似度?

标签 javascript text-mining levenshtein-distance

我有以下任务。

给定一个字符串列表,如下所示:

        var strings = [
            'Steve jobs created the iPod when he was at Apple',
            'I really like the new Macbook by Apple',
            'Jony Ive was concerned being fired by Steve Jobs after his return to Apple',
            'The new Macbook has just one USB-C type connector',
            'I like bananas',
            'The brezels I can buy in my local store are much better than the ones in the supermarket',
            'the',
            'foo',
            'Steve'
        ];

我现在想将每个字符串相互比较,对于每次比较,我想找出它们在 0-1(或 0%-100%)范围内的相似程度。

所以,我用谷歌搜索了一下,发现了这个:Similarity String Comparison in Java

所以,我按照那里的说明,将方法 similarity(String s1, String s2) 移植到 JavaScript:

        function similarity(s1, s2) {
            var longer = s1;
            var shorter = s2;
            if (s1.length < s2.length) {
                longer = s2;
                shorter = s1;
            }
            var longerLength = longer.length;
            if (longerLength == 0) {
                return 1.0;
            }
            return (longerLength - longer.LevenshteinDistance(shorter)) / longerLength;
        }

作为比较算法,我使用了 Levenshtein:

        String.prototype.LevenshteinDistance = function (s2) {
            var array = new Array(this.length + 1);
            for (var i = 0; i < this.length + 1; i++)
                array[i] = new Array(s2.length + 1);

            for (var i = 0; i < this.length + 1; i++)
                array[i][0] = i;
            for (var j = 0; j < s2.length + 1; j++)
                array[0][j] = j;

            for (var i = 1; i < this.length + 1; i++) {
                for (var j = 1; j < s2.length + 1; j++) {
                    if (this[i - 1] == s2[j - 1]) array[i][j] = array[i - 1][j - 1];
                    else {
                        array[i][j] = Math.min(array[i][j - 1] + 1, array[i - 1][j] + 1);
                        array[i][j] = Math.min(array[i][j], array[i - 1][j - 1] + 1);
                    }
                }
            }
            return array[this.length][s2.length];
        };

因此,作为测试,我运行了一个完整的循环,将每个字符串相互比较并像这样打印结果:

            for (var i in strings){
                var s = strings[i];
                print('Checking string: "' + s + '"');
                for (var j in strings){
                    print('-----');
                    var s2 = strings[j];
                    print('vs "' + s2 + '"');
                    var sim = similarity(s, s2);
                    print('Similarity: ' + Math.round(sim*100) + '%');
                }
                print('<br>////// NEXT /////////////////////////////////////////////////<br>');
            }

好的,现在这是结果:https://jsfiddle.net/wxksfa4w/

现在,查看结果,我得到了一些很好的匹配,但也有一些完全不相关,例如:

“史蒂夫·乔布斯在苹果公司时创造了 iPod”和“我喜欢香蕉”匹配 13%?

“史蒂夫·乔布斯在苹果公司时创造了 iPod”,虽然第一句中使用了完全相同的单词“史蒂夫”,但“史蒂夫”的匹配率仅为 10%?

如何获得更好的语义结果? Levenshtein 是错误的算法吗?据我了解,Levenshtein 计算了如何将句子 1 更改为句子 2 的步骤数。因此,即使存在语义相似性,字符串的长度似乎也会对结果产生重大影响。

有什么建议吗?

最佳答案

您可能应该将两个句子中出现的单词作为高度相似性的暗示。一种简单的方法是将每个句子用作单词袋并使用 tf-idf

关于javascript - 如何衡量句子之间的字符串相似度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29324937/

相关文章:

postgresql - 数据库中的集群文本文档

algorithm - 莱文斯坦距离 : Inferring the edit operations from the matrix

language-agnostic - 对字符串匹配的质量进行评级

text - 如何计算字母频率相似度?

javascript - 如何在js中使用require函数

javascript - history.back() 不能像 Chrome 中预期的那样与 HTML5 history API 一起使用

javascript - 如何将图像放入数组中

javascript - HTML5 API Javascript 文件系统

r - 如何可视化 tm 的 findAssocs() 结果

python - 从连续字符串中提取单词