「久しぶりに小説なんか読みたいな〜」と書店に行くも自分ってどんな本が好きなんだっけ?
と分からなくなるし、大手通販サイトはイヤホン買ったらイヤホン勧めてくるしということで自分でレコメンドシステムを作ってみることにしました。
やりたいこと
・Item2Vecという手法を使って、本をベクトル化し自身が今までに読んで面白かった本との類似度を求めることで好みが似通った本をオススメしてもらいたい。
・複数の好みの本を足し合わせたベクトルとの類似度を求めることで新しいジャンルの本と出会いたい!(こちらのスライドを参考にさせていただきました)
Item2Vecとは
そもそもItem2Vecとは単語をベクトル化する手法として有名なWord2Vecをアイテムベースで転用したものです。
ちなみにWord2Vecの解説はこちらの記事がとてもわかりやすいです。(絵で理解するWord2vecの仕組み)
簡単に説明するとWord2Vecは文章内の単語同士の位置関係から各単語をベクトル化するのですが、Item2Vecはユーザーのアクションログや購買ログなどの時系列データの位置関係から各アクション・商品をベクトル化するものです。単語が商品に変わっただけで手法はWord2Vecと何も変わりませんね。
今回はこの商品を本とすることでベクトルを獲得します。
##学習データ
学習データはSeleniumを使って読書メーターという各ユーザーが読んだ本を記録・共有するwebサービスからスクレイピングしユーザーの最近記録した本のIDを10件ずつ取得しました。
各ユーザーの10件の読書ログがWord2Vecにおける1文章にあたります。
(読書メーターさんありがとうございました。)
##Word2Vecの実装
手法自体はWord2Vecとなんら変わらないのでgensimを使ってベクトルを取得します。
ちなみにオプションとして本の多様性が出ればいいなぁとベクトルサイズは少なめの100にしました。
書いたコードはこれだけです。
from gensim.models import word2vec
model = word2vec.LineSentence("data.txt")
book_model = word2vec.Word2Vec(model, size=100, min_count=40, window=10,sg=1)
book_model.wv.most_similar(["本のID"],[],10)
##結果(作品のネタバレあり)
入力例として有名な作品をいくつか入れてみました。
評価指標がないことが難点ですが
「君の名は。」については序盤にスピンオフ作品や新海誠作品が並んでおり、中盤以降の作品に関しては死後の人物と会ったりする話などところどころ「君の名は。」と内容が似ている作品がある気がします。。。。?
しかし「下町ロケット」や「火花」については同じ著者の作品しか出力されなかったり、同じ芥川賞を受賞した作品がレコメンドされるなど内容と関係のない部分が反映されてしまいます。
最後に興味深い点として「君の名は。」と「下町ロケット」を足し算した作品のレコメンドでは両作品の特徴として「若者」+「下克上」テイストが反映されたのか「ビリギャル」などがレコメンドされており面白い結果になったかなと思います。
##追記
結果を見るとだいぶノイズのような作品が多く見受けられたので改善のために別途読書メーターから各ユーザーが読んだ本の著者をスクレイピングしItem2Vecにより著者をベクトル化してみました。
これを行なった理由として「火花」の結果から見てわかるように芸能人の方が書かれた作品のレコメンドには芸能人の作品が多く出力されておりメディアや著者同士の親交が結果に影響しているのではと思ったからです。
結果、入力作品の著者を別途著者モデルに入力することで類似した著者を出力させ、彼らの作品をレコメンドから除くことである程度ノイズを削減することができました。
##終わりに
今回Qiita初投稿だったので、書き方がうまくないかもしれません。
内容も不十分かもしれませんが、間違っている箇所・疑問箇所は何でもコメントしてください!!!