PCA:princomp()是如何工作的?我可以使用它来挑选ARIMA的变量吗?

3
我正在尝试使用PCA来选择好的预测变量,以在arima模型的xreg参数中使用,从而尝试预测下面的tVar变量。我只是使用了简化后的数据集,其中只有几个变量,以使示例更简单。
我正在尝试理解princomp中公式参数的工作原理。对于下面的pc对象,它是否表示“使用xVar1和xVar2来解释na.omit(dfData[,c("tVar","xVar1","xVar2")])中的方差”?
我最终想做的是创建一个新变量,它解释了tVar中大部分的方差。我可以使用PCA来实现这一点吗?如果可以,请有人解释如何或指向一个示例。
代码:
pc <- princomp(~xVar1+xVar2,
               data = na.omit(dfData[,c("tVar","xVar1","xVar2")]), 
               cor=TRUE)

数据:

dput(na.omit(dfData[1:100,c("tVar","xVar1","xVar2")]))
structure(list(tVar = c(11, 14, 17, 5, 5, 5.5, 8, 5.5, 
          6.5, 8.5, 4, 5, 9, 10, 11, 7, 6, 7, 7, 5, 6, 9, 9, 6.5, 9, 3.5, 
          2, 15, 2.5, 17, 5, 5.5, 7, 6, 3.5, 6, 9.5, 5, 7, 4, 5, 4, 9.5, 
          3.5, 5, 4, 4, 9, 4.5, 6, 10, 9.5, 15, 9, 5.5, 7.5, 12, 17.5, 
          19, 7, 14, 17, 3.5, 6, 15, 11, 10.5, 11, 13, 9.5, 9, 7, 4, 6, 
          15, 5, 18, 5, 6, 19, 19, 6, 7, 7.5, 7.5, 7, 6.5, 9, 10, 5.5, 
          5, 7.5, 5, 4, 10, 7, 5, 12), xVar1 = c(0L, 0L, 0L, 0L, 
          0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
          0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 
          0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
          0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 
          1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
          0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
          xVar2  = c(0L, 
          1L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 
          2L, 3L, 0L, 0L, 1L, 0L, 0L, 1L, 1L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 
          0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 1L, 0L, 0L, 
          0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 3L, 1L, 0L, 1L, 2L,
          0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 
          1L, 1L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 
          0L)), .Names = c("tVar", "xVar1", "xVar2"
          ), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 9L, 10L, 11L, 12L, 
          13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L,25L, 
          26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 34L, 35L, 36L, 37L,38L, 
          39L, 40L, 41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 50L,51L, 
          52L, 54L, 55L, 56L, 57L, 58L, 59L, 60L, 61L, 62L, 63L, 64L, 65L,
          66L, 67L, 68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 76L, 77L, 78L, 
          79L, 80L, 81L, 82L, 83L, 84L, 85L, 86L, 87L, 88L, 89L, 90L, 91L, 
          92L, 93L, 94L, 95L, 96L, 97L, 98L, 99L, 100L),
          class  = "data.frame", na.action = structure(c(8L,53L),
          .Names = c("8", "53"), class = "omit"))

你可以使用PCA来完成这个任务。解释如何做将会像写一章书一样。 - Gaurav
1个回答

12

(这是一篇非常好的文章!今天又有一篇关于PCA的文章,虽然那个问题更基础,涉及到princompprcomp之间的差异,但我在答案中用R代码进行了数学细节的讲解,可能对任何学习PCA的人都有益处。)

当:

  1. 您拥有很多(例如p)相关变量x1、x2、...、xp
  2. 您想将它们缩小到少量(例如k<p)新的、线性独立的变量z1、z2、...、zk
  3. 您想使用z1、z2、...、zk而不是x1、x2、...、xp来预测响应变量y
PCA用于降维(低秩逼近)。

基本概念和一些数学知识

假设你有一个响应变量 y,一个完整的线性回归模型不应该删除任何变量,其公式应为:

y ~ x1 + x2 + ... + xp

然而,在主成分分析(PCA)之后,我们可以做出一个合理的近似模型。让X成为上述模型矩阵,即通过按列组合所有观测值x1,x2,...,xp得到的矩阵,则有:

S <- cor(X)  ## get correlation matrix S
E <- eigen(S)  ## compute eigen decomposition of S
root_eigen_value <- sqrt(E$values)  ## square root of eigen values
eigen_vector_mat <- E$vectors  ## matrix of eigen vectors
X1 <- scale(X) %*% eigen_vector_mat  ## transform original matrix

现在,root_eigen_value(一个长度为p的向量)单调递减,即对总协方差的贡献正在减少,因此我们只能选择前k个值。因此,我们可以选择转换矩阵X1的前k列。让我们这样做:
Z <- X1[, 1:k]

现在,我们已经成功地将p个变量减少到k个变量,并且Z的每一列都是新变量z1、z2、...、zk。请记住,这些变量不是原始变量的子集;它们是全新的变量,没有名称。但由于我们只对预测y感兴趣,所以给z1、z2、...、zk起什么名字并不重要。然后,我们可以拟合一个近似线性模型:
y ~ z1 + z2 + ... + zk

使用princomp()

事实上,情况更容易,因为princomp()为我们完成了所有计算。通过调用:

pc <- princomp(~ x1 + x2 + ... + xp, data, cor = TRUE)

我们可以获得所有我们想要的东西。在pc返回的几个值中:

  1. pc$sdev给出了root_eigen_value。如果你执行plot(pc),你会看到一个条形图显示这个值。如果你的输入数据高度相关,那么你会看到这个图中有一个接近指数衰减的趋势,只有少数变量主导着协方差。(不幸的是,你的玩具数据不起作用。xVar1xVar2是二元的,并且它们已经线性独立,因此在PCA之后,你会发现它们都给出了相等的贡献。
  2. pc$loadings给出了eigen_vector_mat
  3. pc$scores给出了X1

使用arima()

变量选择过程很简单。如果您决定从总共p个变量中取出前k个变量,并检查plot(pc),则提取pc$scores矩阵的前k列。每一列形成z1,z2,...,zk,并通过参数reg传递给arima()


回到你关于公式的问题

对于下面的pc对象,它是在说“使用xVar1和xVar2来解释na.omit(dfData[,c("tVar","xVar1","xVar2")])中的方差”吗?

经过我的解释,你应该知道答案是“不是”。不要混淆在回归步骤中使用的响应变量tVar与在PCA步骤中使用的预测变量xVar1,xVars等。

princomp()有三种传递参数的方法:

  1. 通过公式和数据;
  2. 通过模型矩阵;
  3. 通过协方差矩阵。

你选择了第一种方式。公式用于告诉princomp()从data中提取数据,然后它将计算模型矩阵、协方差矩阵、相关矩阵、特征值分解,直到我们最终得到PCA的结果。


关于您的评论的后续

如果我理解正确,PCA主要用于减少变量数量,我不应该在公式或数据中包含响应变量tVar。但我想知道为什么princomp(〜xVar1 + xVar2,data = na.omit(dfData [,c(“tVar”,“xVar1”,“xVar2”])),cor = TRUE)princomp(na.omit(dfData [,c(“xVar1”,“xVar2”])),cor = TRUE)基本上是等效的?

该公式告诉如何从数据框中提取矩阵。由于您使用相同的公式〜xVar1 + xVar2,因此是否将tVars包含在传递给princomp的数据框中并没有任何区别,因为该列不会被princomp修改。

不要在PCA的公式中包含tVars。正如我所说,回归和PCA是不同的问题,不应混淆。

要明确的是,PCA 的策略不是创建一个新变量,它是 xVar1xVar2 的组合,并解释了 tVar 中大部分的差异,而是创建一个新变量,它是 xVar1xVar2 的组合,并解释了 dfData[,c("xVar1","xVar2")] 的大部分差异吗? 是的。在您的设置中,回归(或 arima())用于建立响应变量 tVars 和预测变量 x1、x2、...、xpz1、z2、...、zk 之间的关系。回归/ARIMA 模型将以预测变量为基础解释响应变量的均值和方差。PCA 是一个不同的问题。它仅选择原始预测变量 xVar1、xVar2、... 的低秩(更少参数)表示,以便您可以在后续回归/ARIMA 建模中使用较少的变量。尽管如此,您可能需要考虑是否应该对您的问题进行 PCA。
  1. 你是否有很多变量,比如10个以上?在统计建模中,通常会达到数十万个参数。如果使用所有这些参数,计算速度会变得非常缓慢。在这种情况下,PCA非常有用,可以降低计算复杂度,同时给出原始协方差的合理表示。
  2. 你的变量是否高度相关?如果它们彼此线性独立,那么PCA可能不会减少任何内容。例如,你提供的玩具数据xVar1和xVar2只是线性无关的,因此无法进行维度缩减。你可以通过pairs(mydata)查看数据的相关性。更好的可视化方法可能是使用corrplot R包。请参见this answer以了解如何使用它来绘制协方差矩阵的示例。

非常感谢您的出色回答!如果我理解正确,PCA主要是用于减少变量数量,因此在公式或数据中不应包括响应变量tVar。另外,我想知道princomp(〜xVar1 + xVar2,data = na.omit(dfData [,c(“tVar”,“xVar1”,“xVar2”)]),cor = TRUE)和princomp(na.omit(dfData [,c(“xVar1”,“xVar2”)]),cor = TRUE)基本上是等价的吗? - user3476463
要明确的是,PCA的策略不是创建一个新变量,该变量是xVar1和xVar2的组合,并解释了tVar中大部分的方差,而是创建一个新变量,该变量是xVar1和xVar2的组合,并解释了dfData[,c("xVar1","xVar2")]中大部分的方差。 - user3476463
1
PCA并不考虑你的响应变量在选择成分时的影响,仅仅是关注数据中的差异。如果这些差异恰好对应着响应变量的变化,那么你就很好了,但是如果没有,你可能会被引导舍弃一个解释响应所必需的维度。研究一下偏最小二乘回归(Partial Least Squares),这是一种考虑响应变量的“有监督”降维方法。 - welch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接