Test per la dipendenza lineare tra le colonne di una matrice


26

Ho una matrice di correlazione dei ritorni di sicurezza il cui determinante è zero. (Questo è un po 'sorprendente poiché la matrice di correlazione del campione e la matrice di covarianza corrispondente dovrebbero teoricamente essere definite positive.)

La mia ipotesi è che almeno un titolo dipenda linearmente da altri titoli. Esiste una funzione in R che testa sequenzialmente ogni colonna una matrice per la dipendenza lineare?

Ad esempio, un approccio sarebbe quello di costruire una matrice di correlazione una sicurezza alla volta e calcolare il determinante in ogni fase. Quando il determinante = 0, si interrompe poiché è stato identificato il titolo che è una combinazione lineare di altri titoli.

Qualsiasi altra tecnica per identificare la dipendenza lineare in tale matrice è apprezzata.


La tua matrice è semi-definita positiva, ma non è definita positiva, poiché è singolare.
ttnphns,

Quali sono le dimensioni (n. Variabili; n. Campioni)?
Karl,

Numero di colonne = 480. Numero di righe per ogni serie temporale = 502. In generale, si trova che maggiore è la serie temporale la matrice di covarianza del campione tende ad essere definita positiva. Tuttavia, ci sono molti casi in cui si desidera utilizzare un valore sostanzialmente inferiore di T (o peso esponenziale) per riflettere le recenti condizioni di mercato.
Ram Ahluwalia,

3
La domanda è sbagliata. Se la tua matrice di dati è 480 per 502, dire che la matrice ha rango (lo spazio della colonna della matrice ha dimensione ) equivale matematicamente a dire che una colonna è una combinazione lineare delle altre, ma puoi scegli una colonna e dire che questa è la colonna che è linearmente dipendente. Quindi non esiste una procedura per farlo e la procedura suggerita sceglierà una sicurezza abbastanza arbitraria a seconda dell'ordine in cui sono inclusi. q < 480q<480q<480
NRH

La matrice di covarianza è simmetrica. Viene generato da transpose (A) * A. La matrice A ha dimensioni 480x502. Tuttavia, la matrice di covarianza è 480x480
Ram Ahluwalia,

Risposte:


6

Sembri porre una domanda davvero stimolante: come rilevare, data una singolare matrice di correlazione (o covarianza, o somma di quadrati e prodotto incrociato), quale colonna dipende linearmente da quale. Suppongo provvisoriamente che l' operazione di sweep possa aiutare. Ecco la mia sonda in SPSS (non R) per illustrare.

Generiamo alcuni dati:

        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

Creiamo una dipendenza lineare tra V2, V4 e V5:

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

Quindi, abbiamo modificato la nostra colonna 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.

Le stampe di M in 5 iterazioni:

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

Si noti che alla fine la colonna 5 si è riempita di zeri. Questo significa (come ho capito) che V5 è linearmente legato con alcune delle colonne precedenti . Quali colonne? Guarda l'iterazione dove l'ultima colonna 5 non è piena di zero - iterazione 4. Vediamo lì che V5 è legato con V2 e V4 con coefficienti -.3333 e .8333: V5 = -.3333 * V2 + .8333 * V4, che corrisponde a ciò che abbiamo fatto con i dati: V4 = .4 * V2 + 1.2 * V5.

È così che sapevamo quale colonna è linearmente legata a quale altra. Non ho verificato quanto sia utile l'approccio di cui sopra in casi più generali con molti gruppi di interdipendenze nei dati. Nell'esempio sopra è sembrato utile, comunque.


Non è questa la forma di scaglione ridotto? In tal caso, non ci sono pacchetti / funzioni disponibili in R?
Arun,

@Arun, non sono un utente R, quindi non posso saperlo.
ttnphns,

25

Ecco un approccio semplice: calcolare il rango della matrice risultante dalla rimozione di ciascuna delle colonne. Le colonne che, una volta rimosse, danno il rango più alto sono quelle linearmente dipendenti (poiché rimuoverle non diminuisce il rango, mentre rimuove una colonna linearmente indipendente).

In R:

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

1
Risposta estremamente utile nel determinare la colonna offensiva in una matrice di regressione in cui ho ricevuto l'errore system is exactly singular: U[5,5] = 0 , che ora so significa che la colonna 5 era il problema (sembra ovvio con il senno di poi in quanto è una colonna di zeri!)
Matt Weller

Nel commento di James, ha pubblicato la sceneggiatura: rankifremoved <- sapply (1: ncol (your.matrix), function (x) qr (your.matrix [, - x]) $ rank) che (rankifremoved == max ( rankifremoved)) Ho fatto un test su una matrice, vorrei sapere sull'output di R. Le colonne dell'output sono linearmente dipendenti? Grazie!

@ EltonAraújo: l'output sarà un vettore che fornisce gli indici delle colonne linearmente dipendenti: quindi (2,4,5) per l'esempio nella risposta di ttnphns. Ma mi chiedo come i problemi di precisione numerica influenzeranno questo metodo.
Scortchi - Ripristina Monica

rankifremoved contiene tutte le colonne che sono linearmente dipendenti tra loro o tra di loro. In alcune applicazioni, potremmo voler mantenere una colonna o alcune colonne e non lasciarle tutte
MasterJedi

Questo non dovrebbe restituire un set vuoto per your.matrix = matrix(1:4, 2)?
Holger Brandl,

15

La domanda è "identificare le relazioni [lineari] sottostanti" tra le variabili.

Il modo rapido e semplice per rilevare le relazioni è regredire qualsiasi altra variabile (usare una costante, anche) rispetto a quelle variabili usando il tuo software preferito: qualsiasi buona procedura di regressione rileverà e diagnosticherà la collinearità. (Non ti preoccuperai nemmeno di guardare i risultati della regressione: stiamo solo facendo affidamento su un utile effetto collaterale di impostare e analizzare la matrice di regressione.)

Supponendo che venga rilevata la collinearità, tuttavia, quale sarà il prossimo? L'analisi dei componenti principali (PCA) è esattamente ciò che è necessario: i suoi componenti più piccoli corrispondono a relazioni quasi lineari. Queste relazioni possono essere lette direttamente dai "caricamenti", che sono combinazioni lineari delle variabili originali. I piccoli carichi (cioè quelli associati a piccoli autovalori) corrispondono a quasi collinearità. Un autovalore di corrisponderebbe a una relazione lineare perfetta. Autovalori leggermente più grandi che sono ancora molto più piccoli del più grande corrisponderebbero a relazioni lineari approssimative.0

(C'è un'arte e molta letteratura associata all'identificazione di cosa sia un "piccolo" caricamento. Per modellare una variabile dipendente, suggerirei di includerla all'interno delle variabili indipendenti nel PCA al fine di identificare i componenti, indipendentemente da le loro dimensioni - in cui la variabile dipendente svolge un ruolo importante. Da questo punto di vista, "piccolo" significa molto più piccolo di qualsiasi componente del genere.)


Diamo un'occhiata ad alcuni esempi. (Utilizzati Rper i calcoli e la stampa.) Inizia con una funzione per eseguire PCA, cercare piccoli componenti, tracciarli e restituire le relazioni lineari tra loro.

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

Appliciamo questo ad alcuni dati casuali. Questi sono costruiti su quattro variabili (la ed E della domanda). Ecco una piccola funzione per calcolare A come una data combinazione lineare delle altre. Aggiunge quindi i valori normalmente distribuiti a tutte e cinque le variabili (per vedere quanto bene la procedura esegue quando la multicollinearità è solo approssimativa e non esatta).B,C,D,EA

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

Siamo pronti a partire: resta solo da generare e applicare queste procedure. Uso i due scenari descritti nella domanda: A = B + C + D + E (più alcuni errori in ciascuno) e A = B + ( C + D ) / 2 + E (più alcuni errori in ciascuno). In primo luogo, tuttavia, si noti che la PCA viene quasi sempre applicata ai dati centrati , quindi questi dati simulati vengono centrati (ma non altrimenti riscalati) utilizzando .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

risultati

L'output associato al pannello in alto a sinistra era

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

00ABCDE

L'output per il pannello centrale superiore era

       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

In pratica, spesso non è possibile individuare una variabile come una combinazione ovvia delle altre: tutti i coefficienti possono avere dimensioni comparabili e segni diversi. Inoltre, quando esiste più di una dimensione delle relazioni, non esiste un modo unico per specificarle: sono necessarie ulteriori analisi (come la riduzione delle righe) per identificare una base utile per tali relazioni. È così che funziona il mondo: tutto ciò che puoi dire è che queste combinazioni particolari che sono prodotte da PCA corrispondono a quasi nessuna variazione nei dati. Per far fronte a questo, alcune persone usano i componenti più grandi ("principali") direttamente come variabili indipendenti nella regressione o nell'analisi successiva, qualunque sia la forma che potrebbe assumere. Se lo fai, non dimenticare prima di rimuovere la variabile dipendente dall'insieme di variabili e ripetere il PCA!


Ecco il codice per riprodurre questa 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")

(Ho dovuto armeggiare con la soglia nei casi di errore di grandi dimensioni per visualizzare solo un singolo componente: questa è la ragione per fornire questo valore come parametro a process.)


L'utente ttnphns ha gentilmente indirizzato la nostra attenzione su un thread strettamente correlato. Una delle sue risposte (di JM) suggerisce l'approccio descritto qui.


Caspita, ecco quello che ho capito dalla tua risposta ... ripassa le mie variabili rispetto a qualsiasi altra variabile. Utilizzare il VIF per quindi identificare le variabili correlate ... funziona. È meglio farlo con pezzi di dati alla volta? Rimuovete anche qualsiasi cosa se rilevate la colinearità usando la regressione precedente? gradi usando le variabili originali. Non sono sicuro di quali piccoli carichi e di cosa siano vicini
Samuel,

Questa risposta spiega come interpretare i piccoli componenti: esibiscono le collinearità. Sì, puoi usare sottogruppi di variabili se vuoi. Il metodo di regressione è solo quello di rilevare la presenza di collinearità, non di identificare le relazioni collineari: ecco cosa fa il PCA.
whuber

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

Inoltre, posso chiederti di lasciare la tua opinione sul possibile utilizzo dell'operazione sweep ( stats.stackexchange.com/a/16391/3277 ) nel compito di rintracciare sottoinsiemi di variabili linearmente dipendenti?
ttnphns,

XX=UWVVprincompXV=UWWUW0XVX


3

Ho riscontrato questo problema circa due settimane fa e ho deciso che dovevo rivisitarlo perché quando si gestiscono enormi set di dati, è impossibile eseguire queste operazioni manualmente.

Ho creato un ciclo for () che calcola il grado della matrice una colonna alla volta. Quindi, per la prima iterazione, il rango sarà 1. Il secondo, 2. Ciò si verifica fino a quando il rango diventa MENO del numero di colonna che si sta utilizzando.

Molto semplice:

for (i in 1:47) {

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

per () interruzione del ciclo

  1. calcola il grado per la colonna
  2. stampa il numero di iterazione
  3. stampa il nome della colonna come riferimento
  4. divide la console con "###" in modo da poter scorrere facilmente

Sono sicuro che puoi aggiungere un'istruzione if, non ne ho ancora bisogno perché ho a che fare solo con colonne 50ish.

Spero che sia di aiuto!


2
Sebbene teoricamente non ci sia nulla di sbagliato, si tratta di un algoritmo numericamente instabile e inefficiente. Soprattutto con un gran numero di colonne non può rilevare la quasi collinearità e rilevare falsamente la collinearità laddove non esiste.
whuber

2

Rango, r di una matrice = numero di colonne (o righe) linearmente indipendenti di una matrice. Per una matrice A per n , il rango (A) = n => tutte le colonne (o righe) sono linearmente indipendenti.


2

Non che la risposta fornita da @Whuber debba davvero essere ampliata, ma ho pensato di fornire una breve descrizione della matematica.

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

κj=λmaxλj

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

citazioni

Montgomery, D. (2012). Introduzione all'analisi di regressione lineare, 5a edizione. John Wiley & Sons Inc.


1
X

QRXnKn>>KXR
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.