===== Kálmánův filtr =====
Kálmánův filtr je algoritmus pro filtraci signálů v časové oblasti, velmi často používaný pro predikci neznámých proměnných z dat zatížených šumem a nepřesnostmi. Využívá k tomu nejen naposledy naměřených dat a model systému, ale také vektor údajů o předchozím stavu systému.
Kálmánův filtr je nástrojem k řešení tzv. lineárně-kvadratického gaussovského problému teorie odhadu, který spočívá v odhadu stavu lineárního dynamického systému s gaussovskými náhodnými procesy při použití kvadratické ztrátové funkce. Tento problém zahrnuje tři úlohy:
- **Predikování** spočívá v odhadu stavu systému v určitém čase za využití naměřených pozorování z časů předcházejících času odhadu ($𝑡_{𝑝𝑜𝑧𝑜𝑟𝑜𝑣á𝑛í} < 𝑡_{𝑜𝑑ℎ𝑎𝑑}$).
- **Filtrování** spočívá v odhadu stavu systému v určitém čase za využití naměřených pozorování z tohoto času a z časů předcházejících ($𝑡_{𝑝𝑜𝑧𝑜𝑟𝑜𝑣á𝑛í} ≤ 𝑡_{𝑜𝑑ℎ𝑎𝑑}$).
- **Vyrovnávání** spočívá v odhadu stavu systému v určitém čase za využití naměřených pozorování z časů následujících po čase odhadu ($𝑡_{𝑝𝑜𝑧𝑜𝑟𝑜𝑣á𝑛í} > 𝑡_{𝑜𝑑ℎ𝑎𝑑}$).
==== Implementace algoritmu ====
Algoritmus pracuje ve dvou krocích. V kroku predikce vytváří filtr odhad stavovu systému a nejistoy měření - variance. Jakmile je pozorován výsledek dalšího měření (nutně poškozený určitou mírou chyb, včetně náhodného šumu), jsou tyto odhady aktualizovány pomocí vážený průměru, přičemž větší váha mají odhady s menší variancí. Algoritmus je rekurzivní, může pracovat v reálné čase, s použitím aktuálního měření a dříve vypočítaného stavu a jeho variance.
Optimalita Kalmanova filtru předpokládá, že systém je Gaussovský, v němž platí pro hustotu pravděpodobnosti
$P(x)=\frac{1}{\sigma\sqrt{2\pi}} e^{-(x-\mu)^2}$
V programovacím jazyce Python bychom mohli distribuci popsat třeba následující funkcí. Argumenty funkce jsou $\mu$ a $\sigma^2$.
from math import *
import matplotlib.pyplot as plt
import numpy as np
def f(mu, sigma2, x):
coefficient = 1.0 / sqrt(2.0 * pi *sigma2)
exponential = exp(-0.5 * (x-mu) ** 2 / sigma2)
return coefficient * exponential
Jak provést krok aktualizace? Předpokládejme, že dvě různá měření popsaná Gaussovým rozdělením poskytují různou střední hodnotu a různou varianci. Kombinací obou měření lze vypočítat nové podmíněné rozdělení:
def update(mean1, var1, mean2, var2):
new_mean = (var2*mean1 + var1*mean2)/(var2+var1)
new_var = 1/(1/var2 + 1/var1)
return [new_mean, new_var]
Predikce pak využívá výsledek kroku aktualizace v výpočtu nových hodnot:
def predict(mean1, var1, mean2, var2):
new_mean = mean1 + mean2
new_var = var1 + var2
return [new_mean, new_var]
Představme si nyní úlohu, ve které měříme v diskrétních časových úsecích vzdálednosti a můžeme tedy odhadnout posuny.
measurements = [5., 6., 7., 9., 10.]
motions = [1., 1., 2., 1., 1.]
S počátečním odhadem ''5'' budou další odhady bezvadné, ovšem v našem experimentu nastavíme počáteční hodnotu na ''0'' s vysokou nejistotou ''10000''. Nejistoty měření vzdálednosti a posunu budou pak konstatní.
measurement_sig = 4.
motion_sig = 2.
mu = 0.
sig = 10000.
for n in range(len(measurements)):
# measurement update, with uncertainty
mu, sig = update(mu, sig, measurements[n], measurement_sig)
print('Update: [{}, {}]'.format(mu, sig))
# motion update, with uncertainty
mu, sig = predict(mu, sig, motions[n], motion_sig)
print('Predict: [{}, {}]'.format(mu, sig))
# tisk tabulky s výsledky
print('\n')
print('Final result: [{}, {}]'.format(mu, sig))
Další čtení? [[https://ozzmaker.com/berryimu-python-code-update/]]