Friday 18 August 2017

Exponential Glidande-Medelvärde Filter Algoritmen


Är det möjligt att implementera ett glidande medelvärde i C utan att det behövs ett fönstersamtal Ive har funnit att jag kan optimera lite genom att välja en fönsterstorlek som är en kraft av två för att tillåta bitskiftning istället för att dela men behöver inte en buffert skulle vara trevligt. Finns det ett sätt att uttrycka ett nytt glidande medelresultat endast som en funktion av det gamla resultatet och det nya provet Definiera ett exempel glidande medelvärde, över ett fönster med 4 prov att vara: Lägg till nytt prov e: Ett glidande medel kan implementeras rekursivt , men för en exakt beräkning av glidande medelvärde måste du komma ihåg det äldsta inmatningsprovet i summan (dvs. a i ditt exempel). För ett längd N rörligt medelvärde beräknar du: var yn är utsignalen och xn är ingångssignalen. Eq. (1) kan skrivas rekursivt som Så du behöver alltid komma ihåg provet xn-N för att kunna beräkna (2). Som påpekat av Conrad Turner kan du använda ett (oändligt långt) exponentiellt fönster istället, vilket gör det möjligt att beräkna utmatningen endast från tidigare utmatning och aktuell ingång: men det här är inte ett vanligt (obetydligt) glidande medelvärde men exponentiellt viktade glidande medelvärde, där prov i det förflutna får en mindre vikt, men (åtminstone teoretiskt) glömmer du aldrig någonting (vikterna blir bara mindre och mindre för prover långt ifrån). Jag implementerade ett glidande medelvärde utan individuellt objektminne för ett GPS-spårningsprogram som jag skrev. Jag börjar med 1 prov och dela med 1 för att få nuvarande avg. Sedan lägger jag till ett prov och delar upp med 2 till den nuvarande avg. Detta fortsätter tills jag når längden på medeltalet. Varje gång efteråt lägger jag till i det nya provet, får medelvärdet och tar bort det genomsnittet från summan. Jag är inte matematiker men det verkade som ett bra sätt att göra det. Jag tänkte att det skulle vända på magen på en riktig matte kille men det visar sig att det är ett av de accepterade sätten att göra det. Och det fungerar bra. Kom bara ihåg att ju högre längden desto långsammare följer du vad du vill följa. Det kan inte ha betydelse för det mesta, men när du följer satelliter, kan du vara långsiktig, om det är långt ifrån det faktiska läget och det kommer att se dåligt ut. Du kan ha ett mellanrum mellan mitten och de efterföljande prickarna. Jag valde en längd på 15 uppdaterad 6 gånger per minut för att få tillräcklig utjämning och inte komma för långt från den faktiska lätta positionen med de släta spårpunkterna. svarat 16 november 16 kl 23:03 initialisera totalt 0, count0 (varje gång vi ser ett nytt värde) Då en inmatning (scanf), en lägg till totalnevValue, en ökning (räkning), en delningsgenomsnitt (totalantal) Detta skulle vara ett glidande medelvärde över alla ingångar För att beräkna medelvärdet över endast de senaste 4 ingångarna, skulle det behöva 4 ingångsvariabler, kanske kopiering av varje ingång till en äldre ingångsvariabel och sedan beräkning av det nya glidande medlet. Som summan av de fyra ingångsvariablerna dividerad med 4 (höger skift 2 skulle vara bra om alla ingångar var positiva för att få den genomsnittliga beräkningen besvarad 3 feb 15 kl 4:06 som faktiskt kommer att beräkna det totala genomsnittet och INTE det glidande genomsnittet. När räkningen blir större blir effekten av ett nytt ingångsprov försvinnande liten ndash Hilmar Feb 3 15 kl 13:53 Ditt svar 2017 Stack Exchange, Inc Jag kodar någonting för tillfället där jag tar en massa värden över tiden från en hårdvarukompass. Den här kompassen är mycket exakt och uppdateras mycket ofta, med det resultat att om det jiggles något slutar jag med det udda värdet som är vildt inkonsekvent med sina grannar. Jag vill släta ut dessa värden. Efter att ha läst lite läsning verkar det som att jag vill ha ett högpassfilter, ett lågpassfilter eller ett glidande medelvärde. Flyttande medelvärde jag kan gå ner med, behåll bara en historia av de senaste 5 värdena eller vad som helst, och använd medelvärdet av dessa värden nedströms i min kod där jag en gång bara använde det senaste värdet. Det borde jag, släpa ut dem jigglar snyggt, men det slår mig att det är förmodligen ganska ineffektivt, och det är förmodligen ett av de kända problemen för rättprogrammerare där det är en riktigt snygg kladdmatlösning. Jag är emellertid en av de hemska självlärda programmörerna utan en form av formell utbildning i vad som helst vagt relaterat till CompSci eller Math. Att läsa runt lite tyder på att det här kan vara ett högt eller lågt passfilter, men jag kan inte hitta någonting som förklarar vad som är begripligt för ett hack som jag, hur effekten av dessa algoritmer skulle vara på en uppsättning värden, än mindre hur matematiken Arbetar. Svaret som ges här. till exempel, svarar tekniskt på min fråga, men bara i förståelse för dem som förmodligen redan vet hur man löser problemet. Det skulle vara en väldigt härlig och smart person som vem skulle kunna förklara det här problemet, och hur lösningarna fungerar, vilket är begripligt för en kandidatexamen. frågade 21 sep 10 kl 13:01 Om ditt rörliga medelvärde måste vara långt för att uppnå den nödvändiga utjämningen och du inte behöver någon särskild form av kärna, så är du bättre om du använder ett exponentiellt förfallande glidande medelvärde: var du välj liten för att vara en lämplig konstant (t. ex. om du väljer liten 1- 1N, kommer den att ha samma mängd medelvärde som ett fönster av storlek N, men distribueras annorlunda över äldre punkter). Hur som helst, eftersom nästa värde av det rörliga genomsnittet bara beror på den föregående och dina data behöver du inte behålla en kö eller något. Och du kan tänka på det här som att göra något, ja, jag har en ny punkt, men jag litar verkligen inte på det, så jag ska hålla 80 av min gamla uppskattning av mätningen och lita bara på den nya datapunkten 20. Thats Tämligen detsamma som att säga, Tja, jag litar bara på den här nya punkten 20, och jag använder 4 andra punkter som jag litar på samma belopp, förutom att istället för att uttryckligen ta de 4 andra punkterna antar du att den genomsnittliga tiden du gjorde förra gången var förnuftigt så att du kan använda ditt tidigare arbete. svarat 21 sep 10 kl 14:27 Hej, jag vet att det här är 5 år sent, men tack för ett fantastiskt svar. I39m arbetar på ett spel där ljudet ändras baserat på din hastighet, men på grund av att du kör spelet på en slow-ass-dator, skulle hastigheten fluktuera vildt, vilket var bra för styrning, men mycket irriterande när det gäller ljud. Det var en väldigt enkel och billig lösning på någonting som jag trodde skulle vara ett väldigt komplext problem. ndash Adam Mar 16 15 kl 20:20 Om du försöker ta bort det enstaka udda värdet är ett lågpassfilter det bästa av de tre alternativen du har identifierat. Lågpassfilter tillåter låghastighetsförändringar som de som orsakas av att man roterar en kompass för hand, medan man förkastar höghastighetsförändringar, till exempel de som orsakas av stötar på vägen. Ett glidande medelvärde kommer förmodligen inte vara tillräckligt, eftersom effekterna av ett enda blip i dina data kommer att påverka flera efterföljande värden beroende på storleken på ditt glidande medelfönster. Om de ojämna värdena lätt kan detekteras kan du till och med vara bättre med en glitch-avlägsnande algoritm som helt ignorerar dem: Här är en gickdiagram som illustrerar: Den första grafen är ingångssignalen, med en obehaglig glitch. Den andra grafen visar effekten av ett rörligt medelvärde på 10 prov. Slutgrafen är en kombination av 10-provvärdet och den enkla glitchdetekteringsalgoritmen som visas ovan. När glitchen detekteras används 10-provsmedlet istället för det faktiska värdet. svarat 21 sep 10 kl 13:38 Nätt förklarad och bonuspoäng för grafen) ndash Henry Cooke 22 sep 10 kl 0:50 Wow. Sällan såg ett bra svar ndash Muis 4 juni 13 kl 9:14 Det rörliga genomsnittet är ett lågpassfilter. ndash nomen 21 okt 13 kl 19:36 Prova en löpande median istället. ndash kert 25 apr 14 kl 22:09 Flyttande medelvärde Jag kan komma ner med. men det verkar som om det är ganska ineffektivt. Theres verkligen ingen anledning att ett rörligt medelvärde borde vara ineffektivt. Du behåller antalet datapunkter du vill ha i en viss buffert (som en cirkelkö). På varje ny datapunkt popar du det äldsta värdet och subtraherar det från en summa och trycker på det nyaste och lägger det till summan. Så varje ny datapunkt innebär egentligen bara en poppush, ett tillägg och en subtraktion. Ditt rörliga medelvärde är alltid denna förskjutande sum dividerad med antalet värden i din buffert. Det blir lite svårare om du tar emot data samtidigt från flera trådar, men eftersom dina data kommer från en hårdvarubutik som verkar mycket tveksamt för mig. Åh och också: hemska självlärda programmerare förenar) Det rörliga genomsnittet verkade ineffektivt för mig eftersom du måste lagra en buffert med värden - bättre att bara göra lite Clever Maths med ditt inmatningsvärde och nuvarande arbetsvärde Jag tror att det är hur exponentiell glidande medelvärde Arbetar. En optimering som jag har sett för den här typen av glidande medelvärde innebär att du använder en fast-längd köförstärkare en pekare till var du befinner dig i den köen och bara sveper pekaren runt (med eller om). Voila Ingen dyr manchet. Kraft till amatörerna, bror ndash Henry Cooke Sep 22 10 på 0:54 Henry: För ett rakare rörligt medel behöver du bufferten helt enkelt så att du vet vilket värde som dyker upp när nästa värde blir skjutit. Med detta sagt, den kvoterade längdköppen förstärkaren en pointerquot du beskriver är exakt vad jag menade med kvotcirkelkö. Det var därför jag sa att det inte är ineffektivt. Vad trodde du att jag menade Och om ditt svar är kvot array som ändrar sina värden tillbaka på varje indexerad removalquot (som std :: vektor i C). Ja, då är jag så skadad att jag inte ens vill prata med dig längre) ndash Dan Tao Sep 22 10 på 1:58 Henry: Jag vet inte om AS3, men en Java-programmerare har samlingar som CircularQueue vid hisher bortskaffande (I39m inte en Java-utvecklare så jag är säker på att det finns bättre exempel där ute, det är bara det jag hittade från en snabb Google-sökning), som precis implementerar funktionaliteten vi talar om. Jag är ganska säker på att majoriteten på mellannivå och lågnivå språk med standardbibliotek har något liknande (t ex i QueueltTgt). Hur som helst, jag var filosofi själv, så. allt är förlåtet. ndash Dan Tao 22 sep 10 kl 12:44 Ett exponentiellt förfallande glidande medelvärde kan beräknas för hand med endast trenden om du använder rätt värden. Se fourmilab. chhackdiete4 för en idé om hur man gör det snabbt med en penna och papper om du letar efter exponentiellt slätat glidande medelvärde med 10 utjämning. Men eftersom du har en dator, vill du förmodligen göra binärväxling i motsats till decimalväxling) På så sätt är allt du behöver en variabel för ditt nuvarande värde och en för genomsnittsvärdet. Nästa medelvärde kan då beräknas utifrån det. svarade 21 sep 10 kl 14:39 theres en teknik kallad en intervall grind som fungerar bra med låg förekomst falska prover. förutsatt att användningen av en av de ovannämnda filterteknikerna (glidande medelvärde, exponentiella), när du har tillräcklig historia (en tidskonstant), kan du testa det nya inkommande dataprovet för rimlighet innan det läggs till i beräkningen. viss kunskap om den maximala rimliga hastighetsgraden av signalen krävs. Råprovet jämförs med det senaste släta värdet, och om det absoluta värdet av den skillnaden är större än det tillåtna intervallet, kastas det provet (eller ersätts med en del heuristiska, t. ex. en förutsägelse baserad på lutningsskillnaden eller trenden prediktionsvärde från dubbel exponentiell utjämning) svarat 30 april 16 vid 6: 56C-algoritmen för exponentialrörelse med noll-latens Senast ändrad: 2012-08-13 Jag har försökt att implementera en lågfrekvens cutoff i c som i huvudsak tar en ström av siffror och släpper ut utgången (filtrering av högfrekvent rörelsejitter), men det är viktigt att de främre viktiga talen anses omedelbart eftersom data är tidskritisk (det är att styra en rörelsesimulationsbas med utgång från lite spelprogram). Jag har en arbetsviktad glidande genomsnittlig algoitm men kunde göra med något lite mer responsivt i frontänden, och jag hittade det här: - Pseudokoden finns som följer: Ingångar: Pris (NumericSeries), Period (NumericSimple) Variabler: faktor (0), fördröjning (0) om CurrentBar lt 1 börjar ZLEMA Prisfaktor 2 (Period1) fördröjning (Period 1) 2 slut annars börjar ZLEMA-faktor (2Price-Pricelag) (1-faktor) ZLEMA1 ände Ive översatt den till C och min kod är som följer: Det verkar dock inte som att jag förväntar mig. Det verkar vara nästan där men ibland får jag ett något lägre värde än alla artiklar i köen (när de är alla högre). Min kö och antalet objekt i den passeras som parametrar, med den senaste som alltid är framåt, jag passerar också en inkrementell räknare som börjar vid 0 som krävs av funktionen. Jag är inte säker på att jag har tolkat betydelsen av ZLEMA1 korrekt, eftersom den inte är tydlig i sin pseudokod, så jag antog att detta var de sista samtalen zlema och även Im antar Pris betyder faktiskt Price0. Kanske har jag det här felet Jag skulle kopiera de faktiska zlemaberäknade värdena tillbaka till min ursprungliga kö innan nästa samtal jag ändrar inte den ursprungliga köen på alla andra än att bara flytta alla värden ett till slutet och sätta in det senaste i början . Koden som jag använder för att göra detta är: Skulle vara mycket tacksam om någon med bättre förståelse av matematiken skulle kunna behaga sanity kontrollera detta för mig för att se om jag har något lite fel Tack så mycket i förväg om du kan hjälpa För det första tacka allt för Din insats, mycket uppskattad Det är meningslöst att jag antar att det bästa jag kan hoppas på är helt enkelt ett exponentiellt glidande medelvärde. Att acceptera att det kommer att finnas en liten fördröjning, men detta kommer att minimeras av tyngre frontvikt än vad som anges i typvikten glidande medelvärde Jag har även denna algoritm, men ett liknande problem med att värdena inte verkar riktigt korrekta (om inte detta är formens natur). Till exempel, säg att mitt sortiment innehåller 16 värden, alla 0.4775 - utgången är 0.4983, men Id förväntar att det blir 0,4775 Ser det här ut som det passar dig. Exponentiell rörlig medelvärde. float ema (float vals, int numVals, int currentSample) statisk floatfaktor 0 statisk float lastema 0 float ema if (currentSample lt 1) ema vals0 faktor 2.0 ((float) numVals) 1,0) annars ema (faktor vals0) - faktor) lastema) lastema ema return ema Omvänt är utsignalen ibland lägre än var och en av ingångarna, även om alla är högre. Den kallas på samma sätt som zlema (.) Ovan, med en inkrementell räknare. Formeln och pseudokoden för den här är här: - autotradingstrategy. wordpress20091130exponential-moving-average Tack igen, ursäkta för mitt missförstånd om några av grunderna :( Med vänliga hälsningar, Chris J När det gäller koden jag skrev upp, har du rätt om matrisstorleken Situationen. Det bör lätt lösas. Vad gäller dina frågor: 1) Filterkonstanten representerar en frekvensavbrott. Jag använde en digital signalbehandling (DSP) för denna teknik. en. wikipedia. orgwi kiLow-pas sfilter är en enkel förklaring. Du vill ha sektionen för diskret tid. I mitt fall är A den RC-Constant som de talar om. Så frekvensen som den skär ut är över 1 (2piA). Om du inte har en förståelse för frekvensdomänteori kan detta bli komplicerat. I ditt fall Ju högre du gör A, desto lägre frekvens kommer det här filtret att tillåta, vilket betyder att det kommer att jämna ut kurvan mer och mer. Ju lägre du gör det desto mer ljud får du i systemet. Kom ihåg att ett måste vara större än eller lika med 1 för att vara effektivt. Jag satte igen XLS igen, den här gången utan att ändra rand () tal. Justera A-konstanten och se hur den quotsmoothsquot (eller filter) utger högfrekvensvariationerna. 2) Den sista punkten i ingångsrutan har det senaste värdet. 3) Detsamma gäller för utmatningsraden. Det sista är det senaste värdet. 5) NUMVALS är godtycklig. Du kan kontinuerligt lägga till i inmatnings - och utmatningsfältet så många gånger du vill och det skulle inte effekta filtret. I synnerhet använde jag 49 poäng. Men jag kan enkelt ta bort de senaste 20 och de första 29 utgångarna skulle förbli densamma. Funktionen är inte baserad på hur många poäng som används. Jag skulle vilja nämna att jag utvecklade denna funktion för en engångskonvertering. Om du ville göra en omvandling till nästa värde i flygningen kunde du prova något enklare (som bifogat). Återigen är jag rostig på c. Jag hoppas att det här är rätt. Det enda du behöver leverera är inmatningen och filterkonstanten. Låt mig veta om det här hjälper. Är det möjligt att genomföra ett glidande medelvärde i C utan att det behövs ett fönster i proverna, har jag funnit att jag kan optimera lite, genom att välja en fönsterstorlek som är en kraft av två för att tillåta bitskiftande istället för att dela men inte behöva en buffert skulle vara trevligt. Finns det ett sätt att uttrycka ett nytt glidande medelresultat endast som en funktion av det gamla resultatet och det nya provet Definiera ett exempel glidande medelvärde, över ett fönster med 4 prov att vara: Lägg till nytt prov e: Ett glidande medel kan implementeras rekursivt , men för en exakt beräkning av glidande medelvärde måste du komma ihåg det äldsta inmatningsprovet i summan (dvs. a i ditt exempel). För ett längd N rörligt medelvärde beräknar du: var yn är utsignalen och xn är ingångssignalen. Eq. (1) kan skrivas rekursivt som Så du behöver alltid komma ihåg provet xn-N för att kunna beräkna (2). Som påpekat av Conrad Turner kan du använda ett (oändligt långt) exponentiellt fönster istället, vilket gör det möjligt att beräkna utmatningen endast från tidigare utmatning och aktuell ingång: men det här är inte ett vanligt (obetydligt) glidande medelvärde men exponentiellt viktade glidande medelvärde, där prov i det förflutna får en mindre vikt, men (åtminstone teoretiskt) glömmer du aldrig någonting (vikterna blir bara mindre och mindre för prover långt ifrån). Jag implementerade ett glidande medelvärde utan individuellt objektminne för ett GPS-spårningsprogram som jag skrev. Jag börjar med 1 prov och dela med 1 för att få nuvarande avg. Sedan lägger jag till ett prov och delar upp med 2 till den nuvarande avg. Detta fortsätter tills jag når längden på medeltalet. Varje gång efteråt lägger jag till i det nya provet, får medelvärdet och tar bort det genomsnittet från summan. Jag är inte matematiker men det verkade som ett bra sätt att göra det. Jag tänkte att det skulle vända på magen på en riktig matte kille men det visar sig att det är ett av de accepterade sätten att göra det. Och det fungerar bra. Kom bara ihåg att ju högre längden desto långsammare följer du vad du vill följa. Det kan inte ha betydelse för det mesta, men när du följer satelliter, kan du vara långsiktig, om det är långt ifrån det faktiska läget och det kommer att se dåligt ut. Du kan ha ett mellanrum mellan mitten och de efterföljande prickarna. Jag valde en längd på 15 uppdaterad 6 gånger per minut för att få tillräcklig utjämning och inte komma för långt från den faktiska lätta positionen med de släta spårpunkterna. svarat 16 november 16 kl 23:03 initialisera totalt 0, count0 (varje gång vi ser ett nytt värde) Då en inmatning (scanf), en lägg till totalnevValue, en ökning (räkning), en delningsgenomsnitt (totalantal) Detta skulle vara ett glidande medelvärde över alla ingångar För att beräkna medelvärdet över endast de senaste 4 ingångarna, skulle det behöva 4 ingångsvariabler, kanske kopiering av varje ingång till en äldre ingångsvariabel och sedan beräkning av det nya glidande medlet. Som summan av de fyra ingångsvariablerna dividerad med 4 (höger skift 2 skulle vara bra om alla ingångar var positiva för att få den genomsnittliga beräkningen besvarad 3 feb 15 kl 4:06 som faktiskt kommer att beräkna det totala genomsnittet och INTE det glidande genomsnittet. När räkningen blir större blir effekten av ett nytt ingångsprov försvinnande liten ndash Hilmar Feb 3 15 kl 13:53 Ditt svar 2017 Stack Exchange, Inc

No comments:

Post a Comment