资讯专栏INFORMATION COLUMN

文章相似度计算

Jeffrrey / 2806人阅读

摘要:文章内容相似度计算几种方式及优缺点内置方法是内置的字符串相似度对比函数,是使用方式最便捷的一种但是因为它的时间复杂度是,处理时间会随着内容长度增加若比较字以上的文章,或者比较文章的量级比较大不建议使用只是单篇文章对单篇文章可以使用。

文章内容相似度计算几种方式及优缺点 PHP 内置方法 similar_text

similar_text 是PHP内置的字符串相似度对比函数,是使用方式最便捷的一种,但是因为它的时间复杂度是 O(N**3),处理时间会随着内容长度增加,若比较5000字以上的文章,或者比较文章的量级比较大不建议使用,只是单篇文章对单篇文章可以使用。

通过分词进行余弦相似度对比

解决方案是首先进行文章分词可以用结巴或者迅搜分词服务进行文章分词,然后将需要对比的文章分词结果存入redis,在有新文章进行对比的时候从redis将所有文章的分词结果从内存中取出来然后进行相似度对比,逐词进行相似度计算。相似度计算的准确性很高,但是对比的文章量非常大的时候,处理时间还是会很长,5000文章的相似度计算需要近30S

主要计算代码:

</>复制代码

  1. Class TextSimilarity
  2. {
  3. /**
  4. * [排除的词语]
  5. *
  6. * @var array
  7. */
  8. private $_excludeArr = array("的", "了", "和", "呢", "啊", "哦", "恩", "嗯", "吧");
  9. /**
  10. * [词语分布数组]
  11. *
  12. * @var array
  13. */
  14. private $_words = array();
  15. /**
  16. * [分词后的数组一]
  17. *
  18. * @var array
  19. */
  20. private $_segList1 = array();
  21. /**
  22. * [分词后的数组二]
  23. *
  24. * @var array
  25. */
  26. private $_segList2 = array();
  27. private static $test1 = array();
  28. private static $test2 = array();
  29. /**
  30. * [分词两段文字]
  31. *
  32. * @param [type] $text1 [description]
  33. * @param [type] $text2 [description]
  34. */
  35. public function __construct($text1, $text2)
  36. {
  37. $this->_segList1 = is_array( $text1 ) ? $text1 : $this->segment( $text1 );
  38. $this->_segList2 = is_array( $text2 ) ? $text2 : $this->segment( $text2 );
  39. }
  40. /**
  41. * [外部调用]
  42. *
  43. * @return [type] [description]
  44. */
  45. public function run()
  46. {
  47. $this->analyse();
  48. $rate = $this->handle();
  49. return $rate ? $rate : "errors";
  50. }
  51. /**
  52. * [分析两段文字]
  53. */
  54. private function analyse()
  55. {
  56. //t1
  57. foreach ($this->_segList1 as $v) {
  58. if (!in_array($v, $this->_excludeArr)) {
  59. if (!array_key_exists($v, $this->_words)) {
  60. $this->_words[$v] = array(1, 0);
  61. } else {
  62. $this->_words[$v][0] += 1;
  63. }
  64. }
  65. }
  66. //t2
  67. foreach ($this->_segList2 as $v) {
  68. if (!in_array($v, $this->_excludeArr)) {
  69. if (!array_key_exists($v, $this->_words)) {
  70. $this->_words[$v] = array(0, 1);
  71. } else {
  72. $this->_words[$v][1] += 1;
  73. }
  74. }
  75. }
  76. }
  77. /**
  78. * [处理相似度]
  79. *
  80. * @return [type] [description]
  81. */
  82. private function handle()
  83. {
  84. $sum = $sumT1 = $sumT2 = 0;
  85. foreach ($this->_words as $word) {
  86. $sum += $word[0] * $word[1];
  87. $sumT1 += pow($word[0], 2);
  88. $sumT2 += pow($word[1], 2);
  89. }
  90. $rate = $sum / (sqrt($sumT1 * $sumT2));
  91. return $rate;
  92. }
  93. /**
  94. * [分词 【http://www.xunsearch.com/scws/docs.php#pscws23】]
  95. *
  96. * @param [type] $text [description]
  97. *
  98. * @return [type] [description]
  99. *
  100. * @description 分词只是一个简单的例子,你可以使用任意的分词服务
  101. */
  102. private function segment( $text )
  103. {
  104. $outText = array();
  105. $xs = new XS("demo"); // 必须先创建一个 xs 实例,否则会抛出异常
  106. $tokenizer = new XSTokenizerScws; // 直接创建实例
  107. $tokenizer->setIgnore();
  108. //处理
  109. $outText = $tokenizer->setMulti(1)->getResult($text);
  110. $outText = array_column( $outText, "word");
  111. $res = $xs->getScwsServer();
  112. $res->close();
  113. return $outText;
  114. }
  115. }
SimHash

SimHash的原理是将很长的一段文字降维成一个0和1组成的字符串,然后计算两个01字符串的相似度,从而算出两篇文章的相似程度。也是将文章先分词,计算存量文章的相似度存入redis或者mysql,需要的时候取出来对比,对比速度20000篇文章的计算时间基本上在2s以内,但是当文章字数非常小并且重复词非常多的时候会出现文章不相同但是相似度非常高的问题。
主要计算代码:

</>复制代码

  1. class SimHash
  2. {
  3. protected static $length = 256;
  4. protected static $search = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
  5. protected static $replace = array("0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111");
  6. /**
  7. * [排除的词语]
  8. *
  9. * @var array
  10. */
  11. private static $_excludeArr = array("的", "了", "和", "呢", "啊", "哦", "恩", "嗯", "吧","你","我"," ");
  12. public static function get(array &$set)
  13. {
  14. $boxes = array_fill(0, self::$length, 0);
  15. if (is_int(key($set)))
  16. $dict = array_count_values($set);
  17. else
  18. $dict = &$set;
  19. foreach ($dict as $element => $weight) {
  20. if ( in_array($element, self::$_excludeArr )){
  21. continue;
  22. }
  23. $hash = hash("sha256", $element);
  24. $hash = str_replace(self::$search, self::$replace, $hash);
  25. $hash = substr($hash, 0, self::$length);
  26. $hash = str_pad($hash, self::$length, "0", STR_PAD_LEFT);
  27. for ( $i=0; $i < self::$length; $i++ ) {
  28. $boxes[$i] += ($hash[$i] == "1") ? $weight : -$weight;
  29. }
  30. }
  31. $s = "";
  32. foreach ($boxes as $box) {
  33. if ($box > 0)
  34. $s .= "1";
  35. else
  36. $s .= "0";
  37. }
  38. return $s;
  39. }
  40. public static function hd($h1, $h2)
  41. {
  42. $dist = 0;
  43. for ($i=0;$i

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29724.html

相关文章

  • 基于Tags的简单内容推荐的实现

    摘要:原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容。 原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容。 算法选择 如何能做到相似内容的推荐呢,碍于小网站还跑在虚拟主机上(对的,连一个自...

    CrazyCodes 评论0 收藏0
  • 基于Tags的简单内容推荐的实现

    摘要:原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容。 原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容。 算法选择 如何能做到相似内容的推荐呢,碍于小网站还跑在虚拟主机上(对的,连一个自...

    邱勇 评论0 收藏0
  • 推荐系统02--协同过滤

    摘要:如果做推荐系统不知道基于物品的协同过滤,那等同于做程序员不懂得冒泡排序。基于物品的八卦基于物品的协同过滤算法诞生于年,是由亚马逊首先提出的,并在年由其发明者发表了相应的论文。 不管你有没有剁过手,你对看了这个商品的还看了这样的推荐形式一定不陌生。无论是猫还是狗,或者是其他电商网站,这样的推荐产品可以说是推荐系统的标配了。 类似的还有,如点评标记类网站的喜欢了这部电影的还喜欢了,社交媒...

    jaysun 评论0 收藏0
  • 基于用户的协同过滤算法

    摘要:最近写搜索引擎文章写多了,来一篇之前写的老文,给那些对推荐算法感兴趣想入门的人吧,最近也在做推荐广告系统,又翻出来看了看。 最近写搜索引擎文章写多了,来一篇之前写的老文,给那些对推荐算法感兴趣想入门的人吧,最近也在做推荐广告系统,又翻出来看了看。 什么是推荐算法 推荐算法最早在1992年就提出来了,但是火起来实际上是最近这些年的事情,因为互联网的爆发,有了更大的数据量可以供我们使用,推...

    goji 评论0 收藏0

发表评论

0条评论

Jeffrrey

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<