Untuk matriks acak, bukankah seharusnya SVD tidak menjelaskan apa-apa? Apa yang saya lakukan salah?

13

Jika saya membuat matriks 2-D yang seluruhnya terdiri dari data acak, saya berharap komponen PCA dan SVD pada dasarnya tidak menjelaskan apa-apa.

Sebaliknya, sepertinya kolom SVD pertama muncul untuk menjelaskan 75% dari data. Bagaimana ini bisa terjadi? Apa yang saya lakukan salah?

Ini plotnya:

masukkan deskripsi gambar di sini

Berikut adalah kode 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)

Memperbarui

Terima kasih @ Harun. Cara mengatasinya, seperti yang Anda catat, adalah menambahkan penskalaan ke matriks sehingga angkanya berpusat di sekitar 0 (artinya rata-rata adalah 0).

m <- scale(m, scale=FALSE)

Berikut adalah gambar yang dikoreksi, menunjukkan matriks dengan data acak, kolom SVD pertama mendekati 0, seperti yang diharapkan.

Gambar yang diperbaiki

Contango
sumber
4
[0,1]100R100Rnn1/3n/3-(n-1)/121/12(n/3-(n-1)/12)/(n/3)=3/4+1/(4n)n=10075.25

Jawaban:

11

PC pertama menjelaskan bahwa variabel tidak terpusat di sekitar nol. Melakukan penskalaan pertama atau memusatkan variabel acak Anda di sekitar nol akan memiliki hasil yang Anda harapkan. Misalnya, salah satu dari ini:

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 meninggalkan Stack Overflow
sumber
3
Anda mengangkat poin yang baik, tetapi saya pikir ini hanya menceritakan sebagian dari cerita. Memang, saya akan menebak bahwa OP akan mencoba masing-masing dan masih terkejut dengan hasilnya. Fakta dari masalah ini adalah bahwa karena nilai singular dipesan dalam output, mereka tidak akan muncul (dan memang tidak) terdistribusi secara seragam seperti yang diharapkan secara naif dari data "acak". The distribusi Marchenko-Pastur mengatur perilaku mereka dalam kasus ini.
kardinal
@ Harun Terima kasih, kamu benar sekali. Saya telah menambahkan grafik dari hasil yang diperbaiki di atas untuk menunjukkan betapa indahnya hasilnya.
Contango
1
@ cardinal Terima kasih atas komentar Anda, Anda benar sekali (lihat grafik yang dihasilkan oleh kode yang diperbaiki, di atas). Saya percaya nilai SVD akan menjadi kurang terdistribusi secara seragam karena matriks semakin kecil, karena matriks yang lebih kecil akan memiliki lebih banyak peluang memiliki pola yang tidak akan tergencet oleh hukum angka besar.
Contango
3

Saya akan menambahkan jawaban yang lebih visual untuk pertanyaan Anda, melalui penggunaan perbandingan model nol. Prosedur secara acak mengocok data di setiap kolom untuk mempertahankan varians keseluruhan sementara kovarians antara variabel (kolom) hilang. Ini dilakukan beberapa kali dan distribusi nilai singular yang dihasilkan dalam matriks acak dibandingkan dengan nilai asli.

Saya menggunakan prcompalih-alih svduntuk dekomposisi matriks, tetapi hasilnya serupa:

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

Perbandingan model nol dilakukan pada matriks berpusat di bawah ini:

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)

Berikut ini adalah boxplot dari matriks permutasi dengan kuantil 95% dari setiap nilai singular yang ditunjukkan sebagai garis padat. Nilai asli PCA madalah titik. yang semuanya terletak di bawah garis 95% - Dengan demikian amplitudo mereka tidak dapat dibedakan dari derau acak.

masukkan deskripsi gambar di sini

Prosedur yang sama dapat dilakukan pada versi yang tidak terpusat mdengan hasil yang sama - Tidak ada nilai tunggal yang signifikan:

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

masukkan deskripsi gambar di sini

Sebagai perbandingan, mari kita lihat dataset dengan dataset non-acak: 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)

masukkan deskripsi gambar di sini

Di sini, nilai tunggal pertama adalah signifikan, dan menjelaskan lebih dari 92% dari total varians:

P <- prcomp(m, center = TRUE)
P$sdev^2 / sum(P$sdev^2)
# [1] 0.924618723 0.053066483 0.017102610 0.005212184
Marc di dalam kotak
sumber
+1. Contoh dataset Iris menarik, karena melihat dua PC pertama (seperti misalnya dalam posting Anda sendiri di sini stats.stackexchange.com/a/88092 ), cukup jelas bahwa yang kedua membawa beberapa sinyal. Tes permutasi (alias pengocokan) menunjukkan bahwa hanya yang pertama yang "signifikan". Jelas bahwa pengocokan cenderung meremehkan jumlah PC: varian besar dari PC nyata pertama akan "menyebar" di PC yang diacak dan akan menaikkan semuanya mulai dari yang kedua. Seseorang dapat menyusun tes yang lebih sensitif yang menjelaskan hal itu tetapi ini jarang dilakukan.
Amuba mengatakan Reinstate Monica
@amoeba - Komentar luar biasa. Saya telah bertanya-tanya tentang efek "menyebar" untuk beberapa waktu sekarang. Saya kira tes validasi silang mungkin salah satu yang lebih sensitif yang Anda referensi (mis. Jawaban Anda sini )? Akan lebih bagus jika Anda bisa memberikan contoh / referensi.
Marc di dalam kotak
Saya biasanya lebih suka menggunakan validasi silang (berdasarkan kesalahan rekonstruksi, sesuai jawaban saya di sini ), tetapi saya sebenarnya tidak yakin apakah itu entah bagaimana menderita jenis ketidakpekaan yang sama atau tidak. Mungkin masuk akal untuk mencobanya pada dataset Iris. Mengenai pendekatan berbasis pengocokan, saya tidak tahu referensi untuk akuntansi untuk "penyebaran" ini, saya hanya tahu beberapa orang yang mengerjakannya baru-baru ini. Saya pikir mereka ingin segera menulisnya. Idenya adalah untuk memperkenalkan beberapa faktor downscaling untuk varian PC yang dikocok lebih tinggi.
Amuba kata Reinstate Monica
@amoeba - Terima kasih atas tautannya. Ini menjelaskan banyak hal untuk saya. Saya merasa sangat menarik untuk melihat bahwa validasi silang dalam PCA menggunakan metode yang dapat beroperasi pada dataset dengan nilai yang hilang. Saya melakukan beberapa upaya pada pendekatan ini dan (seperti yang Anda sebutkan) pendekatan model nol pengocokan memang cenderung meremehkan jumlah PC yang signifikan. Namun, untuk set data iris, saya secara konsisten mengembalikan satu PC untuk kesalahan rekonstruksi. Menarik mengingat apa yang Anda sebutkan tentang plot. Bisa jadi jika kita mengukur kesalahan berdasarkan prediksi spesies, hasilnya mungkin berbeda.
Marc di dalam kotak
Karena penasaran, saya mencobanya pada data Iris. Sebenarnya, saya mendapatkan dua PC yang signifikan dengan metode cross-validation. Saya memperbarui posting saya yang ditautkan, silakan lihat di sana.
Amoeba berkata Reinstate Monica