Los algoritmos para calcular la varianza desempeñan un papel importante en la estadística computacional . Una dificultad clave en el diseño de buenos algoritmos para este problema es que las fórmulas para la varianza pueden involucrar sumas de cuadrados, lo que puede conducir a una inestabilidad numérica , así como a un desbordamiento aritmético cuando se trabaja con valores grandes.
Algoritmo ingenuo
Una fórmula para calcular la varianza de una población entera de tamaño N es:
Utilizando la corrección de Bessel para calcular una estimación imparcial de la varianza de la población a partir de una muestra finita de n observaciones, la fórmula es:
Por lo tanto, un algoritmo ingenuo para calcular la varianza estimada viene dado por el siguiente:
- Sea n ← 0, Suma ← 0, Suma cuadrada ← 0
- Para cada dato x :
- n ← n + 1
- Suma ← Suma + x
- SumaCuadrada ← SumaCuadrada + x × x
- Var = (SumaSq − (Suma × Suma) / n) / (n − 1)
Este algoritmo se puede adaptar fácilmente para calcular la varianza de una población finita: simplemente divida por n en lugar de n − 1 en la última línea.
Debido a que SumSq y (Sum×Sum)/ n pueden ser números muy similares, la cancelación puede hacer que la precisión del resultado sea mucho menor que la precisión inherente de la aritmética de punto flotante utilizada para realizar el cálculo. Por lo tanto, este algoritmo no debería utilizarse en la práctica [1] [2] y se han propuesto varios algoritmos alternativos numéricamente estables [3] . Esto es particularmente malo si la desviación estándar es pequeña en relación con la media.
Cálculo de datos desplazados
La varianza es invariante con respecto a los cambios en un parámetro de ubicación , una propiedad que puede utilizarse para evitar la cancelación catastrófica en esta fórmula.
con cualquier constante, lo que conduce a la nueva fórmula
Cuanto más cerca esté del valor medio, más preciso será el resultado, pero simplemente eligiendo un valor dentro del rango de las muestras se garantizará la estabilidad deseada. Si los valores son pequeños, no hay problemas con la suma de sus cuadrados; por el contrario, si son grandes, significa necesariamente que la varianza también es grande. En cualquier caso, el segundo término de la fórmula es siempre menor que el primero, por lo que no puede producirse ninguna cancelación. [2]
Si solo se toma la primera muestra, el algoritmo se puede escribir en lenguaje de programación Python como
def shifted_data_variance ( data ):
if len ( data ) < 2 :
return 0.0
K = data [ 0 ]
n = Ex = Ex2 = 0.0
for x in data :
n += 1
Ex += x - K
Ex2 += ( x - K ) ** 2
variance = ( Ex2 - Ex ** 2 / n ) / ( n - 1 )
# use n en lugar de (n-1) si desea calcular la varianza exacta de los datos dados
# use (n-1) si los datos son muestras de una población más grande
devuelve varianza
Esta fórmula también facilita el cálculo incremental que se puede expresar como
K = Ex = Ex2 = 0,0
n = 0
def add_variable ( x ):
global K , n , Ex , Ex2
si n == 0 :
K = x
n += 1
Ex += x - K
Ex2 += ( x - K ) ** 2
def eliminar_variable ( x ):
global K , n , Ex , Ex2
n -= 1
Ex -= x - K
Ex2 -= ( x - K ) ** 2
def get_mean ():
global K , n , Ex
devuelve K + Ex / n
def obtener_varianza ():
global n , Ex , Ex2
devuelve ( Ex2 - Ex ** 2 / n ) / ( n - 1 )
Algoritmo de dos pasadas
Un enfoque alternativo, que utiliza una fórmula diferente para la varianza, primero calcula la media de la muestra,
y luego calcula la suma de los cuadrados de las diferencias con respecto a la media,
donde s es la desviación estándar. Esto se obtiene mediante el siguiente código:
def two_pass_variance ( datos ):
n = len ( datos )
media = suma ( datos ) / n
varianza = suma (( x - media ) ** 2 para x en datos ) / ( n - 1 )
devuelve varianza
Este algoritmo es numéricamente estable si n es pequeño. [1] [4] Sin embargo, los resultados de ambos algoritmos simples ("ingenuo" y "de dos pasadas") pueden depender excesivamente del orden de los datos y pueden dar resultados deficientes para conjuntos de datos muy grandes debido al error de redondeo repetido en la acumulación de las sumas. Se pueden utilizar técnicas como la suma compensada para combatir este error hasta cierto punto.
Algoritmo en línea de Welford
A menudo resulta útil poder calcular la varianza en una sola pasada , inspeccionando cada valor solo una vez; por ejemplo, cuando se recopilan los datos sin suficiente almacenamiento para guardar todos los valores, o cuando los costos de acceso a la memoria dominan los de cálculo. Para un algoritmo en línea de este tipo , se requiere una relación de recurrencia entre las cantidades a partir de las cuales se pueden calcular las estadísticas requeridas de una manera numéricamente estable.
Las siguientes fórmulas se pueden utilizar para actualizar la media y la varianza (estimada) de la secuencia, para un elemento adicional x n . Aquí, denota la media muestral de las primeras n muestras , su varianza muestral sesgada y su varianza muestral no sesgada .
Estas fórmulas sufren inestabilidad numérica [ cita requerida ] , ya que restan repetidamente un número pequeño de un número grande que escala con n . Una cantidad mejor para actualizar es la suma de los cuadrados de las diferencias con respecto a la media actual, , que aquí se denota como :
Este algoritmo fue descubierto por Welford, [5] [6] y ha sido analizado exhaustivamente. [2] [7] También es común denotar y . [8]
A continuación se muestra un ejemplo de implementación de Python para el algoritmo de Welford.
# Para un nuevo valor new_value, calcula el nuevo conteo, la nueva media, el nuevo M2.
# media acumula la media de todo el conjunto de datos
# M2 agrega la distancia al cuadrado desde la media
# count agrega la cantidad de muestras vistas hasta el momento
def update ( existing_gregate , new_value ):
( count , mean , M2 ) = existing_gregate
count += 1
delta = new_value - mean
mean += delta / count
delta2 = new_value - mean
M2 += delta * delta2
return ( count , mean , M2 )
# Recuperar la media, la varianza y la varianza de la muestra de un agregado
def finalize ( existing_gregate ):
( count , mean , M2 ) = existing_gregate
if count < 2 :
return float ( "nan" )
else :
( mean , variance , sample_variance ) = ( mean , M2 / count , M2 / ( count - 1 ))
return ( mean , variance , sample_variance )
Este algoritmo es mucho menos propenso a la pérdida de precisión debido a una cancelación catastrófica , pero podría no ser tan eficiente debido a la operación de división dentro del bucle. Para un algoritmo de dos pasadas particularmente robusto para calcular la varianza, primero se puede calcular y restar una estimación de la media y luego usar este algoritmo en los residuos.
El algoritmo paralelo a continuación ilustra cómo fusionar múltiples conjuntos de estadísticas calculadas en línea.
Algoritmo incremental ponderado
El algoritmo se puede ampliar para manejar pesos de muestra desiguales, reemplazando el simple contador n con la suma de pesos vistos hasta ahora. West (1979) [9] sugiere este algoritmo incremental :
def varianza_incremental_ponderada ( pares_ponderados_de_datos ):
suma_w = suma_w2 = media = S = 0
para x , w en pares_de_pesos_de_datos :
w_suma = w_suma + w
w_suma2 = w_suma2 + w ** 2
media_antigua = media media
= media_antigua + ( w / w_suma ) * ( x - media_antigua ) S = S + w * ( x - media_antigua ) * ( x - media )
population_variance = S / w_sum
# Corrección de Bessel para muestras ponderadas
# para ponderaciones de frecuencia entera
sample_frequency_variance = S / ( w_sum - 1 )
Algoritmo paralelo
Chan et al. [10] señalan que el algoritmo en línea de Welford detallado anteriormente es un caso especial de un algoritmo que funciona para combinar conjuntos arbitrarios y :
- .
Esto puede ser útil cuando, por ejemplo, se pueden asignar múltiples unidades de procesamiento a partes discretas de la entrada.
El método de Chan para estimar la media es numéricamente inestable cuando y ambos son grandes, porque el error numérico en no se reduce de la forma en que lo hace en este caso. En tales casos, es preferible .
def varianza_paralela ( n_a , avg_a , M2_a , n_b , avg_b , M2_b ):
n = n_a + n_b
delta = avg_b - avg_a
M2 = M2_a + M2_b + delta ** 2 * n_a * n_b / n
var_ab = M2 / ( n - 1 )
devolver var_ab
Esto se puede generalizar para permitir la paralelización con AVX , con GPU y clústeres de computadoras , y para la covarianza. [3]
Ejemplo
Supongamos que todas las operaciones de punto flotante utilizan la aritmética de doble precisión estándar IEEE 754. Consideremos la muestra (4, 7, 13, 16) de una población infinita. Con base en esta muestra, la media poblacional estimada es 10 y la estimación no sesgada de la varianza poblacional es 30. Tanto el algoritmo ingenuo como el algoritmo de dos pasadas calculan estos valores correctamente.
A continuación, considere la muestra ( 10 8 + 4 , 10 8 + 7 , 10 8 + 13 , 10 8 + 16 ), que da lugar a la misma varianza estimada que la primera muestra. El algoritmo de dos pasadas calcula esta estimación de varianza correctamente, pero el algoritmo ingenuo devuelve 29,333333333333332 en lugar de 30.
Si bien esta pérdida de precisión puede ser tolerable y verse como un defecto menor del algoritmo ingenuo, aumentar aún más el desfase hace que el error sea catastrófico. Considere la muestra ( 10 9 + 4 , 10 9 + 7 , 10 9 + 13 , 10 9 + 16 ). Nuevamente, la varianza poblacional estimada de 30 se calcula correctamente mediante el algoritmo de dos pasadas, pero el algoritmo ingenuo ahora la calcula como −170,66666666666666. Este es un problema grave con el algoritmo ingenuo y se debe a la cancelación catastrófica en la resta de dos números similares en la etapa final del algoritmo.
Estadísticas de orden superior
Terriberry [11] extiende las fórmulas de Chan para calcular el tercer y cuarto momento central , necesarios, por ejemplo, al estimar la asimetría y la curtosis :
Aquí están nuevamente las sumas de potencias de diferencias de la media , dando
Para el caso incremental (es decir, ), esto se simplifica a:
Al preservar el valor , solo se necesita una operación de división y las estadísticas de orden superior se pueden calcular con un costo incremental mínimo.
Un ejemplo del algoritmo en línea para curtosis implementado como se describe es:
def online_kurtosis ( datos ):
n = media = M2 = M3 = M4 = 0
para x en los datos :
n1 = n
n = n + 1
delta = x - media
delta_n = delta / n
delta_n2 = delta_n ** 2
término1 = delta * delta_n * n1
media = media + delta_n
M4 = M4 + término1 * delta_n2 * ( n ** 2 - 3 * n + 3 ) + 6 * delta_n2 * M2 - 4 * delta_n * M3
M3 = M3 + término1 * delta_n * ( n - 2 ) - 3 * delta_n * M2
M2 = M2 + término1
# Nota, también puede calcular la varianza usando M2 y la asimetría usando M3
# Precaución: Si todas las entradas son iguales, M2 será 0, lo que dará como resultado una división por 0.
kurtosis = ( n * M4 ) / ( M2 ** 2 ) - 3
return kurtosis
Pébaÿ [12] extiende aún más estos resultados a momentos centrales de orden arbitrario , para los casos incrementales y por pares, y posteriormente Pébaÿ et al. [13] para momentos ponderados y compuestos. También se pueden encontrar allí fórmulas similares para la covarianza .
Choi y Sweetman [14] ofrecen dos métodos alternativos para calcular la asimetría y la curtosis, cada uno de los cuales puede ahorrar requisitos sustanciales de memoria de computadora y tiempo de CPU en ciertas aplicaciones. El primer enfoque es calcular los momentos estadísticos separando los datos en contenedores y luego calculando los momentos a partir de la geometría del histograma resultante, lo que efectivamente se convierte en un algoritmo de una sola pasada para momentos más altos. Un beneficio es que los cálculos de momentos estadísticos se pueden realizar con una precisión arbitraria de modo que los cálculos se puedan ajustar a la precisión de, por ejemplo, el formato de almacenamiento de datos o el hardware de medición original. Un histograma relativo de una variable aleatoria se puede construir de la manera convencional: el rango de valores potenciales se divide en contenedores y se cuenta y se grafica el número de ocurrencias dentro de cada contenedor de modo que el área de cada rectángulo sea igual a la porción de los valores de muestra dentro de ese contenedor:
donde y representan la frecuencia y la frecuencia relativa en el intervalo y es el área total del histograma. Después de esta normalización, los momentos brutos y los momentos centrales de se pueden calcular a partir del histograma relativo:
donde el superíndice indica que los momentos se calculan a partir del histograma. Para un ancho de intervalo constante, estas dos expresiones se pueden simplificar utilizando :
El segundo enfoque de Choi y Sweetman [14] es una metodología analítica para combinar momentos estadísticos de segmentos individuales de un historial temporal de modo que los momentos generales resultantes sean los del historial temporal completo. Esta metodología podría utilizarse para el cálculo paralelo de momentos estadísticos con la posterior combinación de esos momentos, o para la combinación de momentos estadísticos calculados en momentos secuenciales.
Si se conocen conjuntos de momentos estadísticos: para , entonces cada uno puede expresarse en términos de los momentos brutos equivalentes:
donde generalmente se toma como la duración del historial de tiempo o el número de puntos si es constante.
La ventaja de expresar los momentos estadísticos en términos de es que los conjuntos se pueden combinar mediante adición y no hay un límite superior en el valor de .
donde el subíndice representa el historial temporal concatenado o combinado . Estos valores combinados de pueden luego transformarse inversamente en momentos sin procesar que representan el historial temporal concatenado completo
Las relaciones conocidas entre los momentos brutos ( ) y los momentos centrales ( ) se utilizan luego para calcular los momentos centrales de la historia temporal concatenada. Finalmente, los momentos estadísticos de la historia concatenada se calculan a partir de los momentos centrales:
Covarianza
Se pueden utilizar algoritmos muy similares para calcular la covarianza .
Algoritmo ingenuo
El algoritmo ingenuo es
Para el algoritmo anterior, se podría utilizar el siguiente código Python:
def naive_covariance ( datos1 , datos2 ):
n = len ( datos1 )
suma1 = suma ( datos1 )
suma2 = suma ( datos2 )
suma12 = suma ([ i1 * i2 para i1 , i2 en zip ( datos1 , datos2 )])
covarianza = ( suma12 - suma1 * suma2 / n ) / n
devuelve covarianza
Con estimación de la media
En cuanto a la varianza, la covarianza de dos variables aleatorias también es invariante al desplazamiento, por lo que dados dos valores constantes cualesquiera , se puede escribir:
Y, de nuevo, si se elige un valor dentro del rango de valores, se estabilizará la fórmula frente a una cancelación catastrófica y se la hará más robusta frente a grandes sumas. Si se toma el primer valor de cada conjunto de datos, el algoritmo se puede escribir de la siguiente manera:
def shifted_data_covariance ( datos_x , datos_y ):
n = len ( datos_x )
si n < 2 :
devuelve 0
kx = datos_x [ 0 ]
ky = datos_y [ 0 ]
Ex = Ey = Exy = 0
para ix , iy en zip ( datos_x , datos_y ):
Ex += ix - kx
Ey += iy - ky
Exy += ( ix - kx ) * ( iy - ky )
devuelve ( Exy - Ex * Ey / n ) / n
Dos pasadas
El algoritmo de dos pasos primero calcula las medias de muestra y luego la covarianza:
El algoritmo de dos pasos se puede escribir como:
def covarianza_de_dos_pasos ( datos1 , datos2 ):
n = len ( datos1 )
media1 = suma ( datos1 ) / n
media2 = suma ( datos2 ) / n
covarianza = 0
para i1 , i2 en zip ( datos1 , datos2 ):
a = i1 - media1
b = i2 - media2
covarianza += a * b / n
devuelve covarianza
Una versión compensada ligeramente más precisa ejecuta el algoritmo ingenuo completo sobre los residuos. Las sumas finales deberían ser cero, pero la segunda pasada compensa cualquier pequeño error.
En línea
Existe un algoritmo estable de una sola pasada, similar al algoritmo en línea para calcular la varianza, que calcula el co-momento :
La aparente asimetría en esa última ecuación se debe al hecho de que , por lo que ambos términos de actualización son iguales a . Se puede lograr una precisión aún mayor calculando primero las medias y luego utilizando el algoritmo estable de una sola pasada en los residuos.
Por lo tanto, la covarianza se puede calcular como
def online_covariance ( datos1 , datos2 ):
mediax = mediay = C = n = 0
para x , y en zip ( datos1 , datos2 ):
n += 1
dx = x - mediax
mediax += dx / n
mediay += ( y - mediay ) / n
C += dx * ( y - mediay )
población_covar = C / n
# Corrección de Bessel para la varianza de la muestra
muestra_covar = C / ( n - 1 )
También se puede realizar una pequeña modificación para calcular la covarianza ponderada:
def online_weighted_covariance ( datos1 , datos2 , datos3 ):
mediax = mediay = 0
wsum = wsum2 = 0
C = 0
para x , y , w en zip ( datos1 , datos2 , datos3 ):
wsum += w
wsum2 += w * w
dx = x - mediax
mediax += ( w / wsum ) * dx
mediay += ( w / wsum ) * ( y - mediay )
C += w * dx * ( y - mediay )
population_covar = C / wsum
# Corrección de Bessel para la varianza de la muestra
# Ponderaciones de frecuencia
sample_frequency_covar = C / ( wsum - 1 )
# Ponderaciones de confiabilidad
sample_reliability_covar = C / ( wsum - wsum2 / wsum )
Asimismo, existe una fórmula para combinar las covarianzas de dos conjuntos que puede utilizarse para paralelizar el cálculo: [3]
Versión por lotes ponderada
También existe una versión del algoritmo ponderado en línea que realiza actualizaciones por lotes: denotemos los pesos y escribamos
La covarianza puede entonces calcularse como
Véase también
Referencias
- ^ ab Einarsson, Bo (2005). Precisión y confiabilidad en computación científica. SIAM. p. 47. ISBN 978-0-89871-584-2.
- ^ abc Chan, Tony F. ; Golub, Gene H. ; LeVeque, Randall J. (1983). "Algoritmos para calcular la varianza de la muestra: análisis y recomendaciones" (PDF) . The American Statistician . 37 (3): 242–247. doi :10.1080/00031305.1983.10483115. JSTOR 2683386. Archivado (PDF) desde el original el 9 de octubre de 2022.
- ^ abc Schubert, Erich; Gertz, Michael (9 de julio de 2018). Cálculo paralelo numéricamente estable de (co-)varianza. ACM. p. 10. doi :10.1145/3221269.3223036. ISBN 9781450365055.S2CID 49665540 .
- ^ Higham, Nicholas J. (2002). "Problema 1.10". Precisión y estabilidad de algoritmos numéricos (2.ª ed.). Filadelfia, Pensilvania: Sociedad de Matemáticas Industriales y Aplicadas. doi :10.1137/1.9780898718027. ISBN 978-0-898715-21-7. mi ISBN 978-0-89871-802-7 , 2002075848. Los metadatos también figuran en la Biblioteca Digital ACM.
- ^ Welford, BP (1962). "Nota sobre un método para calcular sumas corregidas de cuadrados y productos". Technometrics . 4 (3): 419–420. doi :10.2307/1266577. JSTOR 1266577.
- ^ Donald E. Knuth (1998). El arte de la programación informática , volumen 2: Algoritmos seminuméricos , 3.ª ed., pág. 232. Boston: Addison-Wesley.
- ^ Ling, Robert F. (1974). "Comparación de varios algoritmos para calcular medias y varianzas de muestras". Revista de la Asociación Estadounidense de Estadística . 69 (348): 859–866. doi :10.2307/2286154. JSTOR 2286154.
- ^ Cook, John D. (30 de septiembre de 2022) [1 de noviembre de 2014]. "Cómo calcular con precisión la varianza de la muestra". John D. Cook Consulting: Consultoría experta en matemáticas aplicadas y privacidad de datos .
- ^ West, DHD (1979). "Actualización de estimaciones de media y varianza: un método mejorado". Comunicaciones de la ACM . 22 (9): 532–535. doi : 10.1145/359146.359153 . S2CID 30671293.
- ^ Chan, Tony F. ; Golub, Gene H. ; LeVeque, Randall J. (noviembre de 1979). "Updating Formulae and a Pairwise Algorithm for Computing Sample Variances" (PDF) . Departamento de Ciencias de la Computación, Universidad de Stanford. Informe técnico STAN-CS-79-773, financiado en parte por el contrato del Ejército n.º DAAGEI-'EG-013.
- ^ Terriberry, Timothy B. (15 de octubre de 2008) [9 de diciembre de 2007]. "Computing Higher-Order Moments Online". Archivado desde el original el 23 de abril de 2014. Consultado el 5 de mayo de 2008 .
- ^ Pébay, Philippe Pierre (septiembre de 2008). "Fórmulas para el cálculo robusto en paralelo de una sola pasada de covarianzas y momentos estadísticos de orden arbitrario". Organización patrocinadora: USDOE. Albuquerque, NM y Livermore, CA (Estados Unidos): Sandia National Laboratories (SNL). doi :10.2172/1028931. OSTI 1028931. Informe técnico SAND2008-6212, TRN: US201201%%57, número de contrato del DOE: AC04-94AL85000 – a través de la Biblioteca digital de la UNT.
- ^ Pébaÿ, Philippe; Terriberry, Timothy; Kolla, Hemanth; Bennett, Janine (2016). "Fórmulas numéricamente estables y escalables para el cálculo paralelo y en línea de momentos centrales multivariados de orden superior con pesos arbitrarios". Computational Statistics . 31 (4). Springer: 1305–1325. doi :10.1007/s00180-015-0637-z. S2CID 124570169.
- ^ ab Choi, Myoungkeun; Sweetman, Bert (2010). "Cálculo eficiente de momentos estadísticos para el monitoreo de la salud estructural". Revista de monitoreo de la salud estructural . 9 (1): 13–24. doi :10.1177/1475921709341014. S2CID 17534100.
Enlaces externos
- Weisstein, Eric W. "Cálculo de la varianza de la muestra". MathWorld .