プログラマーのための数学を使わないカルマンフィルター入門

A non-mathematical introduction to Kalman Filters for programmersの機械訳してみた。 コードやグラフは省略したから原文を参照のこと(そのまま載せるわけにもいかないと思うので…)。

内容はとても分かりやすくカルマンフィルタを理解するには良い説明だと思う。

なぜカルマンフィルターなのか?

カルマンフィルターは独創的だ。 もしカルマンフィルターについて聞いたことがないのであれば、非常に直感的な(そして間違いなく還元的な)考え方として、カルマンフィルターを複数のノイズの多いソースから情報を流し込んで、より正確な1つの統計量に凝縮する漏斗のようなものだと考えればいい。 漠然と聞こえるかもしれないが、心配はいらない。直感をさらに深めるために、この言葉をよりわかりやすい例に置き換えてみよう。カルマンフィルターを研究し推論する上で、数学ほど優れたツールはない、というのは早くから言われてきたことである。 しかし、カルマンフィルターの基礎となる数学が難解で、線形代数、確率論、微積分の要素を含んでいることも同様に事実である。 そのため、すべての人が容易に理解できるものではないかもしれない。 この記事の目的は、このテーマについて自分で深く掘り下げる動機付けとなるような、わかりやすい直観を提供することである。 では、このことを頭の片隅に置きながら始めよう: 「以下は直感を提供するためのものであり、完全なものではないかもしれない」。

まず、”なぜカルマンフィルターが必要なのか?”という質問から始めよう。 この質問に対する単純な、しかし意図的に難解な答えは、現実は完璧ではないということだ。 こんな例を考えてみよう: 港(x=0)から出発し、少し旅をする一次元の船を想像して欲しい。 船のエンジンは、船に一定の速度、例えば10m/sを与えるように設定されている。

港を出て2秒後、船はいったいどこにいるのか? 当然、船は港から2*10=20m離れたところにいると言うだろう。 そして理想的な世界では、これは確かに真実であり、カルマンフィルターは全く必要ないだろう。 しかし、現実の世界では、こんな単純なことはない。 まず、各時点で10m/sという正確な速度を一貫して発生させるだけの力を発生させることができるエンジンが存在しないかもしれない。 確かに、ある時点では10.00001、ある時点では9.999999m/s、あるいはその中間の速度が出るかもしれないが、99.99%完璧でも結局は不完全なのだ。 第二に、仮にそのような完璧なエンジンがあるとしても、正確に測定された力を加えたときに、意図した完璧な速度が得られるとは限らない。 波の動きによって船がほんの少し減速したり、風によってスピードが上がったり、何がどう影響するかは誰にもわからない。

このように、自分の船がどこにいるのかは、自分が望んだ場所を測るだけでは決してわからないのだ。

では、私たちは自分が今どこにいるのか、本当に知ることができない運命にあるのだろうか?そうとも言えない! そこでセンサーの出番だ。船乗りのあなたがGPSを持っているとしよう。GPSは、あなたが今どこにいるのかを正確に教えてくれる! 実際、船の速度は必要ありません。船がどのように走行していても、GPSが常に正確に現在地を教えてくれるからだ。 問題は解決したか?というと、そうでもない。現実には、センサーはバグだらけで信頼できないことが多い。 つまり、センサーは確かに現在地を教えてくれるが、その測定は正確ではないかもしれない。 つまり、GPSは3秒後に港から29.998メートル離れているとか、30.002メートル離れているとか、あるいは100メートル離れているとか言うかもしれない。 さらに、センサーが絶対に誤作動を起こさないとは断言できない。例えばGPSセンサー。衛星が届かない場所にいることを知った瞬間、それは機能しないも同然だ。 確かに、絶対にオフラインにならないと保証できて、知りたいことを任意の精度で測定できるセンサーがあれば、カルマンフィルターは全く必要ないだろう。

これで、なぜカルマンフィルターが必要なのかを説明する準備が整った。 そして、その答えは、先にすでに確立したものと変わらない。カルマンフィルターは、2つ以上の不完全で信頼性の低い情報源を取り込み、知りたいことのより正確な推定値を生成する漏斗である。 この例で言えば、カルマンフィルターは、あなたが今どこにいるかという速度の推定値と、GPSがあればその時刻にどこにいるかというGPSの推定値を入力とし、その両方を合わせたものよりも正確な推定値を出す! そして実際、レーダーやソナー、あるいは水中で今見ている魚の種類など、もっと多くの情報源があれば、理論的にはこれらの測定値を組み合わせて、さらに正確な位置の推定を行うことができる。

待って、数学はどこ?

では、カルマンフィルターが何をするのか、どのようにするのかを、このような数学(ウィキペディアより)を使わずに理解するにはどうすればいいのか、ということだ:

まず、1人の乗客ではなく、1000人の乗客がいて、それぞれがGPSデバイスを持っていると仮定する。 さて、各乗客は、まず以下の方法で速度ベースの推定を行うことで、自分がどこにいるのか(ひいては船がどこにいるのか)を推定することができる:

注:ガウス関数に関するより完全な説明は、下の付録を参照されたい。 今のところは、2番目のパラメータで示された順番の乱数(正/負)を生成するというだけで十分である。

要するに、1000人の乗客の一人一人がやっていることはこうである:(現在より前の時刻の)最後の既知の位置を取り、速度を加え、さらに風と波がコースをわずかに変えることを知っているので、それにいくつかのランダムな推定変動を加える。もし、この乗客たちが風速や水流速を推定する優れた方法を持っていれば、それを使うだろう。 しかし、それがないため、乱数を用いて影響を推定しているのだ。 そして本当に、これは実際の生活でも起こっていることなのだ。すべてを測定することはできないので、平均値(0)と偏差パラメータ(0.1と2)を使って、上でやったような簡単な方法で推定するだけなのだ。

今、我々はカルマンフィルタリングの第二段階、すなわち測定にいる。 この段階では、すべての乗客は、自分たちの状態(自分たちがどこにいるか)についての不完全な知識しか(風や水のノイズのために)持っていないことを知っていて、このように動作するセンサを使用してそれを改善しようとする:

センサーは不正確な機器であること、つまり、ほとんど正しい統計値(この場合、変数true_position)を返しますが、本質的にノイズを持っていることを思い出そう。 さらに、センサーの信頼性の低さもモデル化している。 ある場合(t=3とt=6)、センサーはある要因によって基本的に利用できない!。 したがって、すべての乗客は、任意の時点でセンサーを使用しながら、実際には異なる測定値を取得することになる。

真の旅

今、この船が港を出て、1秒間にこれだけの距離を移動すると想像してみよう:

つまり、船は港(x=0)から出発し、最初の1秒間に9メートル進み、2秒間に10.2メートル進み、19.2メートルで終わる。乗客の仕事は、ノイズが多く信頼性の低い測定値を用いて、各秒におけるこれらの異なる位置を可能な限り正確に予測することである。

つまり、時刻t=1において、乗客は上記の関数からこれらの測定値を得ることができる:

そして、乗客全員がそうだった。真実は何なのか? ニュートン物理学の知識の方が信頼できるのか、それともGPSセンサーの方が信頼できるのか?この特別なケースでは、ボートの真の位置がtrue_position変数から9m離れていることがすでに分かっているので、答えは明白かもしれませんが、常にそうとは限らない。 このようなシナリオでは、これら2つの別々の統計量を組み合わせるために、実際には非常に単純な方法に頼ることになる! つまり、2つの統計の平均をとるのです!これで、上の例のようになります:

結合統計量の誤差は、速度推定値のみよりも小さいが、この例ではセンサー推定値よりも悪いことに注目してほしい。 しかし、ここで重要なのは、単純な平均を取るよりももっと良いことができるということだ。 センサーが最新のものであり、かなり信頼できることが分かっている場合を考えてみよう。 この場合、速度更新よりもセンサーの言うことを優先する必要がある。 加重平均と呼ばれるものを使うことで、これを実現することができる。 次のコードを考えてみよう:

これはソースAとBからの2つの数字を組み合わせたものだが、あなたがこれらのソースをどれだけ信頼しているかも考慮に入れている。つまり

最初の通話では、あなたは情報源A(速度)を情報源B(センサー)よりもはるかに信頼している(10対1)ので、得られる答えは情報源Aに引き寄せられる、つまり9.37に近くなる。 この信頼に基づく加重平均がカルマンフィルターの核心であり、これがカルマンフィルターにデータ結合能力を与えている。

しかし今、私たちは新たな問いを突きつけられている。 どのソースがより信頼できるのか、あるいはどのように信頼度を計算するのか? 速度を優先すべきか?それともGPS測定値を優先すべきなのか?それを決めるのが偏差や分散の指標だ。 考えてみてほしい。 大きく変動する情報源とそうでない情報源。 例えば、10局の天気予報ラジオ局にチャンネルを合わせ、そのうち4局は雨、6局は晴れだと伝えたとしよう。 次に、10個の天気予報サイトにログインし、そのうちの9個が雨になると伝え、1個が晴れになると伝えたとする。 どちらの情報源がより信頼できるだろうか?大多数の気象ラジオ局が言うこと(晴れ)を信じたいだろうか? それとも、天気予報サイトの情報(雨)を信じたいだろうか? 合理的な行動としては、ウェブサイトの結論をより支持することである。 なぜなら、ウェブサイトの多くは結論と一致している、つまり分散が少ないからである。 一方、気象ラジオ局は、少なくともこの例では、結論が乱高下しているように見えるので、あまり信用すべきではないだろう。

完全な更新ステップは次のようになる:

注:分散関数については付録を参照のこと。 今のところは、単に数値のリストの揺らぎの尺度として考えて欲しい。

このコードは比較的簡単だ。 各乗客について、ノイジーな速度ベースの測定とノイジーなセンサーベースの測定を行っている。 すべての乗客のこれらの測定値に基づいて、それぞれの測定値の信頼メトリックを分散の逆数として計算し(分散が増加すると信頼が減少するため)、関連する信頼パラメータでcombineメソッドを呼び出す。 ここで重要なのは、各乗客が自分自身の位置情報を更新していることである。 このような個々の更新の最後に、船自体の実際の位置は、すべての乗客の位置の平均として推測することができる。

結果

上で紹介したコード全体を結びつけるために、以下のコードを使用する。

update_plot関数は、プロット用に一時的な統計情報を保存するための基本的な帳簿管理を行うだけである。 ここでの主なイテレーションは単純に一番下のforループで、乗客が持っている現在の最良推定値を使用して、任意の時点で位置推定値を継続的に更新する。 これらを除けば、コードは基本的に自明である。

seabornライブラリを使ってプロットすると、次のような結果が得られる:

現在のスケールのため、解析は少し難しい。特にt=0.75からt=1、つまりセンサーが正常に機能しているときと、t=2からt=4、つまり不具合があるときの2つの領域にズームインしてみよう。

注:包絡線は不確実性を意味する。線の包絡線が広いほど、その数値の不確実性が高いことを意味する。

最初のケースでは、もう分かると思うが、1000人の乗客全員の位置を合わせた推定値は、速度の推定値だけよりも優れている(緑)! これは、カルマンフィルターが不測の変動による乱高下を自動的に調整し、常にそれなりに信頼できる指標を提供してくれるからだ。 下の図にあるように、センサーが回復すると(t=4からt=5)、カルマンフィルターは再びセンサーを優先し始める (センサーの読み取り値と真の値が重なっているため、少し見づらいが)。

結論と備考

カルマンフィルターがどのように機能するかについて、少なくともある程度の直感は得られたと信じたい。 カルマンフィルターの実際の理論的基礎も同様に興味をそそるものであり、もしあなたの仕事に必要であれば、さらに追求することをお勧めする。 その一方で、形式言語としてのCodeが、一見すると難解な概念に直感を与えるのにどれほど役立つかを示すことができればと思う。 また、簡単なコードの助けを借りて、私が魅力的だと思うトピックについて、もう少し洞察を与えることができればと願っている。

付録

ガウス関数

ここで知っておく必要がある唯一の特別な関数は正規分布関数、すなわちgauss(0, 0.1)とgauss(0, 2)だ。簡単に言うと、これは乱数を与えるもので、ほとんどの場合0に近く(技術的に正しい言い方は0を中心とする)、0から離れた数値を得る確率は2番目のパラメータ、つまり2と0.1によって制御される。

つまり、gauss(0,0.1)を呼び出すと、0.06、-0.07、-0.06、0.02、-0.23、-0.06、0.09などの数値が順不同で得られる可能性が高くなる。

一方、gauss(0, 2)を呼び出すと、1.05, 1.03, -1.06, 0.32, 1.29, -0.40, -1.72などの数値が得られる可能性が高い。

直感的に言えば、2番目のパラメータは標準偏差とも呼ばれ、測定しているものがどれくらい変動するかを制御している。 上のコードでは、これは一般的に、風の偏差が大きすぎる(風の強い日)、水の波の偏差が小さい(穏やかな海)と予想されることを意味する。 下のヒストグラムで、deviation=2、deviation=0.1の数値がどれくらいの頻度で生成されるかに注目して欲しい(X軸に特に注目)。 数値の範囲はかなり異なるが、これらのヒストグラムの形はどちらもほぼ同じに見える。 このような鐘のような形は、ガウス分布、正規分布、鐘曲線分布と呼ばれ、自然界ではよく見られる。

分散

分散は一貫性の尺度である。 つまり、一貫性があれば分散は小さく、その逆もまた然りである。 上の図では、実際にはX軸が自動的に調整されるため、分散をよく見ることができない。 上のヒストグラムを同じ軸の制限内でプロットすると、次のようになる:

最初の画像の方が幅が広いことにお気づきだろうか?それは、数字がかなり変化しているからだ。 つまり、-2s、2s、0sが多く、4s、-4sもあることが予想される。 しかし、2番目の画像では、0や0.1、-0.1などがたくさん見つかると予想されるが、-2や2などはもっと少ないと予想される。 正確には、最初の分布は、(0.01)しかない2番目の分布よりも高い分散(正確には4)を持っている。 分散に関するより詳しい情報は、オンラインで見つけることができる。

Adsense広告