Xgboost: [์‹ ๊ทœ ๊ธฐ๋Šฅ] ํŠธ๋ฆฌ ๊ตฌ์„ฑ์˜ Monotonic Constraints

์— ๋งŒ๋“  2016๋…„ 08์›” 27์ผ  ยท  46์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: dmlc/xgboost

์ถœ๋ ฅ๊ณผ ๊ด€๋ จํ•˜์—ฌ ํŠน์ • ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๋‹จ์กฐ ์ œ์•ฝ ์ง€์›์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์š”์ฒญ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

์ฆ‰, ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์ด ๊ณ ์ •๋œ ๊ฒฝ์šฐ ์˜ˆ์ธก์ด ํŠน์ • ์ง€์ •๋œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ๋‹จ์กฐ ์ฆ๊ฐ€ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ ๊ด€์‹ฌ์„ ๋ณด๊ธฐ ์œ„ํ•ด ์ด ํ˜ธ๋ฅผ ์—ฝ๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ๊ด€์‹ฌ์ด ์ถฉ๋ถ„ํ•˜๋ฉด ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒ ํƒ€ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์ด ๊ธฐ๋Šฅ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๋ฌธ์„œ ๋ฐ ์ž์Šต์„œ๋ฅผ ์ œ๊ณตํ•˜๋ ค๋ฉด ์ปค๋ฎค๋‹ˆํ‹ฐ ์ž์› ๋ด‰์‚ฌ์ž์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ์— ํšŒ์‹ ํ•˜์‹ญ์‹œ์˜ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

ํ˜„์žฌ ์ด ๊ธฐ๋Šฅ์€ Sklearn API์— ์—†์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด๋‚˜ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ทธ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๊ฐ์‚ฌ ํ•ด์š”!

๋ชจ๋“  46 ๋Œ“๊ธ€

์‹คํ—˜ ๋ฒ„์ „์€ https://github.com/dmlc/xgboost/pull/1516 ์—์„œ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค https://github.com/tqchen/xgboost ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋ณต์ œ

๋‹ค์Œ ์˜ต์…˜์„ ์ผœ์‹ญ์‹œ์˜ค(python, r API๋ฅผ ํ†ตํ•ด ๊ฐ€๋Šฅํ•จ).

monotone_constraints = "(0,1,1,0)"

๋‘ ๊ฐ€์ง€ ์ฃผ์žฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค

  • monotone_constraints ๋Š” ๊ธฐ๋Šฅ ์ˆ˜์˜ ๊ธธ์ด ๋ชฉ๋ก์ด๋ฉฐ, 1์€ ๋‹จ์กฐ ์ฆ๊ฐ€, -1์€ ๊ฐ์†Œ, 0์€ ์ œํ•œ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ ์ˆ˜๋ณด๋‹ค ์งง์œผ๋ฉด 0์ด ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

    • ํ˜„์žฌ python์˜ ํŠœํ”Œ ํ˜•์‹์„ ์ง€์›ํ•˜๋ฏ€๋กœ r์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฌธ์ž์—ด๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์ธํ•ด์•ผ ํ•  ์‚ฌํ•ญ

  • [x] ์›๋ž˜ ํŠธ๋ฆฌ ๋ถ€์Šคํ„ฐ์˜ ์†๋„๊ฐ€ ๋Š๋ ค์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ์•ฝ๊ฐ„ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ก ์ƒ ํ…œํ”Œ๋ฆฟ ์ตœ์ ํ™”๊ฐ€ ์ธ๋ผ์ธ์„ ์ธ๋ผ์ธํ•˜์ง€๋งŒ ํ™•์ธํ•ด์•ผ ํ•จ)
  • [x] ๋‹จ์กฐ ํšŒ๊ท€์˜ ์†๋„์™€ ์ •ํ™•์„ฑ
  • [x] ์ด ์ œ์•ฝ์„ ๋„์ž…ํ•˜์—ฌ ์„ฑ๋Šฅ

์•Œ๋ ค์ง„ ์ œํ•œ ์‚ฌํ•ญ

ํ˜„์žฌ๋Š” ๋ฉ€ํ‹ฐ ์ฝ”์–ด์—์„œ ์ •ํ™•ํ•œ ํƒ์š• ์•Œ๊ณ ๋ฆฌ์ฆ˜๋งŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์•„์ง ๋ฐฐํฌ ๋ฒ„์ „์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ

@tqchen ์ €๋Š” ์˜ค๋Š˜ ์ง์žฅ์—์„œ ๋‹ค๋ฅธ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ๊ณผ ๋น„๊ตํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋…ธํ†ค ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ๋Š” GBM์„ ๊ตฌ์ถ•ํ•ด ๋‹ฌ๋ผ๋Š” ์š”์ฒญ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ tweedie ์ดํƒˆ๋„ ์†์‹ค๊ณผ ํ•จ๊ป˜์ด๋ฏ€๋กœ ์˜ค๋Š˜๋‚ ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ์ž ์ •์˜ ์†์‹ค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ๋„์›€์„ ์ฃผ๊ณ  ๋™์‹œ์— ์ผ๋ถ€ ์ž‘์—…์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๊ธฐํšŒ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ์ด์•ผ๊ธฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ GBM(R ํŒจํ‚ค์ง€)์€ ๋‹จ์กฐ์„ฑ์„ ๋กœ์ปฌ์—์„œ๋งŒ ์‹œํ–‰ํ•ฉ๋‹ˆ๋‹ค.
XGBoost๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‹จ์กฐ๋กœ์šด ์ œ์•ฝ์„ ์ ์šฉํ•˜๋Š”์ง€ ๋ช…ํ™•ํžˆ ํ•ด์ฃผ์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
XGBoost๊ฐ€ ์ „์—ญ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋กœ์ปฌ ๋˜๋Š” ๊ธ€๋กœ๋ธ” ์ œ์•ฝ์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ž˜๋ชป๋œ ๋งํฌ๋ฅผ ๋ถ™์—ฌ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์˜ฌ๋ฐ”๋ฅธ ๋งํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (๋งํฌ).
๊ฐ ํŠธ๋ฆฌ๋Š” ๊ด€์‹ฌ ์žˆ๋Š” ๊ธฐ๋Šฅ์˜ ํŠน์ • ํ•˜์œ„ ์ง‘ํ•ฉ์—์„œ๋งŒ ๋‹จ์กฐ ์ œ์•ฝ์„ ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋งŽ์€ ํŠธ๋ฆฌ ์•™์ƒ๋ธ”์ด ํ•ด๋‹น ๊ธฐ๋Šฅ์˜ ์ „์ฒด ๋ฒ”์œ„์—์„œ ์ „์ฒด ๋‹จ์กฐ์„ฑ์„ ์œ„๋ฐ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„ค, ์ œ๊ฐ€ ์ดํ•ดํ•˜๊ธฐ๋กœ๋Š” ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์‹œํ–‰๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

๋‹จ๋ณ€๋Ÿ‰ ํšŒ๊ท€์˜ ๋งฅ๋ฝ์—์„œ ๋‹จ์กฐ์„ฑ ์ œ์•ฝ ์กฐ๊ฑด์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ฝ”๋“œ์™€ ๋งค์šฐ ๊ฐ„๋‹จํ•œ ๋ฌธ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/XiaoxiaoWang87/xgboost_mono_test/blob/master/xgb_monotonicity_constraint_testing1-univariate.ipynb

์ผ๋ถ€ ์ดˆ๊ธฐ ๊ด€์ฐฐ:

  • ๋‹จ์ผ ๋ณ€์ˆ˜ ํšŒ๊ท€ ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ๋‹จ์กฐ ์ œ์•ฝ ์กฐ๊ฑด = +1์ด ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ๋‹จ์ผ ๋ณ€์ˆ˜ ํšŒ๊ท€ ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ ๋‚ด ๋ฐ์ดํ„ฐ ์„ธํŠธ์—์„œ ๋‹จ์กฐ ์ œ์•ฝ ์กฐ๊ฑด = -1์€ ๋‹จ์กฐ๋กญ๊ฒŒ ๊ฐ์†Œํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜คํžˆ๋ ค ์ƒ์ˆ˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ ์šฉํ•  ๋•Œ ๊ฐœ์„ ์ด ๋ถ€์กฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์ธํ•˜๋ ค๋ฉด(Tianqi์˜ ์ œ์•ˆ์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ๋’ค์ง‘๊ณ  ์ œ์•ฝ ์กฐ๊ฑด์„ +1๋กœ ์„ค์ •ํ•ด ๋ณด์„ธ์š”).
  • ์ œ์•ฝ ์กฐ๊ฑด์„ (์˜ฌ๋ฐ”๋ฅด๊ฒŒ) ์ถ”๊ฐ€ํ•˜๋ฉด ์ž ์žฌ์ ์œผ๋กœ ๊ณผ์ ํ•ฉ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์ผ๋ถ€ ์„ฑ๋Šฅ/ํ•ด์„ ์ด์ ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Constraint = -1 ๊ฒฝ์šฐ์— ๋ฒ„๊ทธ๋ฅผ ๋„์ž…ํ•œ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ˆ˜์ •์„ ํ‘ธ์‹œํ–ˆ๋Š”๋ฐ ์ตœ์‹  ๋ฒ„์ „์ด ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. ์—ฌ๋Ÿฌ ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

@tqchen ๊ฐ์†Œ ๋ฒ„๊ทธ์— ๋Œ€ํ•œ ์ˆ˜์ • ์‚ฌํ•ญ์„ ํ…Œ์ŠคํŠธํ–ˆ๋Š”๋ฐ ์ง€๊ธˆ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

xgboost-no-constraint
xgboost-with-constraint

์ผ๋ถ€ ํ‘œ์ค€ ๋ฐ์ดํ„ฐ ์„ธํŠธ์—์„œ ์›๋ž˜ ๋ฒ„์ „์— ๋น„ํ•ด ์†๋„๊ฐ€ ๊ฐ์†Œํ•˜๋Š”์ง€ ํ™•์ธํ•œ ๋‹ค์Œ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@tqchen ๋‘ ๊ฐœ์˜ ๋ณ€์ˆ˜ ๋ชจ๋ธ์„ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ์ฆ๊ฐ€ํ•˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๊ฐ์†Œํ•˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ์Šต๋‹ˆ๋‹ค.

params_constrained = params.copy()
params_constrained['updater'] = "grow_monotone_colmaker,prune"
params_constrained['monotone_constraints'] = "(1,-1)"

๊ฒฐ๊ณผ๋Š” ์ข‹๋‹ค

xgboost-two-vars-increasing
xgboost-two-vars-decreasing

์˜ค๋Š˜ ์˜คํ›„์— ์•ฝ๊ฐ„์˜ ํƒ€์ด๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ์‹œ๊ฐ„์„ ์ฐพ๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

montone ์˜ต์…˜์˜ ์ž๋™ ๊ฐ์ง€๋ฅผ ํ—ˆ์šฉํ•˜๋„๋ก #1516์„ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์‚ฌ์šฉ์ž๋Š” monotone_constraints = "(0,1,1,0)" ๋งŒ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

์†๋„ ํ…Œ์ŠคํŠธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ง„ํ–‰๋˜๋ฉด ์ด๊ฒƒ์„ ๋ณ‘ํ•ฉํ•˜๊ณ  ํŠœํ† ๋ฆฌ์–ผ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

@madrury @ XiaoxiaoWang87

์—ฌ๊ธฐ์— ๋‹ค๋ณ€์ˆ˜ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

https://github.com/XiaoxiaoWang87/xgboost_mono_test/blob/master/xgb_monotonicity_constraint_testing2-multivariate.ipynb

  • ์ด์ œ ๋‹จ์กฐ ์ œ์•ฝ ์กฐ๊ฑด = 1 ๋ฐ = -1์ด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹จ์กฐ์„ฑ์„ ์ œํ•œํ•ด๋„ ๋ช…๋ฐฑํ•œ ์†๋„* ์ €ํ•˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    *speed = avg [ ์กฐ๊ธฐ ์ •์ง€๊นŒ์ง€์˜ ์‹œ๊ฐ„ / ์กฐ๊ธฐ ์ •์ง€๊นŒ์ง€์˜ ๋ถ€์ŠคํŒ… ๋ฐ˜๋ณต ํšŸ์ˆ˜ ]

no constraint: 964.9 microseconds per iteration
with constraint: 861.7 microseconds per iteration

(์†๋„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค)

  • non-monotonic ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋ฐฉํ–ฅ์„ ์ œํ•œํ•  ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹ค๋ฅธ ํ•˜์ดํผ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Check failed: (wleft) <= (wright) ๋กœ ์ธํ•ด ์ฝ”๋“œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Jupyter ๋…ธํŠธ๋ถ์—์„œ ๋ช‡ ๊ฐ€์ง€ ํƒ€์ด๋ฐ ์‹คํ—˜์„ ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๋ช‡ ๊ฐ€์ง€ ๊ฐ„๋‹จํ•œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ฐ์ดํ„ฐ. ํ•˜๋‚˜๋Š” ์ฆ๊ฐ€ํ•˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๊ฐ์†Œํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ์žˆ์ง€๋งŒ ๊ฐ ๊ธฐ๋Šฅ์ด ์ง„์ •์œผ๋กœ ๋‹จ์กฐ๋กญ์ง€ ์•Š๋„๋ก ์ค‘์ฒฉ๋œ ์ž‘์€ ์‚ฌ์ธํŒŒ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

X = np.random.random(size=(N, K))
y = (5*X[:, 0] + np.sin(5*2*pi*X[:, 0])
     - 5*X[:, 1] - np.cos(5*2*pi*X[:, 1])
     + np.random.normal(loc=0.0, scale=0.01, size=N))

๋‹ค์Œ์€ ๋ชจ๋…ธํ†ค ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ๊ฑฐ๋‚˜ ์—†๋Š” xgboost์˜ ํƒ€์ด๋ฐ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์กฐ๊ธฐ ์ค‘์ง€๋ฅผ ๋„๊ณ  ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์„ค์ •๋œ ๋ฐ˜๋ณต ํšŸ์ˆ˜๋ฅผ ๋Š˜๋ ธ์Šต๋‹ˆ๋‹ค.

๋ชจ๋…ธํ†ค ์ œ์•ฝ์ด ์—†๋Š” ์ฒซ ๋ฒˆ์งธ:

%%timeit -n 100
model_no_constraints = xgb.train(params, dtrain, 
                                 num_boost_round = 2500, 
                                 verbose_eval = False)

100 loops, best of 3: 246 ms per loop

๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์— ๋‹จ์กฐ์„ฑ ์ œ์•ฝ ์กฐ๊ฑด์ด ์žˆ์Šต๋‹ˆ๋‹ค.

%%timeit -n 100
model_with_constraints = xgb.train(params_constrained, dtrain, 
                                 num_boost_round = 2500, 
                                 verbose_eval = False)

100 loops, best of 3: 196 ms per loop

๋‘ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: sklearn์˜ ์บ˜๋ฆฌํฌ๋‹ˆ์•„ hHousing ๋ฐ์ดํ„ฐ. ์ œ์•ฝ ์—†์ด

%%timeit -n 10
model_no_constraints = xgb.train(params, dtrain, 
                                 num_boost_round = 2500, 
                                 verbose_eval = False)

10 loops, best of 3: 5.9 s per loop

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ ์ œ์•ฝ ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค.

print(params_constrained['monotone_constraints'])

(1,1,1,0,0,1,0,0)

๊ทธ๋ฆฌ๊ณ  ์ œ์•ฝ ๋ชจ๋ธ์˜ ํƒ€์ด๋ฐ

%%timeit -n 10
model_no_constraints = xgb.train(params, dtrain, 
                                 num_boost_round = 2500, 
                                 verbose_eval = False)

10 loops, best of 3: 6.08 s per loop

@XiaoxiaoWang87 ๋‚˜๋Š” wleft์™€ wright์— ๋Œ€ํ•œ ์ˆ˜ํ‘œ๋ฅผ ํ’€๊ธฐ ์œ„ํ•ด ๋˜ ๋‹ค๋ฅธ PR์„ ํ‘ธ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.
@madrury ์ œ์•ฝ ๊ธฐ๋Šฅ์ด ์—†๋Š” ์ด์ „ ๋ฒ„์ „์˜ XGBoost์™€๋„ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@tqchen ๋ฌผ๋ก ์ž…๋‹ˆ๋‹ค. ๋น„๊ตํ•  ์ปค๋ฐ‹ ํ•ด์‹œ๋ฅผ ์ถ”์ฒœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ชจ๋…ธํ†ค ์ œ์•ฝ ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ์ปค๋ฐ‹์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์˜ˆ ์ด์ „ ๊ฒƒ์ด ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค

@tqchen ์—…๋ฐ์ดํŠธ๋œ ๋ฒ„์ „์„ ๋‹ค์‹œ ๋นŒ๋“œํ•  ๋•Œ ์ด์ „์— ์—†์—ˆ๋˜ ๋ช‡ ๊ฐ€์ง€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ ์ด์œ ๊ฐ€ ๋‹น์‹ ์—๊ฒŒ ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด์ „๊ณผ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ์—ญ์ถ”์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

XGBoostError                              Traceback (most recent call last)
<ipython-input-14-63a9f6e16c9a> in <module>()
      8    model_with_constraints = xgb.train(params, dtrain, 
      9                                        num_boost_round = 1000, evals = evallist,
---> 10                                    early_stopping_rounds = 10)  

/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/training.pyc in train(params, dtrain, num_boost_round, evals, obj, feval, maximize, early_stopping_rounds, evals_result, verbose_eval, learning_rates, xgb_model, callbacks)
    201                            evals=evals,
    202                            obj=obj, feval=feval,
--> 203                            xgb_model=xgb_model, callbacks=callbacks)
    204 
    205 

/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/training.pyc in _train_internal(params, dtrain, num_boost_round, evals, obj, feval, xgb_model, callbacks)
     72         # Skip the first update if it is a recovery step.
     73         if version % 2 == 0:
---> 74             bst.update(dtrain, i, obj)
     75             bst.save_rabit_checkpoint()
     76             version += 1

/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/core.pyc in update(self, dtrain, iteration, fobj)
    804 
    805         if fobj is None:
--> 806             _check_call(_LIB.XGBoosterUpdateOneIter(self.handle, iteration, dtrain.handle))
    807         else:
    808             pred = self.predict(dtrain)

/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/core.pyc in _check_call(ret)
    125     """
    126     if ret != 0:
--> 127         raise XGBoostError(_LIB.XGBGetLastError())
    128 
    129 

XGBoostError: [14:08:41] src/tree/tree_updater.cc:18: Unknown tree updater grow_monotone_colmaker

๊ตฌํ˜„ํ•œ ํ‚ค์›Œ๋“œ ์ธ์ˆ˜์— ๋Œ€ํ•ด ๋ชจ๋“  ๊ฒƒ์„ ๋ฐ”๊พธ๋ฉด ์˜ค๋ฅ˜๋„ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

TypeError                                 Traceback (most recent call last)
<ipython-input-15-ef7671f72925> in <module>()
      8                                    monotone_constraints="(1)",
      9                                    num_boost_round = 1000, evals = evallist,
---> 10                                    early_stopping_rounds = 10)  

TypeError: train() got an unexpected keyword argument 'monotone_constraints'

์—…๋ฐ์ดํ„ฐ ์ธ์ˆ˜๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋ชจ๋…ธํ†ค ์ œ์•ฝ ์กฐ๊ฑด ์ธ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋ชจ๋…ธํ†ค ์ œ์•ฝ ์กฐ๊ฑด์ด ํ‘œ์‹œ๋  ๋•Œ ๋ชจ๋…ธํ†ค ์ œ์•ฝ ์—…๋ฐ์ดํ„ฐ๊ฐ€ ์ž๋™์œผ๋กœ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

@tqchen ๋‚ด ์นœ๊ตฌ @amontz ๊ฐ€ ๋‚ด๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฒŒ์‹œํ•œ ์งํ›„์— ๊ทธ๊ฒƒ์„ ์•Œ์•„ monotone_constraints ๋ฅผ .train kwarg๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ•ด์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์กฐ์ •๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”.

@madrury ์†๋„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋˜ํ•œ @madrury ์™€ @XiaoxiaoWang87 ์€ ์ด ๊ธฐ๋Šฅ์ด ์ด์ œ ๊ฑฐ์˜ ๋ณ‘ํ•ฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์†Œ๊ฐœํ•˜๋Š” ์ž์Šต์„œ๋ฅผ ๋งŒ๋“ค๋„๋ก ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ipy ๋…ธํŠธ๋ถ์„ ๋ฉ”์ธ ์ €์žฅ์†Œ๋กœ ์ง์ ‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฏธ์ง€๋Š” https://github.com/dmlc/web-data/tree/master/xgboost ๋กœ ํ‘ธ์‹œํ•˜๊ณ  ๊ธฐ๋ณธ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ ๋งˆํฌ๋‹ค์šดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ int ํŠœํ”Œ์„ ๋ฐฑ์—”๋“œ์—์„œ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ž์—ด ํŠœํ”Œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ”„๋ŸฐํŠธ ์—”๋“œ ์ธํ„ฐํŽ˜์ด์Šค ๋ฌธ์ž์—ด ๋ณ€ํ™˜์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@hetong007 R์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๋ฐ @slundberg ์˜ Julia

@tqchen Julia๋Š” ํ˜„์žฌ 0.4 ๋ฒ„์ „์˜ XGBoost์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์Œ์— ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ  ์‹œ๊ฐ„์ด ์žˆ์„ ๋•Œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์—†๋Š” ๊ฒฝ์šฐ ๋ฐ”์ธ๋”ฉ์„ ์—…๋ฐ์ดํŠธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ ์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๊ตฌํ˜„ ์ด์ „๋ถ€ํ„ฐ ์ดํ›„๊นŒ์ง€ ๋ชจ๋…ธํ†ค ์ œ์•ฝ์ด _์—†๋Š”_ ๋ชจ๋ธ ๊ฐ„์˜ ๋น„๊ต์ž…๋‹ˆ๋‹ค.

Commit 8cac37 : ๋ชจ๋…ธํ†ค ์ œ์•ฝ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „.'
์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ฐ์ดํ„ฐ : 100 loops, best of 3: 232 ms per loop
์บ˜๋ฆฌํฌ๋‹ˆ์•„ ๋ฐ์ดํ„ฐ : 10 loops, best of 3: 5.89 s per loop

Commit b1c224 : ๋ชจ๋…ธํ†ค ์ œ์•ฝ์„ ๊ตฌํ˜„ํ•œ ํ›„.
์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ฐ์ดํ„ฐ : 100 loops, best of 3: 231 ms per loop
์บ˜๋ฆฌํฌ๋‹ˆ์•„ ๋ฐ์ดํ„ฐ : 10 loops, best of 3: 5.61 s per loop

๊ตฌํ˜„ ํ›„ ์บ˜๋ฆฌํฌ๋‹ˆ์•„์˜ ์†๋„ ํ–ฅ์ƒ์ด ์˜์‹ฌ์Šค๋Ÿฌ์›Œ ๋ณด์ด์ง€๋งŒ ๊ฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‘ ๋ฒˆ ์‹œ๋„ํ–ˆ์œผ๋ฉฐ ์ผ๊ด€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํŠœํ† ๋ฆฌ์–ผ์„ ์ž‘์„ฑํ•˜๋Š” ๊ธฐํšŒ๋ฅผ ๊ฐ–๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ธฐ์กด ๋ฌธ์„œ๋ฅผ ๋‘˜๋Ÿฌ๋ณด๊ณ  ์•ž์œผ๋กœ ๋ฉฐ์น  ์•ˆ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ์ •๋ฆฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ PR์ด ๊ณต์‹์ ์œผ๋กœ ๋งˆ์Šคํ„ฐ์— ๋ณ‘ํ•ฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํŠœํ† ๋ฆฌ์–ผ์„ ๋ณผ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค

@madrury๋‹˜ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•˜๋‹ค. ๋‚ด๊ฐ€ ๋ฌด์—‡์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ๋ ค์ฃผ์„ธ์š”. ๋‚˜๋Š” ํ™•์‹คํžˆ ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ์—ฐ๊ตฌ๋ฅผ ํ•  ์˜ํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด์ผ ๊ฐ•ํ™”ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด ๋Œ€์‹  ๋ฌธ์ž์—ด์„ ํ†ตํ•ด C++์™€ ํ†ต์‹ ํ•˜๋Š” ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” R์—์„œ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ฌด์ž‘์œ„๋กœ ๋‘ ๊ฐœ์˜ ๋ณ€์ˆ˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์˜ˆ์ธก์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

  1. xgboost๋Š” ์˜ˆ์ธก์„ ์ œํ•œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  2. monotone_constraints ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์˜ˆ์ธก์„ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ œ๊ฐ€ ์‹ค์ˆ˜ํ•œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ์ง€์ ํ•ด์ฃผ์„ธ์š”.

๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ ( drat ์•„๋‹Œ ์ตœ์‹  github ๋ฒ„์ „ ์—์„œ ํ…Œ์ŠคํŠธ):

set.seed(1024)
x1 = rnorm(1000, 10)
x2 = rnorm(1000, 10)
y = -1*x1 + rnorm(1000, 0.001) + 3*sin(x2)
train = cbind(x1, x2)

bst = xgboost(data = train, label = y, max_depth = 2,
                   eta = 0.1, nthread = 2, nrounds = 10,
                   monotone_constraints = '(1,-1)')

pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'with constraint')
pred.ord = pred[order(train[,1])]
lines(pred.ord)

wc

bst = xgboost(data = train, label = y, max_depth = 2,
                   eta = 0.1, nthread = 2, nrounds = 10)

pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'without constraint')
pred.ord = pred[order(train[,1])]
lines(pred.ord)

woc

์ œ์•ฝ์€ ๋ถ€๋ถ„ ์ฃผ๋ฌธ์— ๋Œ€ํ•ด ์ˆ˜ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ œ์•ฝ ์กฐ๊ฑด์€ montone ์ถ•์„ ์ด๋™ํ•˜๊ณ  ๋‹ค๋ฅธ ์ถ•์€ ๊ณ ์ •๋œ ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

@hetong007 ๋‚ด ์Œ๋ชจ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋‚˜๋Š”

  • x ์ขŒํ‘œ ๊ทธ๋ฆฌ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜์—ฌ ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ์˜ˆ์ธกํ•œ ๋‹ค์Œ ์„  ํ”Œ๋กฏ์— ๊ฒฐํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ R์—์„œ seq ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹ค๋ฅธ ๋ชจ๋“  ๋ณ€์ˆ˜๋ฅผ ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์˜ ํ‰๊ท ๊ฐ’๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ R์˜ colmeans ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ๋‚ด๊ฐ€ ์œ„์— ํฌํ•จ๋œ ํ”Œ๋กฏ์— ์‚ฌ์šฉํ•œ ํŒŒ์ด์ฌ ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™๋“ฑํ•œ R ์ฝ”๋“œ๋กœ ๊ฝค ์‰ฝ๊ฒŒ ๋ณ€ํ™˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

def plot_one_feature_effect(model, X, y, idx=1):

    x_scan = np.linspace(0, 1, 100)    
    X_scan = np.empty((100, X.shape[1]))
    X_scan[:, idx] = x_scan

    left_feature_means = np.tile(X[:, :idx].mean(axis=0), (100, 1))
    right_feature_means = np.tile(X[:, (idx+1):].mean(axis=0), (100, 1))
    X_scan[:, :idx] = left_feature_means
    X_scan[:, (idx+1):] = right_feature_means

    X_plot = xgb.DMatrix(X_scan)
    y_plot = model.predict(X_plot, ntree_limit=bst.best_ntree_limit)

    plt.plot(x_scan, y_plot, color = 'black')
    plt.plot(X[:, idx], y, 'o', alpha = 0.25)

๋‹ค์Œ์€ ๋ถ€๋ถ„ ์ข…์†์„ฑ ํ”Œ๋กฏ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค(์ž„์˜ ๋ชจ๋ธ์˜ ๊ฒฝ์šฐ).

  • ๊ธฐ๋Šฅ X์— ๋Œ€ํ•œ ๊ฐ’ ๊ทธ๋ฆฌ๋“œ๋ฅผ ์Šค์บ”ํ•ฉ๋‹ˆ๋‹ค.
  • ํŠน์„ฑ X์˜ ๋ชจ๋“  ๊ทธ๋ฆฌ๋“œ ๊ฐ’์— ๋Œ€ํ•ด:

    • ์ „์ฒด ๊ธฐ๋Šฅ X ์—ด(๋ชจ๋“  ํ–‰)์„ ์ด ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

    • ๋ชจ๋“  ํ–‰์— ๋Œ€ํ•ด ์˜ˆ์ธกํ•ฉ๋‹ˆ๋‹ค.

    • ์˜ˆ์ธก์˜ ํ‰๊ท ์„ ์ทจํ•˜์‹ญ์‹œ์˜ค.

  • ๊ฒฐ๊ณผ(X ํŠน์„ฑ ๊ฐ’, ํ‰๊ท  ์˜ˆ์ธก) ์Œ์€ X ํŠน์„ฑ ๋ถ€๋ถ„ ์ข…์†์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์•”ํ˜ธ:

def plot_partial_dependency(bst, X, y, f_id):

    X_temp = X.copy()

    x_scan = np.linspace(np.percentile(X_temp[:, f_id], 0.1), np.percentile(X_temp[:, f_id], 99.5), 50)
    y_partial = []

    for point in x_scan:

        X_temp[:, f_id] = point

        dpartial = xgb.DMatrix(X_temp[:, feature_ids])
        y_partial.append(np.average(bst.predict(dpartial)))

    y_partial = np.array(y_partial)

    # Plot partial dependence

    fig, ax = plt.subplots()
    fig.set_size_inches(5, 5)
    plt.subplots_adjust(left = 0.17, right = 0.94, bottom = 0.15, top = 0.9)

    ax.plot(x_scan, y_partial, '-', color = 'black', linewidth = 1)
    ax.plot(X[:, f_id], y, 'o', color = 'blue', alpha = 0.02)

    ax.set_xlim(min(x_scan), max(x_scan))
    ax.set_xlabel('Feature X', fontsize = 10)    
    ax.set_ylabel('Partial Dependence', fontsize = 12)

์•ˆ๋‚ดํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚˜๋Š” ๋‚ด๊ฐ€ ์ค„๊ฑฐ๋ฆฌ์—์„œ ์–ด๋ฆฌ์„์€ ์‹ค์ˆ˜๋ฅผ ์ €์งˆ๋ €๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๋‹ค. ๋‹ค์Œ์€ ์ผ๋ณ€๋Ÿ‰ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋˜ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. ํ”Œ๋กฏ์€ ๊ดœ์ฐฎ์•„ ๋ณด์ž…๋‹ˆ๋‹ค.

set.seed(1024)
x = rnorm(1000, 10)
y = -1*x + rnorm(1000, 0.001) + 3*sin(x)
train = matrix(x, ncol = 1)

bst = xgboost(data = train, label = y, max_depth = 2,
               eta = 0.1, nthread = 2, nrounds = 100,
               monotone_constraints = '(-1)')
pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'with constraint', pch=20)
lines(train[ind,1], pred.ord, col=2, lwd = 5)

rplot

bst = xgboost(data = train, label = y, max_depth = 2,
               eta = 0.1, nthread = 2, nrounds = 100)
pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'without constraint', pch=20)
lines(train[ind,1], pred.ord, col=2, lwd = 5)

woc

@hetong007 ๋”ฐ๋ผ์„œ R ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชฉํ‘œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌธ์ž์—ด ์™ธ์— R ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

monotone_constraints=c(1,-1)

PR ํŠœํ† ๋ฆฌ์–ผ์ด ๋˜๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”.

@hetong007 r-blogger ๋ฒ„์ „์„

@tqchen ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค ์—ฌ๋Ÿฌ๋ถ„, ์ €๋Š” ์ผ์ฃผ์ผ ๋™์•ˆ ์ถœ์žฅ์„

๋‚˜๋Š” monotonic constraint tutorial์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ pull ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์˜ ์ƒ๊ฐ์„ ์•Œ๋ ค์ฃผ์„ธ์š”. ์–ด๋–ค ๋น„ํŒ์ด๋‚˜ ๋น„ํŒ๋„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์งˆ๋ฌธํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ git clone --recursive https://github.com/dmlc/xgboost ์‚ฌ์šฉํ•˜์—ฌ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ์ด๊ฒƒ์ด ์ž‘๋™ํ• ๊นŒ์š”?

์ƒˆ๋กœ์šด ํŠœํ† ๋ฆฌ์–ผ์„ ๋ณด์•˜์„ ๋•Œ ๋ฌป์ง€๋งŒ ์ฝ”๋“œ ์ž์ฒด์˜ ๋ณ€๊ฒฝ์— ๋Œ€ํ•ด์„œ๋Š” ์ƒˆ๋กœ์šด ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์˜ˆ, ํŠœํ† ๋ฆฌ์–ผ์ด ๋ณ‘ํ•ฉ๋˜๊ธฐ ์ „์— ์ƒˆ ๊ธฐ๋Šฅ์ด ๋ณ‘ํ•ฉ๋ฉ๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”,

๋‚˜๋Š” ๋‹น์‹ ์ด ๋‹น์‹ ์˜ ์ฝ”๋“œ์—์„œ ๋ณธ ๊ฒƒ๊ณผ ๊ฐ™์ด ์ „์—ญ์  ๋‹จ์กฐ๋กœ์›€์„ ์„ฑ๊ณต์ ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ง€์—ญ์  ๋‹จ์กฐ๋กœ์›€์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๋‹จ์กฐ๋กœ์›€์„ ๊นจ๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค.

`
df <- data.frame(y = c(2,rep(6,100),1,rep(11,100)),
x1= c(rep(1,101),rep(2,101)),x2 = c(1,rep(2,100),1,rep(2,100)))

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(xgboost)
set.seed(0)
XGB <- xgboost(data=data.matrix(df[,-1]),label=df[,1],
๋ชฉ์ =" ๋“ฑ๋ก:์„ ํ˜• ",
bag.fraction=1,nround=100,monotone_constraints=c(1,0),
์—ํƒ€=0.1 )

sans_corr <- data.frame(x1=c(1,2,1,2),x2=c(1,1,2,2))

sans_corr$prediction <- predict(XGB,data.matrix(sans_corr))
`

๊ท€ํ•˜์˜ ์ฝ”๋“œ์™€ ์˜ˆ์— ๋Œ€ํ•œ ์ œ ์ดํ•ด๊ฐ€ ๊ฑฐ์ง“์ด ์•„๋‹ˆ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ด ๊ธฐ๋Šฅ์€ Sklearn API์— ์—†์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด๋‚˜ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ทธ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๊ฐ์‚ฌ ํ•ด์š”!

์ฆ๊ฐ€ ๋˜๋Š” ๊ฐ์†Œ ์—ฌ๋ถ€๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ๋ณ€์ˆ˜์— ์ผ๋ฐ˜์ ์ธ ๋‹จ์กฐ์„ฑ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@davidADSP ์›ํ•˜๋Š” ์˜ˆ์ธก ๋ณ€์ˆ˜์™€ ๋Œ€์ƒ์— ๋Œ€ํ•ด ์Šคํ”ผ์–ด๋งจ ์ƒ๊ด€ ๊ด€๊ณ„ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ์ฆ๊ฐ€ ๋˜๋Š” ๊ฐ์†Œ๊ฐ€ ์ ์ ˆํ•œ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์€ 'tree_method':'hist'์ผ ๋•Œ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. @tqchen ๋„์›€์ด

์ œ์•ฝ ์กฐ๊ฑด์€ mlogloss์™€ ๊ฐ™์€ ๋‹ค์ค‘ ํด๋ž˜์Šค ๋ชฉํ‘œ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ? ๋‹ค์ค‘ ํด๋ž˜์Šค ์†์‹ค์— ๋Œ€ํ•ด ๋‹จ์กฐ์„ฑ ์ œ์•ฝ์ด ์ง€์›๋ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ์‹œํ–‰๋ฉ๋‹ˆ๊นŒ? (๊ฐ ํด๋ž˜์Šค์—๋Š” ๋‚˜๋ฌด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค)

XGBOOST์— ์ ์šฉ๋œ Monoticity Algorithm์— ๋Œ€ํ•œ ๋ฐฑ์„œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ธ€๋กœ๋ฒŒ ๋˜๋Š” ๋กœ์ปฌ์ž…๋‹ˆ๊นŒ? ๋กœ์ปฌ์€ ํŠน์ • ๋…ธ๋“œ์— ํŠน์ •ํ•œ ๊ฒƒ์„ ์˜๋ฏธํ•˜์ง€๋งŒ ํŠธ๋ฆฌ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ์žˆ๋Š” ๋…ธ๋“œ๋Š” ์ „์ฒด ๋‹จ์กฐ์„ฑ์„ ์œ„๋ฐ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ˆ„๊ตฌ๋“ ์ง€ L412-417 ์ค„์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์„ธ์š”. "w"๊ฐ€ ์œ„์ชฝ๊ณผ ์•„๋ž˜์ชฝ์œผ๋กœ ์ œํ•œ๋˜๋Š” ์ด์œ . ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋‹จ์กฐ์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š”์ง€. 457ํ–‰ - "mid"๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰