Tags实现内容推荐的方法

74次阅读
没有评论

共计 4084 个字符,预计需要花费 11 分钟才能阅读完成。

自动写代码机器人,免费开通

丸趣 TV 小编给大家分享一下 Tags 实现内容推荐的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容。

算法选择

如何能做到相似内容的推荐呢,碍于小网站还跑在虚拟主机上(对的,连一个自己完整可控的服务器都没有),所以可以想的办法不多,条件限制在 只能用 PHP+MySql。所以我想到的办法就是通过 Tags 来匹配相似文章进行推荐。如果两篇文章的 TAGS 比较相似

比如:文章 A 的 TAGS 为:[A,B,C,D,E]
文章 B 的 TAGS 为:[A,D,E,F,G]
文章 C 的 TAGS 为:[C,H,I,J,K]

通过眼睛我们能很方便的发现,文章 B 和文章 A 更为相似,因为它们有三个关键字相同分别为:[A,D,E],哪如何用计算机来判断它们的相似度呢,这里我们用 jaccard 相似度的最基本应用来计算它们的相似度

jaccard 相似度

给定两个集合 A,B,Jaccard 系数定义为 A 与 B 交集的大小与 A 与 B 并集的大小的比值,定义如下:

文章 A 和文章 B 的交集为 [A,D,E], 大小为 3,并集为 [A,B,C,D,E,F,G], 大小为 7,3/7=0.4285…

而文章 A 和文章 C 交集为 [C], 大小为 1,并集为 [A,B,C,D,E,H,I,J,K], 大小为 9,1/9=0.11111…

这样就可以得出文章 A,B 比文章 A,C 更为相似,有了这个算法,计算机就可以来判断两篇文章的相似度了。

具体的推荐思想

给定一篇文章,获取该文章的关键字 TAGS, 然后通过以上算法去数据库比对所有文章的相似度,获取最相似的 N 篇文章进行推荐。

实现过程第一 TAGS 的获取

文章的 TAGS 是通过 TF-IDF 算法,提取文章中的高频词,选取 N 个作为 TAGS,对于中文的文章来说还涉及到一个中文分词的问题,因为是虚拟主机的关系,这步的工作我用 python(为什么用 Python ,jieba 分词,真香)在本地写了一个程序,完成所有文章的分词,词频统计,生成 TAGS,并写回服务器的数据库。由于本文是写推荐的算法,所以分词和建立 TAGS 的部分就不具体展开了,而且不同的系统有不同的 TAGS 建立方式。

第二 TAGS 的存储

建立两张表,用于存储 TAGS
tags,用于存所有 tag 的名称

+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| tag | text | YES | | NULL | |
| count | bigint(20) | YES | | NULL | |
| tagid | int(11) | NO | PRI | 0 | |
+-------+------------+------+-----+---------+-------+

tag_map 建立 tag 和文章的映身关系。

+-----------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | 0 | |
| articleid | bigint(20) | YES | | NULL | |
| tagid | int(11) | YES | | NULL | |
+-----------+------------+------+-----+---------+-------+

tag_map 存的数据类似如下:

+----+-----------+-------+
| id | articleid | tagid |
+----+-----------+-------+
| 1 | 776 | 589 |
| 2 | 776 | 471 |
| 3 | 776 | 1455 |
| 4 | 776 | 1287 |
| 5 | 776 | 52 |
| 6 | 777 | 1386 |
| 7 | 777 | 588 |
| 8 | 777 | 109 |
| 9 | 777 | 603 |
| 10 | 777 | 1299 |
+----+-----------+-------+

其实做相似推荐的时候,只需要用到 tag_map 表就可以了,因为 tagid 和 tag name 是一一对应的。

具体编码 1. 获取所有文章对应的 TAGID

mysql select articleid, GROUP_CONCAT(tagid) as tags from tag_map GROUP BY articleid;
+-----------+--------------------------+
| articleid | tags |
+-----------+--------------------------+
| 12 | 1178,1067,49,693,1227 |
| 13 | 196,2004,2071,927,131 |
| 14 | 1945,713,1711,2024,49 |
| 15 | 35,119,9,1,1180 |
| 16 | 1182,1924,2200,181,1938 |
| 17 | 46,492,414,424,620 |
| 18 | 415,499,153,567,674 |
| 19 | 1602,805,691,1613,194 |
| 20 | 2070,1994,886,575,1149 |
| 21 | 1953,1961,1534,2038,1393 |
+-----------+--------------------------+

通过以上 SQL, 可以一次性查询所用文章,极其对应的所有 tag
在 PHP,我们可以把 tags 变成数组。

public function getAllGroupByArticleId(){
 // 缓存查询数据,因为这个是全表数据,而且不更新文章不会变化,便是每次推荐都要从数据库里获取一次数据,对性能肯定会有影响,所以做个缓存。if($cache = CacheHelper::getCache()){
 return $cache;
 $query_result = $this- query(select articleid, GROUP_CONCAT(tagid) as tags from tag_map GROUP BY articleid 
 $result = [];
 foreach($query_result as $key = $value){
 // 用 articleid 做 key , 值是该 id 下的所有 tagID 数组。$result[$value[ articleid]] = explode( , ,$value[ tags 
 CacheHelper::setCache($result, 86400);
 return $result;
 }

有了这个的返回结果,就比较好办了,接下去的工作就是去应用 jaccard 相似度这个算法了,具体就看代码吧。

/**
 * [更据指定文章返回相似的文章推荐]
 * @param $articleid 指定的文章 ID
 * @param $top 要返回的推荐条数
 * @return Array 推荐条目数组
function getArticleRecommend($articleid, $top = 5){if($cache = CacheHelper::getCache()){
 return $cache;
 try{$articleid = intval($articleid);
 $m = new TagMapModel();
 $all_tags = $m- getAllGroupByArticleId();// 调用上面的函数返回所有文章的 tags
 $finded = $all_tags[$articleid];// 因为上面是包含所有文章了,所以肯定包含了当前文章。unset($all_tags[$articleid]);// 把当前文章从数组中删除,不然自己和自己肯定是相似度最高了。$jaccard_arr = []; // 用于存相似度
 foreach ($all_tags as $key = $value) {$intersect =array_intersect($finded, $value); // 计算交集
 $union = array_unique(array_merge($finded, $value)); // 计算并集
 $jaccard_arr[$key] = (float)(count($intersect) / count($union));
 arsort($jaccard_arr); // 按相似度排序,最相似的排最前面
 $jaccard_keys = array_keys($jaccard_arr);// 由于数组的 key 就是文章 id, 所以这里把 key 取出来就可以了
 array_splice($jaccard_keys, $top);// 获取前 N 条推荐
 // 到这里我们就已经得到了,最相似 N 篇文章的 ID 了,接下去的工作就是通过这几个 ID, 从数据库里把相关信息,查询出来就可以了
 $articleModels = new \Api\Model\ArticleModel();
 $recommendArticles = $articleModels- getRecommendByTag($jaccard_keys);
 CacheHelper::setCache($recommendArticles, 604800); // 缓存 7 天
 return $recommendArticles;
 } catch (\Exception $e) {throw new \Exception( 获取推荐文章错误}

以上是 Tags 实现内容推荐的方法的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道!

向 AI 问一下细节

丸趣 TV 网 – 提供最优质的资源集合!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-18发表,共计4084字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)