Analisi ponderata dei componenti principali


17

Dopo alcune ricerche, trovo ben poco sull'incorporazione di pesi di osservazione / errori di misurazione nell'analisi dei componenti principali. Quello che trovo tende a fare affidamento su approcci iterativi per includere i coefficienti correttori (ad es. Qui ). La mia domanda è: perché è necessario questo approccio? Perché non possiamo usare gli autovettori della matrice di covarianza ponderata?


1
Oltre alle risposte di seguito, consultare la discussione stats.stackexchange.com/q/141754/3277 , dove la PCA ponderata (con pesi su colonne e / o righe) è spiegata come principalmente equivalente alla svd ponderata (generalizzata) biplot.
ttnphns,

Risposte:


33

Dipende da cosa si applicano esattamente i tuoi pesi.

Pesi di fila

Sia la matrice di dati con variabili in colonne e osservazioni in righe. Se ogni osservazione ha un peso associato , allora è davvero semplice incorporare questi pesi nel PCA.Xnxiwi

In primo luogo, bisogna calcolare la media ponderata μ=1wiwixi e sottrarre che dai dati, al fine di centrare esso.

Quindi calcoliamo la matrice di covarianza ponderata 1wiXWX , dove W=diag(wi) è la matrice diagonale dei pesi, e applicare PCA standard per analizzarlo.

Pesi cellulari

L'articolo di Tamuz et al., 2013 , che hai trovato, considera un caso più complicato quando pesi diversi vengono applicati a ciascun elemento della matrice di dati. Quindi davvero non esiste una soluzione analitica e si deve usare un metodo iterativo. Si noti che, come riconosciuto dagli autori, hanno reinventato la ruota, dal momento che tali pesi generali sono stati sicuramente considerati in precedenza, ad esempio in Gabriel e Zamir, 1979, Approssimazione di matrici inferiori con minimi quadrati con qualsiasi scelta di pesi . Anche questo è stato discusso qui .wij

Come ulteriore osservazione: se i pesi variano sia con le variabili che con le osservazioni, ma sono simmetrici, quindi , allora la soluzione analitica è di nuovo possibile, vedi Koren e Carmel, 2004, Robust Riduzione dimensionale lineare .wijwij=wji


Grazie per il chiarimento. Puoi spiegare perché nessuna soluzione analitica è possibile con pesi fuori diagonale? Questo è quello che mi manca sia a Tamuz et al 2013 sia a Gabriel e Zamir 1979.
noname

@noname: non sono a conoscenza di tale prova, e inoltre non sarei sorpreso se non fosse noto. È generalmente abbastanza difficile dimostrare che qualcosa non è possibile , in particolare che qualcosa non è possibile analiticamente. L'impossibilità della trisection angolare ha atteso notoriamente la sua prova per oltre 2000 anni ... (segue)
ameba dice Reinstate Monica

3
@noname: (seguito) Quello che stai chiedendo è mostrare che il problema di minimizzare rispetto ad vincolato ad avere basso rango . non è riducibile a un problema di autovettore. Temo che avresti bisogno di un altro forum per questo (forse mathoverflow?). Ma nota che trovare gli autovettori non è esattamente una soluzione analitica : è solo che le iterazioni sono di solito eseguite silenziosamente da una funzione di libreria standard. i,jwij(XijAij)2Aq
ameba dice di reintegrare Monica il

2
+1. La prima sezione della risposta può essere concettualizzata anche in termini di biplot ponderato (generalizzato) come descritto qui . Tenendo presente come PCA è un "caso specifico di" Biplot (anche interessato alla risposta a righe).
ttnphns,

@ttnphns: dopo che il tuo commento e un altro thread sono stati chiusi come duplicati, ho riletto la mia risposta e ampliato la spiegazione su come gestire i pesi delle righe. Penso che in precedenza non fosse completamente corretto o almeno non fosse completo perché non ho menzionato il centraggio con una media ponderata. Spero che abbia più senso ora!
ameba dice di reintegrare Monica il

5

Grazie mille ameba per la comprensione dei pesi delle file. So che non si tratta di stackoverflow, ma ho avuto alcune difficoltà a trovare un'implementazione di PCA ponderato per riga con spiegazione e, poiché questo è uno dei primi risultati quando si cerca su PCA ponderato, ho pensato che sarebbe stato utile allegare la mia soluzione , forse può aiutare gli altri nella stessa situazione. In questo frammento di codice Python2, un PCA ponderato con un kernel RBF come quello sopra descritto viene utilizzato per calcolare le tangenti di un set di dati 2D. Sarò molto felice di ricevere un feedback!

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()

E un output di esempio (fa lo stesso per ogni punto): inserisci qui la descrizione dell'immagine

Saluti,
Andres

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.