半教師あり NMF による音源分離を Python で実装した

非負値行列因子分解 (NMF; Non-negative Matrix Factorization) は、非負値からなる行列 \boldsymbol{Y} \in ℝ^{m \times n} を、\boldsymbol{H} \in ℝ^{m \times k}\boldsymbol{U} \in ℝ^{k \times n} の積で近似する数学的な操作で、\boldsymbol{H} の列は基底パターンを、\boldsymbol{U} の行は基底パターンの重みを表す。

音響学においては、スペクトログラムを非負値からなる行列とみなして NMF で分解すれば、\boldsymbol{H} は周波数基底を、\boldsymbol{U} は時系列ごとの周波数成分基底の強さを表すことになる。

ここで、分離したい楽器の音から求めた周波数基底をあらかじめ与えて固定化し NMF を適用すれば、高精度で目的の楽器音が分離できる。このように固定的な基底を教師データとして与えられるように NMF を拡張したものを半教師あり NMF (SSMNF; Semi-Supervised NMF) という。

Python機械学習用ライブラリ scikit-learn には NMF の実装がある が、SSNMF の実装がなかったので、ギリギリの数学力で独自に実装して試してみた。

実装コードと実験結果のデモ

一応分離できているけど音がガビガビする。参考にした文献「非負値行列因子分解 NMF の基礎と データ/信号解析への応用」には

基底 T に時間方向の連続性を持たせた convolutive NMF

というものを用いているそうで、これを試した結果も気になるけど、有料の論文だったので実装実験はここまでにした。

それと、Python のパッケージシステムの理解のために SSNMF の実装を nmftools というライブラリにしてみた。パッケージのレイアウトができていれば、PyPI に登録してなくても pip でリポジトリURI を指定することでインストールできるんですね。

pip install git+https://github.com/keik/nmftools.git