랜덤 행렬의 경우 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)

최신 정보

감사합니다 @Aaron. 앞서 언급했듯이 수정은 매트릭스에 스케일링을 추가하여 숫자가 0을 중심으로합니다 (즉 평균은 0입니다).

m <- scale(m, scale=FALSE)

다음은 임의의 데이터가있는 행렬에 대한 수정 된 이미지입니다. 첫 번째 SVD 열은 예상대로 0에 가깝습니다.

보정 된 이미지


4
R 100 R , N , N 1 / 3 N / 3 - ( N - 1 ) / 12 (1) / 12 ( N / 3 - ( N - 1 ) / 12 ) / ( N / 3 ) = 3 / 4 + 1 / ( 4 n )[0,1]100R100Rnn1/3n/3(n1)/121/12(n/3(n1)/12)/(n/3)=3/4+1/(4n)n=10075.25세 번째 줄에 보이는 %.
whuber

답변:


11

첫 번째 PC는 변수가 0을 중심으로하지 않는다고 설명합니다. 먼저 스케일링하거나 임의의 변수를 0 주위에 중심을 맞추면 예상 한 결과가 나타납니다. 예를 들어 다음 중 하나입니다.

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가 이들 각각을 시도 하고 결과에 여전히 놀랄 것이라고 추측 할 것 입니다. 문제의 사실은 출력에 단수 값이 정렬 되어 있기 때문에 "임의의"데이터에서 예상 할 수있는 것처럼 균일하게 분포되지 않고 실제로 분포되지도 않는다는 것입니다. 이 경우 Marchenko-Pastur 배포판 이 해당 동작을 관리합니다.
추기경

@Aaron 감사합니다, 당신은 절대적으로 옳았습니다. 위의 수정 된 출력 그래프를 추가하여 결과가 얼마나 아름다운 지 보여줍니다.
Contango

1
@cardinal 귀하의 의견에 감사드립니다, 당신은 절대적으로 맞습니다 (위의 수정 된 코드에 의해 생성 된 그래프 참조). 매트릭스가 작을수록 SVD 값이 덜 균일하게 분포 될 것이라고 생각합니다.
Contango

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

null 모델 비교는 아래의 중심 행렬에서 수행됩니다.

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 % Quantile이 실선으로 표시된 순열 행렬의 상자 그림입니다. 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 데이터 셋의 예는 흥미 롭습니다. 처음 두 PC를 살펴보면 (예 : stats.stackexchange.com/a/88092 와 같이) 두 번째 PC 가 신호를 전달한다는 것은 분명합니다. 순열 (일명 셔플 링) 테스트는 첫 번째 테스트 만 "중요"하다는 것을 나타냅니다. 셔플 링은 PC의 수를 과소 평가하는 경향이 있음이 분명합니다. 첫 번째 실제 PC의 큰 차이는 셔플 된 PC에서 "확산"되고 두 번째부터 시작하여 모든 PC가 향상 될 것입니다. 그것을 설명하는 더 민감한 테스트를 고안 할 수는 있지만 거의 이루어지지 않습니다.
amoeba 말한다 Reinstate Monica

@amoeba-우수 의견. 나는 한동안 "확산"효과에 대해 궁금해하고 있습니다. 교차 유효성 검사가 더 민감한 테스트 중 하나라고 생각합니다 (예 : 여기에 대한 답변 )? 예제 / 참조를 제공 할 수 있다면 좋을 것입니다.
Marc in the box

나는 일반적으로 교차 검증 ( 여기서 내 대답에 따라 재구성 오류를 기반으로 함)을 사용하는 것을 선호 하지만 실제로 같은 종류의 무감각으로 고통받지 않는지 확실하지 않습니다. Iris 데이터 세트에서 사용해 볼 수 있습니다. 셔플 링 기반 접근 방식과 관련하여, 나는이 "확산"에 대한 설명을 전혀 모른다. 나는 최근에 그 일을해온 일부 사람들을 알고있다. 나는 그들이 곧 그것을 쓰고 싶어 생각합니다. 아이디어는 더 많이 섞인 PC의 차이에 대한 일부 축소 요소를 도입하는 것입니다.
아메바는

@amoeba-해당 링크에 감사드립니다. 그것은 나를 위해 많은 것을 설명합니다. PCA의 교차 유효성 검사에서 결 측값이있는 데이터 세트에서 작동 할 수있는 메소드를 사용한다는 점이 특히 흥미 롭습니다. 나는이 접근법에 대해 몇 가지 시도를했으며 null 모델 셔플 링 접근법은 실제로 중요한 PC의 수를 과소 평가하는 경향이 있습니다. 그러나 홍채 데이터 세트의 경우 재구성 오류에 대해 단일 PC를 일관되게 반환합니다. 줄거리에 대해 언급 한 내용이 흥미 롭습니다. 종 예측을 기반으로 측정 오차를 측정 한 경우 결과가 다를 수 있습니다.
Marc in the box

호기심으로 아이리스 데이터를 사용해 보았습니다. 실제로 교차 검증 방법으로 두 대의 중요한 PC를 얻습니다. 링크 된 게시물을 업데이트했습니다. 여기를 참조하십시오.
amoeba 말한다 Reinstate Monica
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.