読者です 読者をやめる 読者になる 読者になる

はっさんブログ

冷静にやっていき

ざっくり分かる!レコメンドシステムを支える技術 (超入門)

自然言語処理 レコメンドシステム

こんにちは、はっさん(@hassasa3)です。
この記事はKIT Advent Calendar10日目の記事になります。

今回はレコメンドシステムの動向と、内部で使われている手法についてです。

「レコメンドシステム...レコメンドねぇ..中身はどうやってるんだろう。」

この記事ではざっくり、レコメンドシステムってこういうものなんだなと分かるよう解説します。

実際に実装する際の順序は、内容ベース→協調フィルタリングがオススメです。
なぜなら、協調フィルタリングはユーザーの評価が必要なのに対し、内容ベースはアイテムさえあれば類似度の計算ができるからです。

レコメンドシステムの動向

さて、レコメンドシステムと聞いて思いつくものは何でしょうか。
代表的に言われているものは、Amazon「この商品を買った人は、こんな商品も買っています」です。

f:id:usgitan:20161208164335p:plain

Amazonは収益の35%をこれらのレコメンドシステムで打ち出しており、かつ持続した機能であるため、ビジネス面から見ても有益な技術であることがわかります。

では、内部的にどのような手法が行われているのでしょうか?

レコメンドの手法には種類がある

「レコメンド」とは裏を返せば情報のフィルタリングとも言えます。
従来の研究者達は膨大な情報の中から、どのようにしてフィルタリングを行うのかについてその手法を提案してきました。

ここではその手法を大きく分けて2つ紹介します。
一つ目の手法が協調フィルタリングと呼ばれるものです。

協調フィルタリング

協調フィルタリングとは、ユーザの類似性をもとにアイテムを推薦する手法です。
以下に例を挙げました。これは、ユーザのアイテムに対する評価値のデータベースです。

f:id:usgitan:20161210013227p:plain

このときのレコメンドシステムのタスクは、ユーザ1がまだ評価づけを行っていない”アイテム5”を好むか好まないかを判断することです。
既存のデータを分析して、ユーザ1がアイテム5に評価をする予測値が高ければ、レコメンドのリストにアイテム5を追加します。

ではどのように予測値を出すのでしょうか?

予測値を出す方法として、協調フィルタリングには大きく分けて2種類あります。
それは「ユーザーベースの協調フィルタリング」と「アイテムベースの協調フィルタリング」です。

ユーザーベースの協調フィルタリング

ユーザベースの協調フィルタリングとは、あるアイテムに対し同じ興味を示したユーザは、将来的にも同じような興味を持つであろうという考え方です。
例えば、ユーザAとユーザBが非常に共通する購入履歴を持ち、ユーザBが見たことのない本をユーザAが最近購入したとすると、この本をユーザBにも提案することは合理的であると言えます。

そこでユーザ間の類似度を計算する方法の1つとして、ピアソンの相関係数が用いられます。
計算経過は省きますが、これを用いてユーザ1と他ユーザとの類似度を計算すると(ユーザ2、0.85)、(ユーザ3、0.70)、(ユーザ4、0.00)となります。
これにより、ユーザ1はユーザ2と3と類似していることが導き出せます。

一見、評価値の値だけ見るとユーザ1はユーザ3のほうが似ており数値も高く見えるのですが、計算しているのは相関であり、どういう評価を辿っていっているかで類似度を出しているためユーザ2のほうが数値が高い結果になります。
そして、このユーザ2とユーザ3との類似度を用いて最近傍法の式に当てはめると、4.87という予測値を計算することができます。

これにより、アイテム5はユーザー1が好むであろうレコメンドすべきアイテムとして、リストに含めることが出来ます。

アイテムベースの協調フィルタリング

上記で紹介したユーザベースの協調フィルタリング技術は応用され成功しているのですが、大規模な商用サイトにおいて、数百万のユーザや商品を扱うような本格的な取り組みは行われてはいません。

なぜなら、ユーザのアイテムへの評価の特徴として「疎」であるからです。
つまり、非常に多くのアイテムが存在するのですが、ユーザが評価をしているのはごく一部のアイテムであるためデータが欠損しており、まともな値が出てこないのです。

そこで、Amazonをはじめとした大規模な商用サイトでは「アイテムベースの協調フィルタリング」が扱われます。

アイテムベースの協調フィルタリングとは、ユーザ間の類似度ではなくアイテム間の類似度を用いてアイテムを推薦する手法です。

f:id:usgitan:20161210013227p:plain

再度上記の表を例にして、ユーザ1のアイテム5の予測値を大雑把に検討してみます。

アイテム5の縦の列をみてください。

ユーザ1の行を除いたその評価値は(3, 5, 4)であり、アイテム4の評価値(3, 3, 5)と似ています。
さらにアイテム1の評価値(3, 4, 3)とも少し似ている。。つまり、ユーザ1はアイテム5に4から5の間で評価するだろうと予測することが出来ます。

では、それらの数値を用いて類似度を計算する手法である「コサイン類似度」を紹介します。
アイテムベースの協調フィルタリングでは、コサイン類似度が最も標準的な指標として確立しています。

f:id:usgitan:20161210122953p:plain

この式を用いてアイテム1とアイテム5のコサイン類似度を求めると0.99になります。
これによりアイテム1とアイテム5は非常に似ており、アイテム1を高評価しているユーザ1に対して、アイテム5は推薦すべきアイテムだと言えます。

altarf.net

内容ベースフィルタリング

内容ベースフィルタリングとは、アイテム間の類似度を計算した上で、ユーザが興味を示したアイテムに類似したアイテムを推薦する手法です。

例えば、文書をユーザにレコメンドしようとなれば、予め、文書の特徴語を抽出→文書間の類似度を計算しておきます。
そして、ユーザが興味を持って見た文書に付随させる形で「これ、類似してるぜ。好きじゃない?」と言った感じでレコメンドします。

その類似度の計算方法として、k-近傍法があります。
詳細はWikiに詳しいです(まかせたぜ、オラッ!)

注意点として、上記で述べたアイテムベースの協調フィルタリングは「ユーザのアイテムへの評価のみ」を利用する点で、内容ベースフィルタリングとは異なることは注意です。

内容ベースを「もう一歩踏み込む」 (BOW, TF-IDF)

さて、情報の形というのは様々あり、主にテキスト・画像・音声があります。
これらの情報を推薦しようと考えた時に、あなたが人間であれば、パッと構造的に捉えて他人に推薦できるでしょう。

しかし、これを機械にやらせようとしたらどうでしょうか。
機械はテキスト、画像、音声という情報をそのままの形では解析することが出来ません。

そこで、それらのデータを機械が理解できるように、それらを数値化する手法が考えられてきました。
上記の文書の例で言うと、文書のキーワードを抽出(どうやって?)→類似度を計算(計算は数値でないとできないけど、キーワードをどうやって数値化するの?)となるはずです。

今回はその手法を2つ紹介します。

BOW(Bag Of Words)

文章の数値化のための最も素朴なアプローチに「Bag of words」があります。
これは、文書に現れるすべての単語のリストを作成し、それぞれの単語を「次元」と捉え、各文書を数値で表現する方法です。

例えば、[“ゴリラがりんごを食べた”]という文章に対し、[“りんご”、”ゴリラ”、”ラッパ”]という単語のリストがあるとします。
すると[“ゴリラがりんごを食べた”]は[1、1、0]と表すことができるようになります。(!!)

つまり、成分が1であることはその成分に対応する単語が文書に現れることを意味し、成分が0の場合はその単語が文書に現れないことを意味しています。

実際には、全ての文書から単語を抽出してリストを作った後一つ一つの文書を見ていくことで、リスト内の単語の出現頻度により、文書を数値化するという流れになります。

しかし、この手法は一見シンプルゆえに、問題点があります。
それは、すべての単語が同じだけの重要度を持っていることです。

つまり、これでは「単語数は少ないけれど文書の特徴を示す単語」を逃してしまうことになり、類似度を求める際に精度が上がらないといった結果になりがちです。
さらに、文書が長くなるとボンボン単語数が増え、これまた精度の低下が懸念されています。

TF-IDF

そこで特徴語の抽出や次元の削減をすることが一般的になっています。
今回はその内の1つであるTF-IDFという手法を紹介します。TF-IDFは単語頻度・逆文書頻度の略であり、特徴語の抽出のために用いられます。

TF

まず、TF=“単語頻度”についてです。
TFは、重要な語ほど頻繁に現れるという仮説に基づいており、TF=単語の頻度/(文章に出現する総形態素数)で求めることが出来ます。

例えば「今日はいい天気、最高の天気」という文章に対してmecabを用いて形態素に分けると以下の図のように全部で8つの形態素に分けられます。

f:id:usgitan:20161210022245p:plain

ここで“天気”に注目すると"天気"の出現回数は2回、形態素の総数は8のため、TFの値は2/8=0.25となります。

これをすべての単語に行い、tf値が大きい値が重要な単語だと判断できます。
今回は全ての形態素を母数として考えましたが、一般的には名詞を抽出して行われることが多いそうです。

IDF

IDFは“逆文書頻度”の略称です。
IDFはすべての文書に頻繁に現れるキーワードに対する重みを減らすために用いられます。

つまり、一般に頻度の高い単語は文書を区別する役に立たないため、少数の文書に現れる単語の方により多くの重みを与えたほうが良いという考え方です。

例えば、文書A, B, Cが存在したとしましょう。Aには[りんご: 3, 木: 1]という単語、Bには[りんご:5, 蟹: 2 ]、Cには[りんご: 4, 猿: 2]といった単語が出現したとしましょう。

Aはりんごという単語が多く出現しているので特徴語のように感じます。
しかし、BにもCにも多く出現しているためそんなに特徴とは言えそうにないな。なので重みを低下しようというような感じで計算されます。

IDFはlog_2(文書の総数/単語がいくつの文書で現れるか)で求めることが出来ます。

TF-IDF

そして最後にTFにIDFを掛け算することで、いくらTFの値が高かろうと全部の文書に出てきたら全然特徴語ではない。
といったフィルタリングした結果の特徴語を表すことが出来ます。

実装はこちら

usgitan.hatenablog.com

まとめ

今回はレコメンドの手法として、協調フィルタリングと内容ベースフィルタリング。
内容ベースにおけるテキストのベクトル化(数値化)の手法にBOWとTF-IDFを紹介しました。

研究テーマにレコメンドシステムを選択した際はまた見て頂けるとうれしいです。

広告を非表示にする