メモリベース協調フィルタリング
概要
メモリベース協調フィルタリングは、ユーザやアイテムの過去のデータを元に推薦を行う技術である。
主にユーザベースとアイテムベースの二つの手法があり、これらは推薦システムで広く利用されている。
この記事では、メモリベース協調フィルタリングの定義や性質、具体的な応用例について数式とPythonのコードを用いて詳述する。
あくまでも個人的な備忘録である。
ソースコード
github
- jupyter notebook形式のファイルはこちら
google colaboratory
- google colaboratory で実行する場合はこちら
実行環境
OSはmacOSである。LinuxやUnixのコマンドとはオプションが異なりますので注意していただきたい。
!sw_vers
ProductName: macOS
ProductVersion: 13.5.1
BuildVersion: 22G90
!python -V
Python 3.9.17
基本的なライブラリをインポートし watermark を利用してそのバージョンを確認しておきます。 ついでに乱数のseedの設定をします。
import random
import numpy as np
from pprint import pprint
seed = 123
random_state = 123
random.seed(seed)
np.random.seed(seed)
from watermark import watermark
print(watermark(python=True, watermark=True, iversions=True, globals_=globals()))
Python implementation: CPython
Python version : 3.9.17
IPython version : 8.17.2
numpy : 1.25.2
matplotlib: 3.8.1
scipy : 1.11.2
pandas : 2.0.3
Watermark: 2.4.3
メモリベース協調フィルタリングの定義
メモリベース協調フィルタリング(Memory-based Collaborative Filtering)は、過去のユーザの行動データを用いて、将来のユーザの行動を予測する手法である。主に以下の二つの手法が存在する。
- ユーザベース協調フィルタリング:他の類似したユーザの行動を基に推薦を行う手法。
- アイテムベース協調フィルタリング:ユーザが過去に評価したアイテムに類似したアイテムを推薦する手法。
ユーザベース協調フィルタリング
ユーザベース協調フィルタリングでは、まずユーザ間の類似度を計算する。その後、類似度の高いユーザの評価を用いて、対象ユーザに対する推薦を行う。ユーザ間の類似度の計算には、コサイン類似度やピアソン相関係数が用いられる。
コサイン類似度
ユーザ $u$ と $v$ の評価ベクトルをそれぞれ $\mathbf{r}_u$ と $\mathbf{r}_v$ とすると、cos類似度は次のように定義される。
$$ \text{cosine}(u, v) = \frac{\mathbf{r}_u \cdot \mathbf{r}_v}{|\mathbf{r}_u| |\mathbf{r}_v|} $$
ピアソン相関係数
ピアソン相関係数は次のように定義される。
$$ \text{pearson}(u, v) = \frac{\sum_{i \in I_{uv}} (r_{ui} - \overline{r}_u)(r_{vi} - \overline{r}_v)}{\sqrt{\sum_{i \in I_{uv}} (r_{ui} - \overline{r}_u)^2} \sqrt{\sum_{i \in I_{uv}} (r_{vi} - \overline{r}_v)^2}} $$
ここで、$I_{uv}$ はユーザ $u$ と $v$ が両方評価したアイテムの集合であり、$\overline{r}_u$ と $\overline{r}_v$ はそれぞれユーザ $u$ と $v$ の評価値である。
アイテムベース協調フィルタリング
アイテムベース協調フィルタリングでは、まずアイテム間の類似度を計算する。その後、ユーザが過去に評価したアイテムに類似するアイテムを推薦する。アイテム間の類似度の計算にも、cos類似度やピアソン相関係数が用いられる。
メモリベース協調フィルタリングの実装例
以下に、Pythonを用いたユーザベース協調フィルタリングの実装例を示す。ここでは、コサイン類似度を用いてユーザ間の類似度を計算し、推薦を行う。
データセットの準備
まず、適当なサンプルのデータセットを準備する。ここでは、ml-100kにならい映画の評価データを仮定する。
# 適当なサンプルデータの作成
ratings_dict = {
"user_id": [1, 1, 1, 2, 2, 3, 3, 4],
"movie_id": [1, 2, 3, 2, 3, 1, 3, 1],
"rating": [2, 5, 1, 3, 1, 5, 4, 3],
}
ratings_df = pd.DataFrame(ratings_dict)
display(ratings_df)
user_id | movie_id | rating | |
---|---|---|---|
0 | 1 | 1 | 2 |
1 | 1 | 2 | 5 |
2 | 1 | 3 | 1 |
3 | 2 | 2 | 3 |
4 | 2 | 3 | 1 |
5 | 3 | 1 | 5 |
6 | 3 | 3 | 4 |
7 | 4 | 1 | 3 |
ユーザ間の類似度の計算
次に、ユーザ間のcos類似度を計算する。
scikit-learnのcosine_similarity関数を用いると、簡単にユーザ間のcos類似度を簡単に計算できる。 それぞれのユーザーがそれぞれの映画に対して評価を行っているので、ユーザーを行、映画を列とした行列を作成する。pivot_tableを使うと簡単に作成できる。
from sklearn.metrics.pairwise import cosine_similarity
# ユーザごとの評価行列を作成
user_movie_ratings = ratings_df.pivot(index="user_id", columns="movie_id", values="rating").fillna(0)
display(user_movie_ratings)
movie_id | 1 | 2 | 3 |
---|---|---|---|
user_id | |||
1 | 2.0 | 5.0 | 1.0 |
2 | 0.0 | 3.0 | 1.0 |
3 | 5.0 | 0.0 | 4.0 |
4 | 3.0 | 0.0 | 0.0 |
# cos類似度を計算
user_similarities = cosine_similarity(user_movie_ratings)
# データフレームに変換
user_similarities_df = pd.DataFrame(user_similarities, index=user_movie_ratings.index, columns=user_movie_ratings.index)
display(user_similarities_df.round(2))
user_id | 1 | 2 | 3 | 4 |
---|---|---|---|---|
user_id | ||||
1 | 1.00 | 0.92 | 0.40 | 0.37 |
2 | 0.92 | 1.00 | 0.20 | 0.00 |
3 | 0.40 | 0.20 | 1.00 | 0.78 |
4 | 0.37 | 0.00 | 0.78 | 1.00 |
推薦の実施
類似度の高いユーザの評価を基に、対象ユーザへの推薦を行う。
def recommend_movies(user_id, user_similarities_df, user_movie_ratings, num_recommendations=5):
similar_user_list = user_similarities_df[user_id].sort_values(ascending=False).index[1:]
user_ratings = user_movie_ratings.loc[user_id]
weighted_ratings = np.zeros(user_movie_ratings.shape[1])
for similar_user in similar_user_list:
similar_user_ratings = user_movie_ratings.loc[similar_user]
weight = user_similarities_df.loc[user_id, similar_user]
weighted_ratings += weight * similar_user_ratings
recommended_movies = np.argsort(weighted_ratings - user_ratings.values)[::-1]
return recommended_movies[:num_recommendations]
user_id = 1
recommendations = recommend_movies(user_id, user_similarities_df, user_movie_ratings)
print(f"Recommended movies for user {user_id}: {recommendations}")
Recommended movies for user 1: movie_id
3 2
2 0
1 1
Name: 2, dtype: int64
応用例
メモリベース協調フィルタリングは、以下のような場面で応用されている。
- 映画や音楽の推薦:NetflixやSpotifyなどのサービスで利用されている。
- eコマースサイトの推薦:Amazonや楽天などで、ユーザに対する商品推薦に利用されている。
- ソーシャルネットワークの友人推薦:FacebookやLinkedInなどで、友人推薦に利用されている。
結論
この記事では、非常に簡単にではあるが、メモリベース協調フィルタリングの定義や性質、具体的な応用例について数式とPythonのコードを用いて詳述した。
メモリベース協調フィルタリングは、過去のユーザデータを基に推薦を行うシンプルかつ強力な手法であり、多くの分野で応用されている。
しかし、データがスパースな場合やコールドスタート問題などの課題も存在する。これらの課題を解決するためには、より高度な手法やハイブリッドな手法を検討する必要がある。