Это просто дополнение к ответу aniko с черновым наброском деривации и некоторым кодом на python, поэтому все кредиты идут на aniko.
вывод
ИксJ∈ X= { X1, X2, … , Xграмм}граммКJ= | ИксJ|
ЕJВJ= E [ XJ] = 1КJΣя = 1КJИксJ я= V a r [ XJ] = 1КJ- 1Σя = 1КJ( ХJ я- EJ)2
соответственно. Если мы установим
n = ∑граммJ = 1КJдисперсия полного набора данных определяется как:
V a r [ X]= 1n - 1ΣJ = 1граммΣя = 1КJ( ХJ я- E [ X] )2= 1n - 1ΣJ = 1граммΣя = 1КJ( (XJ я- EJ) - ( E [ X] - EJ) )2= 1n - 1ΣJ = 1граммΣя = 1КJ( ХJ я- EJ)2- 2 ( ХJ я- EJ) ( E [ X] - EJ) + ( E [ X] - EJ)2= 1n - 1ΣJ = 1грамм( кJ- 1 ) VJ+ кJ( E [ X] - EJ)2,
Если у нас одинаковый размер
К для каждой части, т.е.
∀ j : kJ= кПриведенная выше формула упрощает
V a r [ X]= 1n - 1ΣJ = 1грамм( к - 1 ) ВJ+ к ( г- 1 ) V a r [ EJ]= к - 1n - 1ΣJ = 1граммВJ+ к ( г- 1 )к - 1V a r [ EJ]
код 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))