XX 'とX'Xの固有値分解でXの有効なSVDを取得できないのはなぜですか?


9

私は手でSVDを実行しようとしています:

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)

しかし、最後の行は戻りませんm。どうして?それはこれらの固有ベクトルの兆候と関係があるようです...または手順を誤解しましたか?



SVDでは記号は重要ではないと繰り返し言われます...このように
失敗した統計学者2017

@Amoeba明確にしていただきありがとうございます。私はコードよりも英語の質問に焦点を合わせていました。Failedstatistician:何を実行するかを確認D=diag(c(-1,1,1)*sqrt(eigen(m%*%t(m))$values))し、平方根(および正規化された固有ベクトル)は符号までしか定義されていないことを覚えておいてください。詳細については、に変更mm <- matrix(-2,1,1)て、へ,1,1)の各呼び出しの最後に含めてくださいdiag。これは、同じ問題を作成する例ですが、非常に単純なので、問題の性質が完全に明らかになります。1×1
whuber

1
とった。ありがとうございました!ベクトルc(-1、1、1)を決定する一般的なルールはありますか?または、2つの分解の兆候をどのように関連付ける必要がありますか?
failedstatistician 2017

1
@whuberのトリックはc(-1,1,1)機能しますが、そのDように定義されているため、特異な値は得られません。定義上、特異値はすべて正でなければなりません。兆候をリンクする方法の問題UV良いです、と私は答えを持っていません。なぜSVDをしないのですか?:-)
アメーバ

回答:


13

問題の分析

マトリックスのSVDが一意になることはありません。行列次元をn × kとし、そのSVDをAn×k

A=UDV

正規直交列を持つ行列U、非負のエントリを持つ対角p × p行列D、および正規直交列を持つk × p行列Vの場合n×pUp×pDk×pV

p×pS±1S2=Ip×pIp

A=UDV=UIDIV=U(S2)D(S2)V=(US)(SDS)(VS)

A

(US)(US)=SUUS=SIpS=SS=S2=Ip
USVSSD
SDS=DS2=D
D

U

AA=(UDV)(UDV)=UDVVDU=UD2U
V
AA=VD2V.
DD2UV

解決策

UV

UAV=U(UDV)V=(UU)D(VV)=D

DAAAASDSDUS

A=UDV=(US)(SD)V.

それはSVDです。

n=p=k=1A=(2)

(2)=(1)(2)(1)

U=(1)D=(2)V=(1)

AA=(4)U=(1)D=(4)=(2)AA=(4)V=(1)

UDV=(1)(2)(1)=(2)A.
D=UAV=(1)(2)(1)=(2).
S=(1)UUS=(1)(1)=(1)DSD=(1)(2)=(2)
A=(1)(2)(1),

コード

ここに変更されたコードがあります。その出力は確認します

  1. メソッドはm正しく再作成されます。
  2. UV
  3. しかし、結果はによって返されるSVDとは異なりsvdます。(どちらも有効です。)
m <- matrix(c(1,0,1,2,1,1,1,0,0),byrow=TRUE,nrow=3)

U <- eigen(tcrossprod(m))$vector
V <- eigen(crossprod(m))$vector
D <- diag(zapsmall(diag(t(U) %*% m %*% V)))
s <- diag(sign(diag(D)))  # Find the signs of the eigenvalues
U <- U %*% s              # Adjust the columns of U
D <- s %*% D              # Fix up D.  (D <- abs(D) would be more efficient.)

U1=svd(m)$u
V1=svd(m)$v
D1=diag(svd(m)$d,n,n)

zapsmall(U1 %*% D1 %*% t(V1)) # SVD
zapsmall(U %*% D %*% t(V))    # Hand-rolled SVD
zapsmall(crossprod(U))        # Check that U is orthonormal
zapsmall(tcrossprod(V))       # Check that V' is orthonormal

1
+1。これは非常に明確です。実際には、Uまたはを計算Vしてから、を乗算して別の行列を取得するだけで十分であることを追加しAます。この方法では、2つではなく1つだけの固有分解を実行し、標識が正しく表示されます。
アメーバ2017

2
@Amoebaそうです。SVDを手動で計算するという精神で、これは明らかに教育的な演習であるため、ここでは効率に注意を払いません。
whuber

2
ご協力ありがとうございます!私はこの問題を(ついに)理解したと思います。
failedstatistician 2017

3
@Federicoそのリマインダーをありがとう。あなたはまったく正しいです。私は暗黙的にすべての固有値が異なると仮定しました。実際、これは統計アプリケーションではほぼ確実に当てはまることであり、「縮退した」固有空間のあいまいさを考慮する習慣から抜け出します。
whuber

3
UV

5

@whuberの回答へのコメントで概説したように、SVDを計算するこの方法は、すべての行列に対して機能するわけではありません。問題は標識に限定されません。

AAAAUVA=[3/54/54/53/5]AA=AA=IIeigenU=V=IUAV=A

UV

AAAAAA2uu2×1016108

2つの固有分解からSVDを計算することは優れた学習例ですが、実際のアプリケーションでは、常にRのsvd関数を使用して特異値分解を計算します。


1
このコメントは良いアドバイスです。ただし、このスレッドはSVDを計算する適切な方法を考慮していないことに注意してください(あなたの推奨に反論する人はいないと思います)。OPはそれがsvd機能することを暗黙的に受け入れます。実際、彼らはそれを手作業の計算と比較するための標準として使用します。その目的は、理解を確認することであり、決して置き換えることではありませんsvd
whuber

@whuber正しい観察。最後の段落を書き直しました。
Federico Poloni、2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.