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.

Ram Ahluwalia
fonte
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.

ttnphns
fonte
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))
James
fonte
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.

whuber
fonte
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
5

502×480

JM não é estatístico
fonte
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!

Nick P
fonte
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.

Uma corrida
fonte
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

tjnel
fonte
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