Behandelt XGBoost Multikollinearität selbstständig?

23

Ich verwende derzeit XGBoost für einen Datensatz mit 21 Features (ausgewählt aus einer Liste von ca. 150 Features). Anschließend werden diese per One-Hot-Code codiert, um ~ 98 Features zu erhalten. Einige dieser 98 Features sind etwas redundant, zum Beispiel: Eine Variable (Feature) auch als B angezeigtEIN undCBEIN .CEIN

Meine Fragen sind:

  • Wie ( wenn? ) Gehen Boosted Decision Trees mit Multikollinearität um?
  • Wie würde sich die Existenz von Multikollinearität auf die Vorhersage auswirken, wenn sie nicht behandelt wird?

Soweit ich weiß, lernt das Modell mehr als einen Baum und die endgültige Vorhersage basiert auf so etwas wie einer "gewichteten Summe" der einzelnen Vorhersagen. Wenn dies korrekt ist, sollten Boosted Decision Trees in der Lage sein, die Abhängigkeit zwischen Variablen zu bewältigen.

Außerdem: Wie funktioniert das Objekt mit variabler Wichtigkeit in XGBoost?

user140323
quelle
Ich verstehe, dass Bäume mit Multikollinearität umgehen können. Aber was ist mit XGBoost auf Regressionsbasis? Kann es auch mit Multi-Kollinearität umgehen? > Entscheidungsbäume sind von Natur aus immun gegen Multikollinearität. Wenn Sie beispielsweise 2 Features haben, die zu 99% korreliert sind, wählt der Baum bei der Entscheidung für eine Aufteilung nur eines davon aus. Andere Modelle wie die logistische Regression würden beide Funktionen nutzen. >> Da geboostete Bäume einzelne Entscheidungsbäume verwenden, sind sie auch von der Multikollinearität unberührt. Es empfiehlt sich jedoch,> redundante Funktionen aus allen Datensätzen zu entfernen, die für tra
Jay Saxena am

Antworten:

27

Entscheidungsbäume sind von Natur aus immun gegen Multikollinearität. Wenn Sie beispielsweise 2 Features haben, die zu 99% korreliert sind, wählt der Baum bei der Entscheidung für eine Aufteilung nur eines davon aus. Andere Modelle wie die logistische Regression würden beide Funktionen nutzen.

Da geboostete Bäume einzelne Entscheidungsbäume verwenden, sind sie auch nicht von Multikollinearität betroffen. Unabhängig vom Algorithmus des Modells empfiehlt es sich jedoch, redundante Features aus allen für das Training verwendeten Datensätzen zu entfernen. In Ihrem Fall können Sie, da Sie neue Features ableiten, diesen Ansatz verwenden, die Wichtigkeit jedes Features bewerten und nur die besten Features für Ihr endgültiges Modell beibehalten.

Die Wichtigkeitsmatrix eines xgboost-Modells ist eigentlich ein data.table-Objekt. In der ersten Spalte sind die Namen aller Features aufgeführt, die tatsächlich in den verstärkten Bäumen verwendet werden. Die zweite Spalte ist die Gain-Metrik, die den relativen Beitrag des entsprechenden Features zum Modell impliziert, der berechnet wird, indem der Beitrag jedes Features für jeden Baum im Modell genommen wird. Ein höherer Wert dieser Metrik im Vergleich zu einem anderen Feature bedeutet, dass es für die Erstellung einer Vorhersage wichtiger ist.

Sandeep S. Sandhu
quelle
7

Ich war neugierig und machte ein paar Tests.

Ich habe ein Modell für den Diamanten-Datensatz trainiert und festgestellt, dass die Variable „x“ am wichtigsten ist, um vorherzusagen, ob der Preis eines Diamanten einen bestimmten Schwellenwert überschreitet. Dann habe ich mehrere Spalten hinzugefügt, die in hohem Maße mit x korreliert sind, dasselbe Modell ausgeführt und dieselben Werte beobachtet.

Wenn die Korrelation zwischen zwei Spalten 1 ist, entfernt xgboost anscheinend die zusätzliche Spalte, bevor das Modell berechnet wird, sodass die Wichtigkeit nicht beeinträchtigt wird. Wenn Sie jedoch eine Spalte hinzufügen, die teilweise mit einer anderen korreliert ist, also einen niedrigeren Koeffizienten aufweist, wird die Bedeutung der ursprünglichen Variablen x verringert.

Wenn ich zum Beispiel eine Variable xy = x + y hinzufüge, nimmt die Wichtigkeit von x und y ab. In ähnlicher Weise nimmt die Bedeutung von x ab, wenn ich neue Variablen mit r = 0,4, 0,5 oder 0,6 hinzufüge, allerdings nur um ein wenig.

Ich denke, dass Kollinearität kein Problem für das Boosten ist, wenn Sie die Genauigkeit des Modells berechnen, da es dem Entscheidungsbaum egal ist, welche der Variablen verwendet wird. Dies kann sich jedoch auf die Wichtigkeit der Variablen auswirken, da das Entfernen einer der beiden korrelierten Variablen keinen großen Einfluss auf die Genauigkeit des Modells hat, da die andere ähnliche Informationen enthält.

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

Bewerten Sie ein Modell anhand der Diamantdaten

Wir sagen voraus, ob der Preis bei allen verfügbaren numerischen Variablen (Karat, Tiefe, Tabelle, x, y, x) höher als 400 ist.

Beachten Sie, dass x die wichtigste Variable mit einer Wichtigkeitszunahme von 0,375954 ist.

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

Auf Diamonds trainiertes Modell, das eine Variable mit r = 1 zu x hinzufügt

Hier fügen wir eine neue Spalte hinzu, die jedoch keine neuen Informationen hinzufügt, da sie perfekt mit x korreliert sind.

Beachten Sie, dass diese neue Variable in der Ausgabe nicht vorhanden ist. Es scheint, dass xgboost perfekt korrelierte Variablen automatisch entfernt, bevor die Berechnung gestartet wird. Der Wichtigkeitsgewinn von x ist der gleiche, 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

Modell auf Diamanten trainiert, Hinzufügen einer Spalte für x + y

Wir fügen eine neue Spalte xy = x + y hinzu. Dies ist teilweise sowohl mit x als auch mit y korreliert.

Beachten Sie, dass die Wichtigkeit von x und y leicht verringert ist und von 0,3759 auf 0,3592 für x und von 0,116 auf 0,079 für y steigt.

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

Auf Diamonds-Daten trainiertes Modell, modifiziert durch Hinzufügen redundanter Spalten

Wir fügen drei neue Spalten hinzu, die mit x korreliert sind (r = 0,4, 0,5 und 0,6) und sehen, was passiert.

Beachten Sie, dass die Bedeutung von x von 0,3759 auf 0,279 sinkt.

#' 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
quelle
6

Es gibt eine Antwort von Tianqi Chen (2018).

Dieser Unterschied wirkt sich auf einen Eckfall in der Merkmalswichtigkeitsanalyse aus: die korrelierten Merkmale. Stellen Sie sich zwei Merkmale vor, die perfekt korreliert sind, Merkmal A und Merkmal B. Wenn der Algorithmus für einen bestimmten Baum eines benötigt, wählt er zufällig aus (wahr sowohl in Boosting als auch in Random Forests ™).

In Random Forests ™ wird diese zufällige Auswahl jedoch für jeden Baum getroffen, da jeder Baum unabhängig von den anderen ist. Daher wählen ungefähr 50% der Bäume in Abhängigkeit von Ihren Parametern das Merkmal A und die anderen 50% das Merkmal B. Die Bedeutung der in A und B enthaltenen Informationen (die dieselben sind, weil sie perfekt korrelieren) ) ist in A und B verdünnt. Sie werden also nicht leicht wissen, dass diese Informationen wichtig sind, um vorherzusagen, was Sie vorhersagen möchten! Es ist noch schlimmer, wenn Sie 10 korrelierte Funktionen haben ...

Wenn der Algorithmus eine bestimmte Verbindung zwischen Merkmal und Ergebnis gelernt hat, wird er versuchen, sich nicht darauf zu konzentrieren (theoretisch ist es das, was passiert, die Realität ist nicht immer so einfach). Daher wird die gesamte Wichtigkeit auf Merkmal A oder Merkmal B (aber nicht auf beiden) liegen. Sie werden wissen, dass ein Merkmal eine wichtige Rolle bei der Verknüpfung zwischen den Beobachtungen und dem Etikett spielt. Es bleibt Ihnen überlassen, nach den korrelierten Merkmalen zu suchen, die als wichtig erkannt wurden, wenn Sie alle kennen müssen.

Zusammenfassend lässt sich sagen, dass Xgboost die korrelierten Merkmale in den einzelnen Bäumen nicht zufällig verwendet. Dieses zufällige Waldmodell leidet unter einer solchen Situation.

Hinweis :

Tianqi Chen, Michaël Benesty, Tong He. 2018. „Verstehen Sie Ihren Datensatz mit Xgboost.“ Https://cran.r-project.org/web/packages/xgboost/vignettes/discoverYourData.html#numeric-vs-categorical-variables .

Jiaxiang
quelle
2

Eine Bemerkung zu Sandeeps Antwort: Angenommen, 2 Ihrer Features sind stark kolinear (sagen wir 99% der Zeit). Tatsächlich wird bei jeder Aufteilung nur 1 Feature ausgewählt, aber für die nächste Aufteilung kann das xgb das andere Feature auswählen. Daher werden die 2 kolinearen Merkmale beim xgb-Merkmalsranking wahrscheinlich gleich eingestuft. Ohne Vorkenntnisse oder eine andere Feature-Verarbeitung haben Sie fast keine Möglichkeit, anhand dieser bereitgestellten Rangfolge zu erkennen, dass die beiden Features kollinear sind.

Was nun die relative Wichtigkeit anbelangt, die den xgboost ausgibt, sollte er sehr ähnlich (oder vielleicht genau ähnlich) sein wie der mit sklearn-Gradienten verstärkte Baumrang. Erklärungen finden Sie hier .

PSAfrance
quelle