Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 查找具有相似文本的文章的算法_String_Algorithm_Text_Language Agnostic_Similarity - Fatal编程技术网

String 查找具有相似文本的文章的算法

String 查找具有相似文本的文章的算法,string,algorithm,text,language-agnostic,similarity,String,Algorithm,Text,Language Agnostic,Similarity,我在数据库中有很多文章(有标题、文本),我正在寻找一种算法来查找X篇最相似的文章,就像Stack Overflow在你提问时的“相关问题” 我试着用谷歌搜索这篇文章,但只找到了关于其他“相似文本”问题的页面,比如将每篇文章与所有其他文章进行比较,并将相似性存储在某个地方。在我刚刚输入的文本上,这是“实时”的 如何进行?您可以使用SQL Server全文索引进行智能比较,我相信使用ajax调用也是如此,它执行查询以返回类似的问题 你在使用什么技术?这里的教程听起来可能正是你所需要的。这是很容易遵循

我在数据库中有很多文章(有标题、文本),我正在寻找一种算法来查找X篇最相似的文章,就像Stack Overflow在你提问时的“相关问题”

我试着用谷歌搜索这篇文章,但只找到了关于其他“相似文本”问题的页面,比如将每篇文章与所有其他文章进行比较,并将相似性存储在某个地方。在我刚刚输入的文本上,这是“实时”的


如何进行?

您可以使用SQL Server全文索引进行智能比较,我相信使用ajax调用也是如此,它执行查询以返回类似的问题

你在使用什么技术?

这里的教程听起来可能正是你所需要的。这是很容易遵循和工作得很好


他的算法既奖励普通的子字符串,也奖励这些子字符串的普通顺序,因此应该很好地挑选出类似的标题。

我建议使用一个完全用Java编写的高性能、全功能文本搜索引擎库为您的文章编制索引。这项技术几乎适用于任何需要全文搜索的应用程序,尤其是跨平台的应用程序。编制索引后,您可以很容易地找到相关文章。

仅在标题上进行比较,而不在问题正文上进行比较,因此仅在较短的字符串上进行比较

你可以在文章标题和关键词上使用他们的算法(不知道它是什么样子)。
如果您有更多的cpu时间需要消耗,也可以在文章摘要上使用。

支持Lucene对全文的建议,但请注意java不是必需的。另请参阅,以获取指向其他项目的链接,包括。

也许您正在寻找的是一些有用的东西。我对这一点只有粗略的了解,但释义是一个概念,用来确定文本中的两段是否真的意味着同一件事——尽管可能使用完全不同的词


不幸的是,我不知道有什么工具可以让你做到这一点(尽管我很有兴趣找到一个)

如果你想寻找伤害相似的单词,你可以转换为soundex和soundex单词来匹配。。。为我工作

这取决于你对相似者的定义

该算法是(拉丁语)词典建议的标准算法,可以处理整个文本。如果两篇文章的单词(字母)顺序基本相同,那么它们就是相似的。因此,以下两篇书评将相当相似:

1) “这是一本好书”

2) “这些不是好书”

(要删除、插入、删除或更改以将(2)转换为(1)的字母数称为“编辑距离”。)

要实现这一点,您需要以编程方式访问每个评论。这可能不像听起来那么昂贵,如果成本太高,您可以作为后台任务进行比较,并将最相似的n个存储在数据库字段中

另一种方法是了解一些(拉丁)语言的结构。如果去掉短词(非大写或引号),并为常用或唯一的词(或前缀)指定权重,则可以进行贝叶斯比较。以下两个书评可能是相似的,并且被发现是相似的:

3) “法国大革命是空谈战争和平空谈法国。”->法国/法国(2)大革命(1)战争(1)和平

4) “这本书简直是法国烹饪的一场革命。”->法国(1)革命(1)

要实现这一点,您需要在创建/更新评论时识别评论中的“关键字”,并在查询的where子句中使用这些关键字(如果数据库支持,最好是“全文”搜索),并可能对结果集进行后处理,以对找到的候选项进行评分


书籍也有分类——以法国为背景的惊悚片是否与法国历史研究相似,等等?标题和文本之外的元数据可能有助于保持结果的相关性。

使用的一种常见算法是。 这是一种神经网络,可以自动对文章进行分类。然后,您可以简单地找到当前文章在地图中的位置,并且它附近的所有文章都是相关的。该算法的重要部分是如何实现。有几种处理文本的方法。你可以散列你的文档/标题,你可以计算单词数,并将其用作n维向量,等等。希望这能有所帮助,尽管我可能已经为你打开了一个潘多拉盒子,告诉你AI的无尽旅程。

不太可能是候选项,因为它取决于拼写/词序,考虑到您实际感兴趣搜索的文档的大小和数量,计算成本比Will让您相信的要高得多


像Lucene这样的东西是最好的选择。为所有文档编制索引,然后当希望查找与给定文档类似的文档时,将给定文档转换为查询,并搜索索引。Lucene将在内部使用和,以使整个过程花费的时间与可能匹配的文档数量成比例,而不是集合中的文档总数。

我尝试了一些方法,但没有一种效果很好。可能会得到这样一个相对满意的结果: 首先:为所有文本的每个段落获取一个Google SimHash代码,并将其存储在数据库中。 第二:SimHash代码的索引。 第三:如上所述处理要比较的文本,得到一个SimHash码,并通过SimHash索引搜索所有文本,该索引以5-10的汉明距离分开。然后将相似性与术语向量进行比较。
这可能适用于大数据。

比较摘要之间相似性的最简单、最快速的方法可能是利用集合概念。首先将抽象文本转换成一组单词。然后检查每套有多少
class Statistics {
  std::unordered_map<std::string, int64_t> _counts;
  int64_t _totWords;

  void process(std::string& token);
public:
  explicit Statistics(const std::string& text);

  double Dist(const Statistics& fellow) const;

  bool IsEmpty() const { return _totWords == 0; }
};

namespace {
  const std::string gPunctStr = ".,;:!?";
  const std::unordered_set<char> gPunctSet(gPunctStr.begin(), gPunctStr.end());
}

Statistics::Statistics(const std::string& text) {
  std::string lastToken;
  for (size_t i = 0; i < text.size(); i++) {
    int ch = static_cast<uint8_t>(text[i]);
    if (!isspace(ch)) {
      lastToken.push_back(tolower(ch));
      continue;
    }
    process(lastToken);
  }
  process(lastToken);
}

void Statistics::process(std::string& token) {
  do {
    if (token.size() == 0) {
      break;
    }
    if (gPunctSet.find(token.back()) != gPunctSet.end()) {
      token.pop_back();
    }
  } while (false);
  if (token.size() != 0) {
    auto it = _counts.find(token);
    if (it == _counts.end()) {
      _counts.emplace(token, 1);
    }
    else {
      it->second++;
    }
    _totWords++;
    token.clear();
  }
}

double Statistics::Dist(const Statistics& fellow) const {
  double sum = 0;
  for (const auto& wordInfo : _counts) {
    const std::string wordText = wordInfo.first;
    const double freq = double(wordInfo.second) / _totWords;
    auto it = fellow._counts.find(wordText);
    double fellowFreq;
    if (it == fellow._counts.end()) {
      fellowFreq = 0;
    }
    else {
      fellowFreq = double(it->second) / fellow._totWords;
    }
    const double d = freq - fellowFreq;
    sum += d * d;
  }
  return std::sqrt(sum);
}