共計(jì) 4084 個(gè)字符,預(yù)計(jì)需要花費(fèi) 11 分鐘才能閱讀完成。
自動(dòng)寫代碼機(jī)器人,免費(fèi)開通
丸趣 TV 小編給大家分享一下 Tags 實(shí)現(xiàn)內(nèi)容推薦的方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
原來為了簡單方便,自己小網(wǎng)站上的文章頁的相關(guān)內(nèi)容推薦就是從數(shù)據(jù)庫里隨機(jī)抽取數(shù)據(jù)來填充一個(gè)列表,所以一點(diǎn)相關(guān)性都沒有,更本沒有辦法引導(dǎo)用戶去訪問推薦內(nèi)容。
算法選擇
如何能做到相似內(nèi)容的推薦呢,礙于小網(wǎng)站還跑在虛擬主機(jī)上(對(duì)的,連一個(gè)自己完整可控的服務(wù)器都沒有),所以可以想的辦法不多,條件限制在 只能用 PHP+MySql。所以我想到的辦法就是通過 Tags 來匹配相似文章進(jìn)行推薦。如果兩篇文章的 TAGS 比較相似
比如:文章 A 的 TAGS 為:[A,B,C,D,E]
文章 B 的 TAGS 為:[A,D,E,F,G]
文章 C 的 TAGS 為:[C,H,I,J,K]
通過眼睛我們能很方便的發(fā)現(xiàn),文章 B 和文章 A 更為相似,因?yàn)樗鼈冇腥齻€(gè)關(guān)鍵字相同分別為:[A,D,E],哪如何用計(jì)算機(jī)來判斷它們的相似度呢,這里我們用 jaccard 相似度的最基本應(yīng)用來計(jì)算它們的相似度
jaccard 相似度
給定兩個(gè)集合 A,B,Jaccard 系數(shù)定義為 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 更為相似,有了這個(gè)算法,計(jì)算機(jī)就可以來判斷兩篇文章的相似度了。
具體的推薦思想
給定一篇文章,獲取該文章的關(guān)鍵字 TAGS, 然后通過以上算法去數(shù)據(jù)庫比對(duì)所有文章的相似度,獲取最相似的 N 篇文章進(jìn)行推薦。
實(shí)現(xiàn)過程第一 TAGS 的獲取
文章的 TAGS 是通過 TF-IDF 算法,提取文章中的高頻詞,選取 N 個(gè)作為 TAGS,對(duì)于中文的文章來說還涉及到一個(gè)中文分詞的問題,因?yàn)槭翘摂M主機(jī)的關(guān)系,這步的工作我用 python(為什么用 Python ,jieba 分詞,真香)在本地寫了一個(gè)程序,完成所有文章的分詞,詞頻統(tǒng)計(jì),生成 TAGS,并寫回服務(wù)器的數(shù)據(jù)庫。由于本文是寫推薦的算法,所以分詞和建立 TAGS 的部分就不具體展開了,而且不同的系統(tǒng)有不同的 TAGS 建立方式。
第二 TAGS 的存儲(chǔ)
建立兩張表,用于存儲(chǔ) 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 和文章的映身關(guān)系。
+-----------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | 0 | |
| articleid | bigint(20) | YES | | NULL | |
| tagid | int(11) | YES | | NULL | |
+-----------+------------+------+-----+---------+-------+
tag_map 存的數(shù)據(jù)類似如下:
+----+-----------+-------+
| 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 |
+----+-----------+-------+
其實(shí)做相似推薦的時(shí)候,只需要用到 tag_map 表就可以了,因?yàn)?tagid 和 tag name 是一一對(duì)應(yīng)的。
具體編碼 1. 獲取所有文章對(duì)應(yīng)的 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, 可以一次性查詢所用文章,極其對(duì)應(yīng)的所有 tag
在 PHP,我們可以把 tags 變成數(shù)組。
public function getAllGroupByArticleId(){
// 緩存查詢數(shù)據(jù),因?yàn)檫@個(gè)是全表數(shù)據(jù),而且不更新文章不會(huì)變化,便是每次推薦都要從數(shù)據(jù)庫里獲取一次數(shù)據(jù),對(duì)性能肯定會(huì)有影響,所以做個(gè)緩存。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 數(shù)組。$result[$value[ articleid]] = explode( , ,$value[ tags
CacheHelper::setCache($result, 86400);
return $result;
}
有了這個(gè)的返回結(jié)果,就比較好辦了,接下去的工作就是去應(yīng)用 jaccard 相似度這個(gè)算法了,具體就看代碼吧。
/**
* [更據(jù)指定文章返回相似的文章推薦]
* @param $articleid 指定的文章 ID
* @param $top 要返回的推薦條數(shù)
* @return Array 推薦條目數(shù)組
function getArticleRecommend($articleid, $top = 5){if($cache = CacheHelper::getCache()){
return $cache;
try{$articleid = intval($articleid);
$m = new TagMapModel();
$all_tags = $m- getAllGroupByArticleId();// 調(diào)用上面的函數(shù)返回所有文章的 tags
$finded = $all_tags[$articleid];// 因?yàn)樯厦媸前形恼铝耍钥隙ò水?dāng)前文章。unset($all_tags[$articleid]);// 把當(dāng)前文章從數(shù)組中刪除,不然自己和自己肯定是相似度最高了。$jaccard_arr = []; // 用于存相似度
foreach ($all_tags as $key = $value) {$intersect =array_intersect($finded, $value); // 計(jì)算交集
$union = array_unique(array_merge($finded, $value)); // 計(jì)算并集
$jaccard_arr[$key] = (float)(count($intersect) / count($union));
arsort($jaccard_arr); // 按相似度排序,最相似的排最前面
$jaccard_keys = array_keys($jaccard_arr);// 由于數(shù)組的 key 就是文章 id, 所以這里把 key 取出來就可以了
array_splice($jaccard_keys, $top);// 獲取前 N 條推薦
// 到這里我們就已經(jīng)得到了,最相似 N 篇文章的 ID 了,接下去的工作就是通過這幾個(gè) ID, 從數(shù)據(jù)庫里把相關(guān)信息,查詢出來就可以了
$articleModels = new \Api\Model\ArticleModel();
$recommendArticles = $articleModels- getRecommendByTag($jaccard_keys);
CacheHelper::setCache($recommendArticles, 604800); // 緩存 7 天
return $recommendArticles;
} catch (\Exception $e) {throw new \Exception( 獲取推薦文章錯(cuò)誤}
以上是 Tags 實(shí)現(xiàn)內(nèi)容推薦的方法的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道!
向 AI 問一下細(xì)節(jié)
丸趣 TV 網(wǎng) – 提供最優(yōu)質(zhì)的資源集合!