在nodejs中对数组中的相似字符串进行分组

Group Similar Strings from an array in nodejs

我正在开发一个 FAQ 系统,其中有大量的问答。我想将相似的问题分组。我一直在使用 npm set-clustering。

该包在令牌匹配的基础上提供了良好的匹配。 问题是我需要提供要创建的组数。

我希望分组应该是自动的,算法应该自己决定要创建的组数(无监督学习)!

如果有任何其他软件包或平台可以帮助我,请告诉我。

问题如下:

告诉我你们产品的定价?

我可以和你的经纪人谈谈吗?

你好朋友

嗨早安

我要花多少钱?

当前结果:(当我给'3'作为组数时)

(嗨,嗨,朋友)

(请告诉我您产品的定价?产品的成本是多少?)

(我可以和你的经纪人谈谈吗?,嗨,早上好)

我想将其分组为:(不提供“3”作为输入)

(嗨,嗨朋友,嗨早安)

(请告诉我您产品的定价?产品的成本是多少?)

(我可以和你的经纪人谈谈吗?)

现有代码:

                    var cluster = require('set-clustering');

                    for (let row of resp) {
                        articles.push({
                            title: row.que,
                            tags: row.tags
                        });
                    }

                    function similarity(x, y) {
                        var score = 0;
                        x.tags.forEach(function(tx) {
                            y.tags.forEach(function(ty) {
                            if (tx == ty)
                                score += 1;
                            });
                        });
                        return score;
                    }

                    // I do not want to provide number of groups over here, I want grouping to be done autonomous 
                    var groups = c.evenGroups(3);

                    var titles = groups.map(function(group) {
                        return group.map(function(article) {
                            return article.title;
                        });
                    });

                    console.log(titles);

参考https://www.npmjs.com/package/set-clustering

let ss = require('sentence-similarity')
var thesaurus = require("thesaurus");

let similarity = ss.sentenceSimilarity;
let similarityScore = ss.similarityScore;
let min = (a,b) => {
    if (a< b) return a;
    else return b;
}

let similar = (sentence1, sentence2) => {
    let s1 = sentence1.split(' ');
    let s2 = sentence2.split(' ');
    let numbers = [];
    for (let e of s1) {
    let syn= thesaurus.find(e);
    for (let i=0; i<syn, i<5; i++) {
        e=syn[i];
        numbers.push(similarity(s1, s2, winkOpts)['score']/min(s1.length,s2.length));
    } 
    }
    return Math.max.apply(null, numbers) >= 0.375;
}

let winkOpts = { f: similarityScore.winklerMetaphone, options : {threshold: 0} }
const filter = (source, maximum = 5) => {
  let _source, matches, x, y;
  _source = source.slice();
  matches = [];
  for (x = _source.length - 1; x >= 0; x--) {
    let output = _source.splice(x, 1);
    for (y = _source.length - 1; y >= 0; y--) {
      if (similar(output[0],_source[y])) {
    output.push(_source[y]);
    _source.splice(y, 1);
    x--;
      }
    }
    matches.push(output);
  }
  // matches.splice(0, 1);
  return matches;
}
let source = ['Your', 'array', 'here'] 
let output = filter(source);

同义词库有助于查找相似词。 https://www.npmjs.com/package/thesaurus

句子相似度有助于匹配。 https://www.npmjs.com/package/sentence-similarity

用我的数据集给出了很好的结果。