[機械学習]5分で説明するレコメンドアルゴリズム

# 初めに。

LTで作成したので、口語での補足説明を前提としている、かつ5分という制約があるので説明不足な箇所があると思われます、ご注意くださいm(_ _)m

## 内容
機械学習を用いた、アニメレコメンド機能のアルゴリズムの一例を、数式抜きで図解を用いて5分ぐらいで説明。


ゴール：どうやってレコメンドされているか、大体のイメージがつかめればおｋ。

## レコメンドする流れ

##### 1, 好きなアニメのタイトルを入力。

##### 2, おすすめアニメTOP5表示

※視聴済みについての制御はかけない。
※海外ニキのデータです。[myanimelist.net](https://myanimelist.net/)

## よてい (5min)
・データについて。(1min)

・アルゴリズムについて。(3min)

・バッファ(1min)

# データについて。


[Anime Recommendations Database](https://www.kaggle.com/CooperUnion/anime-recommendations-database)(kaggle)
ここからDLしました。


## 中身
animeに対するユーザー毎の10段階評価

 (前処理は省略。ここに最も時間がかかる)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/b8bac28f-6086-6375-1782-514f460c2c65.png)

2966行(縦：アニメタイトル数), 69500列(横：ユーザー数)の行列。

このように成分のほとんどが0である行列を<b>疎行列</b>と呼ぶ。

※実際は疎行列のままだと計算効率が悪いので、csr_matrixで変換します。


# アルゴリズムについて

scikit-learnの<b>NearestNeighbors</b>を使う。(類似度を利用)

## イメージ

１、それぞれのアニメをn次元空間の点に落とし込む

２、入力されたアニメと、距離(あるいは角度)が近いアニメたちをレコメンド

<b>空間でとらえることが重要。</b>

次でそれぞれ詳しく説明！

## １、それぞれのアニメをn次元空間の点に落とし込む

わかりやすく2次元(2人の評価)で考える。
先ほどのデータだと、行列(2966×69500)から2ユーザーpick(2966×2)と考える。

今回は<font color="Red">赤点</font>が入力(選択)された時の おすすめアニメを求める。

※図だと間違えて5段階評価にしちゃってます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/6020347b-5bf5-4824-770e-6ea31408c3a0.png)

わかりやすいようにラベルを付ける。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/6577e35a-09f4-4e52-9996-77c53b9de359.png)

本来であれば、これらのアニメがn次元空間の座標に存在する。(nはユーザーの数)

※僕が適当にラベル付けしたので、実際のデータとは関係ない。

## ２、入力されたアニメと、距離(または角度)が近いアニメたちをレコメンド

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198971/6a98c8b1-8833-a552-8e77-2c1e4aa7c6c1.png)

今回は角度(コサイン類似度)を使うので、原点と結んだ直線2つのなす角が小さいアニメが選ばれる。

図より<b>オーバーロード</b>が最も近い。

※これら以外にも色々な方法がある。また結果も異なる。
[こちらが分かりやすい](https://qiita.com/indigo/items/5c263cd14553808ba109#%E3%83%A6%E3%83%BC%E3%82%AF%E3%83%AA%E3%83%83%E3%83%89%E8%B7%9D%E9%9B%A2%E3%81%AEk-means-1)

## コード

学習（NearestNeighbors）

```python
# モジュール読み込み
from sklearn.neighbors import NearestNeighbors 
nn = NearestNeighbors(algorithm= "brute", metric= "cosine")

# 処理済みのデータを読み込み
model_NN = nn.fit(anime_data_csr)
```

構築したモデルでレコメンド実行！

```python
# 好きなアニメのタイトルを入力（English）
Anime = "Overlord"

# 表示処理、最も近い5つを取り出す。
distance, indice = model_NN.kneighbors(anime_data.iloc[anime_data.index== Anime].values.reshape(1,-1),n_neighbors=6)
for i in range(0, len(distance.flatten())):
    if  i == 0:
        print(anime_data[anime_data.index== Anime].index[0],"が好きな人へのおすすめアニメTOP5")
    else:
        print("【{0}位】【{1}】\n score {2}".format(i,anime_data.index[indice.flatten()[i]],round(distance.flatten()[i],5)),"\n")
```

結果

```terminal
Overlord が好きな人へのおすすめアニメTOP5

【1位】【Gate: Jieitai Kanochi nite, Kaku Tatakaeri】
 score 0.38582 

【2位】【Dungeon ni Deai wo Motomeru no wa Machigatteiru Darou ka】
 score 0.43646 

【3位】【Rokka no Yuusha】
 score 0.44624 

【4位】【Gate: Jieitai Kanochi nite, Kaku Tatakaeri 2nd Season】
 score 0.46009 

【5位】【One Punch Man】
 score 0.48241 
```

# まとめ

pythonのモジュールを使えば、誰でも簡単に実装できる。

ただし、数学のお勉強をしていないと<b>アルゴリズムの取捨選択</b>を正確に行えないので、ある程度知識は必要。


おしまい。

### 参考
[kaggle kernels](https://www.kaggle.com/CooperUnion/anime-recommendations-database/kernels)
[sklearn.neighbors.NearestNeighbors](http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.NearestNeighbors.html)