在Julia中运行一个简单的回归模型,存在完美的多重共线性会产生错误。在R中,我们可以运行相同的模型,在相应的协变量的估计中产生NA,R解释:"由于奇点而没有定义"。我们可以使用R。
中的alias()
函数来识别这些变量
有没有什么方法可以在建模之前在Julia中检查完美的多重共线性,以便删除共线变量?
答案 0 :(得分:4)
检测完全共线性
假设X
是您的设计矩阵。您可以通过运行以下方法检查完美的多重共线性:
rank(X) == size(X,2)
如果你有完美的多重共线性,这将产生false
。
识别近共线性+查找哪些列共线或接近共线
我不知道任何特定的内置函数。但是,线性代数的一些基本原理的应用可以很容易地确定这一点。下面是我写的一个函数,它执行此操作,然后对感兴趣的人进行更详细的解释。它的要点是我们想要找到X*X'
的特征值为零(对于完美的共线性)或接近于零(对于近共线性)。然后,我们找到与那些特征值相关的特征向量。那些非零(对于完全共线性)或中等大小的特征向量的分量(由于&#34的性质而模糊的术语;接近共线性"是模糊的)是具有共线性问题的列。
function LinDep(A::Array, threshold1::Float64 = 1e-6, threshold2::Float64 = 1e-1; eigvec_output::Bool = false)
(L, Q) = eig(A'*A)
max_L = maximum(abs(L))
conditions = max_L ./ abs(L)
max_C = maximum(conditions)
println("Max Condition = $max_C")
Collinear_Groups = []
Tricky_EigVecs = []
for (idx, lambda) in enumerate(L)
if lambda < threshold1
push!(Collinear_Groups, find(abs(Q[:,idx]) .> threshold2))
push!(Tricky_EigVecs, Q[:,idx])
end
end
if eigvec_output
return (Collinear_Groups, Tricky_EigVecs)
else
return Collinear_Groups
end
end
简单的例子开头。很容易看出这个矩阵存在共线性问题:
A1 = [1 3 1 2 ; 0 0 0 0 ; 1 0 0 0 ; 1 3 1 2]
4x4 Array{Int64,2}:
1 3 1 2
0 0 0 0
1 0 0 0
1 3 1 2
Collinear_Groups1 = LinDep(A1)
[2,3]
[2,3,4]
Max Condition = 5.9245306995900904e16
这里有两个特征值等于0。因此,该功能给了我们两组&#34;问题&#34;列。我们想在这里删除一个或多个列以解决共线性问题。显然,与共线性的性质一样,没有&#34;权利&#34;回答。例如。 Col3显然只是Col4的1/2。因此,我们可以删除任何一个来解决共线性问题。
注意:此处的最大条件是最大特征值与其他每个特征值的最大比率。一般准则是最大条件> 100表示中等共线性,&gt; 1000表示严重的共线性(参见例如Wikipedia。)但是, LOT 取决于您的具体情况,因此依赖于这样的简单规则并不是特别明智。将此视为许多因素中的一个因素会更好,包括特征向量的分析和您对基础数据的了解以及您怀疑共线性可能存在或可能不存在的位置。无论如何,我们看到它在这里是巨大的,这是可以预期的。
现在,让我们考虑一个更难的情况,那里没有完美的共线性,只是接近共线性。我们可以按原样使用该函数,但我认为打开eigvec_output
选项让我们看到与有问题的特征值对应的特征向量是有帮助的。此外,您可能希望对指定的阈值进行一些修改,以便调整拾取近共线性的灵敏度。或者,只需将它们设置得非常大(特别是第二个),并将大部分时间用于检查生成器输出。
srand(42); ## set random seed for reproducibility
N = 10
A2 = rand(N,N);
A2[:,2] = 2*A2[:,3] +0.8*A2[:,4] + (rand(N,1)/100); ## near collinearity
(Collinear_Groups2, Tricky_EigVecs2) = LinDep(A2, eigvec_output = true)
Max Condition = 4.6675275950744677e8
我们的最大条件现在明显变小了,这很好,但仍然非常严重。
Collinear_Groups2
1-element Array{Any,1}:
[2,3,4]
Tricky_EigVecs2[1]
julia> Tricky_EigVecs2[1]
10-element Array{Float64,1}:
0.00537466
0.414383
-0.844293
-0.339419
0.00320918
0.0107623
0.00599574
-0.00733916
-0.00128179
-0.00214224
在这里,我们看到列2,3,4具有与它们相关联的特征向量的相对大的分量。这向我们展示了这些是近共线性的有问题的列,当然这是我们如何创建矩阵的预期!
从基本线性代数中,任何对称矩阵都可以diagonalized为:
A = Q * L * Q'
其中L
是包含其特征值的对角矩阵,Q
是其对应特征向量的矩阵。
因此,假设我们在回归分析中有一个设计矩阵X
。矩阵X'X
将始终是对称的,因此可以如上所述进行对角化。
同样,我们将始终rank(X) = rank(X'X)
表示如果X
包含线性相关列并且小于完整排名,那么X'X
将是L[i]
。
现在,请回顾一下eigenvalue(Q[:,i]
)和特征向量A * Q[:,i] = L[i] * Q[:,i]
的定义,我们有:
L[i] = 0
如果A * Q[:,i] = 0
成为:
Q[:,i]
对于某些非零A
。这是具有线性相关列的A * Q[:,i] = 0
的定义。
此外,由于A
可以重写为由Q[:,i]
的组件加权的sum (j in S1) A[:,j]*Q[:,i][j] = sum (j in S2) A[:,j]*Q[:,i][j]
列的总和。因此,如果我们让S1和S2成为两个相互排斥的集合,那么我们就有了
L[i] = 0
即。 A列的某些组合可以写为其他列的加权组合。
因此,如果我们知道某些i
的{{1}},然后我们查看相应的Q[:,i]
并查看Q[:,i] = [0 0 1 0 2 0]
,那么我们知道列{{ 1}} = 3
次列-2
,因此我们想删除其中一个。