p_tan's blog

勉強日記です。ツッコミ大歓迎

EigenでNMF

C++の行列演算ライブラリEigenを使うとNMFが超簡単に実装できる。

NMF : Non-negative Matrix Factorization

Wikipediaとか、この文献見るといいです。
Daniel D. Lee and H. Sebastian Seung (2001). "Algorithms for Non-negative Matrix Factorization". Advances in Neural Information Processing Systems 13: Proceedings of the 2000 Conference. MIT Press. pp. 556–562.

コード

#include <Eigen/Core>

/*! ***********************************
 @brief V ≒ WH となるようにNMF
 
 || V - WH || を最小化するようにNMFを実行

 @param[in] V   n x m 行列
 @param[in] k   分解する要素数
 @param[out] W  n x k 行列
 @param[out] H  k x m 行列
 @param[in] loop_max W, Hの更新回数
 @pre k > 0
 ***************************************/ 
void NMF(
    const Eigen::MatrixXd &V, unsigned int k,
    Eigen::MatrixXd &W, Eigen::MatrixXd &H, 
    const unsigned int loop_max = 1000)
{
    // W, Hをランダムな非負数で初期化
    W = Eigen::MatrixXd::Random(V.rows(), k).cwiseAbs();
    H = Eigen::MatrixXd::Random(k, V.cols()).cwiseAbs();
    // W, Hを更新
    for(unsigned int i = 0; i < loop_max; ++i){
        W.array() = W.array() * (V * H.transpose()).array() / 
                     (W * H * H.transpose()).array();
        H.array() = H.array() * (W.transpose() * V).array() /
                     (W.transpose() * W * H).array();
    }   
}

これだけ。EigenマジEigen。