XGBoost сам обрабатывает мультиколлинеарность?

23

В настоящее время я использую XGBoost для набора данных с 21 функцией (выбранной из списка из 150 функций), а затем горячо закодировал их, чтобы получить ~ 98 функций. Некоторые из этих 98 функций несколько избыточны, например: переменная (функция) также отображается как и .AВAСA

Мои вопросы:

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

Из того, что я понимаю, модель изучает более одного дерева, и окончательный прогноз основан на чем-то вроде «взвешенной суммы» отдельных прогнозов. Так что, если это правильно, тогда деревья принятия решений должны быть в состоянии обрабатывать взаимозависимость между переменными.

Кроме того, на заметку о том, как работает объект переменной важности в XGBoost?

user140323
источник
Я понимаю, что деревья могут справиться с мультиколлинеарностью. Но как насчет регрессионного XGBoost? Может ли он справиться с мультиколлинеарностью? > Деревья решений по своей природе невосприимчивы к мультиколлинеарности. Например,> если у вас есть 2 объекта, которые коррелированы на 99%, при> выборе разбиения дерево выберет только один из них. Другие> модели, такие как логистическая регрессия, будут использовать обе функции. >> Поскольку расширенные деревья используют отдельные деревья решений, они также> не подвержены влиянию мультиколлинеарности. Тем не менее, хорошей практикой является> удаление любых избыточных функций из любого набора данных, используемого для tra
Jay Saxena

Ответы:

27

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

Поскольку ускоренные деревья используют отдельные деревья решений, они также не подвержены влиянию мультиколлинеарности. Однако хорошей практикой является удаление любых избыточных функций из любого набора данных, используемого для обучения, независимо от алгоритма модели. В вашем случае, поскольку вы получаете новые функции, вы можете использовать этот подход, оценить важность каждой функции и сохранить только лучшие функции для вашей окончательной модели.

Матрица важности модели xgboost на самом деле представляет собой объект data.table с первым столбцом, в котором перечислены имена всех функций, фактически используемых в повышенных деревьях. Второй столбец - это метрика усиления, которая подразумевает относительный вклад соответствующего объекта в модель, рассчитанный путем учета вклада каждого объекта для каждого дерева в модели. Более высокое значение этого показателя по сравнению с другим признаком означает, что он важнее для создания прогноза.

Сандип С. Сандху
источник
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, y, 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 автоматически удаляет идеально коррелированные переменные перед началом расчета. Прирост важности х такой же, 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

Модель обучена на Алмазах, добавление столбца для х + у

Мы добавляем новый столбец xy = x + y. Это частично связано как с х, так и с у.

Обратите внимание, что значение x и y немного уменьшено: с 0,3759 до 0,3592 для x и с 0,116 до 0,079 для y.

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

Модель обучена на данных Алмазов, изменено добавление избыточных столбцов

Мы добавляем три новых столбца, которые связаны с 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
dalloliogm
источник
6

Есть ответ от Tianqi Chen (2018).

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

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

В процессе ускорения, когда алгоритм определил конкретную связь между характеристикой и результатом, он попытается не переориентироваться на нее (в теории это то, что происходит, реальность не всегда так проста). Следовательно, все значение будет уделяться функции A или функции B (но не обоим). Вы будете знать, что одна особенность играет важную роль в связи между наблюдениями и меткой. Вам по-прежнему нужно искать коррелированные функции, которые будут признаны важными, если вам необходимо знать все из них.

Подводя итог, можно сказать, что Xgboost не использует случайным образом коррелированные функции в каждом дереве, а модель случайного леса страдает от такой ситуации.

Ссылка :

Тяньци Чен, Микаэль Бенести, Тонг Хе. 2018. «Узнайте ваш набор данных с помощью Xgboost». Https://cran.r-project.org/web/packages/xgboost/vignettes/discoverYourData.html#numeric-vs-categorical-variables .

Jiaxiang
источник
2

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

Теперь, что касается относительной важности, которую выводит xgboost, он должен быть очень похож (или, может быть, в точности похож) на ранжирование дерева с градиентом склеарна. Смотрите здесь для объяснений.

PSAfrance
источник