ホームページ  >  記事  >  データベース  >  タグに基づいたコンテンツレコメンデーションを実装する方法(コード)

タグに基づいたコンテンツレコメンデーションを実装する方法(コード)

不言
不言オリジナル
2018-09-14 14:11:422416ブラウズ

この記事は、タグに基づいたコンテンツのレコメンデーションを実装する方法 (コード) に関するものです。必要な方は参考にしていただければ幸いです。

単純さと利便性のために、私の小さな Web サイトの記事ページに関連するコンテンツの推奨事項は、データベースからデータをランダムに抽出してリストを埋めることになっているため、相関関係がまったくないことがわかりました。 、ユーザーを推奨コンテンツにアクセスするように誘導する方法はありません。

アルゴリズムの選択

小規模な Web サイトはまだ仮想ホスト上で実行されているため (完全に制御可能なサーバーさえありません)、どのようにして同様のコンテンツを推奨できるでしょうか?考える方法はあまり多くありません。条件としては、PHP MySql のみを使用できるということです。そこで私が考えたのが、タグを使って類似記事を照合してレコメンドするという方法です。 2 つの記事のタグが類似している場合

例: 記事 A のタグは: [A,B,C,D,E]
記事 B のタグは: [A,D,E,F] ,G]
記事 C のタグは次のとおりです: [C,H,I,J,K]

記事 B と記事 A は、同じキーワードが 3 つあるため、より類似していることが目で簡単にわかります。 : [A、D、E]、コンピューターを使用してそれらの類似性を判断するにはどうすればよいですか? ここでは、jaccard 類似度 の最も基本的なアプリケーションを使用して類似度を計算します

Jaccard 類似度

2 つのセット 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、そしてUnion は [A, B, C, D, E,H,I,J,K]、サイズは 9、1/9=0.11111...

このようにして、次のように結論付けることができます。記事 A と B は、記事 A と C よりも類似しています。このアルゴリズムを使用すると、コンピューターは 2 つの記事の類似性を判断できます。

具体的な推奨アイデア

与えられた記事で、その記事のキーワード TAGS を取得し、上記のアルゴリズムを使用してデータベース内のすべての記事の類似性を比較し、最も類似した N 件の記事を取得します。記事がおすすめです。

実装プロセス

最初のTAGSの取得

記事内の高頻度単語からTF-IDFアルゴリズムにより記事のTAGSを抽出し、N中国語の記事には中国語の単語分割の問題もあります。仮想ホストなので、Python を使用して (Python を使うのはとても美味しいです)、単語分割を完了するプログラムをローカルで書きました。すべての記事、単語頻度統計、タグを生成し、サーバーのデータベースに書き戻します。この記事は推奨アルゴリズムの作成に関するものであるため、単語の分割と TAGS の確立の部分については詳しく説明しません。また、システムが異なれば TAGS を確立する方法も異なります。

2 番目の TAGS の保存

TAGS
タグを保存する 2 つのテーブルを作成し、すべてのタグの名前を保存するために使用します

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

tag_mapタグと記事の反映関係を作成します。

+-----------+------------+------+-----+---------+-------+
| 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 |
+----+-----------+-------+

実際、同様の推奨事項を作成する場合、tagid とタグ名が 1 つにまとめられているため、tag_map テーブルを使用するだけで済みます。対一対応。

具体的なコーディング

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 を通じて、すべての記事と対応するすべてのタグを一度にクエリできます
PHP では、タグを配列に変換できます。

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("获取推荐文章错误");
        }
    }

関連する推奨事項:

PHP で「関連記事の推奨事項」機能を簡単に実装する方法

以上がタグに基づいたコンテンツレコメンデーションを実装する方法(コード)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。