2018年2月1日木曜日

GaussianMixtureとprecisions_cholesky_について

最近, scikit-learnのGMMを使ってプログラムを組むことがあったのでメモ.
間違ってたら斧をなげてください.

GaussianMixture

scikit-learn(sklearn)は主に機械学習に用いられるPythonライブラリです.
機械学習の中の一つに教師なし学習がありますが, それをするためにGMMを使います.
GMMを使うには
import sklearn.mixture
して
gmm = sklearn.mixture.GaussianMixture(n_components=32, covariance_type='full', max_iter=100)
で呼び出せます. コンストラクタ内のパラメータは適当です. 内容に沿って変えてください.
gmm.fit(data)
をすると学習からモデルパラメータを最適にしていきます. 
参考: Furukawa Laboratory 素晴らしいデモが見られます.

詳しい使い方は割愛. 

学習済みGMMパラメータを取り出す

学習したGMMのモデルパラメータは取り出せます.
weight = gmm.weight_
means_, covariances_なども同様に取り出せます.

新しいGMMにモデルパラメータを入れる


新しいGMMに学習済みGMMのモデルパラメータを入れることができます.
new_gmm = sklearn.mixture.GaussianMixture(n_components=32, covariance_type='full', max_iter=100)
new_gmm.weight_ = weight
new_gmm.means_ = mean
new_gmm.covariances_ = cov

この時, new_gmm.precisions_cholesky_も入れないとpredict_proba()が使えません.
これは, 内部の_check_is_fitted()で学習したかどうかの判定で, precisions_cholesky_がチェックされているからです.

precisions_cholesky_

precisions_cholesky_はなんでしょうか?

内部を見てみると, GaussianMixtureクラスがSuper()を使っているので親クラスBaseMixtureクラスと関係がありそうです. 

GaussianMxitureクラスの中に_initialize()があります. fit()時に, _initialize()でprecisions_choleskyは設定されるようです.
self.precisions_cholesky_ = _compute_precision_cholesky(covariances, self.covariance_type)

このことから, _compute_precision_cholesky()にはEMアルゴリズムで分散を推定する役目がありそうです.
そもそも, precisions_cholesky_についてdocumentは何をいっているのか?
The cholesky decomposition of the precision matrices of each mixture component. A precision matrix is the inverse of a covariance matrix. A covariance matrix is symmetric positive definite so the mixture of Gaussian can be equivalently parameterized by the precision matrices. Storing the precision matrices instead of the covariance matrices makes it more efficient to compute the log-likelihood of new samples at test time. 
そもそも, precision matrixがわからないです. 共分散行列の逆行列を精度行列(precision matrix)というらしいです(参考). 精度行列を使うことで, より効率的に計算ができる, みたいな感じでしょうか?

とりあえず, ここを参考に,
from sklearn.mixture.gaussian_mixture import _compute_precision_cholesky
new_gmm.precisions_cholesky_ =_compute_precision_cholesky(covariances_, "full")
と書いておきます. covariances_ = covとしておこう.