LoginSignup
6
9

More than 5 years have passed since last update.

非負値行列因子分解(NMF)を使ったレコメンドの雰囲気を感じてみる

Posted at

NMF(Non-negative Matrix Factorization)を使用したレコメンドをなんとなくわかった気になったので書き留めてみる。

ユーザ毎のアイテムに対する評価を持っている状況でのレコメンドを考える。

使用するデータは以下。
各アイテムに対する各ユーザの評価値(1-5)を持っている。
0は未評価の項目。

df

nmf_df_before.jpg

NMFを使って未評価の部分を補完した行列を作る。

ただし、通常のNMFはscikit-learnにも実装されているが、欠損値を含む場合には対応していないらしい。
https://github.com/scikit-learn/scikit-learn/issues/8447

欠損値を含むNMFについてはこちらが詳しかった。

def update(Y, W, H, M):
    W = W * np.dot(Y * M, H.T) / np.dot(np.dot(W, H) * M, H.T)
    H = H * np.dot(W.T, Y * M) / np.dot(W.T, np.dot(W, H) * M)
    return W, H

この更新式を適当な回数繰り返し、低次元の$W$, $H$によって$M$に近似させる。

k = 5
M = df.values
n, m = M.shape
W = np.random.rand(n, k)
H = np.random.rand(k, m)
mask_M = (M > 0)

# W,Hの更新を適当な回数繰り返す
# W @ H が徐々に M に近づいていく
for _ in range(100):
    W, H = update(M, W, H, mask_M)

pd.DataFrame(W @ H, index=users, columns=items)

nmf_df_after.jpg

評価のあった項目は元の値に近くなっており、未評価の項目にも値が入っている。
例えばuser_0は未評価のアイテムのうち最も評価値の高いitem_8をレコメンドしよう、となる。

6
9
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
6
9