LoginSignup
17
13

More than 5 years have passed since last update.

pythonでNMF(非負値行列因子分解)を実装する

Last updated at Posted at 2017-12-10

NMFとは

"Non-negative Matrix Factorization"のこと。
各要素が非負であるような行列$M \in \mathbb{R}^{m \times n}$に対して

M \approx UV^T\\
s.t. \qquad U \in \mathbb{R}^{m \times k},\;V\in \mathbb{R}^{n \times k},\;k < min(m, n)

を満たすような$U, V$(ただし各要素は非負)を生成する手法。

更新式

以下のような更新式を適当な回数適用することで$U, V$が得られる。

import numpy as np

def update_uv(M, U, V):
    U = U * np.dot(M, V) / np.dot(np.dot(U, V.T), V)
    V = V * np.dot(U.T, M).T / np.dot(U.T, np.dot(U, V.T)).T
    return U, V

$U, V$の初期値はランダムな非負の行列。
dotは行列の積、『*』『/』は要素ごとの乗算、除算をあらわすことに注意。

実装

k = 2
m, n = 3, 5
iters = 30

M = np.random.randint(1, 6, (m, n))

U = np.abs(np.random.uniform(low=0, high=1, size=(m, k)))
V = np.abs(np.random.uniform(low=0, high=1, size=(n, k)))

for _ in range(iters):
    U, V = update_uv(M, U, V)

X = np.dot(U, V.T)

# M =
# [[1 4 1 5 4]
#  [5 3 3 1 3]
#  [2 4 2 5 4]]

# X =
# [[ 0.97226794  3.8740713   1.19828474  5.14962285  3.8740713 ]
#  [ 4.9954159   2.96768054  3.05263671  1.04196113  2.96768054]
#  [ 2.02462211  4.14097417  1.77570319  4.83147475  4.14097417]]

コスト関数

$||M - UV^T||_F^2$は以下のように推移する。
figure_2.png

なお……

scikit-learnにはNMFが実装されているので結果だけが必要ならこちらを使えばよい。
http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.NMF.html

17
13
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
17
13