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 prcomp
au lieu de svd
pour 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 m
sont les points. qui se trouvent tous sous la ligne de 95% - Ainsi, leur amplitude est indiscernable du bruit aléatoire.
La même procédure peut être effectuée sur la version non centrée de m
avec 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)
À 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)
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