Как рассчитать дисперсию разбиения переменных

15

Я провожу эксперимент, в котором я собираю (независимые) выборки параллельно, я вычисляю дисперсию каждой группы выборок, и теперь я хочу объединить все тогда, чтобы найти общую дисперсию всех выборок.

Мне трудно найти выход для этого, так как я не уверен в терминологии. Я думаю об этом как о разделе одного RV.

Поэтому я хочу найти Вaр(Икс) из Вaр(Икс1) , Вaр(Икс2) , ... и Вaр(ИксN) , где Икс = [Икс1,Икс2,...,ИксN] .

РЕДАКТИРОВАТЬ: Разделы не имеют одинаковый размер / количество элементов, но сумма размеров разделов равна числу выборок в общем наборе выборок.

РЕДАКТИРОВАНИЕ 2: Здесь есть формула для параллельных вычислений , но она охватывает только случай разбиения на два набора, а не N наборов.

галламин
источник
Это же , как и мой вопрос здесь: mathoverflow.net/questions/64120/...
Что означает эта последняя скобка? И что вы подразумеваете под "полной дисперсией"? Это что-то, кроме дисперсии объединенного набора данных?
whuber
@whuber какой последний кронштейн? «общая дисперсия» означает дисперсию общего набора данных.
Галламин
Выражение может означать много вещей (хотя условно это будет вектор): я искал разъяснения. [Икс1,Икс2,...,ИксN]
whuber

Ответы:

22

Формула довольно проста, если все подвыборки имеют одинаковый размер выборки. Если у вас было подвыборок размером k (всего g k выборок), то дисперсия объединенной выборки зависит от среднего значения E j и дисперсии V j для каждой выборки: V a r ( X 1 , , X g k ) = k - 1граммКграммКЕJВJгде подVar(Ej)подразумевается дисперсия выборки.

Var(X1,,Xgk)=k1gk1(j=1gVj+k(g1)k1Var(Ej)),
Var(Ej)

Демонстрация в R:

> x <- rnorm(100)
> g <- gl(10,10)
> mns <- tapply(x, g, mean)
> vs <- tapply(x, g, var)
> 9/99*(sum(vs) + 10*var(mns))
[1] 1.033749
> var(x)
[1] 1.033749

Если размеры выборки не равны, формула не так хороша.

РЕДАКТИРОВАТЬ: формула для неравных размеров выборки

граммКJ,Jзнак равно1,...,граммNзнак равноΣКJ

Вaр(Икс1,...,ИксN)знак равно1N-1(ΣJзнак равно1грамм(КJ-1)ВJ+ΣJзнак равно1граммКJ(Икс¯J-Икс¯)2),
Икс¯знак равно(ΣJзнак равно1граммКJИкс¯J)/N

Опять демонстрация:

> k <- rpois(10, lambda=10)
> n <- sum(k)
> g <- factor(rep(1:10, k))
> x <- rnorm(n)
> mns <- tapply(x, g, mean)
> vs <- tapply(x, g, var)
> 1/(n-1)*(sum((k-1)*vs) + sum(k*(mns-weighted.mean(mns,k))^2))
[1] 1.108966
> var(x)
[1] 1.108966

(ИксJя-Икс¯)2Икс¯J[(ИксJя-Икс¯J)-(Икс¯J-Икс¯)]2

Анико
источник
Благодарю. К сожалению, я не могу гарантировать, что мои разделы имеют одинаковый размер. Я запускаю массивно параллельный процесс, в котором мне нужно вычислить дисперсии каждого раздела параллельно, а затем объединить в конце, но результаты / выборки из каждого параллельного процесса не равны (это моделирование полученных фотонов методом Монте-Карло).
Галламин
3
Я не могу +1 этого достаточно, супер полезная формула для параллельных вычислений в среде хранилища данных
Ноа Йеттер
1

Это просто дополнение к ответу aniko с черновым наброском деривации и некоторым кодом на python, поэтому все кредиты идут на aniko.

вывод

ИксJИксзнак равно{Икс1,Икс2,...,Иксграмм}граммКJзнак равно|ИксJ|

ЕJзнак равноЕ[ИксJ]знак равно1КJΣязнак равно1КJИксJяВJзнак равноВaр[ИксJ]знак равно1КJ-1Σязнак равно1КJ(ИксJя-ЕJ)2
соответственно. Если мы установимNзнак равноΣJзнак равно1граммКJдисперсия полного набора данных определяется как:
Вaр[Икс]знак равно1N-1ΣJзнак равно1граммΣязнак равно1КJ(ИксJя-Е[Икс])2знак равно1N-1ΣJзнак равно1граммΣязнак равно1КJ((ИксJя-ЕJ)-(Е[Икс]-ЕJ))2знак равно1N-1ΣJзнак равно1граммΣязнак равно1КJ(ИксJя-ЕJ)2-2(ИксJя-ЕJ)(Е[Икс]-ЕJ)+(Е[Икс]-ЕJ)2знак равно1N-1ΣJзнак равно1грамм(КJ-1)ВJ+КJ(Е[Икс]-ЕJ)2,
Если у нас одинаковый размер К для каждой части, т.е. J:КJзнак равноКПриведенная выше формула упрощает
Вaр[Икс]знак равно1N-1ΣJзнак равно1грамм(К-1)ВJ+К(грамм-1)Вaр[ЕJ]знак равноК-1N-1ΣJзнак равно1граммВJ+К(грамм-1)К-1Вaр[ЕJ]

код Python

Следующая функция python работает для массивов, разделенных по первому измерению, и реализует «более сложную» формулу для деталей разного размера.

import numpy as np

def combine(averages, variances, counts, size=None):
    """
    Combine averages and variances to one single average and variance.

    # Arguments
        averages: List of averages for each part.
        variances: List of variances for each part.
        counts: List of number of elements in each part.
        size: Total number of elements in all of the parts.
    # Returns
        average: Average over all parts.
        variance: Variance over all parts.
    """
    average = np.average(averages, weights=counts)

    # necessary for correct variance in case of multidimensional arrays
    if size is not None:
        counts = counts * size // np.sum(counts, dtype='int')

    squares = (counts - 1) * variances + counts * (averages - average)**2
    return average, np.sum(squares) / (size - 1)

Может использоваться следующим образом:

# sizes k_j and n
ks = np.random.poisson(10, 10)
n = np.sum(ks)

# create data
x = np.random.randn(n, 20)
parts = np.split(x, np.cumsum(ks[:-1]))

# compute statistics on parts
ms = [np.mean(p) for p in parts]
vs = [np.var(p, ddof=1) for p in parts]

# combine and compare
combined = combine(ms, vs, ks, x.size)
numpied = np.mean(x), np.var(x, ddof=1)
distance = np.abs(np.array(combined) - np.array(numpied))
print('combined --- mean:{: .9f} - var:{: .9f}'.format(*combined))
print('numpied  --- mean:{: .9f} - var:{: .9f}'.format(*numpied))
print('distance --- mean:{: .5e} - var:{: .5e}'.format(*distance))
Мистер Цйолдер
источник