補遺 A インストール方法

本書は Jupyter Notebook で書かれている。Jupyter Notebook はブラウザベースの対話的 Python 環境であり、これを使うと Python コード・文章・数式を一つにまとめることができる──対話的環境がなければカルマンフィルタの理解はほぼ不可能だと私は思う。様々なパラメータを変更してすぐに結果が確認できなければ、パラメータの役割を深く理解するのは難しい。対話的な環境があれば、「~したらどうなる?」のシナリオをすぐに試せる。例えば「\(\mathbf{Q}\) をゼロにしたらどうなる?」と疑問に思ったなら、Jupyter Notebook で試してみればいい。

Jupyter Notebook を選んだもう一つの理由が、たいていの教科書で多くの事項が不透明にされていることだ。例えば疑似コードの隣に美しいプロットがあったとしても、そのプロットの生成に使ったソフトウェアを読者は利用できない。本書を生成するのに必要な全てをあなたが利用できるようにしたかった。どうすれば共分散楕円をプロットできるだろうか? たいていの本では読んでも分からないが、Jupyter Notebook で書かれた本ではソースコードを見るだけだ。

本書をオンラインで読むことにしたとしても、自分でカルマンフィルタを書くには Python と SciPy スタックをインストールする必要がある。これらのライブラリをインストールする方法はいくつもあるので全てをカバーすることはできないが、典型的なシナリオにおけるインストール方法をいくつかここに示す。

SciPy スタックのインストール

本書は IPython, Jupyter, NumPy, SciPy, SymPy, Matplotlib を必要とする。NumPy, SciPy, Matplotlib からなる SciPy スタックはサードパーティの Fortran と C のコードに依存しており、ソースコードからインストールするのは簡単でない。SciPy のウェブサイトではビルド済みのインストールの利用が強く推奨されており、このアドバイスには私も同意する。

Jupyter Notebook は Python をブラウザから実行可能にするソフトウェアである──本書はいくつかの Jupyter Notebook 用ドキュメント (ノートブック) から構成される。IPython は Jupyter とデータ可視化のためのインフラストラクチャを提供する。NumPy と SciPy はフィルタで使う線形代数演算の実装を提供するパッケージである。SymPy は数式処理を行う──式の微分を計算するのに利用される。最後に、Matplotlib はプロットの機能を提供する。

私は Anaconda 社が提供する Anaconda という Python ディストリビューションを使っている。Anaconda には最初から大量のパッケージがインストールされており、上述したパッケージも全て含まれる。IPython のインストール方法を説明するページでは Anaconda が推奨されている。インストールは非常に簡単であり、もしマシンに Python が既にインストールされていても問題はない。Anaconda は https://www.anaconda.com/products/individual からダウンロードできる。提供される最新のバージョンの Python 3 を使うことを強く推奨する。なお本書と FilterPy は Python 3.6 以降に対応する。

SciPy スタックをインストールする方法は他にもあり、手順は http://scipy.org/install.html にある。ただ非常に面倒な場合もあるので、手順をここに載せることはせず、サポートもしない。

多くの Linux ディストリビューションには Python などのパッケージがプリインストールされている。ただ、そういったパッケージが古く、新しいバージョンに依存する本書を読むときに更新が必要な場合が多い。特定の Linux ディストリビューションにインストールされているパッケージを更新する手順は本書の範囲を超える。Anaconda という Python ディストリビューションを使う利点の一つが、ローカルの Python が改変されないために Linux ディストリビューションが破壊されないことである。ただ Anaconda とローカルの Python を一緒のものだと思ってしまう人もいるようだ。Anaconda をインストールしてもローカルの Python を起動すると本書のソフトウェアは正しく動作しないので注意してほしい。

私は依存ライブラリの古いバージョンを使ったレグレッションテストを実行していない。実は古いバージョン (2014 年か 2015 年のバージョン) だと本書は正しく動作しない。本書の技術サポートに人生を費やしたくはないので、最近の Python と SciPy スタックをインストールする仕事は読者に任せる。本書には Python 3.6 以降が必要となる。

最新バージョンの Anaconda で何か不具合があったら、本書の github レポジトリにバグを報告してほしい──本書が最新の Anaconda リリースで正しく動作することは保証するつもりである。ただ古いバージョンでの動作を保証することはしない。申し訳ないが、異なるセットアップの全てに対してサポートを提供するだけの時間を私は持っていない。Jupyter Notebook のようなパッケージは高速に進化しているので、変更に追従した上で後方互換性を保つというのは私には不可能だ。

もし他のプロジェクトで使っているソフトウェアが古いバージョンの Python や Python パッケージを使っているなら、Anaconda には複数のバージョンを独立にインストールする機能があるので利用するとよい。詳細は https://conda.io/docs/user-guide/tasks/manage-python.html にある。

FilterPy のインストール

FilterPy は様々なフィルタを実装したライブラリであり、本書で説明されるフィルタも全て含まれる。インストールは pip で簡単に行える。コマンドプロンプトで次のコマンドを実行するだけだ:

pip install filterpy

FilterPy は私が開発している。最新の開発バージョンは https://github.com/rlabbe/filterpy からいつでもダウンロードできる。

本書のダウンロードと実行

本書1は github レポジトリに保存されている。コマンドプロンプトから次のコマンドを実行するとダウンロードできる:

git clone --depth=1 https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python.git

このコマンドを実行すると Kalman-and-Bayesian-Filters-in-Python という名前のディレクトリが作成される。depth パラメータは最新バージョンだけをダウンロードするよう git に伝えている。コミット履歴を全て見たいのではない限り、--depth=1 を付けた方が速くダウンロードできて空間も節約できる。

もし Git がインストールされていないなら、ブラウザで https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python を開いてそこからノートブックをダウンロードすることもできる。

本書がダウンロードできたら、新しく作成されたディレクトリにコマンドプロンプトから移動して Jupyter Notebook を実行すると読む準備が整う。git コマンドを使った場合には次のコマンドで行える:

cd Kalman-and-Bayesian-Filters-in-Python
jupyter notebook

ブラウザが起動し、本書の各章が含まれたノートブックが一覧で表示されるはずだ。後はノートブックをクリックすれば閲覧できる。

Jupyter Notebook の詳しい情報は http://jupyter-notebook-beginner-guide.readthedocs.org/en/latest/execute.html を参照してほしい。

付属コード

本書でのみ使われるコードはサブディレクトリ kf_book に保存されている。このコードは本書が書き進められるに従って書き直される。そのため細かいドキュメントはしていない。ただこのディレクトリにあるコードを本文中で使うときは軽く説明するので、何をしているかが全く分からないことはないはずだ。

kf_book ディレクトリには XXX_internal.py というファイルがある。これらは各章でのみ利用される Python コードを収めたファイルであり、あまり面白くないコードを隠すのに利用される。グラフを作るときはデータを生成するコードだけに集中するべきで、それをプロットする Python コードに紙面を割くべきではない。もちろん隠されている部分が気になったならソースを確認して構わない。

一部の章では以降の章で利用する関数を定義する。こういった関数は最初 Jupyter Notebook の中で定義されるが、同じコードは kf_book ディレクトリの Python ファイルにも含まれており、後の章で必要になったときはそこからインポートされる。以前の章で定義した関数を使うときはそのことをドキュメントするようにしているが、この作業は進行中である。また私はコピペによる関数の使い回しを避けるようにしている: Python ファイルにあるコードが本文中のコードと違ってしまうことを避けるためだ。しかし私の知る限り Jupyter Notebook には他のノートブックからコードをインポートする機能がないので、コードをノートブック間で共有するにはコピペを使うしかない。

ドキュメントされていない experiments というディレクトリもある。これは本文に入れる前に私がコードを書いたりテストしたりするための場所である。興味深いコードもあると思うから、好きに見てほしい。本を書き進めながら例やプロジェクトを追加する予定なので、このディレクトリにあるコードもいずれ本文中に移されるだろう。小さい実験はそのまま削除されるかもしれない。本書を読むことだけに興味があるなら、このディレクトリは無視しても構わない。

kf_book ディレクトリには本の体裁を整えるための CSS ファイルが含まれる2。デフォルトだと Jupyter Notebook の見た目は少し味気ない。この CSS ファイルは Probabilistic Programming and Bayesian Methods for Hackers といった本を真似て作られている。それから Lorena Barba 博士による素晴らしい講義ノート CFDPython にも大きな影響を受けた。本書の体裁を整えられたのはこういったプロジェクトのおかげである。

Jupyter Notebook の使い方

Jupyter Notebook の完全なチュートリアルは本書の範囲を超える。 簡単に言うと、Jupyter Notebook では「セル」に入力した Python コードを実行できる。Python コードを入力できるセルには In [1]: のような印が付いており、コード自体は四角の領域の中に書き込まれる。Python コードを入力するセルを選択した状態で CTRL+Enter を押すと、セル内のコードが実行されて結果がセルの下に表示される。この例を次に示す:

In [1]
print(3+7.2)
Out [1]
10.2

現在 Jupyter Notebook を使って本書を開いているなら、上のセル内の式を変更して CTRL+Enter を押してみてほしい。セルに入力したコードの実行結果で出力が書き換わるはずだ。

SymPy の使い方

SymPy は数式処理を行う Python パッケージである。本書では SymPy の全ての機能を紹介できないが、代数操作や微分方程式の積分の計算、あるいは微分方程式の求解を SymPy は行える。本書では例えばヤコビ行列や期待値を表す積分を計算するのに SymPy を使う。

まず単純な例を示す。次のコードは SymPy をインポートしてプリティプリントの機能 (式を LaTeX 形式で表示する機能) を有効化し、これから使う SymPy の記号を二つ宣言する:

In [2]
import sympy
sympy.init_printing(use_latex='mathjax')

phi, x = sympy.symbols('\phi, x')
phi
Out [2]
\(\displaystyle \phi\)

Jupyter Notebook が phi を数式として表示していることに注目してほしい。では数学的な操作を行ってみよう。\(\sqrt{\phi}\) の微分は何だろうか?

In [3]
sympy.diff('sqrt(phi)')
Out [3]
\(\displaystyle \frac{1}{2 \sqrt{\phi}}\)

多項式の因数分解もできる:

In [4]
sympy.factor(phi**3 -phi**2 + phi - 1)
Out [4]
\(\displaystyle \left(\phi - 1\right) \left(\phi^{2} + 1\right)\)

多項式の展開も行える:

In [5]
((phi+1)*(phi-4)).expand()
Out [5]
\(\displaystyle \phi^{2} - 3 \phi - 4\)

変数に特定の値を代入したときの式の値を求めるには次のようにする:

In [6]
w =x**2 -3*x +4
print(w.subs(x, 4))
print(w.subs(x, 12))
Out [6]
8
112

定義されていない記号の含まれる式を入力するときは文字列を使うこともできる:

In [7]
x = sympy.expand('(t+1)*2')
x
Out [7]
\(\displaystyle 2 t + 2\)

SymPy を使って次の関数のヤコビ行列を計算してみよう:

\[ h=\sqrt{(x^2 + z^2)} \]

\(x\), \(y\), \(z\) に関する \(h\) のヤコビ行列は次のように計算できる:

In [8]
x, y, z = sympy.symbols('x y z')

H = sympy.Matrix([sympy.sqrt(x**2 + z**2)])

state = sympy.Matrix([x, y, z])
H.jacobian(state)
Out [8]
\(\displaystyle \left[\begin{matrix}\frac{x}{\sqrt{x^{2} + z^{2}}} & 0 & \frac{z}{\sqrt{x^{2} + z^{2}}}\end{matrix}\right]\)

続いて、連続プロセスノイズ行列が

\[ \mathbf Q = \Phi_s \begin{bmatrix}0&0&0\\0&0&0\\0&0&1\end{bmatrix} \]

と与えられるときに、離散プロセスノイズ行列を求めてみよう。求めるべき値 \(\mathbf{Q}_d\) は積分で

\[ \mathbf Q_d = \int_0^{\Delta t} \mathbf F(t)\mathbf Q\mathbf F^T(t)\, dt \]

と定義される。ここで \(\mathbf{F}\) は次の通りである:

\[ \mathbf F(\Delta t) = \begin{bmatrix}1 & \Delta t & {\Delta t}^2/2 \\ 0 & 1 & \Delta t\\ 0& 0& 1\end{bmatrix} \]

この積分は次のように計算できる:

In [9]
dt = sympy.symbols('\Delta{t}')
F_k = sympy.Matrix([[1, dt, dt**2/2],
                    [0,  1,      dt],
                    [0,  0,       1]])
Q = sympy.Matrix([[0,0,0],
                  [0,0,0],
                  [0,0,1]])

sympy.integrate(F_k*Q*F_k.T,(dt, 0, dt))
Out [9]
\(\displaystyle \left[\begin{matrix}\frac{\Delta{t}^{5}}{20} & \frac{\Delta{t}^{4}}{8} & \frac{\Delta{t}^{3}}{6}\\\frac{\Delta{t}^{4}}{8} & \frac{\Delta{t}^{3}}{3} & \frac{\Delta{t}^{2}}{2}\\\frac{\Delta{t}^{3}}{6} & \frac{\Delta{t}^{2}}{2} & \Delta{t}\end{matrix}\right]\)

  1. 訳注: 英語版のこと。[return]

  2. 訳注: 現在のバージョンで custom.css は使われていない。[return]

関連書籍 (Amazon アソシエイト)
確率ロボティクス
詳解 確率ロボティクス Pythonによる基礎アルゴリズムの実装
カルマンフィルタの基礎と実装 -自動運転・移動ロボット・鉄道への実践まで
Estimation with Applications to Tracking and Navigation