レコメンデーション入門1　レコメンドシステム

[Aidemy](https://aidemy.net/)　2020/12/3

#はじめに
　こんにちは、んがょぺです！バリバリの文系ですが、AIの可能性に興味を持ったのがきっかけで、AI特化型スクール「Aidemy」に通い、勉強しています。ここで得られた知識を皆さんと共有したいと思い、Qiitaでまとめています。以前のまとめ記事も多くの方に読んでいただけてとても嬉しいです。ありがとうございます！
　今回は、レコメンデーション入門の1つ目の投稿になります。どうぞよろしくお願いします。

＊本記事は「Aidemy」での学習内容を「自分の言葉で」まとめたものになります。表現の間違いや勘違いを含む可能性があります。ご了承ください。

今回学ぶこと
・レコメンドシステムについて
・コンテンツベースフィルタリングの実装

#レコメンドシステムについて
##レコメンドシステムとは
・__レコメンドシステム__とは、__商品を推薦するシステム__のことである。みじかな例としては、Amazonなどのネットショッピングのレコメンドシステムがある。__「あなたへのおすすめ」「この商品を買った人はこちらの商品も買っています」__といったものである。
・レコメンドの種類は、大きく__「アイテムベース」「ユーザーベース」__に分けられる。商品購入の例で言うと、「購入した__商品と類似した__商品を勧める」のがアイテムベース、「__購入者の履歴や同じ購入パターンの人を分析__して商品を勧める」のがユーザーベースである。この二つでは実装方法が異なる。

##協調フィルタリング
・Amazonでは、__他のユーザーの購入パターン__を使って商品をオススメしている。このように、__他ユーザーの行動パターンやアイテムの類似性__を対象のユーザーと比較するレコメンドシステムのことを__「協調フィルタリング」__と言う。
・このシステムは、__「似ているユーザー」__を購入履歴やレーティングから導き、__「ユーザー同士」__あるいは__「ユーザーとアイテム」__を結びつけることで実装される。__最もよく使われているレコメンドシステム__であり、Chapter2でこの実装を行う。

#コンテンツベースフィルタリング
##コンテンツベースフィルタリングとは
・あるユーザーの購入履歴やプロフィールなどから、__そのユーザーの個人的な嗜好を見つけて__コンテンツを進める手法を__「コンテンツベースフィルタリング」__と言う。こちらは協調フィルタリングと違って__他ユーザーのデータを使用しない__。例としては、「筋トレが好き」とプロフィールに記載しているユーザーに筋トレ関連のグッズを勧めるといったことが挙げられる。

##コンテンツベースフィルタリングの実装
・ここからはコンテンツベースフィルタリングを実装していく。流れは以下の通り。
　①アイテムから__単語を抜き出し__、その単語の__重要度を求め__、__特徴ベクトルを作成__する。
　②作成した特徴ベクトルを他アイテムの特徴ベクトルと比較して__類似度を求める__。
　③類似度の高いデータを__レコメンド__する。

##①アイテムから単語を抜き出し、その単語の重要度を求め、特徴ベクトルを作成する
・今回は文章（肉フェス？）を品詞分解して名詞のみをまとめたリスト__「text」__が用意されているので、これを使用する。重要度については、単語の出現頻度を表す__「TermFrequency（TF）」__と、単語の希少性を表す__「InverseDocumentFrequency（IDF）」__で算出し、これらを掛け合わせた__「TF-IDF」__を特徴ベクトルとする。
・TFは__「調べたい単語数÷全単語数」__で求められる。IDFは__「$log_{10}$全文書数/その単語が出現する文書数」__で求められる。
・以下はTFを求める関数__「tf()」__とIDFを求める関数__「idf()」__である。

・コード![スクリーンショット 2020-11-25 16.38.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/896d1263-e879-9a5d-dd18-a799fd30726b.png)


・__「tf()」__について、まず__「terms_unique」__として、単語のリストを__「set()」__を使って__和集合にする__ことで__単語の重複をなくす__。次に__「tf\_values」__はこのそれぞれの単語について、__「count()」__で個数を数える。__「tf\_list」__は__「tf\_values/sum(tf\_values)」__としてTFを算出し、リスト化したものを格納する。返す値については、最後にTF×IDFを行うため、__ndarray型__にして返す。
・__「idf()」__について、IDFの計算では__「文書数」__を使うので、引数では「document」が渡される。こちらもまずは__「set(terms)」__で単語の重複をなくす。次にIDFを計算したものを格納する「idf_list」を作成する。terms内の全ての単語（term）について、__先述した式でIDFを算出する__。対数の計算は__「math.log10()」__で行う。また、全文書数は__「len(document)+1」__で求められ、termを含む文書数は、渡された文書documentsのそれぞれ(document)について、__「bool(term in document)」__で条件を満たす文書を抽出し、その個数を__「sum()」__で合計すれば良い。また、こちらも__ndarray型__で返す。

・最終的には、tf()とidf()を適用してこれらを__かける__ことで__TF-IDF__を算出すれば良い。コード上では__[word, tfidf]__となるようにリストを作成し、値が大きいものから順に並べ替えて出力している。

・結果![スクリーンショット 2020-11-25 16.42.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/3d71ee4d-44ad-2d25-dc3a-538df9c3d592.png)

##②類似度を求める
・今回は__「コサイン類似度」__を使って類似度を判定する。コサイン類似度は文書同士を比較する際によく用いられる計算手法で、三角関数のcosと同じように、__1に近ければ類似__、0に近いほど似ていないと言える。
・以下は二つのベクトルのコサイン類似度を求める関数__「similarity()」__を実装している。詳しくはChapter2参照。

![スクリーンショット 2020-11-25 23.30.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/d915846f-0450-c4ea-ec4f-60187b164bd9.png)

##③類似度の高いデータをレコメンドする
・①で作成したTF-IDFによる__特徴ベクトル__と、②で作成した__コサイン類似度__を使って、複数の商品から対象者に適したものをレコメンドする。
・以下では、「takeshi」さんの映画の好みデータとそれぞれの映画の（客観的な）評価のデータである。これを前項の__「similarity()」__を使って類似度を算出し、類似度の高いものから順に並び替えると言うことを行なっている。
・__[映画名,類似度]__と格納するリスト__「score」__を作成し、各映画のベクトルデータ（movie[1]）とtakeshiさんのベクトルデータ（takeshi）を「similarity()」に渡し、これと映画名（movie[0]）をscoreに格納する。

![スクリーンショット 2020-11-26 10.49.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/2e2659b6-3898-1396-8297-883130ba8069.png)


![スクリーンショット 2020-11-26 10.48.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/8ec0ec68-a0b9-4b6e-5b74-b9b3e2394122.png)

#まとめ
・レコメンドシステムとは、__商品を推薦するシステム__のことである。
・あるユーザーの購入履歴やプロフィールなどから、__そのユーザーの個人的な嗜好を見つけて__コンテンツを進める手法を__「コンテンツベースフィルタリング」__と言う。これを行うには、それぞれのアイテムの__重要度__を算出して特徴ベクトルを作成し、また、__類似度__も算出する必要がある。
・重要度については、単語の出現頻度を表す__「TermFrequency（TF）」__と、単語の希少性を表す__「InverseDocumentFrequency（IDF）」__で算出し、これらを掛け合わせた__「TF-IDF」__を特徴ベクトルとする。
・類似度については、コサイン類似度を使う。詳しくはChapter2で扱う。

今回は以上です。最後まで読んでいただき、ありがとうございました。