Análisis de componentes principales ponderados

17

Después de algunas búsquedas, encuentro muy poco sobre la incorporación de los pesos de observación / errores de medición en el análisis de componentes principales. Lo que encuentro tiende a depender de enfoques iterativos para incluir ponderaciones (por ejemplo, aquí ). Mi pregunta es ¿por qué es necesario este enfoque? ¿Por qué no podemos usar los vectores propios de la matriz de covarianza ponderada?

sin nombre
fuente
1
Además de la (s) respuesta (s) a continuación, consulte estadísticas del hilo.stackexchange.com/q/141754/3277 , donde la PCA ponderada (con ponderaciones en columnas y / o filas) se explica principalmente como equivalente a svd / ponderada (generalizada) biplot
ttnphns

Respuestas:

33

Depende de a qué se apliquen exactamente sus pesos.

Pesas de fila

Sea la matriz de datos con variables en columnas y observaciones en filas. Si cada observación tiene un peso asociado , entonces es realmente sencillo incorporar estos pesos en PCA.Xnxiwi

Primero, uno necesita calcular la media ponderada y de los datos para centrarla .μ=1wiwixi

Luego calculamos la matriz de covarianza ponderada 1wiXWX , donde W=diag(wi) es la matriz diagonal de pesos, y aplique PCA estándar para analizarlo.

Pesos celulares

El documento de Tamuz et al., 2013 , que encontró, considera un caso más complicado cuando se aplican diferentes pesos a cada elemento de la matriz de datos. Entonces, de hecho, no hay una solución analítica y uno tiene que usar un método iterativo. Tenga en cuenta que, como reconocieron los autores, reinventaron la rueda, ya que tales pesos generales ciertamente se han considerado antes, por ejemplo, en Gabriel y Zamir, 1979, Aproximación de matrices de rango inferior por mínimos cuadrados con cualquier elección de pesos . Esto también se discutió aquí .wij

Como observación adicional: si los pesos varían tanto con las variables como con las observaciones, pero son simétricos, de modo que , entonces la solución analítica es posible nuevamente, ver Koren y Carmel, 2004, Robust Reducción de dimensionalidad lineal .wijwij=wji

ameba dice Reinstate Monica
fuente
Gracias por la aclaración. ¿Puede explicar por qué no es posible una solución analítica con pesos fuera de diagonal? Esto es lo que me falta tanto de Tamuz et al 2013 como de Gabriel y Zamir 1979.
noname
@noname: No estoy al tanto de tal prueba, y además no me sorprendería si no se conociera. En general, es bastante difícil demostrar que algo no es posible , en particular que algo no es posible analíticamente. La imposibilidad de trisección del ángulo famoso esperó a su prueba más de 2000 años ... (cont.)
ameba dice Restablecer Mónica
3
@noname: (cont.) Lo que está preguntando es mostrar que el problema de minimizar con respecto a obligado a tener rango bajo . no es reducible a un problema de vector propio. Me temo que necesitarías otro foro para eso (¿quizás mathoverflow?). Pero tenga en cuenta que encontrar vectores propios tampoco es exactamente una solución analítica : es solo que las iteraciones generalmente se realizan en silencio por una función de biblioteca estándar. A qi,jwij(XijAij)2Aq
ameba dice Reinstate Monica
2
+1. La primera sección de la respuesta puede conceptualizarse también en términos de Biplot ponderado (generalizado) como se describe aquí . Teniendo en cuenta cómo PCA es un "caso específico de" Biplot (también preocupado en la respuesta alineada).
ttnphns
@ttnphns: después de que tu comentario y otro hilo se cerraron como duplicado, releí mi respuesta y amplié la explicación de cómo lidiar con los pesos de las filas. Creo que anteriormente no era completamente correcto o al menos no estaba completo porque no mencioné el centrado con una media ponderada. ¡Espero que tenga más sentido ahora!
ameba dice Reinstate Monica
5

Muchas gracias ameba por la información sobre los pesos de las filas. Sé que esto no es stackoverflow, pero tuve algunas dificultades para encontrar una implementación de PCA ponderada en fila con explicación y, dado que este es uno de los primeros resultados al buscar en Google PCA ponderado, pensé que sería bueno adjuntar mi solución , tal vez pueda ayudar a otros en la misma situación. En este fragmento de código Python2, una PCA ponderada con un kernel RBF como el descrito anteriormente se usa para calcular las tangentes de un conjunto de datos 2D. ¡Estaré muy feliz de escuchar algunos comentarios!

def weighted_pca_regression(x_vec, y_vec, weights):
    """
    Given three real-valued vectors of same length, corresponding to the coordinates
    and weight of a 2-dimensional dataset, this function outputs the angle in radians
    of the line that aligns with the (weighted) average and main linear component of
    the data. For that, first a weighted mean and covariance matrix are computed.
    Then u,e,v=svd(cov) is performed, and u * f(x)=0 is solved.
    """
    input_mat = np.stack([x_vec, y_vec])
    weights_sum = weights.sum()
    # Subtract (weighted) mean and compute (weighted) covariance matrix:
    mean_x, mean_y =  weights.dot(x_vec)/weights_sum, weights.dot(y_vec)/weights_sum
    centered_x, centered_y = x_vec-mean_x, y_vec-mean_y
    matrix_centered = np.stack([centered_x, centered_y])
    weighted_cov = matrix_centered.dot(np.diag(weights).dot(matrix_centered.T)) / weights_sum
    # We know that v rotates the data's main component onto the y=0 axis, and
    # that u rotates it back. Solving u.dot([x,0])=[x*u[0,0], x*u[1,0]] gives
    # f(x)=(u[1,0]/u[0,0])x as the reconstructed function.
    u,e,v = np.linalg.svd(weighted_cov)
    return np.arctan2(u[1,0], u[0,0]) # arctan more stable than dividing


# USAGE EXAMPLE:
# Define the kernel and make an ellipse to perform regression on:
rbf = lambda vec, stddev: np.exp(-0.5*np.power(vec/stddev, 2))
x_span = np.linspace(0, 2*np.pi, 31)+0.1
data_x = np.cos(x_span)[:-1]*20-1000
data_y = np.sin(x_span)[:-1]*10+5000
data_xy = np.stack([data_x, data_y])
stddev = 1 # a stddev of 1 in this context is highly local
for center in data_xy.T:
    # weight the  points based on their euclidean distance to the current center
    euclidean_distances = np.linalg.norm(data_xy.T-center, axis=1)
    weights = rbf(euclidean_distances, stddev)
    # get the angle for the regression in radians
    p_grad = weighted_pca_regression(data_x, data_y, weights)
    # plot for illustration purposes
    line_x = np.linspace(-5,5,10)
    line_y = np.tan(p_grad)*line_x
    plt.plot(line_x+center[0], line_y+center[1], c="r")
    plt.scatter(*data_xy)
    plt.show()

Y una salida de muestra (hace lo mismo para cada punto): ingrese la descripción de la imagen aquí

Saludos,
Andres

fr_andres SoportesMonicaCellio
fuente