Próbuję znaleźć sposób na obliczenie ruchomej średniej skumulowanej bez przechowywania liczby i łącznych danych, które zostały do tej pory odebrane.
Wymyśliłem dwa algorytmy, ale oba muszą przechowywać liczbę:
- nowa średnia = ((stara liczba * stare dane) + następne dane) / następna liczba
- nowa średnia = stara średnia + (następne dane - stara średnia) / następny licznik
Problem z tymi metodami polega na tym, że liczba staje się coraz większa, co powoduje utratę precyzji w wynikowej średniej.
Pierwsza metoda używa starego liczenia i następnego liczenia, które oczywiście różnią się o 1. To sprawiło, że pomyślałem, że być może istnieje sposób na usunięcie liczby, ale niestety jeszcze go nie znalazłem. To jednak doprowadziło mnie nieco dalej, w wyniku czego powstała druga metoda, ale liczba nadal jest obecna.
Czy to możliwe, czy po prostu szukam niemożliwego?
moving-average
user1705674
źródło
źródło
Odpowiedzi:
Możesz po prostu zrobić:
Gdzie
N
jest liczba próbek, dla których chcesz przeprowadzić średnią. Należy zauważyć, że to przybliżenie jest równoważne wykładniczej średniej ruchomej. Zobacz: Obliczanie średniej kroczącej / ruchomej w C ++źródło
5
próbek, średnia wyniesie 0,67.avg
inicjowane0
, skończy się3.36
po upływie 55
s, a4.46
po 10: cpp.sh/2ryql na długie średnie, to jest z pewnością przydatna przybliżeniem.Zakłada się, że liczba zmieniła się tylko o jedną wartość. W przypadku zmiany wartości M to:
To jest wzór matematyczny (uważam, że jest najbardziej efektywny), wierzę, że możesz samodzielnie wykonać dalsze kodowanie
źródło
m
nowe wartości są uwzględniane w nowej średniej. Uważam, żesum of new value
tutaj ma być sumam
nowych wartości używanych do obliczenia nowej średniej.new_average = (old_average * (n-1) + new_value) / n
- Usuwa jeden z podziałów.Z bloga na temat przeprowadzania przykładowych obliczeń wariancji, gdzie średnia jest również obliczana metodą Welforda :
Szkoda, że nie możemy przesyłać obrazów SVG.
źródło
Oto kolejna odpowiedź zawierająca komentarz dotyczący tego , jak odpowiedź Muis , Abdullah Al-Ageel i Flip są matematycznie tym samym, z wyjątkiem tego , że są napisane inaczej.
Jasne, mamy analizę José Manuela Ramosa wyjaśniającą, jak błędy zaokrąglania wpływają na każdy z nich nieco inaczej, ale jest to zależne od implementacji i zmieni się w zależności od tego, jak każda odpowiedź została zastosowana do kodu.
Jest jednak dość duża różnica
Jest w Muis 's
N
, flip ' sk
, a Abdullah Al-Ageel „sn
. Abdullah Al-Ageel nie do końca wyjaśnić, con
powinno być, aleN
ik
różnią się tym, żeN
jest „ liczba próbek, w których mają być średnio ponad ”, ak
jest liczba wartości próbki. (Chociaż mam wątpliwości, czy podanieN
liczby próbek jest dokładne.)I tutaj dochodzimy do odpowiedzi poniżej. Zasadniczo jest to ta sama stara wykładnicza ważona średnia krocząca, co pozostałe, więc jeśli szukałeś alternatywy, zatrzymaj się tutaj.
Wykładnicza ważona średnia ruchoma
Początkowo:
Dla każdej wartości:
Różnica jest
min(counter, FACTOR)
częścią. To to samo, co mówieniemin(Flip's k, Muis's N)
.FACTOR
to stała, która wpływa na to, jak szybko średnia „dogania” najnowszy trend. Im mniejsza liczba, tym szybciej. (W1
tym momencie nie jest już średnią i staje się najnowszą wartością).Ta odpowiedź wymaga działającego licznika
counter
. Jeśli jest to problematyczne,min(counter, FACTOR)
można je zastąpić justFACTOR
, zamieniając je w odpowiedź Muis . Problem z robieniem tego polega na tym, że na średnią ruchomą wpływa to, coaverage
jest parafowane. Jeśli zostało zainicjowane0
, to zero może zająć dużo czasu, zanim wyjdzie ze średniej.Jak to się kończy
źródło
max(counter, FACTOR)
.min(counter, FACTOR)
zawsze zwróci FACTOR, prawda?min(counter, FACTOR)
chodzi o uwzględnienie okresu rozgrzewki. Bez tego, jeśli twój FACTOR (lub N, lub pożądana liczba próbek) wynosi 1000, będziesz potrzebować co najmniej 1000 próbek, zanim otrzymasz dokładny wynik, ponieważ wszystkie aktualizacje wcześniej zakładają, że masz 1000 próbek, kiedy możesz tylko mają 20.Odpowiedź Flip jest obliczeniowo bardziej spójna niż odpowiedź Muis.
Używając formatu podwójnej liczby, możesz zobaczyć problem zaokrągleń w podejściu Muis:
Kiedy dzielisz i odejmujesz, zaokrąglenie pojawia się w poprzedniej zapisanej wartości, zmieniając ją.
Jednak podejście odwracania zachowuje przechowywaną wartość i zmniejsza liczbę podziałów, a tym samym zmniejsza zaokrąglenie i minimalizuje błąd propagowany do przechowywanej wartości. Dodanie tylko spowoduje zaokrąglenia, jeśli jest coś do dodania (gdy N jest duże, nie ma nic do dodania)
Te zmiany są niezwykłe, gdy uśredniamy duże wartości, które mają tendencję do zerowania.
Wyniki pokazuję za pomocą arkusza kalkulacyjnego:
Po pierwsze, uzyskane wyniki:
Kolumny A i B to odpowiednio wartości n i X_n.
Kolumna C to podejście Flip, a kolumna D to podejście Muis, wynik przechowywany w średniej. Kolumna E odpowiada średniej wartości użytej w obliczeniach.
Wykres przedstawiający średnią parzystych wartości jest następny:
Jak widać, między oboma podejściami istnieją duże różnice.
źródło
Przykład wykorzystujący javascript dla porównania:
https://jsfiddle.net/drzaus/Lxsa4rpz/
Pokaż fragment kodu
źródło
W Javie8:
masz również
IntSummaryStatistics
,DoubleSummaryStatistics
...źródło
Zgrabne rozwiązanie Pythona oparte na powyższych odpowiedziach:
stosowanie:
źródło