ランダム行列の場合、SVDは何も説明すべきではありませんか?私は何を間違えていますか?


13

完全にランダムデータで構成される2次元行列を作成する場合、PCAおよびSVDコンポーネントは本質的に何も説明しないと予想されます。

代わりに、最初のSVD列がデータの75%を説明するように見えます。これはどのようにできますか?私は何を間違えていますか?

プロットは次のとおりです。

ここに画像の説明を入力してください

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)

更新

ありがとう@アーロン。修正は、既に述べたように、数値が0を中心とするように行列にスケーリングを追加することでした(つまり、平均は0です)。

m <- scale(m, scale=FALSE)

修正された画像は、ランダムデータを含む行列の場合、最初のSVD列が予想どおり0に近いことを示しています。

補正された画像


4
行列は、の単位立方体一様分布に近似します。SVD は、原点の周りの慣性モーメントを計算します。で「全分散」されなければならない倍である単位間隔の。立方体の主軸に沿ったモーメント(原点から発生)は等しく、その他すべてのモーメントは対称性により等しいと計算するのは簡単です。したがって、最初の固有値は合計のです。以下のためです[01]100R100Rnn1/3n/3n1/121/12n/3n1/12/n/3=3/4+1/4nn=10075.25%、3番目のプロットに表示。
whuber

回答:


11

最初のPCは、変数がゼロを中心としていないことを説明しています。最初にスケーリングするか、ランダム変数をゼロ付近にセンタリングすると、期待する結果が得られます。たとえば、次のいずれかです。

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
あなたは良い点を挙げますが、これは物語の一部を伝えるだけだと思います。実際、OPはこれらのそれぞれを試して、その結果に驚かされると思います。問題の事実は、出力で特異値が順序付けられているため、「ランダム」データから単純に予想されるように、それらが均一に分布しないことです(実際にはそうではありません)。マルチェンコ-Pastur分布は、このケースでは彼らの行動を支配します。
枢機

@アーロンありがとう、あなたは絶対に正しかった。上記の修正された出力のグラフを追加して、結果がどれほど美しいかを示しました。
コンタンゴ

1
コメントをありがとう マトリックスが小さいほど、多数の法則によって押しつぶされないパターンを持つ可能性が高くなるため、SVD値はマトリックスが小さくなるにつれて均一に分布しなくなると考えています。
コンタンゴ

3

nullモデルの比較を使用して、あなたの質問に対してより視覚的な回答を追加します。この手順では、変数(列)間の共分散が失われている間、全体の分散を維持するために各列のデータがランダムにシャッフルされます。これは数回実行され、ランダム化されたマトリックスの特異値の結果の分布が元の値と比較されます。

マトリックス分解のprcomp代わりに使用しますsvdが、結果は似ています。

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

ヌルモデルの比較は、以下の中央のマトリックスで実行されます。

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)

以下は、置換行列の箱ひげ図で、各特異値の95%の分位数が実線で示されています。のPCAの元の値はmドットです。これらはすべて95%の線の下にあります。したがって、振幅はランダムノイズと区別できません。

ここに画像の説明を入力してください

中心化されていないバージョンでも同じ手順でm同じ結果が得られます-有意な特異値はありません:

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

ここに画像の説明を入力してください

比較のために、ランダムでないデータセットを持つデータセットを見てみましょう。 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)

ここに画像の説明を入力してください

ここでは、最初の特異値が重要であり、合計分散の92%以上を説明しています。

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

+1。Irisデータセットの例は興味深いです。なぜなら、最初の2台のPCを見ると(たとえば、stats.stackexchange.com / a / 88092にある自分の投稿のように)、2台目のPC が何らかの信号を伝送していることは明らかです。順列(シャッフル)テストは、最初の1つだけが「重要」であることを示します。シャッフルはPCの数を過小評価する傾向があることは明らかです。最初の実際のPCの大きな変動は、シャッフルされたPC全体に「広がり」、2番目以降のすべてのPCを上昇させます。それを考慮したより繊細なテストを考案することはできますが、これはめったに行われません。
アメーバは、モニカーを復活させる

@amoeba-素晴らしいコメント。私はしばらくの間、「拡散」効果について疑問に思っていました。クロス検証テストは、あなたが参照するより敏感なテストの1つかもしれません(たとえば、ここの答え)?例/参照を提供できれば素晴らしいと思います。
ボックス内のマーク

私は通常、クロスバリデーションを使用することを好みます(ここでの私の答えによると再構築エラーに基づいています)が、実際には同じ種類の非感受性に苦しんでいないかどうかはわかりません。Irisデータセットで試してみるとよいでしょう。シャッフルベースのアプローチに関しては、この「拡散」の説明については何も言及していませんが、最近取り組んでいる人を知っています。彼らはすぐにそれを書きたかったと思う。アイデアは、よりシャッフルされたPCの分散にダウンスケーリング要因を導入することです。
アメーバは、モニカを復活させる

@amoeba-そのリンクをありがとう。それは私にとってたくさん説明しています。PCAの相互検証では、欠損値のあるデータセットを操作できるメソッドを使用していることがわかり、特に興味深いことがわかりました。私はこのアプローチでいくつかの試みを行いましたが、(あなたが述べているように)nullモデルシャッフルアプローチは実際に重要なPCの数を過小評価する傾向があります。ただし、アイリスデータセットの場合、再構築エラーのために一貫して単一のPCを返します。あなたがプロットについて述べたことを考えると興味深い。種の予測に基づいてエラーを測定すると、結果が異なる可能性があります。
ボックス内のマーク

好奇心から、アイリスのデータで試してみました。実際、クロスバリデーション法を使用して2つの重要なPCを取得しています。リンクされた投稿を更新しました。参照してください。
アメーバは、モニカの復活
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.