PythonでNMFやるには,nimfaというパッケージを使えばよいらしいです.とりあえず使うだけなら,適当なnumpy行列vecを用意して,以下のように関数に投げてあげます.
factor = nimfa.mf(vec, seed='random_vcol', method='nmf', rank='5', max_iter=10) res = nimfa.mf_run(factor).basis()
とりあえずシードはランダムで,手法はベーシックなnmf.何次元に削減するかをrankで指定して,イテレーション回数を決めればOKです.
nmfは関連手法が山ほどあって,ざっと以下のようになります.説明文は基本的に意訳です.正直意訳があってるかも自信はないので,こちらから元論文を読みましょう*1.
手法 | 概要 |
---|---|
BD | ギブスサンプラーを使ったベイジアンNMF |
BM | バイナリのMF |
ICM | Iterated conditional modesを用いたNMF*2 |
LFNMF | 局所特徴量を用いたフィッシャーのNMF |
LSNMF | 最小二乗法を用いたNMF |
NMF | 通常のNMF(更新式としてユークリッド/KL情報量,損失関数としてFrobenius/divergence/connectivityが指定可能) |
NSNMF | non-smoothなNMF |
PMF | 確率的NMF |
PSMF | 確率的スパースMF |
SNMF | 最小二乗制約に基づく非負性を用いたスパースNMF |
SNMNMF | スパース正則化ネットワークNMF |
PMFCC | 制約クラスタリングによる罰則MF |
ということで,実際に回してみました.前回のマンションポエムデータ,218サンプル*1797次元のデータを10次元に圧縮します.これを10回繰り返して得られた10の圧縮行列に対して,適当なidを選んで類似度上位10件のデータを抜き出し,その一致度を集計しました.
結果は以下の通りで,時間がかかるものほど一致率も高く安定的な結果ということのようです.とはいえ安定しているから結果が良いかというと,パッとみた感じそんなに手法ごとに精度の差が歴然としているかといわれると,若干首をひねらざるを得ない感はあります*3.にしても,全体的に安定性はイマイチです... そしてBDとかPMFとかは,とにかく重すぎてパパッと結果も帰ってこず.まぁギブスサンプラーとか使ってたら思いに決まってるわけですが...
手法 | 一致度 | NMFの算出にかかった時間 [秒] |
---|---|---|
NMF | 16.7% | 0.45秒 |
LSNMF | 30.4% | 0.94秒 |
BMF | 17.8% | 0.33秒 |
SNMF | 40.7% | 47.95秒 |
もう少しちゃんとパラメタとかチューニングしないといけないなぁという思いしかない.