Вычисление нового стандартного отклонения с использованием старого стандартного отклонения после изменения набора данных

16

У меня есть массив из n реальных значений, который имеет среднее значение μold и стандартное отклонение σold . Если элемент массива xi заменяется другим элементом , то новое среднее значение будетxj

μnew=μold+xjxin

Преимущество этого подхода в том, что он требует постоянного вычисления независимо от значения . Есть ли какой-либо подход к вычислению с использованием как вычисление с использованием ?nσnewσoldμnewμold

пользователь
источник
Это домашнее задание? Очень похожая задача была
задана
2
@ user946850: Нет, это не домашняя работа. Я веду свою диссертацию по эволюционному алгоритму . Я хочу использовать стандартное отклонение как показатель разнообразия населения. Просто ищу более эффективное решение.
пользователь
1
SD - это квадратный корень из дисперсии, который является просто среднеквадратичным значением (скорректированным на кратное среднеквадратичного значения, которое вы уже знаете, как обновить). Следовательно, те же методы, которые использовались для вычисления среднего значения, могут применяться без каких-либо фундаментальных изменений для вычисления текущего отклонения. Фактически, гораздо более сложные статистические данные могут быть вычислены в режиме онлайн с использованием тех же идей: например, посмотрите потоки по адресу stats.stackexchange.com/questions/6920 и stats.stackexchange.com/questions/23481 .
whuber
1
@whuber: это упоминается в статье Википедии для Variance , но также с примечанием о возможной катастрофической отмене (или потере значимости). Это переоценено, или реальная проблема для бегущей дисперсии?
krlmlr
Это отличный вопрос. Если вы наивно накапливаете отклонения, не центрируя их заранее, вы действительно можете попасть в беду. Проблема возникает, когда цифры огромны, но их дисперсия невелика. Например, рассмотрим серию точных измерений скорости света в м / с, как в 299792458.145, 299792457.883, 299792457.998, ...: их дисперсия, которая составляет около 0,01, настолько мала по сравнению с их квадратами, которые составляют около , что небрежное вычисление (даже с двойной точностью) приведет к нулевой дисперсии: все значащие цифры исчезнут. 1017
whuber

Ответы:

7

Раздел в статье Википедии о «Алгоритмы для вычисления дисперсии» показывает , как вычислить дисперсию , если элементы добавляются к вашим наблюдениям. (Вспомните, что стандартное отклонение - это квадратный корень из дисперсии.) Предположим, что вы добавили в свой массив, затемxn+1

σnew2=σold2+(xn+1μnew)(xn+1μold).

РЕДАКТИРОВАТЬ : Выше формула, кажется, неправильно, см. Комментарий.

Теперь замена элемента означает добавление наблюдения и удаление другого; оба могут быть вычислены по формуле выше. Однако имейте в виду, что могут возникнуть проблемы численной устойчивости; цитируемая статья также предлагает численно стабильные варианты.

Для того, чтобы вывести формулу самостоятельно, вычислить с использованием определения образца дисперсии и заменить ц н е ш по формуле вы дали , когда это необходимо. Это дает вам σ 2 n e w - σ 2 o l d в конце, и, таким образом, формула для σ n e w задана σ o l d и(n1)(σnew2σold2)μnewσnew2σold2σnewσold . В моей записи я предполагаю, что вы заменяете элемент x n на x n :μoldxnxn

σ2=(n1)1k(xkμ)2(n1)(σnew2σold2)=k=1n1((xkμnew)2(xkμold)2)+ ((xnμnew)2(xnμold)2)=k=1n1((xkμoldn1(xnxn))2(xkμold)2)+ ((xnμoldn1(xnxn))2(xnμold)2)

xkμold

krlmlr
источник
the first formula you gave does not seem correct, well it means that if the xn+1 is smaller/larger then from both new and old mean, the variance always increases, which does not make any sense. It may increase or decrease depending on the distribution.
Emmet B
@EmmetB: Yes, you're right -- this should probably be σnew2=n1nσold2+1n(xn+1μnew)(xn+1μold). Unfortunately, this renders void my whole discussion from there, but I'm leaving it for historic purposes. Feel free to edit, though.
krlmlr
4

Based on what i think i'm reading on the linked Wikipedia article you can maintain a "running" standard deviation:

real sum = 0;
int count = 0;
real S = 0;
real variance = 0;

real GetRunningStandardDeviation(ref sum, ref count, ref S, x)
{
   real oldMean;

   if (count >= 1)
   {
       real oldMean = sum / count;
       sum = sum + x;
       count = count + 1;
       real newMean = sum / count;

       S = S + (x-oldMean)*(x-newMean)
   }
   else
   {
       sum = x;
       count = 1;
       S = 0;         
   }

   //estimated Variance = (S / (k-1) )
   //estimated Standard Deviation = sqrt(variance)
   if (count > 1)
      return sqrt(S / (count-1) );
   else
      return 0;
}

Although in the article they don't maintain a separate running sum and count, but instead have the single mean. Since in thing i'm doing today i keep a count (for statistical purposes), it is more useful to calculate the means each time.

Ian Boyd
источник
0

Given original x¯, s, and n, as well as the change of a given element xn to xn, I believe your new standard deviation s will be the square root of

s2+1n1(2nΔx¯(xnx¯)+n(n1)(Δx¯)2),
where Δx¯=x¯x¯, with x¯ denoting the new mean.

Maybe there is a snazzier way of writing it?

I checked this against a small test case and it seemed to work.

Whistling in the Dark
источник
1
@john / whistling in the Dark: I liked your answer, it seems work properly in my small dataset. Is there any mathematical foundation/reference on it? Could you kindly help?
Alok Chowdhury
The question was all @Whistling in the Dark, I just cleaned it up for the site. You should pose a new question referencing the question and answer here. And also you should upvote this answer if you feel that way.
John