测试矩阵列之间的线性相关性


26

我有一个行列式为零的安全收益相关矩阵。(这有点令人惊讶,因为样本相关矩阵和相应的协方差矩阵在理论上应该是正定的。)

我的假设是,至少一种证券线性依赖于其他证券。R中是否有一个函数可以按顺序测试每个列的线性相关性?

例如,一种方法是一次建立一个安全性的相关矩阵,并在每个步骤计算行列式。当行列式= 0时,请停止运行,因为您已确定证券是其他证券的线性组合。

识别在这样的矩阵中的线性相关性的任何其他技术是可以理解的。


您的矩阵是正半定的,但不是正定的,因为它是奇异的。
ttnphns 2011年

尺寸是多少(变量编号;样本数量)?
卡尔

列数=480。每个时间序列的行数=502。通常,您发现时间序列越大,样本协方差矩阵趋向于是正定的。但是,在许多情况下,您想使用实质上较小的T值(或指数权重)来反映最近的市场状况。
Ram Ahluwalia

3
这个问题是不恰当的。如果您的数据矩阵为480 x 502,则说矩阵的秩为(矩阵的列空间的维数为)在数学上等同于说某列是其他列的线性组合,但是您可以不要挑选一列,并说这是线性相关的列。因此,没有执行此操作的过程,建议的过程将根据包含它们的顺序选择相当随意的安全性。q < 480q<480q<480
NRH

协方差矩阵是对称的。它由transpose(A)* A生成。矩阵A的尺寸为480x502。但是,协方差矩阵为480x480
Ram Ahluwalia

Answers:


6

您似乎在问一个真正令人发人深省的问题:在给定单个相关性(或协方差或平方和与叉积和)的情况下,如何检测哪个列与哪个列线性相关。我暂时认为清除操作可能会有所帮助。这是我在SPSS(不是R)中的探针进行说明。

让我们生成一些数据:

        v1        v2        v3         v4          v5
    -1.64454    .35119   -.06384    -1.05188     .25192
    -1.78520   -.21598   1.20315      .40267    1.14790
     1.36357   -.96107   -.46651      .92889   -1.38072
     -.31455   -.74937   1.17505     1.27623   -1.04640
     -.31795    .85860    .10061      .00145     .39644
     -.97010    .19129   2.43890     -.83642    -.13250
     -.66439    .29267   1.20405      .90068   -1.78066
      .87025   -.89018   -.99386    -1.80001     .42768
    -1.96219   -.27535    .58754      .34556     .12587
    -1.03638   -.24645   -.11083      .07013    -.84446

让我们在V2,V4和V5之间创建一些线性相关性:

compute V4 = .4*V2+1.2*V5.
execute.

因此,我们修改了列V4。

matrix.
get X. /*take the data*/
compute M = sscp(X). /*SSCP matrix, X'X; it is singular*/
print rank(M). /*with rank 5-1=4, because there's 1 group of interdependent columns*/
loop i= 1 to 5. /*Start iterative sweep operation on M from column 1 to column 5*/
-compute M = sweep(M,i).
-print M. /*That's printout we want to trace*/
end loop.
end matrix.

5次迭代中M的打印输出:

M
     .06660028    -.12645565    -.54275426    -.19692972    -.12195621
     .12645565    3.20350385    -.08946808    2.84946215    1.30671718
     .54275426    -.08946808    7.38023317   -3.51467361   -2.89907198
     .19692972    2.84946215   -3.51467361   13.88671851   10.62244471
     .12195621    1.30671718   -2.89907198   10.62244471    8.41646486

M
     .07159201     .03947417    -.54628594    -.08444957    -.07037464
     .03947417     .31215820    -.02792819     .88948298     .40790248
     .54628594     .02792819    7.37773449   -3.43509328   -2.86257773
     .08444957    -.88948298   -3.43509328   11.35217042    9.46014202
     .07037464    -.40790248   -2.86257773    9.46014202    7.88345168

M
    .112041875    .041542117    .074045215   -.338801789   -.282334825
    .041542117    .312263922    .003785470    .876479537    .397066281
    .074045215    .003785470    .135542964   -.465602725   -.388002270
    .338801789   -.876479537    .465602725   9.752781632   8.127318027
    .282334825   -.397066281    .388002270   8.127318027   6.772765022

M
   .1238115070   .0110941027   .0902197842   .0347389906   .0000000000
   .0110941027   .3910328733  -.0380581058  -.0898696977  -.3333333333
   .0902197842  -.0380581058   .1577710733   .0477405054   .0000000000
   .0347389906  -.0898696977   .0477405054   .1025348498   .8333333333
   .0000000000   .3333333333   .0000000000  -.8333333333   .0000000000

M
   .1238115070   .0110941027   .0902197842   .0347389906   .0000000000
   .0110941027   .3910328733  -.0380581058  -.0898696977   .0000000000
   .0902197842  -.0380581058   .1577710733   .0477405054   .0000000000
   .0347389906  -.0898696977   .0477405054   .1025348498   .0000000000
   .0000000000   .0000000000   .0000000000   .0000000000   .0000000000

请注意,第5列最终充满了零。(据我了解),这意味着V5与前面的某些列线性关联。哪几列?看一下第5列最后不为零的迭代-迭代4。我们看到V5与V2和V4绑定在一起,系数为-.3333和.8333:V5 = -.3333 * V2 + .8333 * V4,对应到我们对数据所做的处理:V4 = .4 * V2 + 1.2 * V5。

这就是我们知道哪一列与另一列线性关联的方式。我没有检查上述方法在更一般的情况下对数据中许多相互依赖的组有多大帮助。在上面的示例中,它似乎很有帮助。


这不是缩小行梯形形式吗?如果是这样,R中没有可用的软件包/功能吗?
阿伦(Arun)

@Arun,我不是R用户,所以不知道。
ttnphns 2011年

25

这是一种简单的方法:计算由于删除每一列而产生的矩阵的秩。删除后导致最高等级的列是线性相关的列(因为删除那些不会降低等级,而删除线性独立的列却会降低)。

在R中:

rankifremoved <- sapply(1:ncol(your.matrix), function (x) qr(your.matrix[,-x])$rank)
which(rankifremoved == max(rankifremoved))

1
在确定我收到错误的回归矩阵中system is exactly singular: U[5,5] = 0 有问题的列时,这非常有用的答案,我现在知道这意味着第5列是问题所在(事后看来很明显,因为它是零列!)
Matt Weller 2014年

在James的评论中,他发布了脚本:rankifremoved <-sapply(1:ncol(your.matrix),function(x)qr(your.matrix [,-x])$ rank)其中(rankifremoved == max( rankifremoved))我在矩阵上做了一个测试,我想知道R的输出。输出的列是线性相关的吗?谢谢!

@EltonAraújo:输出将是一个向量,给出线性相关列的索引:ttnphns的答案中的示例为(2,4,5)。但是我不知道数值精度问题将如何影响这种方法。
Scortchi-恢复莫妮卡

rankifremoved包含所有在它们之间或之间线性相关的列。在某些应用程序中,我们可能想保留一列或几列而不是全部删除
MasterJedi'1

这不应该返回一个空集your.matrix = matrix(1:4, 2)吗?
Holger Brandl

15

该问题询问有关“识别变量之间的潜在[线性]关系”的问题。

快速简便的关系检测方法是使用您喜欢的软件对其他变量(使用常数,甚至使用偶数)进行回归:任何良好的回归过程均可检测和诊断共线性。(您甚至不必费心查看回归结果:我们仅依赖于建立和分析回归矩阵的有用副作用。)

但是,假设检测到共线性,下一步怎么办? 主成分分析(PCA)正是需要的:其最小的成分对应于近乎线性的关系。这些关系可以直接从“负荷”中读取,“负荷”是原始变量的线性组合。小载荷(即与小特征值相关的载荷)对应于近似共线性。特征值对应于理想的线性关系。仍然比最大值小得多的稍大的特征值将对应于近似线性关系。0

(确定什么是“小”负载是一门艺术和大量文献。对于建模因变量,我建议将其包括在PCA的自变量中,以识别组件,无论如何它们的大小-在其中因变量起着重要的作用。从这个角度来看,“小”表示比任何此类组件都小得多。)


让我们看一些例子。 (这些R用于计算和绘图。)从执行PCA的功能开始,寻找小零件,对其进行绘图,然后返回它们之间的线性关系。

pca <- function(x, threshold, ...) {
  fit <- princomp(x)
  #
  # Compute the relations among "small" components.
  #
  if(missing(threshold)) threshold <- max(fit$sdev) / ncol(x)
  i <- which(fit$sdev < threshold)
  relations <- fit$loadings[, i, drop=FALSE]
  relations <- round(t(t(relations) / apply(relations, 2, max)), digits=2)
  #
  # Plot the loadings, highlighting those for the small components.
  #
  matplot(x, pch=1, cex=.8, col="Gray", xlab="Observation", ylab="Value", ...)
  suppressWarnings(matplot(x %*% relations, pch=19, col="#e0404080", add=TRUE))

  return(t(relations))
}

让我们将其应用于一些随机数据。这些建立在四个变量(问题的和)的基础上。这是一个将计算为其他给定线性组合的小函数。然后,它将iid正态分布的值添加到所有五个变量中(以查看当多重共线性仅是近似值而不是精确值时,过程执行得如何)。B,C,D,EA

process <- function(z, beta, sd, ...) {
  x <- z %*% beta; colnames(x) <- "A"
  pca(cbind(x, z + rnorm(length(x), sd=sd)), ...)
}

我们都准备好了:仅保留生成并应用这些过程。我使用问题中描述的两种情况:(每个都有一些错误)和(每个都有一些错误)。但是,首先请注意,PCA几乎总是应用于居中数据,因此使用可以将这些模拟数据居中(但不能重新缩放)。B,,EA=B+C+D+EA=B+(C+D)/2+Esweep

n.obs <- 80 # Number of cases
n.vars <- 4 # Number of independent variables
set.seed(17)
z <- matrix(rnorm(n.obs*(n.vars)), ncol=n.vars)
z.mean <- apply(z, 2, mean)
z <- sweep(z, 2, z.mean)
colnames(z) <- c("B","C","D","E") # Optional; modify to match `n.vars` in length

在这里,我们讨论了两种情况和三种错误级别。原始变量始终保留不变:只有和错误项有所不同。B,,EA

结果

与左上方面板相关的输出是

       A  B  C  D  E
Comp.5 1 -1 -1 -1 -1

这表示一排红点-始终为,表示完美的多重共线性-由组合:正好是所指定的。00ABCDE

上中间面板的输出是

       A     B     C     D     E
Comp.5 1 -0.95 -1.03 -0.98 -1.02

系数仍然接近我们的预期,但是由于引入的误差,它们并不完全相同。它在所隐含的五维空间内加厚了四维超平面,并使估计方向稍微倾斜了一点。随着更多的误差,增厚变得可与点的原始散布相媲美,从而使超平面几乎无法估计。现在(在右上方的面板中)系数为(A,B,C,D,E)

       A     B     C     D     E
Comp.5 1 -1.33 -0.77 -0.74 -1.07

它们已经改变了很多,但是仍然反映了基本的基本关系,其中的质数表示已消除(未知)错误的值。A=B+C+D+E

底行的解释方式相同,其输出类似地反映系数。1,1/2,1/2,1

在实践中,通常不会出现将一个变量选为其他变量的明显组合的情况:所有系数的大小都可能相当,符号也不同。此外,当关系有多个维度时,没有唯一的方式来指定它们:需要进一步分析(例如行减少)来确定这些关系的有用基础。这就是世界的运作方式:您只能说PCA输出的这些特定组合几乎不对应数据变化。 为了解决这个问题,某些人可以直接使用最大(“主要”)成分作为回归或后续分析中的自变量,无论采用哪种形式。如果这样做,请不要忘记首先从变量集中删除因变量并重做PCA!


这是复制此图的代码:

par(mfrow=c(2,3))
beta <- c(1,1,1,1) # Also can be a matrix with `n.obs` rows: try it!
process(z, beta, sd=0, main="A=B+C+D+E; No error")
process(z, beta, sd=1/10, main="A=B+C+D+E; Small error")
process(z, beta, sd=1/3, threshold=2/3, main="A=B+C+D+E; Large error")

beta <- c(1,1/2,1/2,1)
process(z, beta, sd=0, main="A=B+(C+D)/2+E; No error")
process(z, beta, sd=1/10, main="A=B+(C+D)/2+E; Small error")
process(z, beta, sd=1/3, threshold=2/3, main="A=B+(C+D)/2+E; Large error")

(在大错误情况下,我不得不摆弄阈值,以便仅显示单个组件:这就是将这个值作为参数提供给的原因process。)


用户ttnphns已将我们的注意力引向了一个密切相关的线程。 其答案之一(由JM提出建议了此处描述的方法。


哇,这是我从您的回复中所了解的..将我的变量与其他变量进行回归。使用VIF然后标识相关变量。最好一次执行一次数据块处理吗?如果使用先验回归来检测共线性,也可以删除任何东西吗?。据我对PCA的理解,通常是基于特征值使用最大的PC(解释最大方差),因为这些特征解释了大多数方差,这些负载会随变化而变化度使用原始变量。我不确定是什么小载荷以及它们与之共线
Samuel

这个答案解释了如何解释这些小的组成部分:它们表现出共线性。是的,您可以根据需要使用变量子组。回归方法只是检测共线性的存在,而不是确定共线性关系:PCA就是这样做的。
ub

"loadings," which are linear combinations of the original variables这句话看起来不准确。荷载是预测变量中各个分量的线性组合的系数。那么,您是说吗?A 1AA1
ttnphns

另外,请问您是否有可能在跟踪线性相关变量子集的过程中使用扫描操作(stats.stackexchange.com/a/16391/3277)留下您的意见?
ttnphns

@ttnphns我在发布此答案之前验证了有关加载的声明。验证包括执行设计矩阵的SVD ,写。矩阵包含线性关系(由所报告的“负荷” ),列是(加权)主成分。将限制为特征值最小的列将使的范数变小,这正是我们想要的。实际上,在特征值为,的相应列(如所述,是列的明确线性组合)全为零。X = U W VX VXV=ûW¯¯W¯¯üW¯¯0XVXX=UWVVprincompXV=UWWUW0XVX
ub

5

为了诊断目的,我将尝试采用 ×矩阵(即转置)并确定矩阵的奇异值(出于诊断目的,您不需要完整的奇异值分解...)。一旦有了480个奇异值,请检查其中有多少个“小”(通常的标准是,如果奇异值小于最大奇异值乘以机器精度,则为“小”)。如果有任何“小”奇异值,则是的,您具有线性依赖性。502×480


3

大约两周前,我遇到了这个问题,并决定需要重新审视它,因为在处理海量数据集时,不可能手动执行这些操作。

我创建了一个for()循环,该循环一次计算矩阵的秩。因此,对于第一个迭代,等级将为1。第二个等级将为2。直到等级比您使用的列数少时才发生。

非常简单:

for (i in 1:47) {

  print(qr(data.frame[1:i])$rank) 
  print(i) 
  print(colnames(data.frame)[i])
  print("###") 
}

for()循环故障

  1. 计算第ith列的排名
  2. 打印迭代次数
  3. 打印列名称以供参考
  4. 用“ ###”分隔控制台,以便您轻松滚动浏览

我确信您可以添加一个if语句,因为我只处理50ish列,所以我现在还不需要它。

希望这可以帮助!


2
尽管从理论上讲这没有错,但它是一种数值不稳定且效率低下的算法。特别是在有大量列的情况下,它可能无法检测到共线性,而在没有共线性的情况下会错误地检测共线性。
whuber

2

矩阵的秩r =矩阵的线性独立列(或行)的数量。对于n×n矩阵Arank(A)= n =>所有列(或行)都是线性独立的。


2

并不是真的需要扩展@Whuber给出的答案,但我认为我会提供数学的简短描述。

XXv=0v0vXXλ=0XXXXXλ=0XXvλ

κj=λmaxλj

XX=[0.0010000.0010000.001].
λ1=λ2=λ3=0.001
κ=λmaxλmin=1

引文

蒙哥马利(D.)(2012)。线性回归分析简介,第5版。约翰·威利父子公司


1
X

QRXnkn>>kXR
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.