LoginSignup
16
15

More than 5 years have passed since last update.

PySparkで協調フィルタリング実装してみる

Posted at

協調フィルタリングの概要

協調フィルタリング

協調フィルタリングとは、ユーザの商品の購入・閲覧・評価などの利用情報を基に、ユーザに対しておすすめの商品をレコメンドするアルゴリズム。
ベーシックなアルゴリズムとして、以下の2つがある。

  • アイテムベース
    • ある商品と関連する商品レコメンデーションを行う手法
    • 履歴から同じユーザが利用している商品の類似性を計算する
    • 「この商品を見た人におすすめの商品」
  • ユーザベース
    • ユーザごとに異なる商品レコメンデーションを行う手法
    • アイテムの利用傾向が似ているユーザが利用した商品を重視した評価値を計算する
    • 「あなたにおすすめの商品」

古典的ではあるが、パーソナライズレコメンデーションの中でも実装が簡単でかつ効果が出やすいので人気がある。

スパース性と行列因子分解、ALS

協調フィルタリングにはいくつか問題があり、その中の1つが計算に使用するデータの「スパース性」である。
ユーザは取り扱っている商品のうちほんの1部しか利用しない。つまり、全ユーザ×商品の組み合わせのうち、ほとんどのデータが存在しない状態になっている。
この状態は、前述のレコメンド計算にあたっては、商品間やユーザ間で類似性の計算が難しくなる。

そこで、ユーザと商品を低次元の特徴量行列で表現し、その組み合わせで元のユーザ×商品の行列を再現する(行列因子分解)。
ユーザと商品にはそれぞれ何らかの固有の特徴量があり、その組み合わせ(内積)によって、ユーザが商品を利用するかどうかを推定するという考え方である。

協調フィルタリングでは、ユーザが使った商品あるいは商品を使ったユーザの情報を特徴として類似性の計算を行うが、この操作をすると、スパース性が解消されたユーザ・商品の特徴量行列が手に入り、類似性の計算が容易になる。

ALSは、行列因子分解をして、特徴量行列を計算するためのアルゴリズムである。

  • ユーザの特徴量行列を固定して、誤差が小さくなるように商品行列を変更
  • 商品の特徴量行列を固定して、誤差が小さくなるようにユーザ行列を変更
  • 上記を繰り返す

協調フィルタリングの実装

アイテムベース

商品間の類似度としてコサイン類似度を使用する。
こちらにあるように、pyspark.mllib.linalg.distributed.RowMatrixを使って計算する。

※MLライブラリで同様の機能は知る限り提供されていない
古典的なアイテムベースは、わざわざサポートする必要がないのかもしれない。

ユーザベース

ALSアルゴリズムを使用して、ユーザベースを計算する。
Sparkでは、ALS用のライブラリのpyspark.ml.recommendation.ALSが存在し、これを用いることでユーザベースの計算が行える。

※厳密には、ALSの目的関数に正規化項を加えたALS-WSというアルゴリズムが採用されている

ALSモデルの学習
from pyspark.ml.recommendation import ALS

# data: user_id, item_id, scoreのDataFrame

als = ALS(userCol='user_id', itemCol='item_id', ratingCol='score')
model = als.fit(data)
ALSモデルの推論
N = 10  # レコメンド商品数
model.recommendForAllUsers(N)

ALSクラスの主要なパラメータ

詳しくはリファレンスを参照

引数 デフォルト値 説明
rank int 10 特徴量行列の次元
maxIter int 10 反復計算回数
regParam float 0.1 正規化係数
implicitPrefs bool False 評価値がレビューなどの明示的(explicit)な値であるか、行動データなどの暗黙的(implicit)な値であるか
seed int None シード
nonnegative bool False 非負値行列因子分解(NMF)を行うか
userCol str 'user' 入力DataFrameのユーザ列名
itemCol str 'item' 入力DataFrameの商品列名
ratingCol str 'rating' 入力DataFrameの評価値列名

ALSモデルの主要メソッド

詳細はリファレンス参照

メソッド 説明
recommendForAllItems(numUsers) 全商品にスコア上位numUsers人のユーザを割り当て
recommendForAllUsers(numItems) 全ユーザにスコア上位numItems件の商品を割り当て

ここでは触れないが、ALSで作成したユーザや商品の特徴行列を取得することが出来るので、ユーザ間や商品間の類似度を定義することもできる。

参考

16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15