PyKalmanパッケージのインストールとコードの修正
Pythonでカルマンフィルタをやりたいなと思って調べたところ、PyKalmanというパッケージがありました。便利そうな作りなのでしばらくこれで遊んでみることにします。
PyKalmanのインストール
最新バージョンは PyKalman 0.95 です。
公式リファレンス: pykalman — pykalman 0.9.2 documentation
GitHub: GitHub - pykalman/pykalman: Kalman Filter, Smoother, and EM Algorithm for Python
pipでのインストール
$ pip install pykalman
でインストール出来ます。 ただし、何故かアンイストールが上手くできず、いつも停止します。僕だけかもしれない。
condaでのインストール
$ conda install pykalman -c phios
でインストールできます。 他のチャンネルでインストールしたい場合は
$ anaconda search -t conda pykalman
を実行するとインストール可能なチャンネルが出てきます。
GitHubからのインストール
$ git clone https://github.com/pykalman/pykalman.git
$ cd pykalman
$ python setup.py install
とすればインストールできます。
コードの修正とデータセットの追加
今のところ、一箇所だけバグがあったので修正しました。
PyKalmanをインストールしたPythonのディレクトリを
C:\python27
とします。 PyKalmanは次の場所にインストールされています。
C:\python27\lib\site-packages\pykalman
GitHubからインストールした方以外の場合
GitHubからクローンを取ってきて直接インストールした場合以外では、なぜか
pykalman/datasets/data pykalman/datasets/descr
が存在しませんでした。 これをGitHubから取ってきて追加しましょう。
GitHub - pykalman/pykalman: Kalman Filter, Smoother, and EM Algorithm for Python
上記のGitHubをダウンロードして、その中身には
pykalman/datasets/data pykalman/datasets/descr
がありますので、これをディレクトリごとコピーして、pykalmanをインストールしている場所の中の
C:\python27\lib\site-packages\pykalman\datasets
の中にコピーしてしまいましょう。 この結果の正しいディレクトリ構成は次のようになります。
./pykalman ┃ ┗ /datasets ┃ ┣ /data ┃ ┗ robot.mat ┣ /descr ┃ ┗ robot.rst ┣ __init__.py ┗ base.py
コードの修正
色々といじくっていたらバグがありました。とは言ってもそこまで主要な部分に影響を及ぼさないので気にならない方はそのままでいいと思います。以下の修正部分を示します。
C:\python27\lib\site-packages\pykalman\standard.py
をエディタで開きます。 その中の一番最後の部分、1529行目にある_parse_observations(self, obs)という関数の内容を変更します。
# 1529行目 def _parse_observations(self, obs): """Safely convert observations to their expected format""" obs = np.ma.atleast_2d(obs) if obs.shape[0] == 1 and obs.shape[1] > 1: obs = obs.T return obs
となっているはずです。これを以下のように修正しましょう。
# 1529行目 def _parse_observations(self, obs): """Safely convert observations to their expected format""" # obs = np.ma.atleast_2d(obs) obs = np.atleast_2d(obs) if obs.shape[0] == 1 and obs.shape[1] > 1: obs = obs.T return obs
これで保存して終了です。
これでどういうバグが発生していたかと言うと、loglikelihoodという関数を使用する際に、引数にNumPyのArrayを代入します。この際に上記の_parse_observations(self, obs)に渡したArrayが代入され、MaskedArrayという形式に変更させられていたわけです。
しかしloglikelihood関数の内部ではSciPy.linalgのtriangular_solve関数が用いられます。triangular_solveは内部でMaskedArrayを拒否する設定になっているので_parse_observations(self, obs)でMaskedArrayに変換されるとエラーを起こすわけです。これがバグの原因でした。
_parse_observations(self, obs)のコメントに書いてあるように
"""Safely convert observations to their expected format"""
つまり「他の関数がちゃんと動作するために引数のArrayを安全な形式に変換する」と書かれています。
np.atleast_2dは引数のArrayを最小2次元Arrayに変換しますが、
np.ma.atleast_2dは、引数のArrayを最小2次元MaskedArrayに変換します。
ここがダメだったので普通のnp.atleast_2dに変更したわけです。