Python 機械学習

【Python】fastFMでFactorization Machines(回帰)によるアニメのレコメンドシステムを実装する

この記事は約6分で読めます。

 

今回はレコメンドで最近注目されている「Factorization Machines」というアルゴリズムを使ってみたので実装方法などを紹介したいと思います。

 

Factorization Machinesとは?

 

Matrix Factorizationを一般化したアルゴリズム。

 

  • Matrix Factorizationではユーザとアイテムの情報しか扱えなかったが、それ以外の情報も扱うことができる
  • Logistic Regressionなどと異なり、疎な行列を扱うことができる
  • 特徴量の間で影響を与え合う交互作用(Interaction)を考慮できるため、相関関係がある特徴量も適切に扱うことができる

 

イメージ図

引用:srendle/libfm: Library for factorization machines

 

 

参照:https://zenn.dev/panyoriokome/scraps/d521e032f3be15

前準備

 

ライブラリ

 

前準備としてfastFMをインストールする必要があります。ただこのライブラリは少し癖があり

 

fastFMには、 Linux(Ubuntu 14.04 LTS)およびOS X Mavericks用の継続的インテグレーション/テストサーバー(Travis)があります。他のOSは積極的にサポートされていません。

とのことです

 

# ライブラリをインストールする
$ pip install fastFM

 

あと「No module named ‘category_encoders’」と出た場合は以下もインストールしてください。

 

# ライブラリをインストールする
$ pip install category_encoders

 

ちなみに軽く調べた感じPython3.7だとインストールでCpython関連のエラーが発生するので3.6以下の環境でしか使えないみたいです。GitHubのソースコードを直接読み込むことで動作するかも?

 

データセットの用意

 

今回は業務で協調フィルタリングを用いたレコメンドロジックをPythonで実装した際のメモになります。使用するデータセットはKaggleに用意されているレコメンド用のアニメ視聴データです。

 

簡単なロジックの仕組みとしてはメモリベースでユーザーの視聴履歴からコサイン類似度を計算し、似たようなユーザーを抽出してその評価数値から上位のものをレコメンドするというユーザーベースのレコメンドロジックになります。

 

データセット→ Anime Recommendations Database | Kaggle

 

<前処理>

import numpy as np
import pandas as pd

df_rating = pd.read_csv(r"C:\Users\~~rating.csv")
df_label = pd.read_csv(r"C:\Users\~~anime.csv")

# 量が多いので500000件以上レビューがある人気アニメに絞る
df_label =df_label[df_label['members']>500000]

# anime_idをキーにして内部結合する
df = pd.merge(df_rating, df_label, on='anime_id', how='inner')[['user_id','anime_id','name','rating_x']]

 

<実行結果>

 

import category_encoders as ce
from sklearn.model_selection import train_test_split 

# ユーザーの視聴履歴を集約
user_data = df.pivot_table(index="user_id",columns="name",values="rating_x")

#ユーザーの評価履歴に過去の評価履歴を内部結合(メモリをかなり食うので10000件だけ)
test_df = pd.merge(df_rating.iloc[:10000,:], user_data, on='user_id', how='inner')

# ユーザーIDの列を削除して欠損値を0埋め
test_df = test_df.drop('user_id',axis=1).fillna(0)

data_y = test_df['rating']
data_X = test_df.drop(['rating'], axis=1)

 

<データの分割>

# 指定の列をone-hotエンコード
enc = ce.OneHotEncoder(cols=['anime_id'])
X = enc.fit_transform(data_X)
y = data_y

# データ分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=0)

 

 

スポンサーリンク
スポンサーリンク

Factorization Machinesによるレコメンド回帰予測をPythonで実装する

 

from fastFM import als
from scipy.sparse import csr_matrix
from sklearn.metrics import mean_squared_error, mean_absolute_error

# モデル作成
fm = als.FMRegression(n_iter=1000, init_stdev=0.1, rank=8, l2_reg_w=0.5, l2_reg_V=0.5, random_state=1)
fm.fit(csr_matrix(X_train), y_train)

# 評価

## 学習データへの当てはまり具合
train_loss = mean_absolute_error(y_train, fm.predict(csr_matrix(X_train)))

## テストデータの誤差
test_loss = mean_absolute_error(y_test, fm.predict(csr_matrix(X_test)))

 

als.FMRegression()のパラメーター設定については公式ドキュメント(https://ibayer.github.io/fastFM/api.html)参照

 

評価予測する際の注意点としては予測の際に使用するデータは通常のデータフレームではなく疎行列用のscipyのcsr_matrix()で変換したデータを指定しないといけない点です。

 

ちなみにcsr_matrixは疎行列(0が多くスカスカな行列)を通常の3×3のような行列とは違い([0,0]地点に 1) ([1,1]地点に 3)といった情報のある個所だけを記載した形に変換する関数です。これにより従来の行列よりも計算量を削減することが可能になるみたいです。

 

参考:https://qiita.com/stkdev/items/a1824c4249a519a523fd

 

 

 

 

コメント

タイトルとURLをコピーしました