Teste de dependência linear entre as colunas de uma matriz


26

Eu tenho uma matriz de correlação de retornos de segurança cujo determinante é zero. (Isso é um pouco surpreendente, pois a matriz de correlação da amostra e a matriz de covariância correspondente devem teoricamente ser definidas positivamente.)

Minha hipótese é que pelo menos um título seja linearmente dependente de outros títulos. Existe uma função em R que testa sequencialmente cada coluna uma matriz para dependência linear?

Por exemplo, uma abordagem seria construir uma matriz de correlação, uma segurança de cada vez, e calcular o determinante em cada etapa. Quando o determinante = 0, pare, pois você identificou o título que é uma combinação linear de outros títulos.

Quaisquer outras técnicas para identificar dependência linear em uma matriz são apreciadas.


Sua matriz é semi-definida positiva, porém não é definitiva, pois é singular.
precisa saber é o seguinte

Quais são as dimensões (sem variáveis; sem amostras)?
Karl

Número de colunas = 480. # de linhas para cada série temporal = 502. Em geral, você descobre que quanto maior a série temporal, a matriz de covariância da amostra tende a ser positiva definida. No entanto, há muitos casos em que você deseja usar um valor substancialmente menor de T (ou peso exponencial) para refletir as condições recentes do mercado.
Ram Ahluwalia

3
A questão é mal colocada. Se sua matriz de dados é de 480 por 502, dizer que a matriz tem classificação (o espaço da coluna da dimensão da dimensão ) é matematicamente equivalente a dizer que alguma coluna é uma combinação linear das outras, mas você pode escolha uma coluna e diga que essa é a coluna que é linearmente dependente. Portanto, não há procedimento para fazer isso, e o procedimento sugerido escolherá uma segurança bastante arbitrária, dependendo da ordem em que forem incluídos. q<480q<480
NRH 01/10

A matriz de covariância é simétrica. É gerado pela transposição (A) * A. A matriz A possui dimensões 480x502. No entanto, a matriz de covariância é 480x480
Ram Ahluwalia

Respostas:


6

Você parece fazer uma pergunta realmente provocadora: como detectar, dada uma matriz de correlação (ou covariância ou soma de quadrados e produtos cruzados) singular, qual coluna é linearmente dependente de qual. Suponho que a operação de varredura possa ajudar. Aqui está minha sonda no SPSS (não R) para ilustrar.

Vamos gerar alguns dados:

        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

Vamos criar alguma dependência linear entre V2, V4 e V5:

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

Então, modificamos nossa coluna 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.

As impressões de M em 5 iterações:

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

Observe que, eventualmente, a coluna 5 ficou cheia de zeros. Isso significa (como eu o entendo) que o V5 está linearmente vinculado a algumas colunas anteriores . Quais colunas? Veja a iteração em que a coluna 5 não está cheia de zeros - iteração 4. Vemos lá que V5 está vinculado a V2 e V4 com os coeficientes -.3333 e .8333: V5 = -.3333 * V2 + .8333 * V4, o que corresponde ao que fizemos com os dados: V4 = 0,4 * V2 + 1,2 * V5.

Foi assim que soubemos qual coluna está linearmente ligada a qual outra. Não verifiquei quão útil é a abordagem acima em casos mais gerais com muitos grupos de interdependências nos dados. No exemplo acima, parecia útil, no entanto.


Não é este o formato de escalão de linha reduzida? Se sim, não existem pacotes / funções disponíveis no R?
Arun #

@Arun, eu não sou usuário R, então não posso saber.
ttnphns

25

Aqui está uma abordagem direta: calcule a classificação da matriz resultante da remoção de cada uma das colunas. As colunas que, quando removidas, resultam na classificação mais alta são as linearmente dependentes (uma vez que removê-las não diminui a classificação, enquanto a remoção de uma coluna linearmente independente o faz).

Em R:

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

11
Resposta extremamente útil para determinar a coluna ofender em uma matriz de regressão onde recebi o erro system is exactly singular: U[5,5] = 0 , o que eu sei agora meios coluna 5 foi a questão (parece óbvio em retrospectiva, como é uma coluna de zeros!)
Matt Weller

No comentário de James, ele postou o script: rankifremoved <- sapply (1: ncol (your.matrix), function (x) qr (your.matrix [, - x]) $ rank) what (rankifremoved == max ( rankifremoved)) Eu fiz um teste em uma matriz, gostaria de saber sobre a saída de R. As colunas da saída são linearmente dependentes? Obrigado!

@ EltonAraújo: A saída será um vetor que fornece os índices das colunas linearmente dependentes: so (2,4,5), por exemplo, na resposta de ttnphns. Mas eu me pergunto como questões de precisão numérica afetarão esse método.
Scortchi - Restabelece Monica

O rankifremoved contém todas as colunas que são linearmente dependentes entre elas ou entre elas. Em algumas aplicações, a gente pode querer manter uma coluna ou uma coluna de poucos e não deixar cair tudo
MasterJedi

Isso não deveria retornar um conjunto vazio para your.matrix = matrix(1:4, 2)?
precisa

15

A pergunta é sobre "identificar relações [lineares" subjacentes "entre variáveis.

A maneira rápida e fácil de detectar relacionamentos é regredir qualquer outra variável (use uma constante, par) contra essas variáveis ​​usando o seu software favorito: qualquer bom procedimento de regressão irá detectar e diagnosticar colinearidade. (Você nem se preocupará em olhar para os resultados da regressão: estamos apenas contando com um efeito colateral útil para configurar e analisar a matriz de regressão.)

Supondo que a colinearidade seja detectada, o que vem a seguir? A Análise de Componentes Principais (PCA) é exatamente o que é necessário: seus menores componentes correspondem a relações quase lineares. Essas relações podem ser lidas diretamente das "cargas", que são combinações lineares das variáveis ​​originais. Carregamentos pequenos (ou seja, aqueles associados a pequenos autovalores) correspondem a quase colinearidades. Um valor próprio de corresponderia a uma relação linear perfeita. Valores próprios ligeiramente maiores que ainda são muito menores que os maiores corresponderiam a relações lineares aproximadas.0

(Existe uma arte e bastante literatura associada à identificação do que é um carregamento "pequeno". Para modelar uma variável dependente, sugiro incluí-lo nas variáveis ​​independentes no PCA para identificar os componentes - independentemente de seus tamanhos - nos quais a variável dependente desempenha um papel importante. Desse ponto de vista, "pequeno" significa muito menor que qualquer componente desse tipo.)


Vejamos alguns exemplos. (Eles são usados Rpara cálculos e plotagem.) Comece com uma função para executar o PCA, procure por pequenos componentes, plote-os e retorne as relações lineares entre eles.

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))
}

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

Resultados

A saída associada ao painel superior esquerdo foi

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

00ABCDE

A saída para o painel do meio superior foi

       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

Na prática, muitas vezes não é o caso de uma variável ser apontada como uma combinação óbvia das outras: todos os coeficientes podem ter tamanhos comparáveis ​​e sinais variados. Além disso, quando há mais de uma dimensão de relações, não há uma maneira única de especificá-las: análises adicionais (como redução de linha) são necessárias para identificar uma base útil para essas relações. É assim que o mundo funciona: tudo o que você pode dizer é que essas combinações específicas produzidas pelo PCA correspondem a quase nenhuma variação nos dados. Para lidar com isso, algumas pessoas usam os componentes maiores ("principais") diretamente como variáveis ​​independentes na regressão ou na análise subsequente, qualquer que seja a forma que possa assumir. Se você fizer isso, não esqueça primeiro de remover a variável dependente do conjunto de variáveis ​​e refazer o PCA!


Aqui está o código para reproduzir esta figura:

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")

(Eu tive que mexer com o limite nos casos de erro grande para exibir apenas um único componente: essa é a razão para fornecer esse valor como parâmetro process.)


O usuário ttnphns direcionou nossa atenção para um tópico relacionado. Uma de suas respostas (por JM) sugere a abordagem descrita aqui.


Uau, aqui está o que eu entendo da sua resposta .. regredir minhas variáveis ​​contra qualquer outra variável. Use o VIF para, então, relacionar variáveis ​​relacionadas ... isso funciona. É melhor fazer isso com pedaços de dados de cada vez? Além disso, você remove qualquer coisa se detectar colinearidade usando a regressão anterior? .. Pelo que entendi sobre o PCA geralmente é que você usa os maiores PCs (explicando a maior variação) com base nos autovalores, já que eles explicam a maior variação, estes são carregados para variar graus usando as variáveis ​​originais. Im inseguro quanto ao que pequenas cargas e que eles são colinear com
Samuel

Esta resposta explica como interpretar os pequenos componentes: eles exibem as colinearidades. Sim, você pode usar subgrupos de variáveis, se quiser. O método de regressão é apenas para detectar a presença de colinearidade, não para identificar as relações colineares: é isso que o PCA faz.
whuber

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

Além disso, posso pedir que você deixe sua opinião sobre o possível uso da operação de varredura ( stats.stackexchange.com/a/16391/3277 ) na tarefa de rastrear subconjuntos de variáveis ​​linearmente dependentes?
ttnphns

XX=UWVVprincompXV=UWWUW0XVX


3

Eu me deparei com esse problema há cerca de duas semanas e decidi que precisava revisitá-lo porque, ao lidar com conjuntos de dados massivos, é impossível fazer essas coisas manualmente.

Criei um loop for () que calcula a classificação da matriz uma coluna por vez. Portanto, para a primeira iteração, a classificação será 1. A segunda, 2. Isso ocorre até que a classificação se torne MENOS que o número da coluna que você está usando.

Muito simples:

for (i in 1:47) {

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

quebra do loop for ()

  1. calcula a classificação para a i-ésima coluna
  2. imprime o número da iteração
  3. imprime o nome da coluna para referência
  4. divide o console com "###" para que você possa rolar facilmente

Tenho certeza de que você pode adicionar uma instrução if, não preciso ainda porque estou lidando apenas com colunas 50ish.

Espero que isto ajude!


2
Embora não haja nada de errado nisso, teoricamente, é um algoritmo numericamente instável e ineficiente. Especialmente com um grande número de colunas, ele pode falhar em detectar quase colinearidade e falsamente detectar colinearidade onde não existe.
whuber

2

Rank, r de uma matriz = número de colunas (ou linhas) linearmente independentes de uma matriz. Para uma matriz n por n A , a classificação (A) = n => todas as colunas (ou linhas) são linearmente independentes.


2

Não que a resposta que o @Whuber deu realmente precise ser expandida, mas pensei em fornecer uma breve descrição da matemática.

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

κj=λmaxλj

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

Citações

Montgomery, D. (2012). Introdução à Análise de Regressão Linear, 5ª Edição. John Wiley & Sons Inc. Empresas


11
O uso dos índices de condição é uma boa ideia (+1). Gostaria apenas de apontar duas coisas. Primeiro, seria mais numericamente estável e mais diretamente relevante para calcular seus recíprocos: divida cada valor próprio pelo maior de todos e veja quão próximo de zero é. Segundo (referindo-se à sua discussão inicial), a menos queXé quadrado, não pode ter autovalores ou autovetores: o conceito não faz sentido para matrizes não quadradas.
whuber

Por que você não realiza uma QR-Decomposição de X (que pode ser n de k, n>>k)? Quaisquer deficiências de classificação deX também estão em Rem que você pode executar a decomposição de autovalor acima mencionada para detectar colunas dependentes lineares (que são facilmente identificadas mesmo com rotação) - esta é a referência: página 179 de Modelos aditivos generalizados para madeira uma introdução a R.
Druss2k
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.