【问题标题】:Resampling not producing expected result of principal component analysis重采样未产生主成分分析的预期结果
【发布时间】:2015-06-25 17:43:33
【问题描述】:

我正在尝试使用带替换的重采样(如引导程序)来生成主成分分析的置信区间。我正在使用 iris 数据集的前 4 列:

prcomp 函数产生以下输出:

> mydf = iris[1:4]
> print(prcomp(mydf))
Standard deviations:
[1] 2.0562689 0.4926162 0.2796596 0.1543862

Rotation:
                     PC1         PC2         PC3        PC4
Sepal.Length  0.36138659 -0.65658877  0.58202985  0.3154872
Sepal.Width  -0.08452251 -0.73016143 -0.59791083 -0.3197231
Petal.Length  0.85667061  0.17337266 -0.07623608 -0.4798390
Petal.Width   0.35828920  0.07548102 -0.54583143  0.7536574

使用带替换的重采样:

> times = 1000
> ll = list()
> for(i in 1:times) {
+ tempdf =  mydf[sample(nrow(mydf), replace = TRUE), ]
+ ll[[length(ll)+1]] = prcomp(tempdf)$rotation
+ }
> 
> dd = data.frame(apply(simplify2array(ll), 1:2, mean))
> print(dd)
                      PC1          PC2          PC3          PC4
Sepal.Length  0.005574165 -0.039480258  0.044537991  0.007778055
Sepal.Width  -0.002587333 -0.040273812 -0.050793200 -0.005473271
Petal.Length  0.015681233  0.010952361 -0.005769051 -0.011351172
Petal.Width   0.006513656  0.008296928 -0.041805210  0.019109323

确定下置信区间:

> ddlower = data.frame(apply(simplify2array(ll), 1:2, quantile, probs=0.025))
> print(ddlower)
                    PC1        PC2        PC3        PC4
Sepal.Length -0.3859257 -0.7274809 -0.6560139 -0.3807826
Sepal.Width  -0.1127749 -0.7907801 -0.6818251 -0.3941001
Petal.Length -0.8633386 -0.2058064 -0.1333520 -0.4919584
Petal.Width  -0.3702979 -0.1328146 -0.6203322 -0.8088710

确定上置信区间:

> ddupper = data.frame(apply(simplify2array(ll), 1:2, quantile, probs=0.975))
> print(ddupper)
                   PC1       PC2       PC3       PC4
Sepal.Length 0.3860431 0.7250412 0.6632126 0.3831889
Sepal.Width  0.1111863 0.7993649 0.6758156 0.3987939
Petal.Length 0.8638549 0.2106540 0.1318556 0.4915670
Petal.Width  0.3721362 0.1510708 0.6246988 0.8083421

我发现加载值非常不同。此外,所有变量和分量的置信区间都在 0 左右。我还检查了其他(大型)数据集,结果非常相似。从这些置信区间来看,没有任何负载与 0 有显着差异。代码中显然存在一些错误,但我似乎找不到它。感谢您的帮助。

【问题讨论】:

  • 嗯,你不是没有提取出"+ ll[[length(ll)+1]] = prcomp(tempdf)$rotation" 行中的$rotation 的第一列吗? (认为​​前 1000 个 princomps 的平均值应该与 prcomp_rotation 的原始计算非常相似)
  • OP 正在为 1000 个引导重采样中的每一个中的每个变量捕获特征向量(加载)的 整个 矩阵。后面的命令然后计算每个特征向量的各个元素的百分置信区间。
  • @GottfriedHelms :这是我的问题。由于 Gavin Simpson 的回答中描述的符号问题,平均值接近 0。
  • @rnso:啊,我明白了。现在这似乎清除了。令人高兴的是,我自己的例程(在我的小型“袖珍”矩阵计算器 MatMate 中)似乎可以很好地通过实现给出归一化的符号......(我通过 svd-rotation 复制了 R:prcomp -procedure(根据其手册)在协方差矩阵上,并为过程 gettrans(cov,"pca") 实现了符号规范化,显然足以满足这个实际情况
  • 啊,好吧,我对 R 还不熟悉。然后在 1000 个样本的每个实验中对特征向量的符号进行归一化(例如,对于项目 sepal.length 的所有主成分都是非负的)就足够了(这只是对我删除的先前评论的文本更正)跨度>

标签: r statistics-bootstrap


【解决方案1】:

鉴于未定义特征向量的符号(您可以翻转配置并获得相同的结果),在 signed 的值上形成置信区间是没有意义的正在加载。

而是计算负载的绝对值的置信区间,而不是有符号值。

想想当 Sepal.Length 的特征向量从 ~ -0.3 翻转到 ~ +0.3 时,你的区间会发生什么?从绝对大小的角度考虑时,两种情况下的负载相似。但是,当您查看实际的有符号值时,加载平均为 0 是合乎逻辑的,因为您平均很多 ~-0.3s 和 ~0.3s。

要查看您最初尝试失败的原因,请运行:

set.seed(1)
mydf <- iris[1:4]
times <- 1000
ll <- vector(mode = "list", length = times)
for (i in seq_len(times)) {
  tempdf  <- mydf[sample(nrow(mydf), replace = TRUE), ]
  ll[[i]] <- prcomp(tempdf)$rotation
}

这实际上是您的代码,已根据我的感受进行了修改。现在提取Sepal.LengthPC1 上的负载并绘制值的直方图:

hist(sapply(ll, `[`, 1, 1))

产生

而是计算负载的绝对值的置信区间,而不是有符号值。

例如

set.seed(1)
mydf <- iris[1:4]
times <- 1000
ll <- vector(mode = "list", length = times)
for (i in seq_len(times)) {
  tempdf  <- mydf[sample(nrow(mydf), replace = TRUE), ]
  ll[[i]] <- abs(prcomp(tempdf)$rotation) ## NOTE: abs(...)
}

这给出了:

> data.frame(apply(simplify2array(ll), 1:2, quantile, probs = 0.025))
                    PC1         PC2        PC3       PC4
Sepal.Length 0.33066830 0.578558222 0.45955051 0.2252653
Sepal.Width  0.05211013 0.623424084 0.49591685 0.2351746
Petal.Length 0.84823899 0.133137927 0.01226608 0.4607265
Petal.Width  0.34284824 0.007403214 0.44932031 0.6780493

> data.frame(apply(simplify2array(ll), 1:2, quantile, probs = 0.975))
                   PC1       PC2       PC3       PC4
Sepal.Length 0.3891499 0.7443276 0.6690553 0.3898237
Sepal.Width  0.1186205 0.7988607 0.7010495 0.4083784
Petal.Length 0.8653324 0.2153410 0.1450756 0.4933340
Petal.Width  0.3742441 0.1645692 0.6350899 0.8154254

【讨论】:

  • 很好的答案。谢谢。只有我必须从原始值中恢复负载的符号。否则他们现在都是积极的。
  • 何必呢?该符号是任意的,当您在不同的机器、操作系统、编译器、CPU 等上运行代码时可能会有所不同。
  • 我需要符号来解释数据,以了解哪些变量是正相关的,哪些是负相关的。
  • 对不起@rnso,我的评论有点简洁。我的意思是,报告观察到的特征向量以及绝对值的置信区间。
  • 这个方法是'bootstrap'方法还是bootsrap还需要一些其他程序,我需要使用'boot'包?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 1970-01-01
  • 1970-01-01
  • 2014-02-15
  • 1970-01-01
  • 2019-12-28
  • 1970-01-01
相关资源
最近更新 更多