J'essaie de faire SVD à la main:
m<-matrix(c(1,0,1,2,1,1,1,0,0),byrow=TRUE,nrow=3)
U=eigen(m%*%t(m))$vector
V=eigen(t(m)%*%m)$vector
D=sqrt(diag(eigen(m%*%t(m))$values))
U1=svd(m)$u
V1=svd(m)$v
D1=diag(svd(m)$d)
U1%*%D1%*%t(V1)
U%*%D%*%t(V)
Mais la dernière ligne ne revient pas m
. Pourquoi? Cela semble avoir quelque chose à voir avec les signes de ces vecteurs propres ... Ou ai-je mal compris la procédure?
r
svd
eigenvalues
statisticien raté
la source
la source
D=diag(c(-1,1,1)*sqrt(eigen(m%*%t(m))$values))
fait et gardez à l'esprit que la racine carrée (ainsi que tout vecteur propre normalisé) n'est définie que jusqu'à signer. Pour plus d'informations, passezm
àm <- matrix(-2,1,1)
et incluez,1,1)
à la fin de chacun des appels àdiag
. Ceci est un exemple qui crée le même problème - mais c'est tellement simple que la nature du problème deviendra complètement évidente.c(-1,1,1)
fonctionne, maisD
défini comme cela ne vous donne pas de valeurs singulières. Les valeurs singulières doivent toutes être positives par définition. La question de savoir comment relier les signes deU
etV
est bonne, et je n'ai pas de réponse. Pourquoi ne faites-vous pas simplement un SVD? :-)Réponses:
Analyse du problème
La SVD d'une matrice n'est jamais unique. Soit la matrice dimensions et que sa SVD soitn × kA n×k
pour un la matrice avec des colonnes orthonormales, une diagonale la matrice avec des entrées non-négatives, et un la matrice avec des colonnes orthonormales.U p × p D k × p Vn×p U p×p D k×p V
Maintenant, choisissez arbitrairement n'importe quelle diagonale matrice ayant s sur la diagonale, de sorte que soit l' identité . alorsS ± 1 S 2 = I p × p I pp×p S ±1 S2=I p×p Ip
est également un SVD de parce que montre que a des colonnes orthonormées et un calcul similaire montre que a des colonnes orthonormées. De plus, puisque et sont diagonaux, ils font la navette, d'où montre que toujours des entrées non négatives.( U S ) ′ ( U S ) = S ′ U ′ U S = S ′ I p S = S ′ S = S 2 = I p U S V S S D S D S = D S 2 = D DA
La méthode implémentée dans le code pour trouver un SVD trouve un qui diagonalise et, de la même façon, un qui diagonale Il procède au calcul de en fonction des valeurs propres trouvées dans . Le problème est que cela ne garantit pas une correspondance cohérente des colonnes de avec les colonnes de .A A ′ = ( U D V ′ ) ( U D V ′ ) ′ = U D V ′ V D ′ U ′ = U D 2 U ′ V A ′ A = V D 2 V ′ . D D 2 U VU
Une solution
Au lieu de cela, après avoir trouvé un tel et un tel , utilisez-les pour calculerVU V
directement et efficacement. Les valeurs diagonales de ce ne sont pas nécessairement positives.D (C'est parce qu'il n'y a rien dans le processus de diagonalisation de ou qui garantira que, puisque ces deux processus ont été effectués séparément.) Rendez-les positifs en choisissant les entrées le long de la diagonale de pour égaler les signes des entrées de , de sorte que ait toutes les valeurs positives. Compensez cela en multipliant à droite par :A′A AA′ S D SD U S
C'est un SVD.
Exemple
Soit avec . Un SVD estn=p=k=1 A=(−2)
avec , et .U=(1) D=(2) V=(−1)
Si vous diagonalisezA′A=(4) U=(1) D=(4–√)=(2) AA′=(4) V=(1)
Code
Voici le code modifié. Sa sortie confirme
m
correctement.svd
. (Les deux sont également valables.)la source
U
ou l' autreV
et puis d'obtenir une autre matrice en multipliant avecA
. De cette façon, on n'effectue qu'une (au lieu de deux) compositions de composition, et les signes sortiront bien.Comme je l'ai souligné dans un commentaire à la réponse de @ whuber, cette méthode pour calculer le SVD ne fonctionne pas pour chaque matrice . Le problème ne se limite pas aux panneaux.
Le problème est qu'il peut y avoir des valeurs propres répétées, et dans ce cas, la composition propre de et n'est pas unique et tous les choix de et ne peuvent pas être utilisés pour récupérer le facteur diagonal de la SVD. Par exemple, si vous prenez une matrice orthogonale non diagonale (disons ), alors . Parmi tous les choix possibles pour la matrice de vecteur propre de , retournera , donc dans ce cas n'est pas diagonal.A A ' U V A = [ 3 / 5 4 / 5 - 4 / 5 3 / 5 ] A A ' = A ' A = I I U = V = I U ' A V = AA′A AA′ U V A=[3/5−4/54/53/5] AA′=A′A=I I U=V=I U′AV=A
eigen
Intuitivement, ceci est une autre manifestation du même problème que @whuber souligne, qu'il doit y avoir une "correspondance" entre les colonnes de et , et le calcul de deux compositions à eigend séparément ne le garantit pas.VU V
Si toutes les valeurs singulières de sont distinctes, alors la composition par eigend est unique (jusqu'à l'échelle / signes) et la méthode fonctionne. Remarque: ce n'est toujours pas une bonne idée de l'utiliser en code de production sur un ordinateur avec une arithmétique à virgule flottante, car lorsque vous les produits et le résultat calculé peut être perturbé par une quantité de l'ordre de , où est la précision de la machine. Si les grandeurs des valeurs singulières diffèrent considérablement (de plus de , grosso modo), cela nuit à la précision numérique des plus petites.A ′ A A A ′ ‖ A ‖ 2 uA A′A AA′ ∥A∥2u u≈2×10−16 10−8
Le calcul de la SVD à partir des deux compositions de type eigend est un excellent exemple d'apprentissage, mais dans les applications réelles, utilisez toujours la
svd
fonction de R pour calculer la décomposition en valeurs singulières.la source
svd
fonctionne. En effet, ils l'utilisent comme un standard par rapport auquel comparer un calcul manuel, dont le but est de vérifier la compréhension, de ne le remplacersvd
en aucune façon.