Тестування на лінійну залежність серед стовпців матриці


26

У мене є кореляційна матриця повернень безпеки, детермінант якої дорівнює нулю. (Це трохи дивно, оскільки матриця кореляції вибірки та відповідна коваріаційна матриця теоретично повинні бути певними.)

Моя гіпотеза полягає в тому, що принаймні один цінний папір лінійно залежить від інших цінних паперів. Чи є в R функція, яка послідовно перевіряє кожен стовпчик матрицею на лінійну залежність?

Наприклад, одним із підходів було б побудувати кореляційну матрицю по одному захисту за один раз та обчислити визначник на кожному кроці. Коли визначник = 0, тоді зупиніть, як ви визначили цінні папери, хто є лінійною комбінацією інших цінних паперів.

Будь-які інші методи ідентифікації лінійної залежності в такій матриці оцінені.


Ваша матриця є позитивною напіввизначеною, хоча не позитивно визначеною, бо вона є сингулярною.
ttnphns

Які розміри (без змінних; немає зразків)?
Карл

Кількість стовпців = 480. # рядків для кожного часового ряду = 502. Взагалі ви вважаєте, що чим більший часовий ряд матриця коваріації вибірки має тенденцію бути певною. Однак є багато випадків, коли ви хочете використовувати значно меншу величину T (або експоненціально вагу) для відображення останніх ринкових умов.
Рам Ахлувалія

3
Питання невдале. Якщо ваша матриця даних становить 480 на 502, то кажучи, що матриця має ранг (простір стовпця матриці має розмірність q < 480 ), математично еквівалентно тому, що деякі стовпці є лінійною комбінацією інших, але ви можете не виберіть один стовпчик і скажіть, що це стовпець, який є лінійно залежним. Отже, для цього немає жодної процедури, і запропонована процедура вибере досить довільну безпеку залежно від порядку, до якого вони включені. q<480q<480
NRH

Коваріаційна матриця симетрична. Він генерується за допомогою транспозиції (A) * A. Матриця A має розміри 480x502. Однак матриця коваріації становить 480х480
Рам Ахлувалія

Відповіді:


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.

Роздруківки M за 5 ітерацій:

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 пов'язаний з V2 і V4 з коефіцієнтами -3333 та .8333: 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 була проблемою (здається очевидною з заднім числом, оскільки це стовпець нулів!)
Метт Веллер

У коментарі Джеймса він розмістив сценарій: rankifremoved <- sapply (1: ncol (your.matrix), функція (x) qr (your.matrix [, - x]) $ rank), який (rankifremoved == max ( rankifremoved)) Я робив тест на матрицю, я хотів би знати на виході R. Колонки виведення лінійно залежні? Спасибі!

@ EltonAraújo: Вихід буде вектором, що дає показники лінійно залежних стовпців: так (2,4,5) для прикладу у відповіді ttnphns. Але мені цікаво, як питання чисельної точності будуть впливати на цей метод.
Scortchi

rankifremoved містить усі стовпці, лінійно залежні між ними або між ними. У якомусь додатку ми можемо захотіти зберегти стовпчик або кілька стовпців і не скидати всіх
MasterJedi

Чи не повинно це повернути порожній набір your.matrix = matrix(1:4, 2)?
Холгер Брандл

15

Питання задає питання про "визначення основних [лінійних] зв'язків" серед змінних.

Швидкий і простий шлях до цього виявити взаємозв'язки - це регресувати будь-яку іншу змінну (використовувати постійну, рівну) проти цих змінних за допомогою улюбленого програмного забезпечення: будь-яка хороша процедура регресії виявить і діагностує колінеарність. (Ви навіть не потрудитесь переглянути результати регресії: ми просто покладаємось на корисний побічний ефект налаштування та аналізу матриці регресії.)

Припускаючи, що виявлена ​​колінеарність, що далі? Аналіз основних компонентів (PCA) - саме те, що потрібно: найменші його компоненти відповідають майже лінійним співвідношенням. Ці відносини можна прочитати безпосередньо з "навантажень", які є лінійними комбінаціями вихідних змінних. Невеликі навантаження (тобто пов'язані з малими власними значеннями) відповідають майже колінеарним. Власне значення 0 відповідатиме ідеальним лінійним відношенням. Трохи більші власні значення, які все ще набагато менші за найбільші, відповідали б приблизним лінійним співвідношенням.

(Існує мистецтво та досить багато літератури, пов’язаної з визначенням того, що таке "невелике" завантаження. Для моделювання залежної змінної я б запропонував включити її до складу незалежних змінних у PCA, щоб визначити компоненти - незалежно від їх розміри - у яких залежна змінна грає важливу роль. З цієї точки зору "малий" означає набагато менший, ніж будь-який такий компонент.)


Давайте розглянемо кілька прикладів. (Вони використовуються 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))
}

Застосуємо це до деяких випадкових даних. Вони засновані на чотирьох змінних (The і Е може бути і мови). Ось невелика функція для обчислення AB,C,D,EA як заданої лінійної комбінації інших. Потім він додає iid Нормально розподілених значень до всіх п'яти змінних (щоб побачити, наскільки добре працює процедура, коли мультиколінеарність лише приблизна і не точна).

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

Ми готові йти: залишається лише генерувати і застосовувати ці процедури. Я використовую два сценарії, описані у запитанні: A = B + C + D + E (плюс деяка помилка у кожному) та A = B + ( C + D ) / 2 + E (плюс деяка помилка у кожному). Спершу, однак, зауважте, що PCA майже завжди застосовується до центрированних даних, тому ці імітовані дані центрируються (але не інакше змінюються масштаби) за допомогою .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

Результати

Вихід, пов'язаний з лівою верхньою панеллю, був

       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

На практиці часто не так, що одна змінна виділяється як очевидна комбінація інших: всі коефіцієнти можуть бути порівнянних розмірів і різними ознаками. Більше того, коли відносин більше, ніж один вимір, не існує єдиного способу їх визначення: необхідний подальший аналіз (наприклад, зменшення рядків), щоб визначити корисну основу для цих відносин. Ось так працює світ: щоб впоратися з цим, деякі люди використовують найбільші ("головні") компоненти безпосередньо як незалежні змінні в регресії чи подальшому аналізі, в якій би формі вона не приймалася. Якщо ви це зробите, не забудьте спочатку вийняти залежну змінну з набору змінних і повторити 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")

(Мені довелося зіткнутися з порогом у випадках великих помилок, щоб відобразити лише один компонент: це причина для подання цього значення в якості параметра process.)


Користувач ttnphns люб’язно скеровував нашу увагу на тісно пов'язану нитку. Одна з його відповідей (Дж. М.) пропонує підхід, описаний тут.


Нічого собі, ось що я розумію з вашої відповіді ... поверніть свої змінні проти будь-якої іншої змінної. Використовуйте VIF, щоб потім змінні пов’язані з ідентифікатором. Це працює. Чи найкраще це робити з фрагментами даних одночасно? Ви також видаляєте що-небудь, якщо виявляєте колінеарність за допомогою попередньої регресії? градусів з використанням оригінальних змінних. Я не впевнений, які невеликі вантажі та з чим вони співпадають
Самуїл

Ця відповідь пояснює, як інтерпретувати дрібні компоненти: вони виявляють колінеарності. Так, ви можете використовувати підгрупи змінних, якщо вам подобається. Метод регресії - це просто виявити наявність колінеарності, а не ідентифікувати колінеарні відносини: саме це і робить PCA.
whuber

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

Також, я можу попросити вас залишити свою думку щодо можливого використання операції розгортки ( stats.stackexchange.com/a/16391/3277 ) у завданні відстеження лінійно залежних наборів змінних?
ttnphns

XX=UWVVprincompXV=UWWUW0XVX


3

Я зіткнувся з цим питанням приблизно два тижні тому і вирішив, що мені потрібно його переглянути, тому що, маючи справу з масовими наборами даних, неможливо робити ці речі вручну.

Я створив цикл for (), який обчислює ранг матриці по одному стовпчику. Отже, для першої ітерації ранг буде 1. Другий, 2. Це відбувається, поки ранг не стане меншим, ніж номер стовпця, який ви використовуєте.

Дуже прямо:

for (i in 1:47) {

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

для () розбиття циклу

  1. обчислює ранг для i-ї колонки
  2. друкує номер ітерації
  3. друкує ім'я стовпця для довідки
  4. ділить консоль на "###", щоб ви могли легко прокручувати

Я впевнений, що ви можете додати оператор if, мені це ще не потрібно, тому що я маю справу лише з 50ish стовпцями.

Сподіваюся, це допомагає!


2
Хоча теоретично в цьому немає нічого поганого, це чисельно нестабільний і неефективний алгоритм. Особливо при великій кількості стовпців він не може виявити майже колінеарність та помилково виявити колінеарність там, де її немає.
whuber

2

Ранг, r матриці = кількість лінійно незалежних стовпців (або рядків) матриці. Для п по п матриці А , ранг (А) = п => всі стовпці (або рядка) лінійно незалежні.


2

Не те, що відповідь @Whuber дали дійсно потрібно розширити, але я подумав, що я надам короткий опис математики.

Якщо лінійна комбінація Х'Хv=0 для v0 потім v є власним вектором Х'Х пов'язані з власним значенням λ=0. Власні вектори та власні значення РосіїХ'Х також є власними векторами та власними значеннями Х, отже, власних векторів Х'Х пов'язані з власними значеннями поблизу λ=0представляють коефіцієнти для приблизних лінійних співвідношень між регресорами. Основний компонентний аналіз виводить власні вектори та власні значенняХ'Х, тож ви можете використовувати власні вектори v пов'язані з малим λ щоб визначити, чи існують лінійні зв’язки серед деяких ваших регресорів.

Одним із методів визначення, чи є власне значення належним чином малим для створення колінеарності, є використання показників стану:

κj=λмахλj
яка вимірює розмір найменших власних значень відносно найбільшого. Загальне правило полягає в тому, що скромна мультиколінеарність пов'язана з індексом стану від 100 до 1000, тоді як сувора мультиколінеарність пов'язана з індексом стану вище 1000 (Montgomery, 2009).

Важливо використовувати відповідний метод визначення того, чи є власне значення мало, оскільки це не абсолютний розмір власних значень, а важливий відносний розмір індексу умови, як це видно на прикладі. Розглянемо матрицю

Х'Х=[0,0010000,0010000,001].
Власні значення цієї матриці є λ1=λ2=λ3=0,001. Хоча ці власні значення здаються невеликими, індекс умови є
κ=λмахλмiн=1
що вказує на відсутність мультиколінності і, власне, стовпці цієї матриці лінійно незалежні.

Цитати

Монтгомері, Д. (2012). Вступ до лінійного регресійного аналізу, 5-е видання. 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.