Онлайн-алгоритм расчета абсолютного отклонения
Я пытаюсь вычислить абсолютное отклонение вектора online, то есть по мере поступления каждого элемента в векторе, без использования всего вектора. Абсолютное отклонение представляет собой сумму абсолютной разницы между каждым элементом вектора и средним значением:
![\sum_{i=0}^{n-1}{{abs%28\overline{x}%20-%20x_i}%29}]()
Я знаю, что дисперсия вектора может быть рассчитана таким образом. Отклонение аналогично абсолютному отклонению, но каждая разница квадратична:
![\frac{\sum_{i=0}^{n-1}{{%28\overline{x}%20-%20x_i}%29}^2}{n}]()
Онлайн-алгоритм для дисперсии выглядит следующим образом:
n = 0
mean = 0
M2 = 0
def calculate_online_variance(x):
n = n + 1
delta = x - mean
mean = mean + delta/n
M2 = M2 + delta*(x - mean) # This expression uses the new value of mean
variance_n = M2/n
return variance_n
Есть ли такой алгоритм для вычисления абсолютного отклонения? Я не могу сформулировать рекурсивное определение сам, но более разумные головы могут преобладать!
Ответы
Ответ 1
Поскольку абсолютное отклонение между x и средним значением может быть определено как квадратный корень квадрата разницы, адаптация тривиальна, если вы довольны последовательной, но предвзятой оценкой (что означает, что предел бесконечности - это ожидаемое значение):
n = 0
mean = 0
M2 = 0
def calculate_online_avg_abs_dev(x):
n = n + 1
delta = x - mean
mean = mean + delta/n
M2 = M2 + sqrt(delta*(x - mean))
avg_abs_dev_n = M2/n
Это относится к среднему абсолютному отклонению. Обычно используется безумная (медианное абсолютное отклонение), которое невозможно запрограммировать рекурсивно. но среднее абсолютное отклонение столь же полезно в большинстве случаев. Когда мы говорим о сотнях значений из близких к нормальным распределениям, оба значения очень близки.
Если вам просто нужна сумма абсолютных отклонений, жизнь еще проще: просто верните M2.
Помните о том, что ОБА алгоритм, который вы дали, и тривиальная адаптация для абсолютного отклонения слегка предвзяты.
Моделирование в R для доказательства алгоритма работает таким образом:
![alt text]()
Красная линия - это истинное значение, черная линия - это прогрессивное значение, следуя описанному выше алгоритму.
Код:
calculate_online_abs_dev <- function(x,n){
M2=0
mean=0
out <- numeric(n)
for(i in 1:n) {
delta <- x[i] - mean
mean <- mean + delta/i
M2 = M2 + sqrt(delta*(x[i] - mean))
out[i] <- M2/i
}
return(out)
}
set.seed(2010)
x <- rnorm(100)
Abs_Dev <- calculate_online_abs_dev(x,length(x))
True_Val <- sapply(1:length(x),function(i)sum(abs(x[1:i]-mean(x[1:i])))/i)
plot(1:length(x),Abs_Dev,type="l",xlab="number of values",lwd=2)
lines(1:length(x),True_Val,col="red",lty=2,lwd=2)
legend("bottomright",lty=c(1,2),col=c("black","red"),
legend=c("Online Calc","True Value"))
Ответ 2
Я не думаю, что это возможно.
В формуле для дисперсии можно разделить термины x и x 2 так что достаточно отслеживать эти суммы (и n). В формуле для абсолютного отклонения это невозможно.
Я думаю, что лучшее, что можно сделать (кроме сохранения всего вектора и вычисления абсолютного отклонения по требованию), сохраняет отсортированный список элементов. Это O (log (n)) для каждого нового элемента, но после добавления элемента стоимость пересчета абсолютного отклонения равна O (log (n)). Это может быть или не быть целесообразным, в зависимости от вашего приложения.
Ответ 3
Формула отклонения, которую вы даете, является ОДНИМ из многих возможных (я могу представить себе три различных способа сделать это вычисление), хотя я не подтвердил, что ваш правильный. Он выглядит достаточно близко к тому, что я помню.
Проблема заключается в том, что абсолютное значение на самом деле более "нелинейное" в некотором смысле, чем сумма квадратов отклонений. Это не позволяет вам выполнять этот расчет в рекурсивной форме в цикле, по крайней мере, не сохраняя всех предыдущих значений x. Вы должны вычислить общее среднее заранее для этой суммы.
Изменить: я вижу, что бета согласна со мной. Если вы сохранили все предыдущие точки данных, в отсортированном списке вы могли бы эффективно вычислить обновленное желаемое отклонение. Но это противоречит духу вашего запроса.