Per una matrice casuale, un SVD non dovrebbe spiegare nulla? Che cosa sto facendo di sbagliato?


13

Se costruissi una matrice 2D composta interamente da dati casuali, mi aspetterei che i componenti PCA e SVD non spieghino sostanzialmente nulla.

Invece, sembra che la prima colonna SVD sembra spiegare il 75% dei dati. Come può essere possibile? Che cosa sto facendo di sbagliato?

Ecco la trama:

inserisci qui la descrizione dell'immagine

Ecco il codice R:

set.seed(1)
rm(list=ls())
m <- matrix(runif(10000,min=0,max=25), nrow=100,ncol=100)
svd1 <- svd(m, LINPACK=T)
par(mfrow=c(1,4))
image(t(m)[,nrow(m):1])
plot(svd1$d,cex.lab=2, xlab="SVD Column",ylab="Singluar Value",pch=19)

percentVarianceExplained = svd1$d^2/sum(svd1$d^2) * 100
plot(percentVarianceExplained,ylim=c(0,100),cex.lab=2, xlab="SVD Column",ylab="Percent of variance explained",pch=19)

cumulativeVarianceExplained = cumsum(svd1$d^2/sum(svd1$d^2)) * 100
plot(cumulativeVarianceExplained,ylim=c(0,100),cex.lab=2, xlab="SVD column",ylab="Cumulative percent of variance explained",pch=19)

Aggiornare

Grazie @Aaron. La correzione, come hai notato, era quella di aggiungere il ridimensionamento alla matrice in modo che i numeri fossero centrati attorno a 0 (ovvero la media è 0).

m <- scale(m, scale=FALSE)

Ecco l'immagine corretta, che mostra per una matrice con dati casuali, la prima colonna SVD è vicina a 0, come previsto.

Immagine corretta


4
La tua matrice approssima una distribuzione uniforme sul cubo unità in R 100 . SVD calcola i suoi momenti di inerzia sull'origine . In R n la "varianza totale" deve essere n volte quella dell'intervallo unitario, che è 1 / 3 . E 'semplice da calcolare che il momento lungo l'asse principale del cubo (che emana dal origine) è pari a n / 3 - ( n - 1 ) / 12 1 / 12[0,1]100R100Rnn1/3n/3-(n-1)/12 e tutti gli altri momenti - in virtù della simmetria - uguale1/12. Pertanto il primo autovalore è 75,25 %, visibile nel terzo grafico. del totale. Per n = 100 questo è(n/3-(n-1)/12)/(n/3)=3/4+1/(4n)n=10075.25
whuber

Risposte:


11

Il primo PC sta spiegando che le variabili non sono centrate attorno allo zero. Scalare prima o centrare le variabili casuali attorno allo zero avrà il risultato che ti aspetti. Ad esempio, uno di questi:

m <- matrix(runif(10000,min=0,max=25), nrow=100,ncol=100)
m <- scale(m, scale=FALSE)

m <- matrix(runif(10000,min=-25,max=25), nrow=100,ncol=100)

3
Sollevi un buon punto, ma penso che questo racconti solo una parte della storia. Anzi, direi che il PO avrebbe cercato ciascuno di questi e ancora essere sorpreso dal risultato. Il fatto è che, poiché i valori singolari sono ordinati nell'output, non appariranno (e anzi non saranno) distribuiti uniformemente come ci si potrebbe aspettare ingenuamente da dati "casuali". La distribuzione Marchenko-Pastur governa il loro comportamento in questo caso.
cardinale

@Aaron Grazie, avevi assolutamente ragione. Ho aggiunto un grafico dell'output corretto sopra per mostrare quanto è bello il risultato.
Contango,

1
@cardinal Grazie per il tuo commento, hai assolutamente ragione (vedi il grafico prodotto dal codice corretto, sopra). Credo che i valori SVD sarebbero distribuiti in modo meno uniforme man mano che la matrice si riduce, poiché una matrice più piccola avrebbe maggiori possibilità di avere schemi che non sarebbero schiacciati dalla legge di grandi numeri.
Contango,

3

Aggiungerò una risposta più visiva alla tua domanda, attraverso l'uso di un confronto del modello nullo. La procedura mescola casualmente i dati in ciascuna colonna per preservare la varianza complessiva mentre si perde la covarianza tra variabili (colonne). Questo viene eseguito più volte e la risultante distribuzione di valori singolari nella matrice randomizzata viene confrontata con i valori originali.

Uso prcompinvece svdla decomposizione della matrice, ma i risultati sono simili:

set.seed(1)
m <- matrix(runif(10000,min=0,max=25), nrow=100,ncol=100)

S <- svd(scale(m, center = TRUE, scale=FALSE))
P <- prcomp(m, center = TRUE, scale=FALSE)
plot(S$d, P$sdev) # linearly related

Il confronto del modello null viene eseguito sulla matrice centrata di seguito:

library(sinkr) # https://github.com/marchtaylor/sinkr

# centred data
Pnull <- prcompNull(m, center = TRUE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda[,1:20], ylim=range(Pnull$Lambda[,1:20], Pnull$Lambda.orig[1:20]), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=FALSE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)

Di seguito è riportato un diagramma a scatole della matrice permutata con il 95% quantile di ciascun valore singolare mostrato come linea continua. I valori originali di PCA di msono i punti. tutti i quali si trovano al di sotto della linea del 95% - Quindi la loro ampiezza è indistinguibile dal rumore casuale.

inserisci qui la descrizione dell'immagine

La stessa procedura può essere eseguita sulla versione non centrata mcon lo stesso risultato - Nessun valore singolare significativo:

# centred data
Pnull <- prcompNull(m, center = FALSE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda[,1:20], ylim=range(Pnull$Lambda[,1:20], Pnull$Lambda.orig[1:20]), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=TRUE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)

inserisci qui la descrizione dell'immagine

Per un confronto, diamo un'occhiata a un set di dati con un set di dati non casuale: iris

# iris dataset example
m <- iris[,1:4]
Pnull <- prcompNull(m, center = TRUE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda, ylim=range(Pnull$Lambda, Pnull$Lambda.orig), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=FALSE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)

inserisci qui la descrizione dell'immagine

Qui, il 1o valore singolare è significativo e spiega oltre il 92% della varianza totale:

P <- prcomp(m, center = TRUE)
P$sdev^2 / sum(P$sdev^2)
# [1] 0.924618723 0.053066483 0.017102610 0.005212184

+1. L'esempio del set di dati di Iris è interessante, perché guardando i primi due PC (come ad esempio nel tuo post qui stats.stackexchange.com/a/88092 ) è abbastanza chiaro che il secondo porta qualche segnale. Il test di permutazione (noto anche come shuffling) indica che solo il primo è "significativo". È chiaro che la mescolanza tende a sottostimare il numero di PC: la grande varianza del primo PC reale verrà "sparsa" su PC mescolati e li eleverà tutti a partire dal secondo. Si possono escogitare test più sensibili che spiegano ciò, ma ciò viene fatto raramente.
ameba dice Reinstate Monica il

@amoeba - Ottimo commento. Mi chiedo da tempo l'effetto "spargimento". Suppongo che un test di convalida incrociata potrebbe essere uno dei test più sensibili a cui fai riferimento (ad es. La tua risposta qui )? Sarebbe bello se potessi fornire un esempio / riferimento.
Marc nella scatola

Di solito preferisco usare la convalida incrociata (basata sull'errore di ricostruzione, secondo la mia risposta qui ), ma in realtà non sono sicuro che non sia in qualche modo affetto dallo stesso tipo di insensibilità o meno. Potrebbe avere senso provarlo sul set di dati di Iris. Per quanto riguarda gli approcci basati sul mescolamento, non conosco alcun riferimento per spiegare questa "diffusione", conosco solo alcune persone che ci hanno lavorato di recente. Penso che volessero scriverlo presto. L'idea è quella di introdurre alcuni fattori di ridimensionamento per le varianze dei PC mescolati più alti.
ameba dice Reinstate Monica l'

@amoeba - Grazie per quel link. Spiega molto per me. Ho trovato particolarmente interessante vedere che la convalida incrociata in PCA utilizza metodi che possono operare su set di dati con valori mancanti. Ho fatto alcuni tentativi su questo approccio e (come dici tu) l'approccio di shuffling del modello nullo tende effettivamente a sottovalutare il numero di PC significativi. Tuttavia, per il set di dati dell'iride, restituisco costantemente un singolo PC per errore di ricostruzione. Interessante dato quello che hai detto sulla trama. Potrebbe essere che se stessimo misurando l'errore in base alle previsioni delle specie, i risultati potrebbero essere diversi.
Marc nella scatola

Per curiosità, l'ho provato sui dati di Iris. In realtà, ottengo due PC significativi con il metodo di convalida incrociata. Ho aggiornato il mio post collegato, vedere qui.
ameba dice Reinstate Monica il
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.