Ruota i componenti PCA per uniformare la varianza in ciascun componente


9

Sto cercando di ridurre la dimensionalità e il rumore di un set di dati eseguendo PCA sul set di dati e gettando via gli ultimi PC. Dopodiché, voglio utilizzare alcuni algoritmi di apprendimento automatico sui PC rimanenti, e quindi voglio normalizzare i dati uniformando la varianza dei PC per far funzionare meglio gli algoritmi.

Un modo semplice è semplicemente normalizzare la varianza ai valori unitari. Tuttavia, il primo PC contiene più varianze rispetto al set di dati originale rispetto ai seguenti, e voglio ancora dargli più "peso". Quindi mi chiedevo: esiste un modo semplice per dividere la sua varianza e condividerla con i PC con meno varianze?

Un altro modo è mappare i PC allo spazio delle caratteristiche originali, ma in tal caso la dimensionalità aumenterebbe anche al valore originale.

Immagino sia meglio mantenere ortogonali le colonne risultanti, ma al momento non è necessario.


1
No ... varimax massimizza la somma delle varianze quadrate dei carichi, quindi cerca di renderli il più ineguali possibile. Inoltre, perché dovresti voler equalizzare i componenti? Il punto è catturare quante più variazioni possibili nel minor numero possibile di componenti.

2
La semplice standardizzazione dei punteggi dei componenti in varianze unitarie non è adatta a te? Allora perche? Che tipo di risultato vuoi: le colonne risultanti devono essere non correlate oltre a varianze uguali?
ttnphns,

2
Dalla tua descrizione sembra che tu voglia semplicemente "sfera" dei dati (di ridotta dimensionalità). Viene spesso eseguito come fase di preelaborazione dell'apprendimento automatico. Per raggiungerlo, devi semplicemente eseguire PCA, scegliere alcuni componenti e standardizzarli. Immagino sia possibile trovare una rotazione ortogonale (come varimax) che ruota componenti standardizzati in modo tale che rimangano non correlati ma spiegano esattamente la stessa quantità di varianza; è una domanda interessante, devo pensarci. Ma non l'ho mai visto fatto, sicuramente non nell'apprendimento automatico.
amoeba,

2
A proposito, quali sono "alcuni algoritmi di apprendimento automatico" che desideri applicare dopo la PCA? Questo potrebbe essere rilevante.
amoeba,

1
Nota che se ruoti i tuoi PC standardizzati, le distanze non cambieranno affatto! Quindi, in realtà, non dovrebbe importare alcun algoritmo basato sulla distanza.
amoeba,

Risposte:


10

Non è del tutto chiaro per me che ciò che stai chiedendo sia ciò di cui hai veramente bisogno: un passo di preelaborazione comune nell'apprendimento automatico è la riduzione della dimensionalità + lo sbiancamento, che significa fare PCA e standardizzare i componenti, nient'altro. Ma mi concentrerò comunque sulla tua domanda così come è formulata, perché è più interessante.


Sia la matrice di dati n × d centrata con punti dati in righe e variabili in colonne. La PCA equivale alla decomposizione del valore singolare X = U S VU k S k V k , dove per eseguire la riduzione dimensionale manteniamo solo k componenti. Una "rotazione fattoriale" ortogonale di questi componenti implica la scelta di una matrice ortogonale k × k R e il suo inserimento nella decomposizione: XU k S k VXn×d

X=USVUKSKVK,
KK×KRQui
XUKSKVK=UKRRSKVK=n-1UKRruotatopunteggi standardizzatiRSKVK/n-1Caricamenti ruotati.
sono componenti standardizzati ruotati e il secondo termine rappresenta i carichi ruotati trasposti. La varianza di ciascun componente dopo la rotazione è data dalla somma dei quadrati del vettore di caricamento corrispondente; prima della rotazione è semplicementes 2 i /(n-1). Dopo la rotazione è qualcos'altro.n-1UKRSio2/(n-1)

Ora siamo pronti a formulare il problema in termini matematici: dati i caricamenti non ruotati , trova la matrice di rotazioneR in modotale che i carichi ruotati,LR, abbiano la stessa somma dei quadrati in ciascuna colonna.L=VKSK/n-1RLR

Risolviamolo. Le somme delle colonne dei quadrati dopo la rotazione sono uguali agli elementi diagonali di Questo ha senso: la rotazione ridistribuisce semplicemente le varianze dei componenti, che sono originariamente dati das 2 i /(n-1), tra loro, secondo questa formula. Dobbiamo ridistribuirli in modo che diventino tutti uguali al loro valore medioμ.

(LR)LR=RS2n-1R.
Sio2/(n-1)μ

Non credo che ci sia una soluzione a forma chiusa a questo, e in effetti ci sono molte soluzioni diverse. Ma una soluzione può essere facilmente costruita in modo sequenziale:

  1. Prendi il primo componente e il componente -esimo. Il primo ha varianza σ max > μ e l'ultimo ha la varianza σ min < μ .Kσmax>μσmin<μ
  2. Ruota solo questi due in modo tale che la varianza della prima diventi uguale a . La matrice di rotazione in 2D dipende solo da un parametro θ ed è facile scrivere l'equazione e calcolare il necessario θ . Infatti, R 2D = ( cos θ sin θ - sin θ cos θ ) e dopo la trasformazione il primo PC otterrà la varianza cos 2 θ σ max + sin 2 θ σ min = cos 2 θ σμθθ
    R2D=(cosθpeccatoθ-peccatoθcosθ)
    da cui si ottiene immediatamente cos 2 θ = μ - σ min
    cos2θσmax+peccato2θσmin=cos2θσmax+(1-cos2θ)σmin=μ,
    cos2θ=μ-σminσmax-σmin.
  3. Il primo componente è ora fatto, ha varianza .μ
  4. Passa alla coppia successiva, prendendo il componente con la varianza più grande e quello con la varianza più piccola. Vai a # 2.

Ciò ridistribuirà equamente tutte le varianze mediante una sequenza di rotazioni 2D. Moltiplicando tutte queste matrici di rotazione insieme si otterrà la R complessiva .(K-1)R


Esempio

Considera la seguente matrice : ( 10 0 0 0 0 6 0 0 0 0 3 0 0 0 0 1 ) . La varianza media è 5 . Il mio algoritmo procederà come segue:S2/(n-1)

(10000060000300001).
5
  1. 51+(10-5)=6

  2. 53+(6-5)=4

  3. 54+(6-1)=5

  4. Fatto.

Ho scritto lo script Matlab che implementa questo algoritmo (vedi sotto). Per questa matrice di input, la sequenza degli angoli di rotazione è:

48.1897   35.2644   45.0000

Varianti dei componenti dopo ogni passaggio (in righe):

10     6     3     1
 5     6     3     6
 5     5     4     6
 5     5     5     5

La matrice di rotazione finale (prodotto di tre matrici di rotazione 2D):

 0.6667         0    0.5270    0.5270
      0    0.8165    0.4082   -0.4082
      0   -0.5774    0.5774   -0.5774
-0.7454         0    0.4714    0.4714

(LR)LR

5.0000         0    3.1623    3.1623
     0    5.0000    1.0000   -1.0000
3.1623    1.0000    5.0000    1.0000
3.1623   -1.0000    1.0000    5.0000

Ecco il codice:

S = diag([10 6 3 1]);
mu = mean(diag(S));
R = eye(size(S));

vars(1,:) = diag(S);
Supdated = S;

for i = 1:size(S,1)-1
    [~, maxV] = max(diag(Supdated));
    [~, minV] = min(diag(Supdated));

    w = (mu-Supdated(minV,minV))/(Supdated(maxV,maxV)-Supdated(minV,minV));
    cosTheta = sqrt(w);
    sinTheta = sqrt(1-w);

    R2d = eye(size(S));
    R2d([maxV minV], [maxV minV]) = [cosTheta sinTheta; -sinTheta cosTheta];
    R = R * R2d;

    Supdated = transpose(R2d) * Supdated * R2d;    

    vars(i+1,:) = diag(Supdated);
    angles(i) = acosd(cosTheta);
end

angles                %// sequence of 2d rotation angles
round(vars)           %// component variances on each step
R                     %// final rotation matrix
transpose(R)*S*R      %// final S matrix

Ecco il codice in Python fornito da @feilong:

def amoeba_rotation(s2):
    """
    Parameters
    ----------
    s2 : array
        The diagonal of the matrix S^2.

    Returns
    -------
    R : array
        The rotation matrix R.

    Examples
    --------
    >>> amoeba_rotation(np.array([10, 6, 3, 1]))
    [[ 0.66666667  0.          0.52704628  0.52704628]
     [ 0.          0.81649658  0.40824829 -0.40824829]
     [ 0.         -0.57735027  0.57735027 -0.57735027]
     [-0.74535599  0.          0.47140452  0.47140452]]

    http://stats.stackexchange.com/a/177555/87414
    """
    n = len(s2)
    mu = s2.mean()
    R = np.eye(n)
    for i in range(n-1):
        max_v, min_v = np.argmax(s2), np.argmin(s2)
        w = (mu - s2[min_v]) / (s2[max_v] - s2[min_v])
        cos_theta, sin_theta = np.sqrt(w), np.sqrt(1-w)
        R[:, [max_v, min_v]] = np.dot(
            R[:, [max_v, min_v]],
            np.array([[cos_theta, sin_theta], [-sin_theta, cos_theta]]))
        s2[[max_v, min_v]] = [mu, s2[max_v] + s2[min_v] - mu]
    return R

Kσio2K


Immagino, per ogni due coppie di componenti (i loro punteggi), l'angolo di rotazione sarebbe di 45 gradi, per uniformare le loro varianze. Tuttavia, non riesco a immaginare come svolgere l'intero compito con 3+ componenti in modo saggio.
ttnphns,

1
@feilong, penso che equalizzare la varianza di una coppia di componenti alla volta sia un algoritmo molto non ottimale. Quello che ho suggerito è di scegliere le rotazioni in modo tale che la varianza di un componente diventi esattamente uguale alla varianza media globale. Quindi questo componente viene "fatto" e si può occuparsi del resto. Questo è garantito per equalizzare tutte le varianze in un numero finito di passaggi. Vedi il mio commento precedente per un esempio.
amoeba,

1
@amoeba Hai ragione, è una soluzione migliore e dovrebbe finire con n-1 passaggi.
fino al

1
@amoeba Ho aggiunto la mia implementazione minima usando Python. Ho modificato la parte moltiplicando l'intera matrice, poiché ciò può richiedere molto tempo per matrici di grandi dimensioni.
fino al

1
@amoeba Specificamente per i componenti principali, è possibile risparmiare più tempo rimuovendo la parte cercando il massimo e il minimo. Possiamo semplicemente ruotare il 1 ° e il 2 ° componente (per fare in modo che il 1 ° componente abbia una varianza media), quindi il 2 ° e il 3 ° e così via. Dobbiamo solo assicurarci che la varianza totale di ogni coppia sia maggiore di mu.
Feilong

2

XYσmun'X2σmion2Xμ2Yσmun'X2+σmion2-μ2

cosθ

μ2=cos2θ(σmun'X2)+peccato2θ(σmion2)

ma non ha dimostrato da dove provenga questa equazione; probabilmente pensando che sia ovvio senza spiegazioni. Ovvio o no, credo che valga la pena chiarire - in qualche modo. La mia risposta presenta un modo.

XYθXXX*

illustrazione della rotazione

X X*X'=XcosθX*X'X'-X*yypeccatoθ

X*=X'-(X'-X*)=Xcosθ-ypeccatoθ

μ2X*

μ2=ΣX*2=Σ(Xcosθ-ypeccatoθ)2=Σ(X2cos2θ+y2peccato2θ-2Xycosθpeccatoθ)=cos2θΣX2+peccato2θΣy2-2cosθpeccatoθΣXy= 0 (X e Y non sono correlati)=cos2θ(σmun'X2)+peccato2θ(σmion2)

cosθ


2
(cosθpeccatoθ-peccatoθcosθ)(σmax200σmin2)(cosθpeccatoθ-peccatoθcosθ),
amoeba,

E penso che la tua spiegazione geometrica e il calcolo "diretto" (senza matrici) siano più facili da capire e molto utili per sviluppare le giuste intuizioni.
amoeba,

0

Se interpreto le cose correttamente, intendi che il primo componente principale (autovalore) spiega la maggior parte della varianza nei dati. Ciò può accadere quando il metodo di compressione è lineare. Tuttavia, potrebbero esserci dipendenze non lineari nello spazio delle funzionalità.

TL / DR: PCA è un metodo lineare. Utilizzare i codificatori automatici (pca non lineare) per la riduzione della dimensionalità. Se la parte di apprendimento automatico è apprendimento supervisionato, è sufficiente monitorare la funzione di perdita mentre si regolano i parametri (iper) per il codificatore automatico. In questo modo finirai con una versione compressa molto migliore dei tuoi dati originali.

Ecco un esempio di scikit in cui eseguono la ricerca in griglia per trovare il numero ottimale di componenti principali da conservare (iperparametro) utilizzando PCA. Infine applicano la regressione logistica nello spazio dimensionale inferiore: http://scikit-learn.org/stable/auto_examples/plot_digits_pipe.html#example-plot-digits-pipe-py

Protip: i codificatori automatici non dispongono di una soluzione a forma chiusa (afaik), quindi se il tuo contesto è lo streaming di dati, ciò significa che puoi aggiornare continuamente il tuo codificatore automatico (rappresentazione compressa) e quindi compensare cose come la deriva dei concetti. Con pca devi ri-addestrare la modalità batch di volta in volta quando arrivano nuovi dati.

Per dare ad alcune funzionalità più "peso", vedi la regolarizzazione (vorrei iniziare dalle norme https://en.wikipedia.org/wiki/Norm_(mathematics) ). Potresti anche essere sorpreso di quanto sia simile la regressione logistica al percettrone.


Non vedo come questo risponda alla domanda del PO; la tua risposta sembra essere completamente estranea alla domanda.
amoeba,

Quindi mi chiedevo: esiste un modo semplice per dividere la sua varianza e condividerla con i PC con meno varianze? OP vuole ridurre la dimensionalità. Ho offerto un'alternativa per risolvere il suo problema, poiché alla fine ciò che OP desidera non garantisce risultati migliori se non vengono misurate. Lavorare in spazi Hilbert / spazi normati non garantisce risultati migliori. La misurazione delle prestazioni porta a risultati migliori.
shuriken x blue,
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.