Wednesday, 6 December 2017

Effektiv glidande medelvärde filter


För närvarande utvecklar jag ett grafiskt LCD-system för att visa temperaturer, flöden, spänningar, kraft och energi i ett värmepumpsystem. Användningen av en grafisk LCD-skärm innebär att hälften av min SRAM och .75 av min blixt har använts av en skärmbuffert Och strängar. Jag visar för närvarande mina maxmedelvärden för energi Vid midnatt när den dagliga siffran återställs kontrollerar systemet om konsumtionen för dagen är över eller under föregående minimum eller maximalt och lagrar värdet. Medelvärdet beräknas genom att dividera Den kumulativa energiförbrukningen med antalet dagar. Jag skulle vilja visa det dagliga genomsnittet under den senaste veckan och månaden 4 veckor för enkelhet, dvs rullande medelvärde. För närvarande innebär detta att du behåller en mängd värden under de senaste 28 dagarna och beräknar ett genomsnitt över Hela utbudet för månadsvisa och sista 7 dagar för varje vecka. Initialt gjorde jag det här med en uppsättning floats eftersom energin är i form 12 12 kWh, men det användes 28 4 byte 112 byte 5 4 av SRAM Jag har inte min D har bara en decimaltal upplösning, så jag ändrade till att använda uint16t och multiplicera siffran med 100 Det betyder att 12 12 representeras som 1212, och jag delar upp med 100 för visning. Storleken på matrisen är nu nere till 56 byte mycket bättre. Det finns inget triviellt sätt att minska siffran ner till en uint8t som jag kan se jag kunde tolerera förlusten av en decimal 12 1kWh istället för 12 12kWh men konsumtionen är ofta högre än 25 5kWh 255 är den högsta Värde representerat av ett 8-bitars unsigned integer Förbrukningen har aldrig varit under 10 0kWh eller över 35 0kWh, så troligt att jag kunde subtrahera 10 från de lagrade figurerna men jag vet att vi en dag kommer att överskrida dessa gränser. Jag testade sedan koden för att packa 9-bitars värden i en array Detta ger ett intervall på 0-51 2kWh och använder totalt 32 byte. Det är dock ganska långsamt att komma åt en array så här, särskilt när du måste iterera över alla värden för att beräkna ett genomsnitt. Så min fråga Är - finns det ett effektivare sätt på ca Lculating ett glidande medelvärde med tre fönster - livstid, 28 dagar och 7 dagar Effektivitet betyder mindre när det gäller SRAM-användning men utan straffet för stor kod Kan jag undvika att lagra alla värden. Skriven mar 7 14 på 8 32. Jag har tänkt Och du har rätt Så det gör tekniskt mitt svar felaktigt Jag investerar lite mer tid och tålamod i det. Kanske någonting ur lådan ska jag låta dig veta om jag kommer upp med något Vi gör något så mycket på min arbetsplats Låt mig Fråga runt Ledsen om förvirringen Aditya Somani Mar 8 14 på 17 15. finns det ett effektivare sätt att beräkna ett glidande medelvärde med 28 dagar och 7 dagar som behöver komma ihåg 27 dagars historia. Du kan få nära nog att lagra 11 värden i stället för 28 värden, kanske något liknande. Med andra ord, istället för att lagra varje detalj varje dag under de senaste 27 dagarna, en butik 7 eller så värden av detaljerad daglig information under de senaste 7 eller så dagarna, och även b lagra 4 eller så Sammanfattade värden av total eller genomsnittlig information Ation för var och en av de senaste 4 eller så veckorna. Jag har väldigt en mängd värden som denna. Den ovanstående matrisen är förenklad, jag samlar 1 värde per millisekund i min riktiga kod och jag behöver bearbeta utmatningen på en algoritm som jag skrev Att hitta den närmaste toppen före en tidpunkt Min logik misslyckas, eftersom i mitt exempel ovan är 0 36 den verkliga toppen, men min algoritm skulle se bakåt och se det sista numret 0 25 som toppen, eftersom det sänker till 0 24 innan det. Målet är att ta dessa värden och tillämpa en algoritm för dem som släpper ut dem lite så att jag har mer linjära värden, det vill säga att jag tycker att resultaten är svaga, inte jaggediga. Jag har blivit tillsagd att tillämpa Ett exponentiellt glidande medelfilter till mina värden Hur kan jag göra det? Det är verkligen svårt för mig att läsa matematiska ekvationer. Jag hanterar mycket bättre med kod. Hur bearbetar jag värden i min matris och tillämpar en exponentiell glidande medelberäkning för att jämna dem ut. asked Feb 8 12 på 20 27.Till beräkna en exponentiell rörlig averag E du behöver behålla någon stat runt och du behöver en inställningsparameter Detta kräver en liten klass om du antar att du använder Java 5 eller senare. Inställning med den sönderfallsparameter du vill ha kan ta tuning bör vara mellan 0 och 1 och använd sedan genomsnittet för Filter. När du läser en sida om matematisk återkommande är allt du verkligen behöver veta när du gör det till kod, att matematiker gillar att skriva indexer i arrayer och sekvenser med prenumerationer. De har några andra noteringar också, vilket hjälper inte. Men, EMA är ganska enkel eftersom du bara behöver komma ihåg ett gammalt värde, inga komplicerade statliga arrays krävs. Svarade 8 februari 12 på 20 42. TKKocheran Ganska mycket Är det inte trevligt när saker kan vara enkla Om du börjar med en ny sekvens får du en ny Averager Observera att de första villkoren i den genomsnittliga sekvensen kommer att hoppa runt lite på grund av gränseffekter, men du får även de med andra glidande medelvärden. En bra fördel är dock att du kan linda den glidande genomsnittliga logiken in i ave Rager och experimentera utan att störa resten av ditt program för mycket Donal Fellows 9 feb 12 på 0 06. Jag har svårt att förstå dina frågor, men jag kommer att försöka svara ändå.1 Om din algoritm funnit 0 25 istället för 0 36 , Då är det fel Det är fel eftersom det förutsätter en monotonisk ökning eller minskning som alltid går upp eller alltid går ner Om du inte är genomsnittlig ALLA dina data, dina datapunkter --- som du presenterar dem --- är olinjära Om du verkligen Vill hitta det maximala värdet mellan två punkter i tid, skära sedan din matris från tmin till tmax och hitta max av den subarray.2 Nu är konceptet med glidande medelvärden mycket enkelt att föreställa mig att jag har följande lista 1 4, 1 5, 1 4, 1 5, 1 5 Jag kan släta ut det genom att ta medeltalet av två nummer 1 45, 1 45, 1 45, 1 5 Observera att det första numret är genomsnittet av 1 5 och 1 4 sekund och första Siffror den andra nya listan är genomsnittet av 1 4 och 1 5 tredje och andra gamla listan den tredje nya listan i genomsnitt 1 5 och 1 4 fjärde och tredje och så vidare kunde jag ha gjort det period tre eller fyra eller n Observera hur dataen är mycket jämnare Ett bra sätt att se glidande medelvärden på jobbet är att gå till Google Finance, välj ett lager försök Tesla Motors Ganska flyktig TSLA och klicka på technicals längst ner i diagrammet Välj Flytta genomsnittet med en given period och Exponentiell glidande medelvärde för att jämföra deras skillnader. Exponentialt glidande medelvärde är bara en annan utarbetande av detta men viktar de äldre data mindre än de nya data Detta är ett sätt att förspänna utjämningen mot baksidan. Läs Wikipedia-posten. Så det här är mer en kommentar än ett svar, men den lilla kommentarrutan var bara för liten lycka till. Om du har problem med matte Kan gå med ett enkelt glidande medelvärde istället för exponentiellt Så den utmatning du får skulle vara de sista x-termerna dividerad med x Otestad pseudokod. Notera att du kommer att behöva hantera start - och slutdelarna av data eftersom det klart är att du inte kan genomsnittsera den sista 5 termer när Du är på din 2: a datapunkt Det finns också mer effektiva sätt att beräkna den här glidande summan summan - äldsta nyaste, men det här är att få konceptet av vad som händer across. answered Feb 8 12 på 20 41. Jag har nyligen lärt mig om Strider i svaret på det här inlägget och undrade hur jag kunde använda dem för att beräkna ett glidande medelfilter mer effektivt än vad jag föreslagit i det här inlägget med hjälp av konvolutionsfilter. Det här är vad jag har hittills. Det tar en bild av den ursprungliga matrisen då Rullar den med nödvändig mängd och summerar kärnvärdena för att beräkna medelvärdet Jag är medveten om att kanterna inte hanteras korrekt men jag kan ta hand om det efteråt Finns det ett bättre och snabbare sätt Målet är att filtrera stora flytpunkter Upp till 5000x5000 x 16 lager i storlek, en uppgift som är ganska långsam på. Notera att jag letar efter 8 grannanslutning, det är ett 3x3 filter tar medeltalet 9 pixlar 8 runt fokuspunkten och tilldelar det värdet till Pixel i det nya Image. EDIT Förtydligande om hur jag ser detta works. use stridetricks för att generera en array som 0,1,2, 1,2,3, 2,3,4 som motsvarar den övre raden i filterkärnan. Rulla längs vertikal Axeln för att få den centrala raden i kärnan 10,11,12,11,12,13,13,14,15 och lägg till den i matrisen som jag kom in 1.Tryck för att få den nedre raden i kärnan 20,21, 22, 21,22,23, 22,23,24 Vid denna punkt tar jag summan av varje rad och delar den med antalet element i filtret, vilket ger mig genomsnittet för varje pixel, förskjutet av 1 rad och 1 Kol och med några konstigheter runt kanterna, men jag kan ta hand om det senare. Vad jag hoppades på är en bättre användning av stridetricks för att få de 9 värdena eller summan av kärnelementen direkt, för hela matrisen eller det Någon kan övertyga mig om en annan effektivare metod. Skriven den 8 februari 11 på 18 05. För vad det är värt, här är hur du gör det med hjälp av snygga tricks. Jag skulle posta det här igår, men blev distraherad av det faktiska arbetet. Paul äter båda har bra implementeringar med olika andra sätt att göra detta Bara för att fortsätta saker från den tidigare frågan, tänkte jag att jag d postade den N-dimensionella motsvarigheten. Du kommer inte att kunna tappa funktioner för 1D-arrays betydligt, men borde Men om du försöker få ett flerdimensionellt rörligt fönster riskerar du att minnesanvändningen sprängs när du oavsiktligt gör en kopia av din matris. Medan den ursprungliga rullande matrisen bara är en vy i minnet av din ursprungliga matris, Mellanliggande steg som kopierar matrisen kommer att göra en kopia som är storleksordningar som är större än din ursprungliga matris, dvs Låt oss säga att du arbetar med en 100x100 originalmatris Utsikten till den för en filterstorlek på 3,3 kommer att vara 98x98x3x3 men använd Samma minne som originalet. Alla kopior kommer dock att använda mängden minne som en fullständig 98x98x3x3-array skulle. Basiskt är det bra att använda galen stridstickor när du vill vektorisera rörliga fönsteroperationer på En enkel axel av en ndarray Det gör det väldigt lätt att beräkna saker som en rörlig standardavvikelse mm med mycket lite överhuvudet När du vill börja göra detta längs flera axlar är det möjligt, men du brukar bli bättre med mer specialiserade funktioner Så som etc. An vilket som helst fall, så är det hur du gör det. Så vad vi får när vi gör b rollingwindow a är filtsize en 8x8x3x3-serie, det är faktiskt en vy i samma minne som den ursprungliga 10x10-serien. Vi kunde bara ha Lika enkelt använt olika filterstorlek längs olika axlar eller endast drivs utmed valda axlar i en N-dimensionell array, dvs filtisera 0,3,0,3 på en 4-dimensionell array skulle ge oss en 6-dimensionell vy. Vi kan sedan tillämpa en godtycklig Funktionen till den sista axeln upprepade gånger för att effektivt beräkna saker i ett rörligt fönster. Men eftersom vi lagrar temporära arrayer som är mycket större än vår ursprungliga array på varje steg med medelvärde eller std eller vad som helst, är det inte alls minneseffektivt Kommer inte heller att vara te Rribly fast, either. The motsvarande för ndimage är just. This kommer att hantera en mängd olika gränsvillkor, göra suddning på plats utan att behöva en tillfällig kopia av matrisen och vara väldigt snabb. Tricktricks är ett bra sätt att tillämpa en funktion Till ett rörligt fönster längs en axel, men de är inte ett bra sätt att göra det längs flera axlar, vanligtvis. Bara min 0 02, i vilket fall. Mycket bra. Stödtrick är ett bra sätt att tillämpa en funktion på ett rörligt fönster Längs en axel, men de är inte ett bra sätt att göra det längs flera axlar. Vanligtvis Och självklart är din förklaring av minnesuppblåsningen viktig. En typ av sammanfattning från ditt svar åtminstone för mig är det inte för långt fiskande, Den quarenteed fångsten är redan i scipy Tack äta 9 feb 11 på 16 37. Tack, Joe, för det här svaret I rullande fönster bör om det inte hända att återvända rollingwindowlastaxis istället för att rullavinda unutbu 12 feb 11 kl 16 47. Jag är inte bekant nog med Python att skriva ut kod för det, men de två bästa wa Ys för att påskynda omvandlingar är att antingen skilja filtret eller använda Fourier-transformen. Separat filterkonvolution är OMN, där M och N är antal pixlar i bilden och filtret. Eftersom medelfiltrering med en 3-vid-3 Kärnan motsvarar att filtrera först med en 3-i-1-kärna och sedan en 1-vid-3-kärna, kan du få 3 3 3 3,30 hastighetsförbättring genom konsekutiv konvolvering med två 1-d-kärnor blir det uppenbarligen bättre när kärnan blir Större Du kan fortfarande använda stride-tricks här, förstås. Främjare Transform conv A, B är ekvivalent med ifft fft En fft B dvs konvolvering i direktutrymme blir en multiplikation i Fourier-rymden, där A är din bild och B är din Filter Eftersom den elementvisa multiplikationen av Fouriertransformationerna kräver att A och B har samma storlek, är B en uppsättning av storlek A med din kärna i centrum av bilden och nollor överallt för att placera en 3-vid-3 Kärna i mitten av en matris, kan du behöva pad A till od D-storlek Beroende på implementeringen av Fourier-omvandlingen kan detta vara mycket snabbare än konvolutten och om du använder samma filter flera gånger kan du förberäkna fft B som sparar ytterligare 30 av beräkningen time. answered 9 feb 11 kl 15 27.För vad det är värt, i python implementeras dessa i och respektive Joe Kington 9 feb 11 på 15 44. Jonas Cool Den separerade filtermetoden fungerar bra, som du säger att det sparar mer tid då kärnstorleken ökar För en 5000x5000 Array, i en 11x11 kärnstorlek får jag 7 7s för 2d convolution med och 2s för två 1d-omvälvningar med hjälp av För din andra lösning vad är B Benjamin 9 februari 11 på 16 02. En sak som jag är säker på måste fixas är Din synvinkel b. Det har några föremål från odelat minne, så du får kraschar. Ge din nya beskrivning av din algoritm, det första som behöver fixas är att du strider utanför allokeringen av a. Eftersom jag m Fortfarande inte helt greppa metoden och det verkar t O vara enklare sätt att lösa problemet, jag kommer bara att sätta detta här. Det verkar bara som det enkla sättet. Den enda externa operationen är att den har allokerat och befolkade B endast en gång. Alla tillägg, division och indexering måste göras Oavsett Om du gör 16 band behöver du bara allokera B en gång om du har för avsikt att spara en bild. Även om det inte är någon hjälp kan det förklara varför jag inte förstår problemet, eller åtminstone tjäna som riktmärke för att Time speedups av andra metoder Detta körs i 2 6 sekunder på min bärbara dator på en 5k x 5k array av float64 s, 0 5 av vilka är skapandet av B. answered Feb 8 11 på 19 31. Det är inte så klart bilda din Fråga, men jag antar nu att du verkligen vill förbättra denna typ av medelvärde väsentligt. Nu, vilken typ av prestandaförbättringar skulle du faktiskt förvänta dig. Uppdatera Först och främst en varning koden i sin nuvarande situation anpassar sig inte korrekt till Kärnformen Men det är inte min primära fråga just nu ändå Tanken är att det redan finns ett sätt att anpassa sig ordentligt. Jag har just valt den nya formen av en 4D A intuitivt, för mig är det verkligen meningsfullt att tänka på ett 2D-kärncentrum som ska centreras till varje rasterposition av original 2D A. Men det 4D-formning kan egentligen inte vara det bästa jag tycker att det verkliga problemet här är resultatet av summering. En bör för att kunna hitta den bästa beställningen av 4D A inorder för att fullt ut kunna utnyttja maskinens cache-arkitektur. Men den här ordern kanske inte är densamma för Små arrays vilken slags samverkar med maskinens cache och de större, vilket inte alls är så enkelt. Uppdatera 2 Här är en något modifierad version av mf. Det är klart att det är bättre att omforma till en 3D-array först och sedan Istället för att summera bara göra prickprodukt har detta fördelen, så att den här kärnan kan vara godtycklig. Men det är fortfarande lite 3x långsammare på min maskin än Pauls uppdaterade function. answered 8 februari 11 på 19 33.

No comments:

Post a Comment