Pour une matrice aléatoire, un SVD ne devrait-il rien expliquer du tout? Qu'est-ce que je fais mal?

13

Si je construis une matrice 2-D entièrement composée de données aléatoires, je m'attendrais à ce que les composants PCA et SVD n'expliquent essentiellement rien.

Au lieu de cela, il semble que la première colonne SVD semble expliquer 75% des données. Comment cela peut-il être? Qu'est-ce que je fais mal?

Voici l'intrigue:

entrez la description de l'image ici

Voici le code 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)

Mise à jour

Merci @Aaron. Le correctif, comme vous l'avez noté, consistait à ajouter une mise à l'échelle à la matrice afin que les nombres soient centrés autour de 0 (c'est-à-dire que la moyenne est 0).

m <- scale(m, scale=FALSE)

Voici l'image corrigée, montrant pour une matrice avec des données aléatoires, la première colonne SVD est proche de 0, comme prévu.

Image corrigée

Contango
la source
4
[0,1]100R100Rnn1/3n/3-(n-1)/121/12(n/3-(n-1)/12)/(n/3)=3/4+1/(4n)n=10075,25

Réponses:

11

Le premier PC explique que les variables ne sont pas centrées autour de zéro. La mise à l'échelle en premier ou le centrage de vos variables aléatoires autour de zéro donnera le résultat attendu. Par exemple, l'un ou l'autre:

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)
Aaron a laissé Stack Overflow
la source
3
Vous soulevez un bon point, mais je pense que cela ne raconte qu'une partie de l'histoire. En effet, je suppose que le PO essaierait chacun d'eux et serait toujours surpris par le résultat. Le fait est que parce que les valeurs singulières sont ordonnées dans la sortie, elles n'apparaîtront pas (et en fait ne sont pas) uniformément réparties comme on pourrait le croire naïvement à partir de données "aléatoires". La distribution Marchenko-Pastur régit leur comportement dans ce cas.
Cardinal
@Aaron Merci, vous aviez absolument raison. J'ai ajouté un graphique de la sortie corrigée ci-dessus pour montrer à quel point le résultat est beau.
Contango
1
@cardinal Merci pour votre commentaire, vous avez absolument raison (voir le graphique produit par le code corrigé ci-dessus). Je crois que les valeurs SVD deviendraient moins uniformément réparties à mesure que la matrice devient plus petite, car une matrice plus petite aurait plus de chances d'avoir des motifs qui ne seraient pas écrasés par la loi des grands nombres.
Contango
3

J'ajouterai une réponse plus visuelle à votre question, en utilisant une comparaison de modèle nulle. La procédure mélange de manière aléatoire les données de chaque colonne pour conserver la variance globale tandis que la covariance entre les variables (colonnes) est perdue. Ceci est effectué plusieurs fois et la distribution résultante des valeurs singulières dans la matrice randomisée est comparée aux valeurs d'origine.

J'utilise prcompau lieu de svdpour la décomposition matricielle, mais les résultats sont similaires:

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

La comparaison du modèle nul est effectuée sur la matrice centrée ci-dessous:

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)

Ce qui suit est une boîte à moustaches de la matrice permutée avec le quantile à 95% de chaque valeur singulière représentée en trait plein. Les valeurs originales de PCA de msont les points. qui se trouvent tous sous la ligne de 95% - Ainsi, leur amplitude est indiscernable du bruit aléatoire.

entrez la description de l'image ici

La même procédure peut être effectuée sur la version non centrée de mavec le même résultat - Pas de valeurs singulières significatives:

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

entrez la description de l'image ici

À titre de comparaison, regardons un ensemble de données avec un ensemble de données non aléatoire: 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)

entrez la description de l'image ici

Ici, la 1ère valeur singulière est significative et explique plus de 92% de la variance totale:

P <- prcomp(m, center = TRUE)
P$sdev^2 / sum(P$sdev^2)
# [1] 0.924618723 0.053066483 0.017102610 0.005212184
Marc dans la boîte
la source
+1. L'exemple du jeu de données Iris est intéressant, car en regardant les deux premiers PC (comme par exemple dans votre propre article ici stats.stackexchange.com/a/88092 ), il est assez clair que le second transporte un certain signal. Le test de permutation (aka shuffling) indique cependant que seul le premier est "significatif". Il est clair que le brassage a tendance à sous-estimer le nombre de PC: la grande variance du premier vrai PC se "répartira" sur les PC mélangés et les élèvera tous à partir du second. On peut concevoir des tests plus sensibles qui en tiennent compte, mais cela se fait rarement.
amibe dit Réintégrer Monica
@amoeba - Excellent commentaire. Je m'interroge sur l'effet "d'étalement" depuis un certain temps maintenant. Je suppose qu'un test de validation croisée pourrait être l'un des plus sensibles auxquels vous faites référence (par exemple, votre réponse ici )? Ce serait génial si vous pouviez fournir un exemple / une référence.
Marc dans la boite le
Je préfère généralement utiliser la validation croisée (basée sur une erreur de reconstruction, selon ma réponse ici ), mais je ne sais pas vraiment si elle ne souffre pas du même type d'insensibilité ou non. Il pourrait être judicieux de l'essayer sur l'ensemble de données Iris. En ce qui concerne les approches basées sur le brassage, je ne connais aucune référence pour expliquer cette "diffusion", je connais juste des gens qui y travaillaient récemment. Je pense qu'ils voulaient l'écrire bientôt. L'idée est d'introduire certains facteurs de réduction d'échelle pour les variances des PC mélangés plus élevés.
amibe dit Réintégrer Monica
@amoeba - Merci pour ce lien. Cela m'explique beaucoup. J'ai trouvé particulièrement intéressant de voir que la validation croisée dans PCA utilise des méthodes qui peuvent fonctionner sur des ensembles de données avec des valeurs manquantes. J'ai fait quelques tentatives sur cette approche et (comme vous le dites), l'approche de réarrangement du modèle nul a en effet tendance à sous-estimer le nombre de PC importants. Cependant, pour l'ensemble de données iris, je renvoie systématiquement un seul PC pour une erreur de reconstruction. Intéressant compte tenu de ce que vous avez mentionné sur l'intrigue. Il se pourrait que si nous évaluions l'erreur sur la base des prévisions d'espèces, les résultats pourraient être différents.
Marc dans la boite le
Par curiosité, je l'ai essayé sur les données Iris. En fait, j'obtiens deux PC importants avec la méthode de validation croisée. J'ai mis à jour mon message lié, veuillez y voir.
amibe dit Réintégrer Monica le