Xgboostは多重共線性を単独で処理しますか?
-
16-10-2019 - |
質問
現在、21の機能を備えたデータセット(約150の機能のリストから選択)でXgboostを使用しています。その後、ワンホットがそれらをコーディングして〜98の機能を取得しました。これらの98の機能のいくつかは、たとえば、多少冗長です。たとえば、変数(機能)$ a $も$ frac {b} {a} $および$ frac {c} {a} $として表示されます。
私の質問は次のとおりです。
- どのように (もしも?)ブーストされた決定木は多重共線性を処理しますか?
- 多重共線性の存在は、処理されない場合、予測にどのように影響しますか?
私が理解していることから、モデルは複数のツリーを学習しており、最終的な予測は個々の予測の「加重和」のようなものに基づいています。これが正しい場合は、決定ツリーを後押ししました したほうがいい 変数間の共依存性を処理できるようにします。
また、関連するメモで - xgboostの可変重要性オブジェクトはどのように機能しますか?
解決
意思決定ツリーは、本質的に多重共線性の免疫があります。たとえば、99%相関した2つの機能がある場合、分割を決定するときにツリーは1つのみを選択します。ロジスティック回帰などの他のモデルは、両方の機能を使用します。
ブーストされた木は個々の決定ツリーを使用しているため、多コリアン性の影響もありません。ただし、モデルのアルゴリズムに関係なく、トレーニングに使用されるデータセットから冗長機能を削除することは良い習慣です。新しい機能を導き出しているため、このアプローチを使用し、各機能の重要性を評価し、最終モデルに最適な機能のみを保持することができます。
xgboostモデルの重要性マトリックスは、実際にはdata.tableオブジェクトです。最初の列は、ブーストツリーで実際に使用されるすべての機能の名前をリストします。 2番目の列はゲインメトリックで、モデル内の各ツリーの各機能の寄与を取得することによって計算されたモデルに対応する特徴の相対的な寄与を意味します。別の機能と比較すると、このメトリックの値が高いことは、予測を生成するためにより重要であることを意味します。
他のヒント
私はこれに興味があり、いくつかのテストをしました。
ダイヤモンドデータセットのモデルをトレーニングしましたが、変数「x」がダイヤモンドの価格が特定のしきい値よりも高いかどうかを予測するために最も重要であることを観察しました。次に、xと高度に相関した複数の列を追加し、同じモデルを実行し、同じ値を観察しました。
2つの列間の相関が1の場合、xgboostはモデルを計算する前に追加の列を削除するため、重要性は影響を受けません。ただし、別の列に部分的に相関する列を追加すると、係数が低い場合、元の変数xの重要性が低下します。
たとえば、変数xy = x + yを追加すると、xとyの両方の減少の重要性が減少します。同様に、xの重要性は、r = 0.4、0.5、または0.6の新しい変数を追加すると減少します。
決定ツリーが変数のどれが使用されるかを気にしないため、モデルの精度を計算するときに、コリニアラリティはブーストの問題ではないと思います。ただし、2つの相関変数のいずれかを削除することは、他の相関変数に同様の情報が含まれていることを考えると、モデルの精度に大きな影響を与えないため、変数の重要性に影響を与える可能性があります。
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)
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
ダイヤモンドでトレーニングされたモデル、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
ダイヤモンドでトレーニングされたモデル、x + yの列を追加
新しい列xy = x + yを追加します。これは、xとyの両方に部分的に相関しています。
xとyの重要性はわずかに減少し、xで0.3759から0.3592、yで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
ダイヤモンドデータでトレーニングされたモデル、冗長列の追加修正
x(r = 0.4、0.5、0.6)と相関する3つの新しい列を追加し、何が起こるかを確認します。
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
Tianqi Chen(2018)からの答えがあります。
この違いは、特徴の重要性分析におけるコーナーケースに影響を及ぼします:相関関係の特徴。 2つの機能が完全に相関し、機能Aと機能Bを想像してください。1つの特定のツリーに対して、アルゴリズムがそのうちの1つを必要とする場合、ランダムに選択します(Boosting Forest™とランダムフォレスト™の両方で真)。
ただし、ランダムフォレスト™では、各ツリーが他のツリーから独立しているため、このランダムな選択は各ツリーに対して行われます。したがって、近似的には、パラメーターに応じて、木の50%が機能Aを選択し、他の50%が機能Bを選択します。したがって、AとBに含まれる情報の重要性(これは同じです。 )AとBで希釈されているので、この情報が予測したいことを予測するために重要であることを簡単に知ることはできません! 10個の相関した機能がある場合、さらに悪いことです…
ブーストでは、機能と結果の間の特定のリンクがアルゴリズムによって学習されている場合、それに焦点を合わせないようにします(理論的には、現実は必ずしもそれほど単純ではありません)。したがって、すべての重要性は、機能Aまたは機能Bにあります(ただし、両方ではありません)。 1つの機能が、観測とラベルの間のリンクに重要な役割を果たしていることがわかります。すべてのことを知る必要がある場合、重要であると検出された機能に相関した機能を検索するのは、まだあなた次第です。
要約すると、XGBoostは各ツリーの相関機能をランダムに使用しません。ランダムフォレストモデルはそのような状況に苦しんでいます。
参照:
Tianqi Chen、MichaëlBenesty、Tong He。 2018.「xgboostでデータセットを理解してください。」 https://cran.r-project.org/web/packages/xgboost/vignettes/discoveryourdata.html#numeric-vs-categorical-variables.
Sandeepの回答に関する発言:2つの機能が非常に共生的であると仮定すると(たとえば、99%の時間と等しい)、各分割で1つの機能のみが選択されますが、次の分割では、XGBが他の機能を選択できます。したがって、XGB機能のランキングは、おそらく2つの共線機能を等しくランク付けします。事前の知識やその他の機能処理がなければ、2つの機能が結合していることを検出するためのランキングを提供する手段はほとんどありません。
さて、xgboostを出力する相対的な重要性については、Sklearn Gradientブースティー付きツリーランキングと非常に似ている(または正確に類似している)必要があります。見る ここ 説明のために。