Matematika v robotice 11. Exponenciální klouzavý průměr

4. srpna 2013 v 4:37 | Petr |  Roboti a Matematika
Miliardář a bojovník proti korupci Karel Janeček založil firmu, která je zdrojem jeho bohatství v roce 1995. Ta firma se jmenuje RSJ a zabývá se tím, že počítače řízené softwarem s umělou inteligencí obchodují na burzách po celém světě. Mnohem méně známé je, že stejnou ideu jsme s Ondřejem Bendou měli už o rok dříve než Karel Janeček (který je o rok mladší) a že jsme v roce 1994 začali experimentovat s obchodováním pomocí softwarových "agentů" řízených pravidly, které vybíraly "genetické algoritmy" - no prostě nebyl jsem vždycky programátorský neumětel, jako jsem teď ....

Proč je miliardář Karel Janeček a ne já ? Já jsem v té době byl máti z domu vykopnutý a nekonečnými zkouškami trápený medik, Ondřej Benda byl v té době student, kterého znechutily "dřistoprdy" na divadelní fakultě JAMU a na nás oba se podvodníci ve finanční sféře dívali velmi podezřívavě. Karel Janeček měl navíc nimbus geniálního "matfyzáka" - který má zakázáno navštěvovat kasina v Las Vegas - protože v nich - díky své genialitě - mnohokrát rozbil bank.....

Zdá se, že jsem odbočil, ale nikoliv, protože co jsou ceny na burze - data zatížená šumem. Jak se s nimi pracuje - pomocí klouzavých průměrů. Mně se například v roce 1994 velice líbila tzv. Bollingerova stuha - což je naprosto stejný klouzavý průměr, který jsme probírali minule. (Schválně si odkliněte ten link).

Druhou variantou Bollingerovy stuhy byl "Exponential moving average". Tedy exponenciální klouzavý průměr. Představte si že místo prográmku s kruhovým bufferem, který jsme si popisovali minule :
i=1
WHILE ( !END ) {
POSLEDNI = BUFFER [i]
SUMA = SUMA - POSLEDNI + X
Y = SUMA / 10
BUFFER [i] = X
i = i + 1
IF i > 10 THEN i = 1
}
Napíšete jenom a pouze
WHILE ( !END ) {
Y = ( 9 * Y + X ) / 10
}
Jednoduché jako facka na hodině matematiky ne ? V čem je tedy kouzlo ?
Vtip je v tom, že místo abyste průměrovali 10 sousedních hodnot, které musíte udržovat v kruhovém bufferu atd. Tak prostě novou hodnotu spočtete jako 90% starého výsledku + 10% nového měření.
Jak se takový exponenciální průměr chová - vidíte na obrázku. K objasnění používáme tzv. "Diracovu jednotkovou funkci" která ale má v bode 0 hodnotu nekonečno - s tím jsou trošku problémy - tak používáme její integrál (nepodstatné). Co je podstatné je tohle - po náhlé změně vstupu - fialový lineární klouzavý průměr - prostě klesá lineárně až se ustálí na nové hodnotě. Exponenciální klouzavý průměr se na začátku mění stejně jako lineární, ale přesné hodnoty nového vstupu nikdy nedosáhne.....
Navíc - jak jste si jistě všimli tak exponenciální klouzavý průměr vnáší do signálu ještě větší zpoždění než lineární průměr. Nidky jsem to matematicky nestudoval, ale zkušednost říká, že lineárnímu klouzavému prměru 10 sousedních prvku (tedy N=10) odpovídá exponenciální klouzavý průměr přibližně poloviční síly tedy N=5.
Že si úplně nevymýšlím vidíte na obrázku - Všimněte si "zázračné" shody žluté a fialové křivky. Tedy v praxi téměř vždy místo otravování se s kruhovým bufferem pro 10 hodnot stačí spočítat něco jako
Y = ( 4 * Y + X ) / 5
Mimochodem když jsme mluvili o "síle" exponenciálního klouzavého průměru doufám že jste pochopili, že exponenciální průměr síly (stupně N) se počítá jako
Y = (Y * (N-1) + X) / N
tedy
N = 2 .... Y = (Y+X) / 2
N = 3 .... Y = (2*Y+X) / 3
N = 4 .... Y = (3*Y+X) / 4 atd ....
Proč jsem jako programátor v Assembleru klouzavý průměr tak miloval ?
No pokud si zvoíte N jako mocniny 2 tedy 2, 4, 6, 16 atd pak v assembleru počítáte klouzavý průměr třeba pro N=8 takto
Y = ( (Y << 3) - Y + X + 4 ) >> 3
Tedy tak složitou věc jako EXPONENCIÁLNÍ kouzavý průměr počítáte bez jediného násobení, nebo dělení - zajímavé ne ? Už rozumíte proč jsme v přechozích dílech tak drilovali násobení a dělení bitovým posuvem ?
Ještě než skončíme - dovolím si vám prozradit informaci, které žádná žena neodolá: Klouzavé průměry jsou totéž co dolní propusti v numerickém zpracování signálu (DSP algoritmech).
Exponencíální klouzavý průměr je naprosto přesně totéž co RC dolní propust z analogové elektroniky a "vědecky" se mu říká "Infinite impulse response filter" neboli "filtr s nekonečnou impuslní odzevou". Lineární klouzavý průměr nemá svůj ekvivalent v analogové elektronice - nicméně numerickému filtru tohoto typu se říká "Fininte impulse response filter" - tedy něco jako "filtr s konečnou impulsní odezvou".
Schválně si proklikejte odkazy - abyste viděli jak "složitou matematiku" jsme dneska probrali. Myslím, že tak složitou, že pokud se dostatečně ledabyle zmíníte o tom, čemu rozumíte před vaší potenciální kořistí, žádná žena "která za to stojí" vám neodolá a dopadnete jako já - takže pozor !!!

Nezbývá než několik poznámek na závěr:
Exponenciální klouzavý průměr napodobuje RC fitry tak důkladně, že se může při špatném nastavení i rozkmitat (schválně si to zkuste pro N = - 2)
Obsah této kapitoly prosím naprogramujte do svého robota, ale rozhodně jej nevykládejte nikde ve škole - robot vám bude fungovat, ale já vaše studijní výsledky vaším sdělovat nebudu - pěkně se to naučte i se všemi integrály Tau a Epsilon - jak to máte v těch odkazech.

Zbývá už jenom rada paní Kubáčové novomanželkám - Vysoké podpatky, krátké sukně, dlouhé vlasy - to všechno miláčka dovelo rozvášnit před svatbou - teď k tomu přistupuje i umytá podlaha, vyžehlené prádlo a uvařená večeře - vidíte jak vaše možnosti po svatbě stoupají ?
 

Buď první, kdo ohodnotí tento článek.

Komentáře

1 Mroks Mroks | 5. srpna 2013 v 12:23

na robotike.cz Zbyněk Winkler píše:

"Odhad plovoucího průměru

Pokud si nechceme nebo nemůžeme pamatovat všechna měření z průměrovacího okna, musíme se pokusit tato data něčím nahradit, nějak je odhadnout. Nejlepší odhad nejstaršího měření, které bychom chtěli z výpočtů odstranit, je poslední hodnota průměru. Místo vlastního měření, tedy odečteme posledni průměr:
avg = (avg*k - avg + y[n]) / k;
Při zápisu pomocí korekce pak:
avg = avg + 1/k * (y[n] - avg);
Touto úpravou získáme jednoduché, rychlé a praktické řešení, které bude ve většině případů dostačující. Popisované řešení se někdy nazývá průměrování s exponenciálním zapomínáním, protože výsledná hodnota obsahuje např. i naše první měření y[Smazaný komentář]. Jeho váha je však ((k-1)/k)^n a tedy exponenciálně klesá."

na a práve vzorec:"avg = (avg*k - avg + y[n]) / k;"  je ideálny pre celočíselnú matematiku - pre k= mocnina 2 sú to len bitové posuny a odčítanie, sčítanie. Dokonca netreba ošetrovať záporné čísla, ako pri druhom vzorci (zápis pomocou korekcie). Samozrejme len v prípade, že priemerované hodnoty sú len kladné...

A do tejto idylky mi "nepasujú" Tvoje váhy : "Tak prostě novou hodnotu spočtete jako 90% starého výsledku + 10% nového měření."

2 petr-kubac petr-kubac | 5. srpna 2013 v 18:09

Vezmeme Zbyňlův vzorec avg = (avg*k - avg + y[n]) / k a spočteme koeficienty pro K=8
AVG = (AVG*8 - AVG + Y[n]) / 8 neboli po úpravě AVG = (7 * AVG + Y) / 8 - neboli Winkler a Kubáč se vůbec neliší ....

Ještě k těm vahám
Váha současného Y je 1/8
váha minulého Y je 1/8 * 7/8
Váha předminulého Y je 1/8 * 7/8 * 7/8

a tak dále a tak podobně - tedy současné Y má největší váhu přestože to je jenom 1/8

Jasné ?

3 Mroks Mroks | 6. srpna 2013 v 6:06

[2]:Vraviam sa späť do školy.....

Komentáře jsou uzavřeny.


Aktuální články

Reklama