Чи XGBoost самостійно обробляє мультиколінеарність?


23

В даний час я використовую XGBoost для набору даних з 21 функцією (вибрано зі списку з приблизно 150 функцій), потім однокольоровим кодуванням їх, щоб отримати ~ 98 функцій. Деякі з цих 98 особливостей є дещо зайвими, наприклад: змінна (функція) також з'являється як і .АБАСА

Мої запитання:

  • Як ( якщо? ) Дерева з посиленими рішеннями поводяться з мультиколінеарністю?
  • Як би існування мультіколінеарності впливало на прогнозування, якщо його не обробляти?

З того, що я розумію, модель вивчає більше одного дерева, і остаточне прогнозування базується на чомусь на зразок "зваженої суми" окремих прогнозів. Отже, якщо це правильно, тоді прискорені дерева рішень повинні мати можливість взаємодіяти між змінними.

Також у відповідній примітці - як працює об'єкт змінної важливості у XGBoost?


Я розумію, що дерева можуть впоратися з мультиколінеарністю. А як щодо XGBoost на основі регресії? Чи може він також впоратися з мультиколінеарністю? > Дерева рішень від природи несприйнятливі до мультиколінеарності. Наприклад, якщо у вас є дві функції, які на 99% співвідносяться, то при вирішенні розщеплення дерево вибере лише одну з них. Інші> моделі, такі як регрес логістики, використовуватимуть обидві функції. >> Оскільки прискорені дерева використовують окремі дерева рішень, їх також не впливає мультиколінеарність. Однак є хорошою практикою> видалити зайві функції з будь-якого набору даних, використовуваних для траєкторії
Jay Saxena

Відповіді:


27

Дерева рішень від природи несприйнятливі до мультиколінеарності. Наприклад, якщо у вас є дві особливості, які на 99% співвідносяться, то при вирішенні розщеплення дерево вибере лише одну з них. Інші моделі, такі як логістична регресія, будуть використовувати обидві функції.

Оскільки підсилені дерева використовують окремі дерева рішень, їх також не впливає мультиколінеарність. Однак є гарною практикою видаляти зайві функції з будь-якого набору даних, що використовуються для навчання, незалежно від алгоритму моделі. У вашому випадку, оскільки ви отримуєте нові функції, ви можете використовувати цей підхід, оцінити важливість кожної функції та зберегти лише найкращі функції для остаточної моделі.

Матриця важливості моделі xgboost - це фактично об'єкт даних, у якому в першому стовпці перелічені назви всіх функцій, які фактично використовуються у завантажених деревах. Другий стовпець - це показник Gain, який передбачає відносний внесок відповідної ознаки в модель, обчислену шляхом взяття внеску кожного елемента для кожного дерева в моделі. Більш високе значення цього показника порівняно з іншою ознакою означає, що воно важливіше для формування прогнозу.


7

Мені було цікаво з цього приводу і зробили кілька тестів.

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

Схоже, що коли кореляція між двома стовпцями дорівнює 1, xgboost видаляє зайвий стовпець перед обчисленням моделі, тому на значення не впливає. Однак, коли ви додаєте стовпчик, який частково співвідноситься з іншим, таким чином, з меншим коефіцієнтом, важливість вихідної змінної x знижується.

Наприклад, якщо я додаю змінну xy = x + y, важливість і x, і y зменшується. Аналогічно, значення x зменшується, якщо я додаю нові змінні з r = 0,4, 0,5 або 0,6, хоча трохи.

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

library(tidyverse)
library(xgboost)

evaluate_model = function(dataset) {
    print("Correlation matrix")
    dataset %>% select(-cut, -color, -clarity, -price) %>% cor %>% print

    print("running model")
    diamond.model = xgboost(
        data=dataset %>% select(-cut, -color, -clarity, -price) %>% as.matrix, 
        label=dataset$price > 400, 
        max.depth=15, nrounds=30, nthread=2, objective = "binary:logistic",
        verbose=F
        )

    print("Importance matrix")
    importance_matrix <- xgb.importance(model = diamond.model)
    importance_matrix %>% print
    xgb.plot.importance(importance_matrix)
    }

> diamonds %>% head
carat   cut color   clarity depth   table   price   x   y   z
0.23    Ideal   E   SI2 61.5    55  326 3.95    3.98    2.43
0.21    Premium E   SI1 59.8    61  326 3.89    3.84    2.31
0.23    Good    E   VS1 56.9    65  327 4.05    4.07    2.31
0.29    Premium I   VS2 62.4    58  334 4.20    4.23    2.63
0.31    Good    J   SI2 63.3    58  335 4.34    4.35    2.75
0.24    Very Good   J   VVS2    62.8    57  336 3.94    3.96    2.48

Оцініть модель на даних алмазів

Ми прогнозуємо, чи буде ціна вищою за 400, враховуючи всі числові змінні, доступні (карат, глибина, таблиця, х, у, х)

Зауважимо, що x - найважливіша змінна, з оцінкою посилення важливості 0,375954.

evaluate_model(diamonds)
    [1] "Correlation matrix"
               carat       depth      table           x           y          z
    carat 1.00000000  0.02822431  0.1816175  0.97509423  0.95172220 0.95338738
    depth 0.02822431  1.00000000 -0.2957785 -0.02528925 -0.02934067 0.09492388
    table 0.18161755 -0.29577852  1.0000000  0.19534428  0.18376015 0.15092869
    x     0.97509423 -0.02528925  0.1953443  1.00000000  0.97470148 0.97077180
    y     0.95172220 -0.02934067  0.1837601  0.97470148  1.00000000 0.95200572
    z     0.95338738  0.09492388  0.1509287  0.97077180  0.95200572 1.00000000
    [1] "running model"
    [1] "Importance matrix"
       Feature       Gain      Cover  Frequency
    1:       x 0.37595419 0.54788335 0.19607102
    2:   carat 0.19699839 0.18015576 0.04873442
    3:   depth 0.15358261 0.08780079 0.27767284
    4:       y 0.11645929 0.06527969 0.18813751
    5:   table 0.09447853 0.05037063 0.17151492
    6:       z 0.06252699 0.06850978 0.11786929

Модель тренується на Diamonds, додаючи змінну з r = 1 до x

Тут ми додаємо новий стовпець, який, однак, не додає нової інформації, оскільки він ідеально співвідноситься з x.

Зауважте, що цієї нової змінної немає у висновку. Здається, що xgboost автоматично видаляє ідеально корельовані змінні перед початком обчислення. Коефіцієнт посилення x однаковий, 0,3759.

diamonds_xx = diamonds %>%
    mutate(xx = x + runif(1, -1, 1))
evaluate_model(diamonds_xx)
[1] "Correlation matrix"
           carat       depth      table           x           y          z
carat 1.00000000  0.02822431  0.1816175  0.97509423  0.95172220 0.95338738
depth 0.02822431  1.00000000 -0.2957785 -0.02528925 -0.02934067 0.09492388
table 0.18161755 -0.29577852  1.0000000  0.19534428  0.18376015 0.15092869
x     0.97509423 -0.02528925  0.1953443  1.00000000  0.97470148 0.97077180
y     0.95172220 -0.02934067  0.1837601  0.97470148  1.00000000 0.95200572
z     0.95338738  0.09492388  0.1509287  0.97077180  0.95200572 1.00000000
xx    0.97509423 -0.02528925  0.1953443  1.00000000  0.97470148 0.97077180
               xx
carat  0.97509423
depth -0.02528925
table  0.19534428
x      1.00000000
y      0.97470148
z      0.97077180
xx     1.00000000
[1] "running model"
[1] "Importance matrix"
   Feature       Gain      Cover  Frequency
1:       x 0.37595419 0.54788335 0.19607102
2:   carat 0.19699839 0.18015576 0.04873442
3:   depth 0.15358261 0.08780079 0.27767284
4:       y 0.11645929 0.06527969 0.18813751
5:   table 0.09447853 0.05037063 0.17151492
6:       z 0.06252699 0.06850978 0.11786929

Модель тренується на Diamonds, додаючи стовпчик для x + y

Додаємо новий стовпець xy = x + y. Це частково корелює як з x, так і з y.

Зауважимо, що значення x і y дещо зменшуються, ідучи від 0,3759 до 0,3592 для x, і від 0,116 до 0,079 для у.

diamonds_xy = diamonds %>%
    mutate(xy=x+y)
evaluate_model(diamonds_xy)

[1] "Correlation matrix"
           carat       depth      table           x           y          z
carat 1.00000000  0.02822431  0.1816175  0.97509423  0.95172220 0.95338738
depth 0.02822431  1.00000000 -0.2957785 -0.02528925 -0.02934067 0.09492388
table 0.18161755 -0.29577852  1.0000000  0.19534428  0.18376015 0.15092869
x     0.97509423 -0.02528925  0.1953443  1.00000000  0.97470148 0.97077180
y     0.95172220 -0.02934067  0.1837601  0.97470148  1.00000000 0.95200572
z     0.95338738  0.09492388  0.1509287  0.97077180  0.95200572 1.00000000
xy    0.96945349 -0.02750770  0.1907100  0.99354016  0.99376929 0.96744200
              xy
carat  0.9694535
depth -0.0275077
table  0.1907100
x      0.9935402
y      0.9937693
z      0.9674420
xy     1.0000000
[1] "running model"
[1] "Importance matrix"
   Feature       Gain      Cover  Frequency
1:       x 0.35927767 0.52924339 0.15952849
2:   carat 0.17881931 0.18472506 0.04793713
3:   depth 0.14353540 0.07482622 0.24990177
4:   table 0.09202059 0.04714548 0.16267191
5:      xy 0.08203819 0.04706267 0.13555992
6:       y 0.07956856 0.05284980 0.13595285
7:       z 0.06474029 0.06414738 0.10844794

Модель тренується на даних Diamonds, модифікуючи додавання надмірних стовпців

Додаємо три нові стовпчики, які співвідносяться з x (r = 0,4, 0,5 і 0,6) і дивимося, що відбувається.

Зауважте, що значення x зменшується, знижуючись з 0,3759 до 0,279.

#' given a vector of values (e.g. diamonds$x), calculate three new vectors correlated to it
#' 
#' Source: https://stat.ethz.ch/pipermail/r-help/2007-April/128938.html
calculate_correlated_vars = function(x1) {

    # create the initial x variable
    #x1 <- diamonds$x

    # x2, x3, and x4 in a matrix, these will be modified to meet the criteria
    x234 <- scale(matrix( rnorm(nrow(diamonds) * 3), ncol=3 ))

    # put all into 1 matrix for simplicity
    x1234 <- cbind(scale(x1),x234)

    # find the current correlation matrix
    c1 <- var(x1234)

    # cholesky decomposition to get independence
    chol1 <- solve(chol(c1))

    newx <-  x1234 %*% chol1 

    # check that we have independence and x1 unchanged
    zapsmall(cor(newx))
    all.equal( x1234[,1], newx[,1] )

    # create new correlation structure (zeros can be replaced with other r vals)
    newc <- matrix( 
    c(1  , 0.4, 0.5, 0.6, 
      0.4, 1  , 0  , 0  ,
      0.5, 0  , 1  , 0  ,
      0.6, 0  , 0  , 1  ), ncol=4 )

    # check that it is positive definite
    eigen(newc)

    chol2 <- chol(newc)

    finalx <- newx %*% chol2 * sd(x1) + mean(x1)

    # verify success
    mean(x1)
    colMeans(finalx)

    sd(x1)
    apply(finalx, 2, sd)

    zapsmall(cor(finalx))
    #pairs(finalx)

    all.equal(x1, finalx[,1])
    finalx
}
finalx = calculate_correlated_vars(diamonds$x)
diamonds_cor = diamonds
diamonds_cor$x5 = finalx[,2]
diamonds_cor$x6 = finalx[,3]
diamonds_cor$x7 = finalx[,4]
evaluate_model(diamonds_cor)
[1] "Correlation matrix"
           carat        depth       table           x           y          z
carat 1.00000000  0.028224314  0.18161755  0.97509423  0.95172220 0.95338738
depth 0.02822431  1.000000000 -0.29577852 -0.02528925 -0.02934067 0.09492388
table 0.18161755 -0.295778522  1.00000000  0.19534428  0.18376015 0.15092869
x     0.97509423 -0.025289247  0.19534428  1.00000000  0.97470148 0.97077180
y     0.95172220 -0.029340671  0.18376015  0.97470148  1.00000000 0.95200572
z     0.95338738  0.094923882  0.15092869  0.97077180  0.95200572 1.00000000
x5    0.39031255 -0.007507604  0.07338484  0.40000000  0.38959178 0.38734145
x6    0.48879000 -0.016481580  0.09931705  0.50000000  0.48835896 0.48487442
x7    0.58412252 -0.013772440  0.11822089  0.60000000  0.58408881 0.58297414
                 x5            x6            x7
carat  3.903125e-01  4.887900e-01  5.841225e-01
depth -7.507604e-03 -1.648158e-02 -1.377244e-02
table  7.338484e-02  9.931705e-02  1.182209e-01
x      4.000000e-01  5.000000e-01  6.000000e-01
y      3.895918e-01  4.883590e-01  5.840888e-01
z      3.873415e-01  4.848744e-01  5.829741e-01
x5     1.000000e+00  5.925447e-17  8.529781e-17
x6     5.925447e-17  1.000000e+00  6.683397e-17
x7     8.529781e-17  6.683397e-17  1.000000e+00
[1] "running model"
[1] "Importance matrix"
   Feature       Gain      Cover  Frequency
1:       x 0.27947762 0.51343709 0.09748172
2:   carat 0.13556427 0.17401365 0.02680747
3:      x5 0.13369515 0.05267688 0.18155971
4:      x6 0.12968400 0.04804315 0.19821284
5:      x7 0.10600238 0.05148826 0.16450041
6:   depth 0.07087679 0.04485760 0.11251015
7:       y 0.06050565 0.03896716 0.08245329
8:   table 0.04577057 0.03135677 0.07554833
9:       z 0.03842355 0.04515944 0.06092608

6

Є відповідь від Tianqi Chen (2018).

Ця різниця впливає на кутовий випадок аналізу важливості функції: співвідносні риси. Уявіть дві особливості, які повністю співвідносяться, особливість A та особливість B. Для одного конкретного дерева, якщо алгоритму потрібно одне з них, воно вибереться випадковим чином (вірно і в прискореному, і в Random Forests ™).

Однак у Random Forests ™ цей випадковий вибір буде зроблено для кожного дерева, оскільки кожне дерево незалежне від інших. Тому, орієнтовно, залежно від ваших параметрів, 50% дерев виберуть функцію A, а інші 50% - обрать функцію B. Отже, важливість інформації, що міститься в A і B (це те саме, оскільки вони ідеально співвідносяться ) розведений в А і В. Тому ви не будете легко знати цю інформацію, важливо передбачити, що ви хочете передбачити! Ще гірше, коли у вас є 10 корельованих функцій ...

Підсилюючи, коли алгоритм дізнається певний зв’язок між ознакою та результатом, він намагатиметься не переосмислити його (теоретично це те, що відбувається, реальність не завжди така проста). Тому все значення буде приділено функції A або на функції B (але не обох). Ви будете знати, що одна особливість відіграє важливу роль у зв’язку між спостереженнями та етикеткою. Вам залишається шукати співвіднесені функції до тієї, яку визначили як важливу, якщо вам потрібно знати їх усі.

Підводячи підсумок, Xgboost не випадково використовує співвідносні функції у кожному дереві, яке випадкова лісова модель страждає від такої ситуації.

Довідка :

Tianqi Chen, Michaël Benesty, Tong He. 2018. "Розуміння набору даних за допомогою Xgboost". Https://cran.r-project.org/web/packages/xgboost/vignettes/discoverYourData.html#numeric-vs-categorical-variables .


2

Зауваження до відповіді Сандіпа: Якщо припустити, що 2 ваші особливості є високолінійними (скажімо, рівними 99% часу) Дійсно лише 1 функція вибирається при кожному розщепленні, але для наступного розколу xgb може вибрати іншу особливість. Тому ранжування функції xgb, ймовірно, класифікує 2 колінеарних ознаки однаково. Не маючи попередніх знань чи іншої обробки функцій, у вас майже немає засобів із цього наданого рейтингу, щоб визначити, що дві особливості є колінними.

Тепер, що стосується відносної важливості, яка виводить xgboost, вона повинна бути дуже схожою (або, можливо, точно подібною) до ранжирування дерев, підсилених градієнтом sklearn. Дивіться тут для пояснень.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.