行列の列間の線形依存性のテスト


26

行列式がゼロのセキュリティリターンの相関行列があります。(サンプル相関行列と対応する共分散行列は理論的には正定でなければならないため、これは少し驚くべきことです。)

私の仮説は、少なくとも1つの証券が他の証券に線形に依存しているということです。Rに線形依存関係の各列を順番にテストする関数がありますか?

たとえば、1つのアプローチは、相関行列を一度に1つのセキュリティで構築し、各ステップで行列式を計算することです。行列式= 0の場合、他の証券の線形結合である証券を特定したため停止します。

そのような行列の線形依存性を特定する他の技術が評価されます。


行列は正の半正定行列ですが、正則ではないため、正定ではありません。
ttnphns

ディメンションとは何ですか(変数なし、サンプルなし)。
カール

列数=480。各時系列の行数=502。一般に、時系列が大きいほどサンプル共分散行列は正定値になる傾向があります。ただし、最近の市場の状況を反映するために、Tの大幅に小さい値(または指数関数的な重み)を使用したい場合が多くあります。
ラムAhluwalia

3
質問は不適切です。データ行列が480 x 502の場合、行列のランクが(行列の列空間の次元はq < 480)であると言うことは、一部の列が他の列の線形結合であると言うことと数学的に同等ですが、 1つの列を選択して、これが線形に依存する列であると言ってはいけません。そのため、これを行う手順はありません。推奨される手順では、含まれる順序に応じて非常にquite意的なセキュリティを選択します。q<480q<480
NRH

共分散行列は対称です。transpose(A)* Aによって生成されます。行列Aの次元は480x502です。ただし、共分散行列は480x480
Ram Ahluwalia

回答:


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は、係数-.3333および.8333でV2およびV4と結び付けられていることがわかります。V5= -.3333 * V2 + .8333 * V4。データで行ったこと:V4 = .4 * V2 + 1.2 * V5。

これにより、どの列が他の列と直線的に結び付けられているかがわかりました。データ内の相互依存関係の多くのグループで、より一般的なケースで上記のアプローチがどれほど役立つかについてはチェックしませんでした。ただし、上記の例では便利なようです。


これは行の縮小された階層型ではありませんか?もしそうなら、Rで利用可能なパッケージ/機能はありませんか?
アルン

@Arun、私はRユーザーではないのでわかりません。
ttnphns

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 14年

Jamesのコメントで、彼はスクリプトを投稿しました:rankifremoved <-sapply(1:ncol(your.matrix)、function(x)qr(your.matrix [、-x])$ rank)which(rankifremoved == max( rankifremoved))私は行列でテストを行いました、Rの出力について知りたいのですが、出力の列は線形に依存していますか?感謝!

@EltonAraújo:出力は、線形依存列のインデックスを与えるベクトルになります。そのため、ttnphnsの答えの例では(2,4,5)です。しかし、数値精度の問題がこの方法にどのように影響するのだろうかと思います。
スコッチ-モニカの復職

rankifremovedには、列間または列間で線形に依存するすべての列が含まれます。一部のアプリケーションでは、1つまたは複数の列を保持し、すべてをドロップしない場合があります
-MasterJedi

これは空のセットを返しませんyour.matrix = matrix(1:4, 2)か?
ホルガーブランドル

15

質問は、変数間の「基礎となる[線形]関係の識別」について尋ねます。

すばやく簡単な方法 関係検出するは、お気に入りのソフトウェアを使用して、これらの変数に対して他の変数を回帰することです(定数を使用することもできます)。優れた回帰手順は、共線性を検出および診断します。(回帰結果を見ることに煩わされることさえありません。単に、回帰行列を設定して分析することの有用な副作用に頼っているだけです。)

しかし、共線性が検出されたと仮定すると、次は何ですか? 主成分分析(PCA)はまさに必要なものです。その最小成分はほぼ線形の関係に対応します。これらの関係は、元の変数の線形結合である「負荷」から直接読み取ることができます。小さな負荷(つまり、小さな固有値に関連付けられた負荷)は、ほぼ共線性に対応します。固有値は、完全な線形関係に対応します。最大値よりもはるかに小さいわずかに大きい固有値は、近似線形関係に対応します。0

(「小さな」負荷が何であるかを特定することに関連した技術と非常に多くの文献があります。サイズ-従属変数が重要な役割を果たします。この観点から、「小さい」とは、そのようなコンポーネントよりもはるかに小さいことを意味します。


いくつかの例を見てみましょう。 (これら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))
}

これをランダムデータに適用してみましょう。これらは4つの変数(質問のおよびE)に基づいています。他の線形結合としてAを計算する小さな関数を次に示します。次に、5つの変数すべてにiid Normal-Distributed値を追加します(多重共線性が近似のみで正確ではない場合の手順のパフォーマンスを確認するため)。B,C,D,EA

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

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

Results

左上のパネルに関連付けられた出力は

       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

実際には、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")

(1つのコンポーネントのみを表示するために、大きなエラーの場合はしきい値をいじる必要がありました。それが、この値をパラメーターとしてに提供する理由ですprocess。)


ユーザーttnphnsは、密接に関連するスレッドに注意を向けてくれました。 その答えの1つ(JMによる)は、ここで説明するアプローチを示唆しています。


うわー、私はあなたの応答から理解したことをここに示します。他の変数に対する私の変数の回帰。VIFを使用して、関連する変数を識別します。これは機能します。一度にデータのチャンクでこれを行うのが最善ですか?また、前に回帰を使用して共線性を検出した場合、何かを削除しますか?元の変数を使用した度。どんな小さな負荷とそれらが共線性であるかについて不確かです
サミュエル

この回答は、小さなコンポーネントを解釈する方法を説明します。それらは共線性を示します。はい、必要に応じて変数のサブグループを使用できます。回帰法は、共線関係を特定することではなく、共線性の存在を検出することです。それがPCAの役割です。
whuber

"loadings," which are linear combinations of the original variablesAA1

また、変数の線形依存サブセットを追跡するタスクでスイープ操作(stats.stackexchange.com/a/16391/3277)を使用する可能性について意見をお聞かせください。
ttnphns

XX=UWVVprincompXV=UWWUW0バツV-列の明示的な線形結合である バツ、前述のように、すべてゼロです。
whuber

5

診断目的でここでやろうとすることは、 502×480行列(つまり、転置)を使用して、行列の特異値を決定します(診断のために、完全な特異値分解はまだ必要ありません...)。480個の特異値が得られたら、それらの数が「小さい」ことを確認します(通常は、最大値にマシンの精度を掛けた値よりも小さい場合、特異値は「小さい」ということです)。「小さな」特異値がある場合、はい、線形依存性があります。


3

約2週間前にこの問題に遭遇し、大量のデータセットを扱う場合、これらの作業を手動で行うことは不可能であるため、再検討する必要があると判断しました。

一度に1列ずつマトリックスのランクを計算するfor()ループを作成しました。したがって、最初の反復では、ランクは1になります。2番目、2になります。これは、ランクが使用している列番号よりも少なくなるまで発生します。

非常に簡単です:

for (i in 1:47) {

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

for()ループの詳細

  1. i番目の列のランクを計算します
  2. 反復数を出力します
  3. 参照用に列名を出力します
  4. コンソールを「###」で区切って、簡単にスクロールできるようにします

ifステートメントを追加できると確信しています。50の列のみを扱っているため、まだ必要ありません。

お役に立てれば!


2
理論的にはこれには何の問題もありませんが、数値的に不安定で非効率的なアルゴリズムです。特に、多数の列がある場合、ほぼ共線性を検出できず、存在しない場合に共線性を誤って検出する可能性があります。
whuber

2

ランク、行列のr =行列の線形独立列(または行)の数。以下のためにNによってN行列Aランク(A)= N =>すべての列(または行)線形独立です。


2

@Whuberが与えた答えを実際に拡張する必要はありませんが、数学の簡単な説明を提供すると思いました。

線形結合の場合 バツバツv=0 ために v0 それから v はの固有ベクトルです バツバツ 固有値に関連付けられています λ=0。の固有ベクトルと固有値バツバツ are also the eigenvectors and eigenvalues of X, so the eigenvectors of XX associated with eigenvalues near λ=0 represent the coefficients for approximate linear relationships among the regressors. Principal Component Analysis outputs the eigenvectors and eigenvalues of XX, so you can use the eigenvectors v associated with small λ to determine if linear relationships exist among some of your regressors.

One method of determining if an eigenvalue is appropriately small to constitute collinearity is to use the Condition Indices:

κj=λmaxλj
which measures the size of the smallest eigenvalues relative to the largest. A general rule of thumb is that modest multicollinearity is associated with a condition index between 100 and 1,000 while severe multicollinearity is associated with a condition index above 1,000 (Montgomery, 2009).

It's important to use an appropriate method for determining if an eigenvalue is small because it's not the absolute size of the eigenvalues, it's the relative size of the condition index that's important, as can be seen in an example. Consider the matrix

XX=[0.0010000.0010000.001].
The eigenvalues for this matrix are λ1=λ2=λ3=0.001. Although these eigenvalues appear small the condition index is
κ=λmaxλmin=1
indicating absence of multicolinearity and , in fact, the columns of this matrix are linearly independent.

Citations

Montgomery, D. (2012). Introduction to Linear Regression Analysis, 5th Edition. John Wiley & Sons Inc.


1
Use of the condition indices is a good idea (+1). I would like only to point out two things. First, it would be more numerically stable and more directly relevant to compute their reciprocals: divide each eigenvalue by the largest of them all and see how close to zero it is. Second (referring to your initial discussion), unless X is square, it cannot have eigenvalues or eigenvectors: the concept makes no sense for non-square matrices.
whuber

Why dont you perform a QR-Decomposition of X (which may be n by k, n>>k)? Any rank deficiencies of X are also in R on which you could perform the aforementioned eigenvalue-decomposition to detect linear dependent columns (which are easy identified even under pivoting) - this is the reference: page 179 of Wood Generalized Additive Models an Introduction with R.
Druss2k
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.