지금까지받은 수와 총 데이터를 저장하지 않고 이동 누적 평균을 계산하는 방법을 찾으려고합니다.
두 가지 알고리즘을 생각해 냈지만 둘 다 개수를 저장해야합니다.
- 새 평균 = ((이전 개수 * 이전 데이터) + 다음 데이터) / 다음 개수
- 새 평균 = 이전 평균 + (다음 데이터-이전 평균) / 다음 개수
이러한 방법의 문제점은 개수가 점점 커져 결과 평균의 정밀도를 잃는다는 것입니다.
첫 번째 방법은 분명히 1로 떨어져있는 이전 개수와 다음 개수를 사용합니다. 이것은 아마도 카운트를 제거하는 방법이 있다고 생각하게했지만 불행히도 아직 찾지 못했습니다. 그래도 조금 더 나아서 두 번째 방법을 얻었지만 여전히 카운트가 존재합니다.
가능합니까, 아니면 불가능한 것을 찾고 있습니까?
답변
간단하게 다음을 수행 할 수 있습니다.
double approxRollingAverage (double avg, double new_sample) {
avg -= avg / N;
avg += new_sample / N;
return avg;
}
N
평균화하려는 샘플 수는 어디에 있습니까 ? 이 근사는 지수 이동 평균과 동일합니다. 참조 : C ++에서 롤링 / 이동 평균 계산
답변
New average = old average * (n-1)/n + new value /n
이것은 카운트가 하나의 값만큼만 변경되었다고 가정합니다. M 값으로 변경된 경우 :
new average = old average * (n-len(M))/n + (sum of values in M)/n).
이것은 수학적 공식입니다 (가장 효율적인 공식이라고 생각합니다). 스스로 추가 코드를 작성할 수 있다고 믿습니다.
답변
답변
Muis , Abdullah Al-Ageel 및 Flip 의 답변이 다르게 쓰여진 것을 제외하고 는 모두 수학적으로 동일한 방법에 대한 주석을 제공하는 또 다른 답변 이 있습니다.
물론, 반올림 오류가 각각에 약간 다른 영향을 미치는 방식을 설명하는 José Manuel Ramos 의 분석이 있지만 이는 구현에 따라 다르며 각 답변이 코드에 어떻게 적용되었는지에 따라 변경됩니다.
그러나 다소 큰 차이가 있습니다
그것은 Muis ‘s N
, Flip ‘s k
및 Abdullah Al-Ageel ‘s에 n
있습니다. 압둘라 알 – Ageel은 매우 무엇인지 설명하지 않습니다 n
해야하지만 N
하고 k
있다는 점에서 차이가 N
있다 ” 당신이 평균 이상으로 원하는 샘플 수는 “동안은 k
샘플링 값의 수입니다. ( N
샘플 수를 호출 하는 것이 정확한지 의심 스럽지만 )
그리고 여기에서 우리는 아래의 답을 얻습니다. 본질적으로 다른 것들 과 동일한 오래된 지수 가중 이동 평균 이므로 대안을 찾고 있다면 여기에서 중지하십시오.
지수 가중 이동 평균
처음에는 :
average = 0
counter = 0
각 값에 대해 :
counter += 1
average = average + (value - average) / min(counter, FACTOR)
차이점은 min(counter, FACTOR)
부분입니다. 이것은 말하는 것과 같습니다 min(Flip's k, Muis's N)
.
FACTOR
평균이 최신 추세를 “따라 잡는”속도에 영향을주는 상수입니다. 숫자가 작을수록 빠릅니다. ( 1
더 이상 평균이 아니며 단지 최신 값이됩니다.)
이 대답에는 실행 카운터가 필요합니다 counter
. 문제가있는 경우 min(counter, FACTOR)
를로 대체하여 Muis 의 대답 FACTOR
으로 바꿀 수 있습니다 . 이 작업의 문제는 이동 평균 이 초기화되는 항목의 영향을 받는다는 것입니다. 로 초기화 된 경우 해당 0이 평균을 벗어나는 데 오랜 시간이 걸릴 수 있습니다.average
0
어떻게 보이는지
답변
Flip의 대답은 Muis보다 계산적으로 더 일관 적입니다.
이중 숫자 형식을 사용하면 Muis 접근 방식에서 반올림 문제를 볼 수 있습니다.
나누고 빼면 이전에 저장된 값에 반올림이 나타나 변경됩니다.
그러나 Flip 접근 방식은 저장된 값을 보존하고 분할 수를 줄여서 반올림을 줄이고 저장된 값으로 전파되는 오류를 최소화합니다. 추가 할 항목이있는 경우에만 반올림이 표시됩니다 (N이 크면 추가 할 항목이 없음).
큰 값의 평균을 만들 때 이러한 변화는 그 평균이 0이되는 경향이 있습니다.
스프레드 시트 프로그램을 사용하여 결과를 보여드립니다.
A 및 B 열은 각각 n 및 X_n 값입니다.
C 열은 Flip 접근 방식이고 D 열은 Muis 접근 방식이며 그 결과는 평균에 저장됩니다. E 열은 계산에 사용 된 중간 값에 해당합니다.
다음은 짝수 값의 평균을 보여주는 그래프입니다.
보시다시피 두 접근 방식에는 큰 차이가 있습니다.
답변
비교를 위해 자바 스크립트를 사용하는 예 :
https://jsfiddle.net/drzaus/Lxsa4rpz/
function calcNormalAvg(list) {
// sum(list) / len(list)
return list.reduce(function(a, b) { return a + b; }) / list.length;
}
function calcRunningAvg(previousAverage, currentNumber, index) {
// [ avg' * (n-1) + x ] / n
return ( previousAverage * (index - 1) + currentNumber ) / index;
}
답변
Java8에서 :
LongSummaryStatistics movingAverage = new LongSummaryStatistics();
movingAverage.accept(new data);
...
average = movingAverage.getAverage();
당신은 또한 가지고 IntSummaryStatistics
, DoubleSummaryStatistics
…