WordPressにレコメンドエンジンを実装すべく調べ始めてから2ヶ月ほどで、実際に搭載することができた。いろいろやりながらだったため思いがけず時間がかかったが、ポイントとなる点を整理しておく。
目次
- 要件
- レコメンドエンジンとは
- 情報推薦システムについてを勉強しよう
- Pythonでレコメンドエンジンをいじってみる
- レコメンドエンジンの要件定義をしよう
- データ取得のための仕込みにJavaScriptを使う
- データをもとにレコメンドエンジンを動かす
- レコメンドエンジンのデータをDBに登録する
- WordPressの側をつくる
WordPressにレコメンドエンジンを導入すべく、機械学習のライブラリを用いて自分で実装してみた。WordPressのプラグインは使わずに実装するのが目的で、これによってどういう理論で記事が推薦されるのか深く理解できたし、エンジニアとして提案の幅も広がった。レコメンドエンジンを導入したはいいがまったく効果がないという経験があるウェブ運用者が世の中にいるだろうが、そういう場合の解決策も提示できるようになりいいことづくめである。
この記事ではWordPressにレコメンドエンジンを実装するまでの大まかな流れを説明する。
要件
- プラグインを使わない
- google analyticsと連携しない
- まずはシンプルなアイテムベース協調フィルタリングを実装することを目的とする
必要なスキル
WordPressにレコメンドエンジンを必要なスキルは下記の通り多岐に渡るが、今回はそれぞれの過程で複雑なことはしない。エンジニアとしてウェブ周りの一通りの経験があれば、簡単なレコメンドエンジンならそこまで苦労せず実装できるだろう。
- Pythonとそれを動かす環境の用意
- SQL
- JavaScript
- PHP
- アクセス解析
- 情報推薦システムとそれに関する数学の知識
レコメンドエンジンとは
簡単にレコメンドエンジンについて説明しておく。YoutubeやNetflixなどの動画サイトやAmazonなどのECサイトでよく見られる「あなたにおすすめの動画」「この商品を買った人はこの商品も購入してます」というアレがレコメンドエンジンだ。
さすがにAmazonくらいになれば、長い運用で得た膨大なデータに基づいて高速表示する高機能なレコメンドエンジンなのだろうが、一般のブログや小規模なECサイトであればそもそものデータ数は多くないのでシンプルなレコメンドエンジンで十分である。
今回はもっとも基本的な情報推薦システムである協調型推薦を実装することを目的とする。これより複雑なレコメンドエンジンを開発したいという人ならそれなりの勉強家で経験もあるだろうから、この記事を読む必要はないだろう。
情報推薦システムについて勉強しよう
まず、レコメンドエンジンの理論の部分に関心がある人は『情報推薦システム入門 理論と実践』を読むことを強く勧める。
というか、レコメンドエンジンを実装したいエンジニアであれば関心がなくても読んだほうがいい。というのも、情報推薦システムに関する基礎的な知識がなければ、レコメンドエンジンのアプリをどう設計したらいいか分からないからだ。浅い理解のまま進めてもいいアプリは完成しない。仮に開発できてもレコメンドエンジンの精度が低い、効果がなくても修正できないなど、意味のないものができあがってしまう。
実は理論の部分を知らないでレコメンドエンジンをウェブアプリに実装したエンジニアの事例を知っているが、記事推薦の精度が低く、そのアプリは使いものならないものだった。せっかく時間をかけて開発してもそれでは寂しいからね。
Pythonでレコメンドエンジンをいじってみる
まずはレコメンドエンジンのデータセットを利用して、情報推薦システムがどんな動きをするか見てみよう。これについての詳細は初めてのレコメンドエンジン Jupyter notebookでサンプルを動かそうを参照してください。この記事を読んだ人は内容が重複するので、次の見出しまで飛ばしてください
実際にどんな動きをするかをまず見れば、完成後のイメージも広がるだろう。ローカルでレコメンドエンジンを動かすにはjupyter notebookが手軽でいい。Anacondaというディストリビューションを利用すればjupyter notebookも入っている。インストールしたら、コマンドラインで#jupyter notebookとするだけでpythonを動かせる。私はjupyter notebookはpythonの開発にはものすごく便利だと思って愛用している。
jupyter notebookを動かせる環境が用意できたら、機械学習を使って630万件のレビューに基づいたアニメのレコメンド機能を作ってみよう(機械学習 k近傍法 初心者向け)を一読するといい。必要なデータセットの案内とどういうライブラリを使うかが懇切丁寧に解説してある。この記事にあるコードをそのまま開発環境で動かせるので、サンプルとして実にいい。
ただ、この記事ではPythonの特にpandasというライブラリの使い方は学べないので、その辺りはしっかり勉強する必要がある。ちなみにpandasとはSQLやエクセルのようにデータの集計をするためのpythonのライブラリだ。データが多いと効力を発揮する。
pandasの他にもnumpyやmathplotlibなど流行りのデータサイエンスに必要なpythonのライブラリついては、私は『Pythonによるあたらしいデータ分析の教科書』でさらっと概要を学んだ。あくまで「さらっと」程度で、深くは学べないのでご注意あれ。本書で概要を学びネットで重点的に学ぶでもいいだろう。
以上であなたはレコメンドエンジンの概要とpythonの基礎知識を学んだと仮定し、前にすすもう。
レコメンドエンジンの要件定義をしよう
ウェブサイトに搭載するレコメンドエンジンには目的がある。
- ニュースサイトでもっと多くの記事を読んでもらう
- ECサイトでもっと多くの商品を買ってもらう
- 個人ブログでもっと多くの記事を読んでもらう
- 動画サイトでもっと多くの動画を観てもらう
- アフィリエイトサイトでもっと多くの広告をクリックしてもらう
さて、あなたはレコメンドエンジンで何をしたいのだろう?なんのためにレコメンドエンジンを実装したいのだろう。この問いに対して答えられるように、最初によく考える必要がある。今回はWordPressにレコメンドエンジンを搭載するわけだから、閲覧者により多くの記事を読んでもらい回遊率を上げ直帰率を下げることが目的となる。この前提で話しを進める。
余談だが、個人経営の美容師やら歯科医やら中小零細企業の社長などが自分のコーポレートサイトサイトのトップページにおすすめ記事を載せたい、とか一般的なウェブ運用の観点から意味の分からないことを平気で言うことがあるが、そういうのは相手にする必要はない。エンジニアが素人のいうことをそのまま受け入れてアプリを作っていては、とんでもないものが出来上がってしまう。あくまで開発者たるエンジニアがアプリのコンセプトを明確に理解して設計するのだ。そのほうがいいものができる。エンジニアが作りたいものをイメージできていないのに、他者に言われたままにプログラムを作ると、これは最悪の結果となる。
データ取得のための仕込みにJavaScriptを使う
さて、レコメンドエンジンの目的は定まった。次にレコメンドエンジンに必要なデータについて考えよう。これは超重要です。『情報推薦システム入門 理論と実践』を少し読めばわかるのだが、また、上で紹介した記事のレコメンドエンジンのサンプルを動かした人なら分かるだろうが、協調型推薦にはユーザーの記事に対する評価が必要となる。記事データはWordPressにデータベースがあるから問題ないが、ユーザー評価は存在しない。だから自分でデータベースにtableを追加しなくてはならない。
しかし、なにをもってしてユーザーの記事に対する評価とすればいいのかという疑問に直面する。まさか記事にアンケートボタンをつけるわけにはいかない。そんなものは飽きっぽいネットユーザーは誰も協力してくれないし、仮に協力してくれても本音の評価かどうか分からない。アンケートのために500円券を配るわけにもいくまい。
そこで役立つのがアクセス解析データだ。ウェブ運用をしていればgoogle analyticsを使ったことのない人はいないと思うが、あのツールから分かる通りjavascriptはデータ収集に強力な解決策となる。google analyticsと連携してもいいのだが、今回は連携しない。なぜならgoogle analyticsと連携するにはgaのAPI処理が必要なり、手間が増えるからだ。そして何よりgaだと直帰した場合のデータがとれない。これは痛い。だから自力で設計する必要がある。
ちなみにgoogle analyticsを知らないウェブエンジニアの方っていますか?大学で理論だけ勉強した新卒のエンジニアとかであれば、そういう人はいると思う。というか過去にそういう若い人を実際に見た。エンジニアの中には言われたものは作ることができるけど、自分でウェブ運用したことない人というのはけっこういる。現場の課題を深く理解してこそウェブエンジニアで、いい提案もできる。だからエンジニアでも積極的にウェブ運用の現場の課題を知る必要がある。
直帰率についての考え方
アクセス解析において直帰率が高いというとイメージが悪いかもしれないが、あるページをよく読んだうえでの直帰と、よく読まない直帰ではまったく意味合いが異なる。google analyticsではこの両者は区別できないのだ。だから自分でjavascriptを記述してデータを取得する。必要なのはあるページ内におけるページ滞在時間だ。この滞在時間をもってページの評価指標とする。もちろんあなたに独自の考えがあるなら別の滞在時間以外のデータ、例えばスクロール率などを指標にしてもいいが、ここでは滞在時間を前提とする。
ページ遷移すればサーバーサイドの言語でも滞在時間を取得できるが、直帰の場合はPHPなどでは滞在時間を取得できない。だからクライアントサイドのjavascriptが必要となる。考え方としてはページ読み込みの最初のほうにperformance.now();などでタイマーをセットしておく。次にsetIntervalなどで読み込み開始から何秒経過したかをサーバーに定期的にデータを送信する。こういうプログラムを書いて個別の記事ページに仕込めばいい。
具体的にはsendbeaconというメソッドを使用して、サーバーにデータ送信をする。これについてはJavaScriptのsetinterval、sendBeaconでページ滞在時間を取得するに詳細を書いた。
腕のいいjs職人ならもっと効率よくできると思うが、今回はあまり複雑なことはしない。シンプルにレコメンドエンジンの実装を目指す。では、このデータ取得について内容をまとめよう。
- ユーザーの記事に対する評価指標が必要である
- 評価指標は閲覧時間とする
- JavaScriptを利用しサーバーにデータを送信する
- データのセキュリティ処理をしてデータベースに登録する
サーバーにデータを送信する間隔によってはデータや負荷が大きくなるし、セキュリティにも配慮する必要があるので、この辺りはウェブ開発の経験が必要となる。なお、セキュリティに気が配れないならアプリ開発はしないほうがいい。面倒で放置した場合は、かなり高い確率で後で痛い目を見るし、もちろん納品先のお客様に迷惑をかけることになる。
さて、ここまででレコメンドエンジンに必要なデータを取得できたと仮定しよう。
ちなみにアクセス数が極端に少ないとか、コンテンツ記事が少ない等の場合はレコメンドエンジンを導入する意味はまったくないことは言うまでもない。そもそも取得できるデータが少ない場合など、そういうウェブサイトはレコメンドエンジンを導入するより内容を充実させるほうが先だ。
データをもとにレコメンドエンジンを動かす
sendbeaconで得たデータはセキュリティチェックをした上でDBに登録するなどしよう。例えばwp_analyticsのようなtableを作り、そこに登録する。具体的には以下のようなデータだ。 これはあくまで一例でありこの通りでないといけないわけではない。セッションIDやIPでもって個別のユーザーと見なし、それぞれのユーザーがどのページをどれくらいの時間閲覧したかが分かる。
| session_id | url | date | scroll_percent | staying_time | ip | page_id |
+———————————-+—————————————–+———————+—————-+————–+—————–+———+
| a014d2e0b8173 | /2021/01/04/wp-list-img/ | 2021-02-04 16:01:42 | 0.20 | 0.51 | xxx.xxx.xxx.xxxx | 162 |
| 3042fa14554f7f6 | /2021/02/03/books/ | 2021-02-04 19:04:15 | 1.21 | 4.01 | xxx.xxx.xxx.xxxx | 233 |
| 7beca37435729a | /2020/07/14/ssl-nss/ | 2021-02-04 23:59:46 | 0.97 | 255.05 | xxx.xxx.xxx.xxxx | 344 |
レコメンドエンジンのデータをDBに登録する
さて分析データは取得できた。これで各ユーザーのそれぞれのページに対する評価を得られたと仮定しよう。ここまでくればレコメンドエンジンを回すだけだ。この初めてのレコメンドエンジン Jupyter notebookでサンプルを動かそう”で紹介した通り、レコメンドエンジンに記事IDを渡すとおすすめ記事のIDを返してくれる。そのデータをDBに登録すれば準備完了だ。具体的には下記のようなデータだ。繰り返しとなるが、この通りである必要はない。
| id | recommend_id | post_id |
+——+————–+———+
| 2401 | 112 | 418 |
| 2402 | 455 | 418 |
| 2403 | 463 | 418 |
| 2404 | 496 | 418 |
| 2405 | 52 | 149 |
| 2406 | 680 | 149 |
| 2407 | 455 | 149 |
| 2408 | 463 | 149 |
| 2409 | 112 | 257 |
| 2410 | 455 | 257 |
post_idが記事IDで、それに対してどの記事を推薦するかというtableである。左端のIDはデータ処理の便宜上あるものだ。記事IDさえ得られれば、あとはWordPressにIDを渡すだけでいい。なお記事データはURLではなく、あくまで記事IDを扱うほうが処理が楽でいい。これはWordPressに限らずどのCMSについても言える。たいていのCMSはページや記事のURLは動的に生成されることがあり、運用の中でURLが変化することは多々ある。だから最初から固有のIDで処理すればトラブルは少なくて済む。
では、次でいよいよ最後の項目となる。
WordPressの側をつくる
これはCMSを扱うエンジニアであれば簡単でしょう。データを引っ張ってきてWordPressに表示させるだけ。上述の通り記事IDをキーにするので、流れとしては以下のような感じだ。やりようはいくらでもあるだろう。フロントにどう表示させるかはデザイナーやアクセス解析担当者と相談すればいい。
- 記事ページにその記事自体のIDを出力する
- その記事IDをキーにしてレコメンドIDをDBから取得する
- 取得したIDのタイトルなどを取得して表示する
以上でこの記事を終えるが、かなり駆け足のざっくりとした内容となってしまったことについてはご了承願う。というのも、実装における細かい点は各サーバーや各ウェブサイトごとに事情が異なり、逐一書くことができないからである。したがってこの記事では、レコメンドエンジンを実装するに際しての大まかな原則のようなものを書くことに徹した。
また、この記事では「レコメンドエンジン」と表記してはいるがWordPressというブログシステムに実装するので、より具体的には「アイテムベース協調フィルタリング」を前提としている。ECシステムであればユーザーベースもあるべきだし、他にも内容ベース、知識ベース、それらのハイブリッド型など様々なレコメンドエンジンが存在する。今後より複雑で魅力的なレコメンドエンジンの実装についても、順次案内していくつもりだ。
また、レコメンドエンジン導入後のアクセス状況なども追ってレポートする。