Compare commits
817 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e343159ef | ||
|
|
99e802f2ff | ||
|
|
6a29afb480 | ||
|
|
8e321adac8 | ||
|
|
d0ec65520a | ||
|
|
7aec915dcd | ||
|
|
a78d0d4110 | ||
|
|
76c361431f | ||
|
|
d95d02132a | ||
|
|
7109c6c1f2 | ||
|
|
bce7ca313c | ||
|
|
8be2cd8c91 | ||
|
|
c5f0cdbc72 | ||
|
|
1bf3899983 | ||
|
|
c39f6b25f0 | ||
|
|
2b3e301543 | ||
|
|
10d3419fa6 | ||
|
|
b273e5bd4c | ||
|
|
3a83fcb0eb | ||
|
|
3efc4ea0d1 | ||
|
|
a2c778e2d1 | ||
|
|
8a0db293c5 | ||
|
|
028ec5f028 | ||
|
|
38c80bcec4 | ||
|
|
16ff63905d | ||
|
|
a9b09919f9 | ||
|
|
f3b060401a | ||
|
|
42d31d9dcb | ||
|
|
2ce2a1a4d8 | ||
|
|
cc581b3b6b | ||
|
|
00218d065a | ||
|
|
c120822a24 | ||
|
|
a7b42adb74 | ||
|
|
44a9d69efb | ||
|
|
9c9070aea2 | ||
|
|
c763b50dd0 | ||
|
|
4d1d5d4010 | ||
|
|
e426b6e040 | ||
|
|
3cca1c5fa1 | ||
|
|
3ac173fc8b | ||
|
|
ae1662028a | ||
|
|
5cb24d0d39 | ||
|
|
512b464cfa | ||
|
|
fcd6fad822 | ||
|
|
4ccf92ea34 | ||
|
|
fcfeb4959c | ||
|
|
e5193c21a1 | ||
|
|
5a33c2f3a0 | ||
|
|
c1a62b5fa2 | ||
|
|
c90f968d92 | ||
|
|
c5645180a6 | ||
|
|
12d27f43ff | ||
|
|
d711d648cb | ||
|
|
debeae2509 | ||
|
|
6e12c2a6f8 | ||
|
|
8a17610666 | ||
|
|
7f101d1b33 | ||
|
|
a5cfa7841e | ||
|
|
43efadea2e | ||
|
|
9564886d9f | ||
|
|
e65e3cf36e | ||
|
|
184e2eac7d | ||
|
|
d411f98d26 | ||
|
|
519cee115a | ||
|
|
f3a4253984 | ||
|
|
51e6531315 | ||
|
|
2cc9662005 | ||
|
|
29745c6df2 | ||
|
|
7756192906 | ||
|
|
5a7b3592ed | ||
|
|
048acf81cd | ||
|
|
5e1e972aea | ||
|
|
f0fe18fc28 | ||
|
|
6ff331b705 | ||
|
|
b181a88f9f | ||
|
|
c80657b542 | ||
|
|
608bda7052 | ||
|
|
74ea82209b | ||
|
|
dfac5f89e9 | ||
|
|
6383757dca | ||
|
|
d261ba029a | ||
|
|
671971e12e | ||
|
|
e8884c4637 | ||
|
|
143b278267 | ||
|
|
c4da967b5c | ||
|
|
f6169c0b16 | ||
|
|
3310e208fd | ||
|
|
cc76724762 | ||
|
|
4e9c4f2d73 | ||
|
|
e1de390e6e | ||
|
|
f0c3ff313f | ||
|
|
b180223d18 | ||
|
|
8e0f5a6fc7 | ||
|
|
c8ec62103a | ||
|
|
bcfab4d726 | ||
|
|
d61b628bf5 | ||
|
|
2686d32a36 | ||
|
|
677f676172 | ||
|
|
1300467d36 | ||
|
|
b5c2a47b20 | ||
|
|
81c37c28d5 | ||
|
|
d1254808d5 | ||
|
|
ddf37cca30 | ||
|
|
7f6ed5780c | ||
|
|
5037abeb86 | ||
|
|
cdcdab98b8 | ||
|
|
65ea42bd42 | ||
|
|
549f361b71 | ||
|
|
6d293020fb | ||
|
|
52452bebb9 | ||
|
|
3098d7cee0 | ||
|
|
3da5a69dc9 | ||
|
|
06e453ddf4 | ||
|
|
b51a717deb | ||
|
|
bed7ae4083 | ||
|
|
734a911a26 | ||
|
|
0fc263ead5 | ||
|
|
b05073bda5 | ||
|
|
2443275891 | ||
|
|
70c2039748 | ||
|
|
2241563f23 | ||
|
|
ab5b35134f | ||
|
|
b5b24354b8 | ||
|
|
c991eb612d | ||
|
|
70ce5216b5 | ||
|
|
6bc9747df5 | ||
|
|
a4ce0eae43 | ||
|
|
4cfdcaaf7b | ||
|
|
ddc4f20e54 | ||
|
|
a2fea33103 | ||
|
|
5908598666 | ||
|
|
1013224888 | ||
|
|
f121f2738f | ||
|
|
fd58005edf | ||
|
|
750bd0ae9a | ||
|
|
cf4f019ed6 | ||
|
|
e0e4f15d0e | ||
|
|
eb7946ff25 | ||
|
|
6bc41df2fe | ||
|
|
f0c63902ff | ||
|
|
444131a2e6 | ||
|
|
798af22ff4 | ||
|
|
7622b8cdb8 | ||
|
|
52c0b3f100 | ||
|
|
dda9e1e487 | ||
|
|
434a3f35a3 | ||
|
|
07355599c2 | ||
|
|
e6a238c020 | ||
|
|
03b8fdec74 | ||
|
|
2c4dedb7a0 | ||
|
|
bd2b1eabd0 | ||
|
|
72ef553550 | ||
|
|
5b05f88ba9 | ||
|
|
14afdb4d92 | ||
|
|
78d72ef936 | ||
|
|
678ea40b24 | ||
|
|
c686bc0461 | ||
|
|
e033caa3ba | ||
|
|
452ac8ea62 | ||
|
|
33d80ffad0 | ||
|
|
7065779afa | ||
|
|
210c131ce7 | ||
|
|
c932fb50a1 | ||
|
|
a069a21e03 | ||
|
|
e319b63f9e | ||
|
|
cc82ca167a | ||
|
|
5384ed85c8 | ||
|
|
6bc9b9dc4f | ||
|
|
9e955fb9b0 | ||
|
|
33577ef5d3 | ||
|
|
47350f6acb | ||
|
|
b5f52f0b1b | ||
|
|
c6f2b8c841 | ||
|
|
1453bee3e7 | ||
|
|
07945290a2 | ||
|
|
c92d751ad1 | ||
|
|
08bdb2efc8 | ||
|
|
00b0ad1293 | ||
|
|
d0ccb13d09 | ||
|
|
9338582d79 | ||
|
|
3dcd85fab5 | ||
|
|
318bffaa10 | ||
|
|
b0001a6e29 | ||
|
|
da61d9460b | ||
|
|
93e9af43bb | ||
|
|
e5d40b39cd | ||
|
|
5994f3b14c | ||
|
|
974ba12f38 | ||
|
|
68c55a37d9 | ||
|
|
24ca9348f7 | ||
|
|
2e907abdb8 | ||
|
|
0e2d5669f6 | ||
|
|
3912f3de06 | ||
|
|
9be969cc7a | ||
|
|
ada964f16e | ||
|
|
c1ca872d1e | ||
|
|
3a990433f9 | ||
|
|
9bddecee05 | ||
|
|
2fcc4f2886 | ||
|
|
80c8547147 | ||
|
|
9c14e430af | ||
|
|
81d8dd79ca | ||
|
|
20c95be625 | ||
|
|
9a4e8b1d81 | ||
|
|
b3193052b3 | ||
|
|
4729458a36 | ||
|
|
cfced58c1c | ||
|
|
a144daf034 | ||
|
|
b9ebbffc57 | ||
|
|
7a46515d3d | ||
|
|
7be2e04bd4 | ||
|
|
1fd29edf66 | ||
|
|
24f2e6c97e | ||
|
|
29b7fea572 | ||
|
|
90355b4f00 | ||
|
|
f58e41bad8 | ||
|
|
e51cba6195 | ||
|
|
989ddd036f | ||
|
|
4d99c58a5f | ||
|
|
a418278064 | ||
|
|
14d5ce712c | ||
|
|
111968ca58 | ||
|
|
1c5904df3f | ||
|
|
d240463b38 | ||
|
|
511bb22ffd | ||
|
|
e3ec7b01df | ||
|
|
674c409e9d | ||
|
|
12e3fb6a6c | ||
|
|
9adb812a0a | ||
|
|
c3ea3b7e37 | ||
|
|
ee70a2380b | ||
|
|
bd6b7f4aa7 | ||
|
|
6f7112a848 | ||
|
|
f93f1c03fc | ||
|
|
0b2a26fa74 | ||
|
|
388f975cf5 | ||
|
|
7cf3e9be59 | ||
|
|
589b385ec6 | ||
|
|
801e6b6800 | ||
|
|
4acdd7c6f6 | ||
|
|
9c6e791e64 | ||
|
|
dde9c5aaff | ||
|
|
8599f87597 | ||
|
|
9c93531709 | ||
|
|
1149a7a292 | ||
|
|
b069431c28 | ||
|
|
e6cd74ead3 | ||
|
|
74bf00a5ab | ||
|
|
8fe7f5dc43 | ||
|
|
a6008d5d93 | ||
|
|
4fb34a008d | ||
|
|
2f7fcff4d7 | ||
|
|
6e563951af | ||
|
|
0d6a853212 | ||
|
|
493ad834a1 | ||
|
|
1907b25cd0 | ||
|
|
90e2239372 | ||
|
|
2f25347168 | ||
|
|
d22e0809a8 | ||
|
|
33dbc10aab | ||
|
|
8e2c201d23 | ||
|
|
ed9328ceae | ||
|
|
6dab74689c | ||
|
|
5d1b613910 | ||
|
|
af7281afe3 | ||
|
|
ddcc2d85da | ||
|
|
e92641887b | ||
|
|
d4ce6807c7 | ||
|
|
9a7ac85d7e | ||
|
|
5797dcb64e | ||
|
|
dba32d54d1 | ||
|
|
65b718a5e7 | ||
|
|
fc85f776f4 | ||
|
|
a429748e24 | ||
|
|
5c3b36f346 | ||
|
|
e3d51d3e62 | ||
|
|
ecd4bf7aae | ||
|
|
785d7e54d3 | ||
|
|
ed06e0c6af | ||
|
|
1cc34f01db | ||
|
|
0101a4719c | ||
|
|
05941a5f96 | ||
|
|
eb2590b774 | ||
|
|
3a35dabfae | ||
|
|
69cdfae22f | ||
|
|
785bde6f87 | ||
|
|
edc403fb2c | ||
|
|
87143deb4c | ||
|
|
fc5072b100 | ||
|
|
7bc46b8c75 | ||
|
|
440e81db0b | ||
|
|
0759d5ed2b | ||
|
|
2eb1a1a371 | ||
|
|
41c96a25a9 | ||
|
|
0b406754fa | ||
|
|
ab5f203b44 | ||
|
|
a1acf23b60 | ||
|
|
a764d45cfb | ||
|
|
21b5e12913 | ||
|
|
032152ad24 | ||
|
|
af1b7d6e7a | ||
|
|
a9a2a69dc1 | ||
|
|
cd1db1afaa | ||
|
|
1007a26641 | ||
|
|
7e15fdd9c6 | ||
|
|
2dd7476ad7 | ||
|
|
9d235c31a7 | ||
|
|
8f61535b83 | ||
|
|
b8aec1730c | ||
|
|
e19fced5cb | ||
|
|
849b20b7c8 | ||
|
|
be50e7b632 | ||
|
|
aeb4008606 | ||
|
|
1392e9f3da | ||
|
|
225f5258c7 | ||
|
|
56ec4263f9 | ||
|
|
e3188afbe8 | ||
|
|
c7d53aecc3 | ||
|
|
26c87ec6e7 | ||
|
|
f0f07ecd22 | ||
|
|
e814dc8a4b | ||
|
|
d45fca0298 | ||
|
|
7479791f6a | ||
|
|
73b6e9bbd0 | ||
|
|
112d866dc9 | ||
|
|
05b958c178 | ||
|
|
bed63208af | ||
|
|
291ab05023 | ||
|
|
de251635b1 | ||
|
|
3a6be65a20 | ||
|
|
e81a11dd7e | ||
|
|
35c3b371ea | ||
|
|
c71ed6fccb | ||
|
|
62e5647a33 | ||
|
|
732f1c634c | ||
|
|
2fa6e0245a | ||
|
|
053766503c | ||
|
|
7b59dcb8b8 | ||
|
|
5934950ce2 | ||
|
|
f5381871a3 | ||
|
|
44b60490f4 | ||
|
|
387339bf17 | ||
|
|
9d4397aa4a | ||
|
|
2879a4853b | ||
|
|
30e3110170 | ||
|
|
9ff0301515 | ||
|
|
6b629c2e81 | ||
|
|
32e19558e6 | ||
|
|
8f4839d1d9 | ||
|
|
93137b2e52 | ||
|
|
7eeeb79599 | ||
|
|
a8f00cc4a5 | ||
|
|
19b0f019c7 | ||
|
|
dd011849b7 | ||
|
|
c1cdc194e9 | ||
|
|
fcf0f4351a | ||
|
|
cbc21ae531 | ||
|
|
62ddfa7709 | ||
|
|
aefc05cb91 | ||
|
|
2aee9b4959 | ||
|
|
fe4e7c2b96 | ||
|
|
800198349f | ||
|
|
5ca33e48ea | ||
|
|
88f7d24de9 | ||
|
|
29d43ab52f | ||
|
|
fe8bb3b60e | ||
|
|
229c71d9b5 | ||
|
|
7424218392 | ||
|
|
d1d45bbdae | ||
|
|
1e8813f3bd | ||
|
|
1ccc9903a1 | ||
|
|
0323e0670e | ||
|
|
679a835d38 | ||
|
|
7ea5b7c209 | ||
|
|
b73e2be55e | ||
|
|
174228356d | ||
|
|
1838e25b8a | ||
|
|
bc4e957c39 | ||
|
|
fba6fc208c | ||
|
|
025110185e | ||
|
|
d50b905824 | ||
|
|
d4f2509178 | ||
|
|
cdf401a77c | ||
|
|
fef0ef26f1 | ||
|
|
cef360d782 | ||
|
|
c125d2a8bb | ||
|
|
270a49ee75 | ||
|
|
744f9015bb | ||
|
|
1cb5cad50c | ||
|
|
8cc07ba391 | ||
|
|
d74f126592 | ||
|
|
52b3dcdf07 | ||
|
|
099581b591 | ||
|
|
1258046f14 | ||
|
|
7addac910b | ||
|
|
0ea7adff92 | ||
|
|
f858856586 | ||
|
|
d8eac4ae27 | ||
|
|
3cc49ad0e8 | ||
|
|
ceedf4ea96 | ||
|
|
fd8920c71d | ||
|
|
8bbed35736 | ||
|
|
9520b90c4f | ||
|
|
df14bb1671 | ||
|
|
f441dc7ed8 | ||
|
|
2467942886 | ||
|
|
181ef47053 | ||
|
|
1582180e5b | ||
|
|
e0b7da0302 | ||
|
|
fa99857467 | ||
|
|
24f17df782 | ||
|
|
4fe8d1d66b | ||
|
|
a5d77ca08d | ||
|
|
d1d2ab4599 | ||
|
|
e1ddcc2eb7 | ||
|
|
6745667eb0 | ||
|
|
c5b4610cfe | ||
|
|
fed1683b9b | ||
|
|
c01520f173 | ||
|
|
27340f95e4 | ||
|
|
e03eabccda | ||
|
|
82ca10acb6 | ||
|
|
6601939588 | ||
|
|
df8f917463 | ||
|
|
c60b284e1f | ||
|
|
c67967161e | ||
|
|
f52daf9be1 | ||
|
|
7568f75f45 | ||
|
|
3bf8661ec1 | ||
|
|
18f4d6c0ba | ||
|
|
bcfbe51e7e | ||
|
|
ad383b084d | ||
|
|
3b8c04a902 | ||
|
|
9dd97cc141 | ||
|
|
ef13aaf379 | ||
|
|
50a66b3855 | ||
|
|
e08542c635 | ||
|
|
e95c96232a | ||
|
|
b15f6cd2ac | ||
|
|
5634ec3008 | ||
|
|
2dd6c2f0c9 | ||
|
|
38d7f999a7 | ||
|
|
8acb96a627 | ||
|
|
911a1f0ce2 | ||
|
|
732d8c33d1 | ||
|
|
684ea0ad26 | ||
|
|
8cb4c02165 | ||
|
|
be2ff703bc | ||
|
|
16975b447c | ||
|
|
eb1f4a4003 | ||
|
|
59e63bc135 | ||
|
|
62330505e1 | ||
|
|
14477f9f5a | ||
|
|
75a6d349c6 | ||
|
|
e3c76bfafb | ||
|
|
8b3c435241 | ||
|
|
2035799817 | ||
|
|
7751b2b320 | ||
|
|
769031375a | ||
|
|
bd346b4844 | ||
|
|
faba1dca6c | ||
|
|
6f7783e4f6 | ||
|
|
e5f034040e | ||
|
|
3ed9ec808f | ||
|
|
e552ac401e | ||
|
|
b2505e3d6f | ||
|
|
bc696c9273 | ||
|
|
f3e867ed97 | ||
|
|
5dc843cff3 | ||
|
|
cd9c81be91 | ||
|
|
1e23af2adc | ||
|
|
f165ffbc95 | ||
|
|
8cc650847a | ||
|
|
fad4d69ee4 | ||
|
|
0fd6197b8b | ||
|
|
7423837303 | ||
|
|
d25de54008 | ||
|
|
e5a9e31d13 | ||
|
|
ed3bee84c2 | ||
|
|
07740003b8 | ||
|
|
9b66e7edf2 | ||
|
|
6812f14886 | ||
|
|
08e1c16dd2 | ||
|
|
d6b68286ee | ||
|
|
146e069000 | ||
|
|
19cb685c40 | ||
|
|
4cf3c13750 | ||
|
|
20daddbeda | ||
|
|
c57dad8b17 | ||
|
|
295d8a12f1 | ||
|
|
994cb02a66 | ||
|
|
014c86603d | ||
|
|
091634b259 | ||
|
|
d558f6f550 | ||
|
|
c8efc01367 | ||
|
|
28ca7becbd | ||
|
|
ca4b20fad1 | ||
|
|
1133628c01 | ||
|
|
6a1167611c | ||
|
|
a607047aa1 | ||
|
|
2c1cfd8be6 | ||
|
|
4f28e32ebd | ||
|
|
2fbda812bc | ||
|
|
3258bcf531 | ||
|
|
67ebf81e7a | ||
|
|
9b6bf57e79 | ||
|
|
395d5c29d5 | ||
|
|
88ce76767e | ||
|
|
19be870562 | ||
|
|
a1bd3c64f0 | ||
|
|
1a573f987b | ||
|
|
29476f1c6b | ||
|
|
d4ec037f2e | ||
|
|
6612fcf36c | ||
|
|
d29892cb22 | ||
|
|
4fa054e26e | ||
|
|
75c647cd84 | ||
|
|
e4ce8efab5 | ||
|
|
76ecb4a031 | ||
|
|
2e1c4c945e | ||
|
|
4db0a62a06 | ||
|
|
87017bd4cd | ||
|
|
dc703e1b62 | ||
|
|
c171440324 | ||
|
|
7db2070598 | ||
|
|
581fe06a9b | ||
|
|
d2f252f87a | ||
|
|
4a5b9e5f78 | ||
|
|
12ee049a74 | ||
|
|
37a28376bb | ||
|
|
6ade7cba94 | ||
|
|
1bb8fe9615 | ||
|
|
fb13cab216 | ||
|
|
1479e370f8 | ||
|
|
0ca7a63670 | ||
|
|
5ef4830b55 | ||
|
|
93a13381c1 | ||
|
|
4ebe657dd7 | ||
|
|
85b746394e | ||
|
|
fe6366eb40 | ||
|
|
a98720ebc9 | ||
|
|
1db6449b01 | ||
|
|
c7282acb2a | ||
|
|
f332750359 | ||
|
|
9edb3b306f | ||
|
|
c46120a46b | ||
|
|
537497f520 | ||
|
|
56a80f431b | ||
|
|
774d501c1f | ||
|
|
7396c87249 | ||
|
|
c7533f92bb | ||
|
|
38b7fec37a | ||
|
|
c798fc2a29 | ||
|
|
f5245c615c | ||
|
|
aebb7998a3 | ||
|
|
b87da8fe9a | ||
|
|
1f35478b82 | ||
|
|
6d5ac6446c | ||
|
|
8f23eb11d7 | ||
|
|
0617281863 | ||
|
|
7d67f6f26d | ||
|
|
34c8253ad6 | ||
|
|
86e61ad6a5 | ||
|
|
6dbaddd2b9 | ||
|
|
a7faac2f09 | ||
|
|
f161d2f1e5 | ||
|
|
797fe27efe | ||
|
|
a57c5c5425 | ||
|
|
968b33ec79 | ||
|
|
87c7817124 | ||
|
|
bddfa2fc24 | ||
|
|
d05df9836b | ||
|
|
2f2e481fc3 | ||
|
|
1dda51f1fa | ||
|
|
348a1e7619 | ||
|
|
478d250818 | ||
|
|
532575b752 | ||
|
|
c127f9650c | ||
|
|
3419cf9aa7 | ||
|
|
877fc42e40 | ||
|
|
f79e5fc041 | ||
|
|
95c6d7398f | ||
|
|
5c7967e863 | ||
|
|
54e2f7e90d | ||
|
|
48c42bf189 | ||
|
|
92c94176c1 | ||
|
|
15e085cd32 | ||
|
|
2d72c853df | ||
|
|
9a4a81f100 | ||
|
|
61626aaf85 | ||
|
|
5a457d69fc | ||
|
|
7572794add | ||
|
|
60a10b3322 | ||
|
|
ec3fd9bd2a | ||
|
|
34cde09b2b | ||
|
|
8dd94461e1 | ||
|
|
9e04ab62fb | ||
|
|
9907bafa1d | ||
|
|
30f3971bee | ||
|
|
6b651176a3 | ||
|
|
a120edc56e | ||
|
|
5146409a1d | ||
|
|
db2ebf7410 | ||
|
|
bfc3f61010 | ||
|
|
78bfe867e6 | ||
|
|
03dca6d6b3 | ||
|
|
b2dec95862 | ||
|
|
26b5fdac40 | ||
|
|
00323f462a | ||
|
|
981f69ff55 | ||
|
|
5e843cfbbd | ||
|
|
b5ac85f103 | ||
|
|
d81fb6a9e6 | ||
|
|
d269cb9c50 | ||
|
|
2d97833f48 | ||
|
|
eef79067a8 | ||
|
|
aea4c10847 | ||
|
|
7eb4258951 | ||
|
|
c6d0be57d4 | ||
|
|
80b0d06b7e | ||
|
|
8685b740cc | ||
|
|
7fa23f2d2f | ||
|
|
ed264002a0 | ||
|
|
2e3361f0e0 | ||
|
|
363994f29d | ||
|
|
3f4bf96c5d | ||
|
|
0100fdd18d | ||
|
|
c0f85c681e | ||
|
|
43c129f431 | ||
|
|
500a57697d | ||
|
|
c2ab64afe3 | ||
|
|
6b30fb2bea | ||
|
|
9d34d2e036 | ||
|
|
76c15dffde | ||
|
|
d986693fbd | ||
|
|
7f5cb3aa0e | ||
|
|
697a01bfb4 | ||
|
|
1b4921977f | ||
|
|
be355c1e60 | ||
|
|
d10a435d64 | ||
|
|
eb2b086b65 | ||
|
|
08ca3b0849 | ||
|
|
61f21859d9 | ||
|
|
2bfbbfb381 | ||
|
|
31a3d22af4 | ||
|
|
90a8505208 | ||
|
|
06206e1d03 | ||
|
|
bfb9aa3d77 | ||
|
|
1bcea65117 | ||
|
|
bdfa1a0220 | ||
|
|
39504825d8 | ||
|
|
76abd80cb7 | ||
|
|
b1340bf310 | ||
|
|
c731e82fae | ||
|
|
491716c418 | ||
|
|
d64d0ef1dc | ||
|
|
27d6977a3e | ||
|
|
15836eb98e | ||
|
|
0dd51d5dd0 | ||
|
|
6e6031cbe9 | ||
|
|
d82a6ed811 | ||
|
|
ab7492dbc2 | ||
|
|
d3433c5946 | ||
|
|
975bcc8261 | ||
|
|
dd8d9646c4 | ||
|
|
bb2ecc6ad5 | ||
|
|
7a2ae105ea | ||
|
|
fd533d9a76 | ||
|
|
5fe3c58b4a | ||
|
|
dcb6e22a9e | ||
|
|
12399a1d42 | ||
|
|
a624051b85 | ||
|
|
cfea4dbe85 | ||
|
|
e40047f9c2 | ||
|
|
10bb407a2c | ||
|
|
ecf91ee081 | ||
|
|
925d014271 | ||
|
|
77d74f6c0d | ||
|
|
5570e7ceae | ||
|
|
e72a869fd1 | ||
|
|
2c0a0671ad | ||
|
|
6151899ce2 | ||
|
|
6bf282c6c2 | ||
|
|
8c35cff02c | ||
|
|
9f42b78a18 | ||
|
|
69d7f71ae8 | ||
|
|
1754fdbf4e | ||
|
|
58331067f8 | ||
|
|
aa2cb38543 | ||
|
|
6b18ee9edb | ||
|
|
c8faed0b54 | ||
|
|
dbd05a65b5 | ||
|
|
31403a41cd | ||
|
|
3f22596e3c | ||
|
|
cc5efb8d81 | ||
|
|
5aff7fab29 | ||
|
|
dfb3961eea | ||
|
|
39f2dcdfef | ||
|
|
2750679270 | ||
|
|
b38fa40fa6 | ||
|
|
8d570b54c7 | ||
|
|
e2adce1cc1 | ||
|
|
322e40c72e | ||
|
|
328cf187ba | ||
|
|
20b03e781c | ||
|
|
fcf2f0a03d | ||
|
|
cd8ab469ff | ||
|
|
659b9cd517 | ||
|
|
52d472c209 | ||
|
|
9ed59e71f6 | ||
|
|
e0053c62e1 | ||
|
|
8f0d7d1d3e | ||
|
|
771891491c | ||
|
|
f203d13efc | ||
|
|
14e400226a | ||
|
|
58f80c5675 | ||
|
|
4a7d84e861 | ||
|
|
1519f74f3c | ||
|
|
0e012cb05e | ||
|
|
19631ecef6 | ||
|
|
a569bf2698 | ||
|
|
dc12958fc7 | ||
|
|
67b68ceae6 | ||
|
|
54eb5623cb | ||
|
|
d9c22e54de | ||
|
|
7765e2dc55 | ||
|
|
ab278513ab | ||
|
|
e7a22792ac | ||
|
|
e05098cacb | ||
|
|
f9e95ab522 | ||
|
|
bb7d6814a7 | ||
|
|
e00fb99e7b | ||
|
|
e9a3f5169e | ||
|
|
1af3e81ada | ||
|
|
7cd5474f1a | ||
|
|
821eb21ae2 | ||
|
|
cc410b8c90 | ||
|
|
79e7862583 | ||
|
|
f9d634ce06 | ||
|
|
65a1cdf8e5 | ||
|
|
67229fd7a9 | ||
|
|
3033177e9e | ||
|
|
656a8fa3a2 | ||
|
|
0e9b64649a | ||
|
|
9da3c6c573 | ||
|
|
09a1305628 | ||
|
|
7d314fef78 | ||
|
|
dece767084 | ||
|
|
63bf9c7995 | ||
|
|
1c76483b4b | ||
|
|
9abe6ad4d8 | ||
|
|
8175df1002 | ||
|
|
a1a1a8895e | ||
|
|
69af79d45d | ||
|
|
e3a95b2d1a | ||
|
|
5c23b94069 | ||
|
|
85bb6cd027 | ||
|
|
90b9f1a98a | ||
|
|
55c2a5dc83 | ||
|
|
1d0d5bb141 | ||
|
|
7a983a4079 | ||
|
|
2523288509 | ||
|
|
8a6768763d | ||
|
|
a186f8c3aa | ||
|
|
ceeb6f0690 | ||
|
|
f3e5b6e13c | ||
|
|
34f2f887b1 | ||
|
|
20b51cc9ce | ||
|
|
56aad86231 | ||
|
|
ed1de6df80 | ||
|
|
8cb5b68cb6 | ||
|
|
e4abca9494 | ||
|
|
0a3300d773 | ||
|
|
2fab05c83e | ||
|
|
40f7ee1cab | ||
|
|
2c166d7a3a | ||
|
|
dcea64c838 | ||
|
|
255218a2f3 | ||
|
|
b76cd5858c | ||
|
|
46b5d46111 | ||
|
|
993ff8bb91 | ||
|
|
2cde04867f | ||
|
|
337840d29b | ||
|
|
fd2c57b8a4 | ||
|
|
1c5167d96e | ||
|
|
0d63646015 | ||
|
|
b5367f48f6 | ||
|
|
62c8ce9657 | ||
|
|
eb2ca06d67 | ||
|
|
16f729115e | ||
|
|
9355f5faf2 | ||
|
|
8cef2086f5 | ||
|
|
f7928c68a3 | ||
|
|
ecb09a23bc | ||
|
|
b9b58a1275 | ||
|
|
4a6c01c83c | ||
|
|
27f6f8ea9e | ||
|
|
d8d648549f | ||
|
|
38cd595235 | ||
|
|
7a60cb7f3e | ||
|
|
68f13cd739 | ||
|
|
d1ce3c697c | ||
|
|
2e536eda29 | ||
|
|
155ed3a814 | ||
|
|
5b0bb53184 | ||
|
|
42505f473d | ||
|
|
98756c068a | ||
|
|
aa54a038f2 | ||
|
|
a30075794b | ||
|
|
a8128493c2 | ||
|
|
faed8285cd | ||
|
|
21f3f3eec4 | ||
|
|
2f1ba40786 | ||
|
|
c565104491 | ||
|
|
54fcff189f | ||
|
|
d37f38c455 | ||
|
|
5e5bdda491 |
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +1,2 @@
|
||||
open_collective: xgboost
|
||||
custom: https://xgboost.ai/sponsors
|
||||
|
||||
254
.github/workflows/main.yml
vendored
254
.github/workflows/main.yml
vendored
@@ -7,17 +7,110 @@ name: XGBoost-CI
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
R_PACKAGES: c('XML', 'igraph', 'data.table', 'magrittr', 'stringi', 'ggplot2', 'DiagrammeR', 'Ckmeans.1d.dp', 'vcd', 'testthat', 'lintr', 'knitr', 'rmarkdown', 'e1071', 'cplm', 'devtools')
|
||||
R_PACKAGES: c('XML', 'igraph', 'data.table', 'magrittr', 'ggplot2', 'DiagrammeR', 'Ckmeans.1d.dp', 'vcd', 'testthat', 'lintr', 'knitr', 'rmarkdown', 'e1071', 'cplm', 'devtools', 'float', 'titanic')
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
gtest-cpu:
|
||||
name: Test Google C++ test (CPU)
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-10.15]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
brew install lz4 ninja libomp
|
||||
- name: Build gtest binary
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DGOOGLE_TEST=ON -DUSE_OPENMP=ON -DUSE_DMLC_GTEST=ON -DPLUGIN_LZ4=ON -DPLUGIN_DENSE_PARSER=ON -GNinja
|
||||
ninja -v
|
||||
- name: Run gtest binary
|
||||
run: |
|
||||
cd build
|
||||
ctest --extra-verbose
|
||||
|
||||
gtest-cpu-nonomp:
|
||||
name: Test Google C++ unittest (CPU Non-OMP)
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends ninja-build
|
||||
- name: Build and install XGBoost
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GNinja -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON -DUSE_OPENMP=OFF
|
||||
ninja -v
|
||||
- name: Run gtest binary
|
||||
run: |
|
||||
cd build
|
||||
ctest --extra-verbose
|
||||
|
||||
c-api-demo:
|
||||
name: Test installing XGBoost lib + building the C API demo
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ["ubuntu-latest"]
|
||||
python-version: ["3.8"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends ninja-build
|
||||
- uses: conda-incubator/setup-miniconda@v2
|
||||
with:
|
||||
auto-update-conda: true
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Display Conda env
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
- name: Build and install XGBoost
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_STATIC_LIB=ON -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -GNinja
|
||||
ninja -v install
|
||||
- name: Build and run C API demo
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
cd demo/c-api/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GNinja -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
|
||||
ninja -v
|
||||
cd ..
|
||||
./build/api-demo
|
||||
|
||||
test-with-jvm:
|
||||
name: Test JVM on OS ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, windows-2016, ubuntu-latest]
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -35,17 +128,106 @@ jobs:
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('./jvm-packages/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2
|
||||
|
||||
- name: Test JVM packages
|
||||
- name: Test XGBoost4J
|
||||
run: |
|
||||
cd jvm-packages
|
||||
mvn test -pl :xgboost4j_2.12
|
||||
mvn test -B -pl :xgboost4j_2.12
|
||||
|
||||
- name: Test XGBoost4J-Spark
|
||||
run: |
|
||||
rm -rfv build/
|
||||
cd jvm-packages
|
||||
mvn -B test
|
||||
if: matrix.os == 'ubuntu-latest' # Distributed training doesn't work on Windows
|
||||
env:
|
||||
RABIT_MOCK: ON
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: Code linting for Python and C++
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
python -m pip install wheel setuptools
|
||||
python -m pip install pylint cpplint numpy scipy scikit-learn
|
||||
- name: Run lint
|
||||
run: |
|
||||
make lint
|
||||
|
||||
doxygen:
|
||||
runs-on: ubuntu-latest
|
||||
name: Generate C/C++ API doc using Doxygen
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends doxygen graphviz ninja-build
|
||||
python -m pip install wheel setuptools
|
||||
python -m pip install awscli
|
||||
- name: Run Doxygen
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_C_DOC=ON -GNinja
|
||||
ninja -v doc_doxygen
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
id: extract_branch
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
- name: Publish
|
||||
run: |
|
||||
cd build/
|
||||
tar cvjf ${{ steps.extract_branch.outputs.branch }}.tar.bz2 doc_doxygen/
|
||||
python -m awscli s3 cp ./${{ steps.extract_branch.outputs.branch }}.tar.bz2 s3://xgboost-docs/ --acl public-read
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_IAM_S3_UPLOADER }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_IAM_S3_UPLOADER }}
|
||||
|
||||
sphinx:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build docs using Sphinx
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends graphviz
|
||||
python -m pip install wheel setuptools
|
||||
python -m pip install -r doc/requirements.txt
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
id: extract_branch
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
- name: Run Sphinx
|
||||
run: |
|
||||
make -C doc html
|
||||
env:
|
||||
SPHINX_GIT_BRANCH: ${{ steps.extract_branch.outputs.branch }}
|
||||
|
||||
lintr:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
name: Run R linters on OS ${{ matrix.config.os }}, R ${{ matrix.config.r }}, Compiler ${{ matrix.config.compiler }}, Build ${{ matrix.config.build }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
@@ -81,25 +263,17 @@ jobs:
|
||||
run: |
|
||||
cd R-package
|
||||
R.exe CMD INSTALL .
|
||||
Rscript.exe tests/run_lint.R
|
||||
|
||||
Rscript.exe tests/helper_scripts/run_lint.R
|
||||
|
||||
test-with-R:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
name: Test R on OS ${{ matrix.config.os }}, R ${{ matrix.config.r }}, Compiler ${{ matrix.config.compiler }}, Build ${{ matrix.config.build }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {os: windows-latest, r: 'release', compiler: 'msvc', build: 'autotools'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'msvc', build: 'autotools'}
|
||||
- {os: windows-latest, r: 'release', compiler: 'msvc', build: 'cmake'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'msvc', build: 'cmake'}
|
||||
- {os: windows-latest, r: 'release', compiler: 'mingw', build: 'autotools'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'mingw', build: 'autotools'}
|
||||
- {os: windows-latest, r: 'release', compiler: 'mingw', build: 'cmake'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'msvc', build: 'cmake'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'mingw', build: 'cmake'}
|
||||
env:
|
||||
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
|
||||
@@ -130,9 +304,53 @@ jobs:
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.6' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
|
||||
- name: Test R
|
||||
run: |
|
||||
python tests/ci_build/test_r_package.py --compiler="${{ matrix.config.compiler }}" --build-tool="${{ matrix.config.build }}"
|
||||
|
||||
test-R-CRAN:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {r: 'release'}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: r-lib/actions/setup-r@master
|
||||
with:
|
||||
r-version: ${{ matrix.config.r }}
|
||||
|
||||
- uses: r-lib/actions/setup-tinytex@master
|
||||
|
||||
- name: Cache R packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.R_LIBS_USER }}
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-1-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-2-
|
||||
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install libcurl4-openssl-dev libssl-dev libssh2-1-dev libgit2-dev
|
||||
|
||||
- name: Install dependencies
|
||||
shell: Rscript {0}
|
||||
run: |
|
||||
install.packages(${{ env.R_PACKAGES }},
|
||||
repos = 'http://cloud.r-project.org',
|
||||
dependencies = c('Depends', 'Imports', 'LinkingTo'))
|
||||
|
||||
- name: Check R Package
|
||||
run: |
|
||||
# Print stacktrace upon success of failure
|
||||
make Rcheck || tests/ci_build/print_r_stacktrace.sh fail
|
||||
tests/ci_build/print_r_stacktrace.sh success
|
||||
|
||||
44
.github/workflows/r_nold.yml
vendored
Normal file
44
.github/workflows/r_nold.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# Run R tests with noLD R. Only triggered by a pull request review
|
||||
# See discussion at https://github.com/dmlc/xgboost/pull/6378
|
||||
|
||||
name: XGBoost-R-noLD
|
||||
|
||||
on:
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
env:
|
||||
R_PACKAGES: c('XML', 'igraph', 'data.table', 'magrittr', 'ggplot2', 'DiagrammeR', 'Ckmeans.1d.dp', 'vcd', 'testthat', 'lintr', 'knitr', 'rmarkdown', 'e1071', 'cplm', 'devtools', 'float', 'titanic')
|
||||
|
||||
jobs:
|
||||
test-R-noLD:
|
||||
if: github.event.comment.body == '/gha run r-nold-test' && contains('OWNER,MEMBER,COLLABORATOR', github.event.comment.author_association)
|
||||
timeout-minutes: 120
|
||||
runs-on: ubuntu-latest
|
||||
container: rhub/debian-gcc-devel-nold
|
||||
steps:
|
||||
- name: Install git and system packages
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update && apt-get install -y git libcurl4-openssl-dev libssl-dev libssh2-1-dev libgit2-dev libxml2-dev
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
cat > install_libs.R <<EOT
|
||||
install.packages(${{ env.R_PACKAGES }},
|
||||
repos = 'http://cloud.r-project.org',
|
||||
dependencies = c('Depends', 'Imports', 'LinkingTo'))
|
||||
EOT
|
||||
/tmp/R-devel/bin/Rscript install_libs.R
|
||||
|
||||
- name: Run R tests
|
||||
shell: bash
|
||||
run: |
|
||||
cd R-package && \
|
||||
/tmp/R-devel/bin/R CMD INSTALL . && \
|
||||
/tmp/R-devel/bin/R -q -e "library(testthat); setwd('tests'); source('testthat.R')"
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -71,6 +71,7 @@ build
|
||||
build_plugin
|
||||
recommonmark/
|
||||
tags
|
||||
TAGS
|
||||
*.class
|
||||
target
|
||||
*.swp
|
||||
@@ -104,4 +105,13 @@ R-package/src/Makevars
|
||||
/cmake-build-debug/
|
||||
|
||||
# GDB
|
||||
.gdb_history
|
||||
.gdb_history
|
||||
|
||||
# Python joblib.Memory used in pytest.
|
||||
cachedir/
|
||||
|
||||
# Files from local Dask work
|
||||
dask-worker-space/
|
||||
|
||||
# Jupyter notebook checkpoints
|
||||
.ipynb_checkpoints/
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,9 +1,9 @@
|
||||
[submodule "dmlc-core"]
|
||||
path = dmlc-core
|
||||
url = https://github.com/dmlc/dmlc-core
|
||||
[submodule "rabit"]
|
||||
path = rabit
|
||||
url = https://github.com/dmlc/rabit
|
||||
[submodule "cub"]
|
||||
path = cub
|
||||
url = https://github.com/NVlabs/cub
|
||||
[submodule "gputreeshap"]
|
||||
path = gputreeshap
|
||||
url = https://github.com/rapidsai/gputreeshap.git
|
||||
|
||||
50
.travis.yml
50
.travis.yml
@@ -1,38 +1,40 @@
|
||||
# disable sudo for container build.
|
||||
sudo: required
|
||||
|
||||
# Enabling test OS X
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
osx_image: xcode10.1
|
||||
dist: bionic
|
||||
|
||||
# Use Build Matrix to do lint and build seperately
|
||||
env:
|
||||
matrix:
|
||||
# python package test
|
||||
- TASK=python_test
|
||||
# test installation of Python source distribution
|
||||
- TASK=python_sdist_test
|
||||
# java package test
|
||||
- TASK=java_test
|
||||
# cmake test
|
||||
- TASK=cmake_test
|
||||
|
||||
global:
|
||||
- secure: "PR16i9F8QtNwn99C5NDp8nptAS+97xwDtXEJJfEiEVhxPaaRkOp0MPWhogCaK0Eclxk1TqkgWbdXFknwGycX620AzZWa/A1K3gAs+GrpzqhnPMuoBJ0Z9qxXTbSJvCyvMbYwVrjaxc/zWqdMU8waWz8A7iqKGKs/SqbQ3rO6v7c="
|
||||
- secure: "dAGAjBokqm/0nVoLMofQni/fWIBcYSmdq4XvCBX1ZAMDsWnuOfz/4XCY6h2lEI1rVHZQ+UdZkc9PioOHGPZh5BnvE49/xVVWr9c4/61lrDOlkD01ZjSAeoV0fAZq+93V/wPl4QV+MM+Sem9hNNzFSbN5VsQLAiWCSapWsLdKzqA="
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
arch: amd64
|
||||
env: TASK=python_sdist_test
|
||||
- os: linux
|
||||
arch: arm64
|
||||
env: TASK=python_sdist_test
|
||||
- os: linux
|
||||
arch: arm64
|
||||
env: TASK=python_test
|
||||
- os: linux
|
||||
services:
|
||||
- docker
|
||||
- os: osx
|
||||
arch: amd64
|
||||
osx_image: xcode10.2
|
||||
env: TASK=python_test
|
||||
- os: osx
|
||||
arch: amd64
|
||||
osx_image: xcode10.2
|
||||
env: TASK=python_sdist_test
|
||||
- os: osx
|
||||
arch: amd64
|
||||
osx_image: xcode10.2
|
||||
env: TASK=java_test
|
||||
- os: linux
|
||||
env: TASK=cmake_test
|
||||
arch: s390x
|
||||
env: TASK=s390x_test
|
||||
|
||||
# dependent brew packages
|
||||
addons:
|
||||
@@ -47,6 +49,10 @@ addons:
|
||||
- wget
|
||||
- r
|
||||
update: true
|
||||
apt:
|
||||
packages:
|
||||
- snapd
|
||||
- unzip
|
||||
|
||||
before_install:
|
||||
- source tests/travis/travis_setup_env.sh
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(xgboost LANGUAGES CXX C VERSION 1.2.0)
|
||||
project(xgboost LANGUAGES CXX C VERSION 1.3.2)
|
||||
include(cmake/Utils.cmake)
|
||||
list(APPEND CMAKE_MODULE_PATH "${xgboost_SOURCE_DIR}/cmake/modules")
|
||||
cmake_policy(SET CMP0022 NEW)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
if ((${CMAKE_VERSION} VERSION_GREATER 3.13) OR (${CMAKE_VERSION} VERSION_EQUAL 3.13))
|
||||
@@ -23,9 +24,11 @@ write_version()
|
||||
set_default_configuration_release()
|
||||
|
||||
#-- Options
|
||||
## User options
|
||||
option(BUILD_C_DOC "Build documentation for C APIs using Doxygen." OFF)
|
||||
option(USE_OPENMP "Build with OpenMP support." ON)
|
||||
option(BUILD_STATIC_LIB "Build static library" OFF)
|
||||
option(RABIT_BUILD_MPI "Build MPI" OFF)
|
||||
## Bindings
|
||||
option(JVM_BINDINGS "Build JVM bindings" OFF)
|
||||
option(R_LIB "Build shared library for R package" OFF)
|
||||
@@ -37,6 +40,7 @@ option(ENABLE_ALL_WARNINGS "Enable all compiler warnings. Only effective for GCC
|
||||
option(LOG_CAPI_INVOCATION "Log all C API invocations for debugging" OFF)
|
||||
option(GOOGLE_TEST "Build google tests" OFF)
|
||||
option(USE_DMLC_GTEST "Use google tests bundled with dmlc-core submodule" OFF)
|
||||
option(USE_DEVICE_DEBUG "Generate CUDA device debug info." OFF)
|
||||
option(USE_NVTX "Build with cuda profiling annotations. Developers only." OFF)
|
||||
set(NVTX_HEADER_DIR "" CACHE PATH "Path to the stand-alone nvtx header")
|
||||
option(RABIT_MOCK "Build rabit with mock" OFF)
|
||||
@@ -60,6 +64,9 @@ address, leak, undefined and thread.")
|
||||
## Plugins
|
||||
option(PLUGIN_LZ4 "Build lz4 plugin" OFF)
|
||||
option(PLUGIN_DENSE_PARSER "Build dense parser plugin" OFF)
|
||||
option(PLUGIN_RMM "Build with RAPIDS Memory Manager (RMM)" OFF)
|
||||
## TODO: 1. Add check if DPC++ compiler is used for building
|
||||
option(PLUGIN_UPDATER_ONEAPI "DPC++ updater" OFF)
|
||||
option(ADD_PKGCONFIG "Add xgboost.pc into system." ON)
|
||||
|
||||
#-- Checks for building XGBoost
|
||||
@@ -69,6 +76,9 @@ endif (USE_DEBUG_OUTPUT AND (NOT (CMAKE_BUILD_TYPE MATCHES Debug)))
|
||||
if (USE_NCCL AND NOT (USE_CUDA))
|
||||
message(SEND_ERROR "`USE_NCCL` must be enabled with `USE_CUDA` flag.")
|
||||
endif (USE_NCCL AND NOT (USE_CUDA))
|
||||
if (USE_DEVICE_DEBUG AND NOT (USE_CUDA))
|
||||
message(SEND_ERROR "`USE_DEVICE_DEBUG` must be enabled with `USE_CUDA` flag.")
|
||||
endif (USE_DEVICE_DEBUG AND NOT (USE_CUDA))
|
||||
if (BUILD_WITH_SHARED_NCCL AND (NOT USE_NCCL))
|
||||
message(SEND_ERROR "Build XGBoost with -DUSE_NCCL=ON to enable BUILD_WITH_SHARED_NCCL.")
|
||||
endif (BUILD_WITH_SHARED_NCCL AND (NOT USE_NCCL))
|
||||
@@ -82,11 +92,23 @@ endif (R_LIB AND GOOGLE_TEST)
|
||||
if (USE_AVX)
|
||||
message(SEND_ERROR "The option 'USE_AVX' is deprecated as experimental AVX features have been removed from XGBoost.")
|
||||
endif (USE_AVX)
|
||||
if (PLUGIN_RMM AND NOT (USE_CUDA))
|
||||
message(SEND_ERROR "`PLUGIN_RMM` must be enabled with `USE_CUDA` flag.")
|
||||
endif (PLUGIN_RMM AND NOT (USE_CUDA))
|
||||
if (PLUGIN_RMM AND NOT ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")))
|
||||
message(SEND_ERROR "`PLUGIN_RMM` must be used with GCC or Clang compiler.")
|
||||
endif (PLUGIN_RMM AND NOT ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")))
|
||||
if (PLUGIN_RMM AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
||||
message(SEND_ERROR "`PLUGIN_RMM` must be used with Linux.")
|
||||
endif (PLUGIN_RMM AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
||||
if (ENABLE_ALL_WARNINGS)
|
||||
if ((NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
|
||||
message(SEND_ERROR "ENABLE_ALL_WARNINGS is only available for Clang and GCC.")
|
||||
endif ((NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
|
||||
endif (ENABLE_ALL_WARNINGS)
|
||||
if (BUILD_STATIC_LIB AND (R_LIB OR JVM_BINDINGS))
|
||||
message(SEND_ERROR "Cannot build a static library libxgboost.a when R or JVM packages are enabled.")
|
||||
endif (BUILD_STATIC_LIB AND (R_LIB OR JVM_BINDINGS))
|
||||
|
||||
#-- Sanitizer
|
||||
if (USE_SANITIZER)
|
||||
@@ -106,7 +128,7 @@ if (USE_CUDA)
|
||||
endif()
|
||||
set(GEN_CODE "")
|
||||
format_gencode_flags("${GPU_COMPUTE_VER}" GEN_CODE)
|
||||
message(STATUS "CUDA GEN_CODE: ${GEN_CODE}")
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/gputreeshap)
|
||||
endif (USE_CUDA)
|
||||
|
||||
if (FORCE_COLORED_OUTPUT AND (CMAKE_GENERATOR STREQUAL "Ninja") AND
|
||||
@@ -126,9 +148,6 @@ if (USE_OPENMP)
|
||||
find_package(OpenMP REQUIRED)
|
||||
endif (USE_OPENMP)
|
||||
|
||||
# core xgboost
|
||||
add_subdirectory(${xgboost_SOURCE_DIR}/src)
|
||||
|
||||
# dmlc-core
|
||||
msvc_use_static_runtime()
|
||||
add_subdirectory(${xgboost_SOURCE_DIR}/dmlc-core)
|
||||
@@ -147,40 +166,13 @@ endif (MSVC)
|
||||
if (ENABLE_ALL_WARNINGS)
|
||||
target_compile_options(dmlc PRIVATE -Wall -Wextra)
|
||||
endif (ENABLE_ALL_WARNINGS)
|
||||
target_link_libraries(objxgboost PUBLIC dmlc)
|
||||
|
||||
# rabit
|
||||
set(RABIT_BUILD_DMLC OFF)
|
||||
set(DMLC_ROOT ${xgboost_SOURCE_DIR}/dmlc-core)
|
||||
set(RABIT_WITH_R_LIB ${R_LIB})
|
||||
add_subdirectory(rabit)
|
||||
|
||||
if (RABIT_MOCK)
|
||||
target_link_libraries(objxgboost PUBLIC rabit_mock_static)
|
||||
if (MSVC)
|
||||
target_compile_options(rabit_mock_static PRIVATE
|
||||
-D_CRT_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE)
|
||||
endif (MSVC)
|
||||
else()
|
||||
target_link_libraries(objxgboost PUBLIC rabit)
|
||||
if (MSVC)
|
||||
target_compile_options(rabit PRIVATE
|
||||
-D_CRT_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE)
|
||||
endif (MSVC)
|
||||
endif(RABIT_MOCK)
|
||||
foreach(lib rabit rabit_base rabit_empty rabit_mock rabit_mock_static)
|
||||
# Explicitly link dmlc to rabit, so that configured header (build_config.h)
|
||||
# from dmlc is correctly applied to rabit.
|
||||
if (TARGET ${lib})
|
||||
target_link_libraries(${lib} dmlc ${CMAKE_THREAD_LIBS_INIT})
|
||||
if (HIDE_CXX_SYMBOLS) # Hide all C++ symbols from Rabit
|
||||
set_target_properties(${lib} PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
endif (HIDE_CXX_SYMBOLS)
|
||||
if (ENABLE_ALL_WARNINGS)
|
||||
target_compile_options(${lib} PRIVATE -Wall -Wextra)
|
||||
endif (ENABLE_ALL_WARNINGS)
|
||||
endif (TARGET ${lib})
|
||||
endforeach()
|
||||
# core xgboost
|
||||
add_subdirectory(${xgboost_SOURCE_DIR}/src)
|
||||
target_link_libraries(objxgboost PUBLIC dmlc)
|
||||
|
||||
# Exports some R specific definitions and objects
|
||||
if (R_LIB)
|
||||
@@ -198,14 +190,15 @@ else (BUILD_STATIC_LIB)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
target_link_libraries(xgboost PRIVATE objxgboost)
|
||||
|
||||
if (USE_NVTX)
|
||||
enable_nvtx(xgboost)
|
||||
endif (USE_NVTX)
|
||||
if (USE_CUDA)
|
||||
xgboost_set_cuda_flags(xgboost)
|
||||
endif (USE_CUDA)
|
||||
|
||||
#-- Hide all C++ symbols
|
||||
if (HIDE_CXX_SYMBOLS)
|
||||
set_target_properties(objxgboost PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(xgboost PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
foreach(target objxgboost xgboost dmlc)
|
||||
set_target_properties(${target} PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
endforeach()
|
||||
endif (HIDE_CXX_SYMBOLS)
|
||||
|
||||
target_include_directories(xgboost
|
||||
@@ -267,7 +260,20 @@ include(GNUInstallDirs)
|
||||
install(DIRECTORY ${xgboost_SOURCE_DIR}/include/xgboost
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(TARGETS xgboost runxgboost
|
||||
# Install libraries. If `xgboost` is a static lib, specify `objxgboost` also, to avoid the
|
||||
# following error:
|
||||
#
|
||||
# > install(EXPORT ...) includes target "xgboost" which requires target "objxgboost" that is not
|
||||
# > in any export set.
|
||||
#
|
||||
# https://github.com/dmlc/xgboost/issues/6085
|
||||
if (BUILD_STATIC_LIB)
|
||||
set(INSTALL_TARGETS xgboost runxgboost objxgboost dmlc)
|
||||
else (BUILD_STATIC_LIB)
|
||||
set(INSTALL_TARGETS xgboost runxgboost)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
install(TARGETS ${INSTALL_TARGETS}
|
||||
EXPORT XGBoostTargets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
|
||||
224
Jenkinsfile
vendored
224
Jenkinsfile
vendored
@@ -38,26 +38,15 @@ pipeline {
|
||||
agent { label 'job_initializer' }
|
||||
steps {
|
||||
script {
|
||||
def buildNumber = env.BUILD_NUMBER as int
|
||||
if (buildNumber > 1) milestone(buildNumber - 1)
|
||||
milestone(buildNumber)
|
||||
|
||||
checkoutSrcs()
|
||||
commit_id = "${GIT_COMMIT}"
|
||||
}
|
||||
sh 'python3 tests/jenkins_get_approval.py'
|
||||
stash name: 'srcs'
|
||||
milestone ordinal: 1
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Formatting Check') {
|
||||
agent none
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'clang-tidy': { ClangTidy() },
|
||||
'lint': { Lint() },
|
||||
'sphinx-doc': { SphinxDoc() },
|
||||
'doxygen': { Doxygen() }
|
||||
])
|
||||
}
|
||||
milestone ordinal: 2
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Build') {
|
||||
@@ -65,22 +54,21 @@ pipeline {
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'clang-tidy': { ClangTidy() },
|
||||
'build-cpu': { BuildCPU() },
|
||||
'build-cpu-rabit-mock': { BuildCPUMock() },
|
||||
'build-cpu-non-omp': { BuildCPUNonOmp() },
|
||||
// Build reference, distribution-ready Python wheel with CUDA 10.0
|
||||
// using CentOS 6 image
|
||||
'build-gpu-cuda10.0': { BuildCUDA(cuda_version: '10.0') },
|
||||
// The build-gpu-* builds below use Ubuntu image
|
||||
'build-gpu-cuda10.1': { BuildCUDA(cuda_version: '10.1') },
|
||||
'build-gpu-cuda10.2': { BuildCUDA(cuda_version: '10.2') },
|
||||
'build-gpu-cuda10.2': { BuildCUDA(cuda_version: '10.2', build_rmm: true) },
|
||||
'build-gpu-cuda11.0': { BuildCUDA(cuda_version: '11.0') },
|
||||
'build-jvm-packages-gpu-cuda10.0': { BuildJVMPackagesWithCUDA(spark_version: '3.0.0', cuda_version: '10.0') },
|
||||
'build-jvm-packages': { BuildJVMPackages(spark_version: '3.0.0') },
|
||||
'build-jvm-doc': { BuildJVMDoc() }
|
||||
])
|
||||
}
|
||||
milestone ordinal: 3
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Test') {
|
||||
@@ -89,20 +77,18 @@ pipeline {
|
||||
script {
|
||||
parallel ([
|
||||
'test-python-cpu': { TestPythonCPU() },
|
||||
'test-python-gpu-cuda10.2': { TestPythonGPU(host_cuda_version: '10.2') },
|
||||
// artifact_cuda_version doesn't apply to RMM tests; RMM tests will always match CUDA version between artifact and host env
|
||||
'test-python-gpu-cuda10.2': { TestPythonGPU(artifact_cuda_version: '10.0', host_cuda_version: '10.2', test_rmm: true) },
|
||||
'test-python-gpu-cuda11.0-cross': { TestPythonGPU(artifact_cuda_version: '10.0', host_cuda_version: '11.0') },
|
||||
'test-python-gpu-cuda11.0': { TestPythonGPU(artifact_cuda_version: '11.0', host_cuda_version: '11.0') },
|
||||
'test-python-mgpu-cuda10.2': { TestPythonGPU(artifact_cuda_version: '10.2', host_cuda_version: '10.2', multi_gpu: true) },
|
||||
'test-cpp-gpu-cuda10.2': { TestCppGPU(artifact_cuda_version: '10.2', host_cuda_version: '10.2') },
|
||||
'test-python-mgpu-cuda10.2': { TestPythonGPU(artifact_cuda_version: '10.0', host_cuda_version: '10.2', multi_gpu: true, test_rmm: true) },
|
||||
'test-cpp-gpu-cuda10.2': { TestCppGPU(artifact_cuda_version: '10.2', host_cuda_version: '10.2', test_rmm: true) },
|
||||
'test-cpp-gpu-cuda11.0': { TestCppGPU(artifact_cuda_version: '11.0', host_cuda_version: '11.0') },
|
||||
'test-jvm-jdk8-cuda10.0': { CrossTestJVMwithJDKGPU(artifact_cuda_version: '10.0', host_cuda_version: '10.0') },
|
||||
'test-jvm-jdk8': { CrossTestJVMwithJDK(jdk_version: '8', spark_version: '3.0.0') },
|
||||
'test-jvm-jdk11': { CrossTestJVMwithJDK(jdk_version: '11') },
|
||||
'test-jvm-jdk12': { CrossTestJVMwithJDK(jdk_version: '12') },
|
||||
'test-r-3.5.3': { TestR(use_r35: true) }
|
||||
'test-jvm-jdk12': { CrossTestJVMwithJDK(jdk_version: '12') }
|
||||
])
|
||||
}
|
||||
milestone ordinal: 4
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Deploy') {
|
||||
@@ -113,7 +99,6 @@ pipeline {
|
||||
'deploy-jvm-packages': { DeployJVMPackages(spark_version: '3.0.0') }
|
||||
])
|
||||
}
|
||||
milestone ordinal: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,7 +129,7 @@ def ClangTidy() {
|
||||
echo "Running clang-tidy job..."
|
||||
def container_type = "clang_tidy"
|
||||
def docker_binary = "docker"
|
||||
def dockerArgs = "--build-arg CUDA_VERSION=10.1"
|
||||
def dockerArgs = "--build-arg CUDA_VERSION_ARG=10.1"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${dockerArgs} python3 tests/ci_build/tidy.py
|
||||
"""
|
||||
@@ -152,50 +137,6 @@ def ClangTidy() {
|
||||
}
|
||||
}
|
||||
|
||||
def Lint() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Running lint..."
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "source activate cpu_test && make lint"
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def SphinxDoc() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Running sphinx-doc..."
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
def docker_extra_params = "CI_DOCKER_EXTRA_PARAMS_INIT='-e SPHINX_GIT_BRANCH=${BRANCH_NAME}'"
|
||||
sh """#!/bin/bash
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} bash -c "source activate cpu_test && make -C doc html"
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def Doxygen() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Running doxygen..."
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/doxygen.sh ${BRANCH_NAME}
|
||||
"""
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
echo 'Uploading doc...'
|
||||
s3Upload file: "build/${BRANCH_NAME}.tar.bz2", bucket: 'xgboost-docs', acl: 'PublicRead', path: "doxygen/${BRANCH_NAME}.tar.bz2"
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCPU() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
@@ -208,14 +149,14 @@ def BuildCPU() {
|
||||
# We want to make sure that we use the configured header build/dmlc/build_config.h instead of include/dmlc/build_config_default.h.
|
||||
# See discussion at https://github.com/dmlc/xgboost/issues/5510
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_via_cmake.sh -DPLUGIN_LZ4=ON -DPLUGIN_DENSE_PARSER=ON
|
||||
${dockerRun} ${container_type} ${docker_binary} build/testxgboost
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "cd build && ctest --extra-verbose"
|
||||
"""
|
||||
// Sanitizer test
|
||||
def docker_extra_params = "CI_DOCKER_EXTRA_PARAMS_INIT='-e ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer -e ASAN_OPTIONS=symbolize=1 -e UBSAN_OPTIONS=print_stacktrace=1:log_path=ubsan_error.log --cap-add SYS_PTRACE'"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_via_cmake.sh -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address;leak;undefined" \
|
||||
-DCMAKE_BUILD_TYPE=Debug -DSANITIZER_PATH=/usr/lib/x86_64-linux-gnu/
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} build/testxgboost
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} bash -c "cd build && ctest --exclude-regex AllTestsInDMLCUnitTests --extra-verbose"
|
||||
"""
|
||||
|
||||
stash name: 'xgboost_cli', includes: 'xgboost'
|
||||
@@ -238,39 +179,31 @@ def BuildCPUMock() {
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCPUNonOmp() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build CPU without OpenMP"
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_via_cmake.sh -DUSE_OPENMP=OFF
|
||||
"""
|
||||
echo "Running Non-OpenMP C++ test..."
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} build/testxgboost
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCUDA(args) {
|
||||
node('linux && cpu_build') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build with CUDA ${args.cuda_version}"
|
||||
def container_type = GetCUDABuildContainerType(args.cuda_version)
|
||||
def docker_binary = "docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION=${args.cuda_version}"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
def arch_flag = ""
|
||||
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
|
||||
arch_flag = "-DGPU_COMPUTE_VER=75"
|
||||
}
|
||||
def wheel_tag = "manylinux2010_x86_64"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_via_cmake.sh -DUSE_CUDA=ON -DUSE_NCCL=ON -DOPEN_MP:BOOL=ON -DHIDE_CXX_SYMBOLS=ON ${arch_flag}
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "cd python-package && rm -rf dist/* && python setup.py bdist_wheel --universal"
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} manylinux2010_x86_64
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} ${wheel_tag}
|
||||
"""
|
||||
if (args.cuda_version == ref_cuda_ver) {
|
||||
sh """
|
||||
${dockerRun} auditwheel_x86_64 ${docker_binary} auditwheel repair --plat ${wheel_tag} python-package/dist/*.whl
|
||||
mv -v wheelhouse/*.whl python-package/dist/
|
||||
# Make sure that libgomp.so is vendored in the wheel
|
||||
${dockerRun} auditwheel_x86_64 ${docker_binary} bash -c "unzip -l python-package/dist/*.whl | grep libgomp || exit -1"
|
||||
"""
|
||||
}
|
||||
echo 'Stashing Python wheel...'
|
||||
stash name: "xgboost_whl_cuda${args.cuda_version}", includes: 'python-package/dist/*.whl'
|
||||
if (args.cuda_version == ref_cuda_ver && (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release'))) {
|
||||
@@ -280,17 +213,33 @@ def BuildCUDA(args) {
|
||||
}
|
||||
echo 'Stashing C++ test executable (testxgboost)...'
|
||||
stash name: "xgboost_cpp_tests_cuda${args.cuda_version}", includes: 'build/testxgboost'
|
||||
if (args.build_rmm) {
|
||||
echo "Build with CUDA ${args.cuda_version} and RMM"
|
||||
container_type = "rmm"
|
||||
docker_binary = "docker"
|
||||
docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
sh """
|
||||
rm -rf build/
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_via_cmake.sh --conda-env=gpu_test -DUSE_CUDA=ON -DUSE_NCCL=ON -DPLUGIN_RMM=ON ${arch_flag}
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "cd python-package && rm -rf dist/* && python setup.py bdist_wheel --universal"
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} manylinux2010_x86_64
|
||||
"""
|
||||
echo 'Stashing Python wheel...'
|
||||
stash name: "xgboost_whl_rmm_cuda${args.cuda_version}", includes: 'python-package/dist/*.whl'
|
||||
echo 'Stashing C++ test executable (testxgboost)...'
|
||||
stash name: "xgboost_cpp_tests_rmm_cuda${args.cuda_version}", includes: 'build/testxgboost'
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildJVMPackagesWithCUDA(args) {
|
||||
node('linux && gpu') {
|
||||
node('linux && mgpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build XGBoost4J-Spark with Spark ${args.spark_version}, CUDA ${args.cuda_version}"
|
||||
def container_type = "jvm_gpu_build"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION=${args.cuda_version}"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
def arch_flag = ""
|
||||
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
|
||||
arch_flag = "-DGPU_COMPUTE_VER=75"
|
||||
@@ -301,7 +250,7 @@ def BuildJVMPackagesWithCUDA(args) {
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_jvm_packages.sh ${args.spark_version} -Duse.cuda=ON $arch_flag
|
||||
"""
|
||||
echo "Stashing XGBoost4J JAR with CUDA ${args.cuda_version} ..."
|
||||
stash name: 'xgboost4j_jar_gpu', includes: "jvm-packages/xgboost4j/target/*.jar,jvm-packages/xgboost4j-spark/target/*.jar,jvm-packages/xgboost4j-example/target/*.jar"
|
||||
stash name: 'xgboost4j_jar_gpu', includes: "jvm-packages/xgboost4j-gpu/target/*.jar,jvm-packages/xgboost4j-spark-gpu/target/*.jar"
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
@@ -365,38 +314,21 @@ def TestPythonGPU(args) {
|
||||
echo "Test Python GPU: CUDA ${args.host_cuda_version}"
|
||||
def container_type = "gpu"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION=${args.host_cuda_version}"
|
||||
if (args.multi_gpu) {
|
||||
echo "Using multiple GPUs"
|
||||
// Allocate extra space in /dev/shm to enable NCCL
|
||||
def docker_extra_params = "CI_DOCKER_EXTRA_PARAMS_INIT='--shm-size=4g'"
|
||||
sh """
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_python.sh mgpu
|
||||
"""
|
||||
} else {
|
||||
echo "Using a single GPU"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_python.sh gpu
|
||||
"""
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.host_cuda_version}"
|
||||
def mgpu_indicator = (args.multi_gpu) ? 'mgpu' : 'gpu'
|
||||
// Allocate extra space in /dev/shm to enable NCCL
|
||||
def docker_extra_params = (args.multi_gpu) ? "CI_DOCKER_EXTRA_PARAMS_INIT='--shm-size=4g'" : ''
|
||||
sh "${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_python.sh ${mgpu_indicator}"
|
||||
if (args.test_rmm) {
|
||||
sh "rm -rfv build/ python-package/dist/"
|
||||
unstash name: "xgboost_whl_rmm_cuda${args.host_cuda_version}"
|
||||
unstash name: "xgboost_cpp_tests_rmm_cuda${args.host_cuda_version}"
|
||||
sh "${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_python.sh ${mgpu_indicator} --use-rmm-pool"
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestCppRabit() {
|
||||
node(nodeReq) {
|
||||
unstash name: 'xgboost_rabit_tests'
|
||||
unstash name: 'srcs'
|
||||
echo "Test C++, rabit mock on"
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/runxgb.sh xgboost tests/ci_build/approx.conf.in
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestCppGPU(args) {
|
||||
def nodeReq = 'linux && mgpu'
|
||||
def artifact_cuda_version = (args.artifact_cuda_version) ?: ref_cuda_ver
|
||||
@@ -406,26 +338,19 @@ def TestCppGPU(args) {
|
||||
echo "Test C++, CUDA ${args.host_cuda_version}"
|
||||
def container_type = "gpu"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION=${args.host_cuda_version}"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.host_cuda_version}"
|
||||
sh "${dockerRun} ${container_type} ${docker_binary} ${docker_args} build/testxgboost"
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def CrossTestJVMwithJDKGPU(args) {
|
||||
def nodeReq = 'linux && mgpu'
|
||||
node(nodeReq) {
|
||||
unstash name: "xgboost4j_jar_gpu"
|
||||
unstash name: 'srcs'
|
||||
if (args.spark_version != null) {
|
||||
echo "Test XGBoost4J on a machine with JDK ${args.jdk_version}, Spark ${args.spark_version}, CUDA ${args.host_cuda_version}"
|
||||
} else {
|
||||
echo "Test XGBoost4J on a machine with JDK ${args.jdk_version}, CUDA ${args.host_cuda_version}"
|
||||
if (args.test_rmm) {
|
||||
sh "rm -rfv build/"
|
||||
unstash name: "xgboost_cpp_tests_rmm_cuda${args.host_cuda_version}"
|
||||
echo "Test C++, CUDA ${args.host_cuda_version} with RMM"
|
||||
container_type = "rmm"
|
||||
docker_binary = "nvidia-docker"
|
||||
docker_args = "--build-arg CUDA_VERSION_ARG=${args.host_cuda_version}"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "source activate gpu_test && build/testxgboost --use-rmm-pool --gtest_filter=-*DeathTest.*"
|
||||
"""
|
||||
}
|
||||
def container_type = "gpu_jvm"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION=${args.host_cuda_version}"
|
||||
sh "${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_jvm_gpu_cross.sh"
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
@@ -452,30 +377,13 @@ def CrossTestJVMwithJDK(args) {
|
||||
}
|
||||
}
|
||||
|
||||
def TestR(args) {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Test R package"
|
||||
def container_type = "rproject"
|
||||
def docker_binary = "docker"
|
||||
def use_r35_flag = (args.use_r35) ? "1" : "0"
|
||||
def docker_args = "--build-arg USE_R35=${use_r35_flag}"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_test_rpkg.sh || tests/ci_build/print_r_stacktrace.sh
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def DeployJVMPackages(args) {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
echo 'Deploying to xgboost-maven-repo S3 repo...'
|
||||
def container_type = "jvm"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/deploy_jvm_packages.sh ${args.spark_version}
|
||||
${dockerRun} jvm_gpu_build docker --build-arg CUDA_VERSION_ARG=10.0 tests/ci_build/deploy_jvm_packages.sh ${args.spark_version}
|
||||
"""
|
||||
}
|
||||
deleteDir()
|
||||
|
||||
@@ -25,12 +25,14 @@ pipeline {
|
||||
agent { label 'job_initializer' }
|
||||
steps {
|
||||
script {
|
||||
def buildNumber = env.BUILD_NUMBER as int
|
||||
if (buildNumber > 1) milestone(buildNumber - 1)
|
||||
milestone(buildNumber)
|
||||
checkoutSrcs()
|
||||
commit_id = "${GIT_COMMIT}"
|
||||
}
|
||||
sh 'python3 tests/jenkins_get_approval.py'
|
||||
stash name: 'srcs'
|
||||
milestone ordinal: 1
|
||||
}
|
||||
}
|
||||
stage('Jenkins Win64: Build') {
|
||||
@@ -41,7 +43,6 @@ pipeline {
|
||||
'build-win64-cuda10.1': { BuildWin64() }
|
||||
])
|
||||
}
|
||||
milestone ordinal: 2
|
||||
}
|
||||
}
|
||||
stage('Jenkins Win64: Test') {
|
||||
@@ -52,7 +53,6 @@ pipeline {
|
||||
'test-win64-cuda10.1': { TestWin64() },
|
||||
])
|
||||
}
|
||||
milestone ordinal: 3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ def BuildWin64() {
|
||||
bat """
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G"Visual Studio 15 2017 Win64" -DUSE_CUDA=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON ${arch_flag}
|
||||
cmake .. -G"Visual Studio 15 2017 Win64" -DUSE_CUDA=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON ${arch_flag} -DCMAKE_UNITY_BUILD=ON
|
||||
"""
|
||||
bat """
|
||||
cd build
|
||||
|
||||
8
Makefile
8
Makefile
@@ -134,14 +134,18 @@ Rpack: clean_all
|
||||
sed -i -e 's/@OPENMP_LIB@//g' xgboost/src/Makevars.win
|
||||
rm -f xgboost/src/Makevars.win-e # OSX sed create this extra file; remove it
|
||||
bash R-package/remove_warning_suppression_pragma.sh
|
||||
bash xgboost/remove_warning_suppression_pragma.sh
|
||||
rm xgboost/remove_warning_suppression_pragma.sh
|
||||
rm -rfv xgboost/tests/helper_scripts/
|
||||
|
||||
R ?= R
|
||||
|
||||
Rbuild: Rpack
|
||||
R CMD build --no-build-vignettes xgboost
|
||||
$(R) CMD build xgboost
|
||||
rm -rf xgboost
|
||||
|
||||
Rcheck: Rbuild
|
||||
R CMD check xgboost*.tar.gz
|
||||
$(R) CMD check --as-cran xgboost*.tar.gz
|
||||
|
||||
-include build/*.d
|
||||
-include build/*/*.d
|
||||
|
||||
181
NEWS.md
181
NEWS.md
@@ -3,6 +3,177 @@ XGBoost Change Log
|
||||
|
||||
This file records the changes in xgboost library in reverse chronological order.
|
||||
|
||||
## v1.2.0 (2020.08.22)
|
||||
|
||||
### XGBoost4J-Spark now supports the GPU algorithm (#5171)
|
||||
* Now XGBoost4J-Spark is able to leverage NVIDIA GPU hardware to speed up training.
|
||||
* There is on-going work for accelerating the rest of the data pipeline with NVIDIA GPUs (#5950, #5972).
|
||||
|
||||
### XGBoost now supports CUDA 11 (#5808)
|
||||
* It is now possible to build XGBoost with CUDA 11. Note that we do not yet distribute pre-built binaries built with CUDA 11; all current distributions use CUDA 10.0.
|
||||
|
||||
### Better guidance for persisting XGBoost models in an R environment (#5940, #5964)
|
||||
* Users are strongly encouraged to use `xgb.save()` and `xgb.save.raw()` instead of `saveRDS()`. This is so that the persisted models can be accessed with future releases of XGBoost.
|
||||
* The previous release (1.1.0) had problems loading models that were saved with `saveRDS()`. This release adds a compatibility layer to restore access to the old RDS files. Note that this is meant to be a temporary measure; users are advised to stop using `saveRDS()` and migrate to `xgb.save()` and `xgb.save.raw()`.
|
||||
|
||||
### New objectives and metrics
|
||||
* The pseudo-Huber loss `reg:pseudohubererror` is added (#5647). The corresponding metric is `mphe`. Right now, the slope is hard-coded to 1.
|
||||
* The Accelerated Failure Time objective for survival analysis (`survival:aft`) is now accelerated on GPUs (#5714, #5716). The survival metrics `aft-nloglik` and `interval-regression-accuracy` are also accelerated on GPUs.
|
||||
|
||||
### Improved integration with scikit-learn
|
||||
* Added `n_features_in_` attribute to the scikit-learn interface to store the number of features used (#5780). This is useful for integrating with some scikit-learn features such as `StackingClassifier`. See [this link](https://scikit-learn-enhancement-proposals.readthedocs.io/en/latest/slep010/proposal.html) for more details.
|
||||
* `XGBoostError` now inherits `ValueError`, which conforms scikit-learn's exception requirement (#5696).
|
||||
|
||||
### Improved integration with Dask
|
||||
* The XGBoost Dask API now exposes an asynchronous interface (#5862). See [the document](https://xgboost.readthedocs.io/en/latest/tutorials/dask.html#working-with-asyncio) for details.
|
||||
* Zero-copy ingestion of GPU arrays via `DaskDeviceQuantileDMatrix` (#5623, #5799, #5800, #5803, #5837, #5874, #5901): Previously, the Dask interface had to make 2 data copies: one for concatenating the Dask partition/block into a single block and another for internal representation. To save memory, we introduce `DaskDeviceQuantileDMatrix`. As long as Dask partitions are resident in the GPU memory, `DaskDeviceQuantileDMatrix` is able to ingest them directly without making copies. This matrix type wraps `DeviceQuantileDMatrix`.
|
||||
* The prediction function now returns GPU Series type if the input is from Dask-cuDF (#5710). This is to preserve the input data type.
|
||||
|
||||
### Robust handling of external data types (#5689, #5893)
|
||||
- As we support more and more external data types, the handling logic has proliferated all over the code base and became hard to keep track. It also became unclear how missing values and threads are handled. We refactored the Python package code to collect all data handling logic to a central location, and now we have an explicit list of of all supported data types.
|
||||
|
||||
### Improvements in GPU-side data matrix (`DeviceQuantileDMatrix`)
|
||||
* The GPU-side data matrix now implements its own quantile sketching logic, so that data don't have to be transported back to the main memory (#5700, #5747, #5760, #5846, #5870, #5898). The GK sketching algorithm is also now better documented.
|
||||
- Now we can load extremely sparse dataset like URL, although performance is still sub-optimal.
|
||||
* The GPU-side data matrix now exposes an iterative interface (#5783), so that users are able to construct a matrix from a data iterator. See the [Python demo](https://github.com/dmlc/xgboost/blob/release_1.2.0/demo/guide-python/data_iterator.py).
|
||||
|
||||
### New language binding: Swift (#5728)
|
||||
* Visit https://github.com/kongzii/SwiftXGBoost for more details.
|
||||
|
||||
### Robust model serialization with JSON (#5772, #5804, #5831, #5857, #5934)
|
||||
* We continue efforts from the 1.0.0 release to adopt JSON as the format to save and load models robustly.
|
||||
* JSON model IO is significantly faster and produces smaller model files.
|
||||
* Round-trip reproducibility is guaranteed, via the introduction of an efficient float-to-string conversion algorithm known as [the Ryū algorithm](https://dl.acm.org/doi/10.1145/3192366.3192369). The conversion is locale-independent, producing consistent numeric representation regardless of the locale setting of the user's machine.
|
||||
* We fixed an issue in loading large JSON files to memory.
|
||||
* It is now possible to load a JSON file from a remote source such as S3.
|
||||
|
||||
### Performance improvements
|
||||
* CPU hist tree method optimization
|
||||
- Skip missing lookup in hist row partitioning if data is dense. (#5644)
|
||||
- Specialize training procedures for CPU hist tree method on distributed environment. (#5557)
|
||||
- Add single point histogram for CPU hist. Previously gradient histogram for CPU hist is hard coded to be 64 bit, now users can specify the parameter `single_precision_histogram` to use 32 bit histogram instead for faster training performance. (#5624, #5811)
|
||||
* GPU hist tree method optimization
|
||||
- Removed some unnecessary synchronizations and better memory allocation pattern. (#5707)
|
||||
- Optimize GPU Hist for wide dataset. Previously for wide dataset the atomic operation is performed on global memory, now it can run on shared memory for faster histogram building. But there's a known small regression on GeForce cards with dense data. (#5795, #5926, #5948, #5631)
|
||||
|
||||
### API additions
|
||||
* Support passing fmap to importance plot (#5719). Now importance plot can show actual names of features instead of default ones.
|
||||
* Support 64bit seed. (#5643)
|
||||
* A new C API `XGBoosterGetNumFeature` is added for getting number of features in booster (#5856).
|
||||
* Feature names and feature types are now stored in C++ core and saved in binary DMatrix (#5858).
|
||||
|
||||
### Breaking: The `predict()` method of `DaskXGBClassifier` now produces class predictions (#5986). Use `predict_proba()` to obtain probability predictions.
|
||||
* Previously, `DaskXGBClassifier.predict()` produced probability predictions. This is inconsistent with the behavior of other scikit-learn classifiers, where `predict()` returns class predictions. We make a breaking change in 1.2.0 release so that `DaskXGBClassifier.predict()` now correctly produces class predictions and thus behave like other scikit-learn classifiers. Furthermore, we introduce the `predict_proba()` method for obtaining probability predictions, again to be in line with other scikit-learn classifiers.
|
||||
|
||||
### Breaking: Custom evaluation metric now receives raw prediction (#5954)
|
||||
* Previously, the custom evaluation metric received a transformed prediction result when used with a classifier. Now the custom metric will receive a raw (untransformed) prediction and will need to transform the prediction itself. See [demo/guide-python/custom\_softmax.py](https://github.com/dmlc/xgboost/blob/release_1.2.0/demo/guide-python/custom_softmax.py) for an example.
|
||||
* This change is to make the custom metric behave consistently with the custom objective, which already receives raw prediction (#5564).
|
||||
|
||||
### Breaking: XGBoost4J-Spark now requires Spark 3.0 and Scala 2.12 (#5836, #5890)
|
||||
* Starting with version 3.0, Spark can manage GPU resources and allocate them among executors.
|
||||
* Spark 3.0 dropped support for Scala 2.11 and now only supports Scala 2.12. Thus, XGBoost4J-Spark also only supports Scala 2.12.
|
||||
|
||||
### Breaking: XGBoost Python package now requires Python 3.6 and later (#5715)
|
||||
* Python 3.6 has many useful features such as f-strings.
|
||||
|
||||
### Breaking: XGBoost now adopts the C++14 standard (#5664)
|
||||
* Make sure to use a sufficiently modern C++ compiler that supports C++14, such as Visual Studio 2017, GCC 5.0+, and Clang 3.4+.
|
||||
|
||||
### Bug-fixes
|
||||
* Fix a data race in the prediction function (#5853). As a byproduct, the prediction function now uses a thread-local data store and became thread-safe.
|
||||
* Restore capability to run prediction when the test input has fewer features than the training data (#5955). This capability is necessary to support predicting with LIBSVM inputs. The previous release (1.1) had broken this capability, so we restore it in this version with better tests.
|
||||
* Fix OpenMP build with CMake for R package, to support CMake 3.13 (#5895).
|
||||
* Fix Windows 2016 build (#5902, #5918).
|
||||
* Fix edge cases in scikit-learn interface with Pandas input by disabling feature validation. (#5953)
|
||||
* [R] Enable weighted learning to rank (#5945)
|
||||
* [R] Fix early stopping with custom objective (#5923)
|
||||
* Fix NDK Build (#5886)
|
||||
* Add missing explicit template specializations for greater portability (#5921)
|
||||
* Handle empty rows in data iterators correctly (#5929). This bug affects file loader and JVM data frames.
|
||||
* Fix `IsDense` (#5702)
|
||||
* [jvm-packages] Fix wrong method name `setAllowZeroForMissingValue` (#5740)
|
||||
* Fix shape inference for Dask predict (#5989)
|
||||
|
||||
### Usability Improvements, Documentation
|
||||
* [Doc] Document that CUDA 10.0 is required (#5872)
|
||||
* Refactored command line interface (CLI). Now CLI is able to handle user errors and output basic document. (#5574)
|
||||
* Better error handling in Python: use `raise from` syntax to preserve full stacktrace (#5787).
|
||||
* The JSON model dump now has a formal schema (#5660, #5818). The benefit is to prevent `dump_model()` function from breaking. See [this document](https://xgboost.readthedocs.io/en/latest/tutorials/saving_model.html#difference-between-saving-model-and-dumping-model) to understand the difference between saving and dumping models.
|
||||
* Add a reference to the GPU external memory paper (#5684)
|
||||
* Document more objective parameters in the R package (#5682)
|
||||
* Document the existence of pre-built binary wheels for MacOS (#5711)
|
||||
* Remove `max.depth` in the R gblinear example. (#5753)
|
||||
* Added conda environment file for building docs (#5773)
|
||||
* Mention dask blog post in the doc, which introduces using Dask with GPU and some internal workings. (#5789)
|
||||
* Fix rendering of Markdown docs (#5821)
|
||||
* Document new objectives and metrics available on GPUs (#5909)
|
||||
* Better message when no GPU is found. (#5594)
|
||||
* Remove the use of `silent` parameter from R demos. (#5675)
|
||||
* Don't use masked array in array interface. (#5730)
|
||||
* Update affiliation of @terrytangyuan: Ant Financial -> Ant Group (#5827)
|
||||
* Move dask tutorial closer other distributed tutorials (#5613)
|
||||
* Update XGBoost + Dask overview documentation (#5961)
|
||||
* Show `n_estimators` in the docstring of the scikit-learn interface (#6041)
|
||||
* Fix a type in a doctring of the scikit-learn interface (#5980)
|
||||
|
||||
### Maintenance: testing, continuous integration, build system
|
||||
* [CI] Remove CUDA 9.0 from CI (#5674, #5745)
|
||||
* Require CUDA 10.0+ in CMake build (#5718)
|
||||
* [R] Remove dependency on gendef for Visual Studio builds (fixes #5608) (#5764). This enables building XGBoost with GPU support with R 4.x.
|
||||
* [R-package] Reduce duplication in configure.ac (#5693)
|
||||
* Bump com.esotericsoftware to 4.0.2 (#5690)
|
||||
* Migrate some tests from AppVeyor to GitHub Actions to speed up the tests. (#5911, #5917, #5919, #5922, #5928)
|
||||
* Reduce cost of the Jenkins CI server (#5884, #5904, #5892). We now enforce a daily budget via an automated monitor. We also dramatically reduced the workload for the Windows platform, since the cloud VM cost is vastly greater for Windows.
|
||||
* [R] Set up automated R linter (#5944)
|
||||
* [R] replace uses of T and F with TRUE and FALSE (#5778)
|
||||
* Update Docker container 'CPU' (#5956)
|
||||
* Simplify CMake build with modern CMake techniques (#5871)
|
||||
* Use `hypothesis` package for testing (#5759, #5835, #5849).
|
||||
* Define `_CRT_SECURE_NO_WARNINGS` to remove unneeded warnings in MSVC (#5434)
|
||||
* Run all Python demos in CI, to ensure that they don't break (#5651)
|
||||
* Enhance nvtx support (#5636). Now we can use unified timer between CPU and GPU. Also CMake is able to find nvtx automatically.
|
||||
* Speed up python test. (#5752)
|
||||
* Add helper for generating batches of data. (#5756)
|
||||
* Add c-api-demo to .gitignore (#5855)
|
||||
* Add option to enable all compiler warnings in GCC/Clang (#5897)
|
||||
* Make Python model compatibility test runnable locally (#5941)
|
||||
* Add cupy to Windows CI (#5797)
|
||||
* [CI] Fix cuDF install; merge 'gpu' and 'cudf' test suite (#5814)
|
||||
* Update rabit submodule (#5680, #5876)
|
||||
* Force colored output for Ninja build. (#5959)
|
||||
* [CI] Assign larger /dev/shm to NCCL (#5966)
|
||||
* Add missing Pytest marks to AsyncIO unit test (#5968)
|
||||
* [CI] Use latest cuDF and dask-cudf (#6048)
|
||||
* Add CMake flag to log C API invocations, to aid debugging (#5925)
|
||||
* Fix a unit test on CLI, to handle RC versions (#6050)
|
||||
* [CI] Use mgpu machine to run gpu hist unit tests (#6050)
|
||||
* [CI] Build GPU-enabled JAR artifact and deploy to xgboost-maven-repo (#6050)
|
||||
|
||||
### Maintenance: Refactor code for legibility and maintainability
|
||||
* Remove dead code in DMatrix initialization. (#5635)
|
||||
* Catch dmlc error by ref. (#5678)
|
||||
* Refactor the `gpu_hist` split evaluation in preparation for batched nodes enumeration. (#5610)
|
||||
* Remove column major specialization. (#5755)
|
||||
* Remove unused imports in Python (#5776)
|
||||
* Avoid including `c_api.h` in header files. (#5782)
|
||||
* Remove unweighted GK quantile, which is unused. (#5816)
|
||||
* Add Python binding for rabit ops. (#5743)
|
||||
* Implement `Empty` method for host device vector. (#5781)
|
||||
* Remove print (#5867)
|
||||
* Enforce tree order in JSON (#5974)
|
||||
|
||||
### Acknowledgement
|
||||
**Contributors**: Nan Zhu (@CodingCat), @LionOrCatThatIsTheQuestion, Dmitry Mottl (@Mottl), Rory Mitchell (@RAMitchell), @ShvetsKS, Alex Wozniakowski (@a-wozniakowski), Alexander Gugel (@alexanderGugel), @anttisaukko, @boxdot, Andy Adinets (@canonizer), Ram Rachum (@cool-RR), Elliot Hershberg (@elliothershberg), Jason E. Aten, Ph.D. (@glycerine), Philip Hyunsu Cho (@hcho3), @jameskrach, James Lamb (@jameslamb), James Bourbeau (@jrbourbeau), Peter Jung (@kongzii), Lorenz Walthert (@lorenzwalthert), Oleksandr Kuvshynov (@okuvshynov), Rong Ou (@rongou), Shaochen Shi (@shishaochen), Yuan Tang (@terrytangyuan), Jiaming Yuan (@trivialfis), Bobby Wang (@wbo4958), Zhang Zhang (@zhangzhang10)
|
||||
|
||||
**Reviewers**: Nan Zhu (@CodingCat), @LionOrCatThatIsTheQuestion, Hao Yang (@QuantHao), Rory Mitchell (@RAMitchell), @ShvetsKS, Egor Smirnov (@SmirnovEgorRu), Alex Wozniakowski (@a-wozniakowski), Amit Kumar (@aktech), Avinash Barnwal (@avinashbarnwal), @boxdot, Andy Adinets (@canonizer), Chandra Shekhar Reddy (@chandrureddy), Ram Rachum (@cool-RR), Cristiano Goncalves (@cristianogoncalves), Elliot Hershberg (@elliothershberg), Jason E. Aten, Ph.D. (@glycerine), Philip Hyunsu Cho (@hcho3), Tong He (@hetong007), James Lamb (@jameslamb), James Bourbeau (@jrbourbeau), Lee Drake (@leedrake5), DougM (@mengdong), Oleksandr Kuvshynov (@okuvshynov), RongOu (@rongou), Shaochen Shi (@shishaochen), Xu Xiao (@sperlingxx), Yuan Tang (@terrytangyuan), Theodore Vasiloudis (@thvasilo), Jiaming Yuan (@trivialfis), Bobby Wang (@wbo4958), Zhang Zhang (@zhangzhang10)
|
||||
|
||||
## v1.1.1 (2020.06.06)
|
||||
This patch release applies the following patches to 1.1.0 release:
|
||||
|
||||
* CPU performance improvement in the PyPI wheels (#5720)
|
||||
* Fix loading old model (#5724)
|
||||
* Install pkg-config file (#5744)
|
||||
|
||||
## v1.1.0 (2020.05.17)
|
||||
|
||||
### Better performance on multi-core CPUs (#5244, #5334, #5522)
|
||||
@@ -203,6 +374,16 @@ Upgrading to latest pip allows us to depend on newer versions of system librarie
|
||||
|
||||
**Reviewers**: Nan Zhu (@CodingCat), @LeZhengThu, Rory Mitchell (@RAMitchell), @ShvetsKS, Egor Smirnov (@SmirnovEgorRu), Steve Bronder (@SteveBronder), Nikita Titov (@StrikerRUS), Andrew Kane (@ankane), Avinash Barnwal (@avinashbarnwal), @brydag, Andy Adinets (@canonizer), Chandra Shekhar Reddy (@chandrureddy), Chen Qin (@chenqin), Codecov (@codecov-io), David Díaz Vico (@daviddiazvico), Darby Payne (@dpayne), Jason E. Aten, Ph.D. (@glycerine), Philip Hyunsu Cho (@hcho3), James Lamb (@jameslamb), @johnny-cat, Mu Li (@mli), Mate Soos (@msoos), @rnyak, Rong Ou (@rongou), Sriram Chandramouli (@sriramch), Toby Dylan Hocking (@tdhock), Yuan Tang (@terrytangyuan), Oleksandr Pryimak (@trams), Jiaming Yuan (@trivialfis), Liang-Chi Hsieh (@viirya), Bobby Wang (@wbo4958),
|
||||
|
||||
## v1.0.2 (2020.03.03)
|
||||
This patch release applies the following patches to 1.0.0 release:
|
||||
|
||||
* Fix a small typo in sklearn.py that broke multiple eval metrics (#5341)
|
||||
* Restore loading model from buffer (#5360)
|
||||
* Use type name for data type check (#5364)
|
||||
|
||||
## v1.0.1 (2020.02.21)
|
||||
This release is identical to the 1.0.0 release, except that it fixes a small bug that rendered 1.0.0 incompatible with Python 3.5. See #5328.
|
||||
|
||||
## v1.0.0 (2020.02.19)
|
||||
This release marks a major milestone for the XGBoost project.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Package: xgboost
|
||||
Type: Package
|
||||
Title: Extreme Gradient Boosting
|
||||
Version: 1.2.0.1
|
||||
Date: 2020-02-21
|
||||
Version: 1.3.2.1
|
||||
Date: 2020-08-28
|
||||
Authors@R: c(
|
||||
person("Tianqi", "Chen", role = c("aut"),
|
||||
email = "tianqi.tchen@gmail.com"),
|
||||
@@ -55,7 +55,8 @@ Suggests:
|
||||
igraph (>= 1.0.1),
|
||||
jsonlite,
|
||||
float,
|
||||
crayon
|
||||
crayon,
|
||||
titanic
|
||||
Depends:
|
||||
R (>= 3.3.0)
|
||||
Imports:
|
||||
@@ -63,6 +64,5 @@ Imports:
|
||||
methods,
|
||||
data.table (>= 1.9.6),
|
||||
magrittr (>= 1.5),
|
||||
stringi (>= 0.5.2)
|
||||
RoxygenNote: 7.1.1
|
||||
SystemRequirements: GNU make, C++14
|
||||
|
||||
@@ -38,6 +38,7 @@ export(xgb.dump)
|
||||
export(xgb.gblinear.history)
|
||||
export(xgb.ggplot.deepness)
|
||||
export(xgb.ggplot.importance)
|
||||
export(xgb.ggplot.shap.summary)
|
||||
export(xgb.importance)
|
||||
export(xgb.load)
|
||||
export(xgb.load.raw)
|
||||
@@ -46,6 +47,7 @@ export(xgb.plot.deepness)
|
||||
export(xgb.plot.importance)
|
||||
export(xgb.plot.multi.trees)
|
||||
export(xgb.plot.shap)
|
||||
export(xgb.plot.shap.summary)
|
||||
export(xgb.plot.tree)
|
||||
export(xgb.save)
|
||||
export(xgb.save.raw)
|
||||
@@ -79,11 +81,6 @@ importFrom(graphics,title)
|
||||
importFrom(magrittr,"%>%")
|
||||
importFrom(stats,median)
|
||||
importFrom(stats,predict)
|
||||
importFrom(stringi,stri_detect_regex)
|
||||
importFrom(stringi,stri_match_first_regex)
|
||||
importFrom(stringi,stri_replace_all_regex)
|
||||
importFrom(stringi,stri_replace_first_regex)
|
||||
importFrom(stringi,stri_split_regex)
|
||||
importFrom(utils,head)
|
||||
importFrom(utils,object.size)
|
||||
importFrom(utils,str)
|
||||
|
||||
@@ -352,9 +352,15 @@ cb.early.stop <- function(stopping_rounds, maximize = FALSE,
|
||||
finalizer <- function(env) {
|
||||
if (!is.null(env$bst)) {
|
||||
attr_best_score <- as.numeric(xgb.attr(env$bst$handle, 'best_score'))
|
||||
if (best_score != attr_best_score)
|
||||
stop("Inconsistent 'best_score' values between the closure state: ", best_score,
|
||||
" and the xgb.attr: ", attr_best_score)
|
||||
if (best_score != attr_best_score) {
|
||||
# If the difference is too big, throw an error
|
||||
if (abs(best_score - attr_best_score) >= 1e-14) {
|
||||
stop("Inconsistent 'best_score' values between the closure state: ", best_score,
|
||||
" and the xgb.attr: ", attr_best_score)
|
||||
}
|
||||
# If the difference is due to floating-point truncation, update best_score
|
||||
best_score <- attr_best_score
|
||||
}
|
||||
env$bst$best_iteration <- best_iteration
|
||||
env$bst$best_ntreelimit <- best_ntreelimit
|
||||
env$bst$best_score <- best_score
|
||||
|
||||
@@ -20,6 +20,12 @@ NVL <- function(x, val) {
|
||||
stop("typeof(x) == ", typeof(x), " is not supported by NVL")
|
||||
}
|
||||
|
||||
# List of classification and ranking objectives
|
||||
.CLASSIFICATION_OBJECTIVES <- function() {
|
||||
return(c('binary:logistic', 'binary:logitraw', 'binary:hinge', 'multi:softmax',
|
||||
'multi:softprob', 'rank:pairwise', 'rank:ndcg', 'rank:map'))
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Low-level functions for boosting --------------------------------------------
|
||||
@@ -167,9 +173,8 @@ xgb.iter.eval <- function(booster_handle, watchlist, iter, feval = NULL) {
|
||||
evnames <- names(watchlist)
|
||||
if (is.null(feval)) {
|
||||
msg <- .Call(XGBoosterEvalOneIter_R, booster_handle, as.integer(iter), watchlist, as.list(evnames))
|
||||
msg <- stri_split_regex(msg, '(\\s+|:|\\s+)')[[1]][-1]
|
||||
res <- as.numeric(msg[c(FALSE, TRUE)]) # even indices are the values
|
||||
names(res) <- msg[c(TRUE, FALSE)] # odds are the names
|
||||
mat <- matrix(strsplit(msg, '\\s+|:')[[1]][-1], nrow = 2)
|
||||
res <- structure(as.numeric(mat[2, ]), names = mat[1, ])
|
||||
} else {
|
||||
res <- sapply(seq_along(watchlist), function(j) {
|
||||
w <- watchlist[[j]]
|
||||
@@ -188,13 +193,23 @@ xgb.iter.eval <- function(booster_handle, watchlist, iter, feval = NULL) {
|
||||
# Helper functions for cross validation ---------------------------------------
|
||||
#
|
||||
|
||||
# Possibly convert the labels into factors, depending on the objective.
|
||||
# The labels are converted into factors only when the given objective refers to the classification
|
||||
# or ranking tasks.
|
||||
convert.labels <- function(labels, objective_name) {
|
||||
if (objective_name %in% .CLASSIFICATION_OBJECTIVES()) {
|
||||
return(as.factor(labels))
|
||||
} else {
|
||||
return(labels)
|
||||
}
|
||||
}
|
||||
|
||||
# Generates random (stratified if needed) CV folds
|
||||
generate.cv.folds <- function(nfold, nrows, stratified, label, params) {
|
||||
|
||||
# cannot do it for rank
|
||||
if (exists('objective', where = params) &&
|
||||
is.character(params$objective) &&
|
||||
strtrim(params$objective, 5) == 'rank:') {
|
||||
objective <- params$objective
|
||||
if (is.character(objective) && strtrim(objective, 5) == 'rank:') {
|
||||
stop("\n\tAutomatic generation of CV-folds is not implemented for ranking!\n",
|
||||
"\tConsider providing pre-computed CV-folds through the 'folds=' parameter.\n")
|
||||
}
|
||||
@@ -207,19 +222,16 @@ generate.cv.folds <- function(nfold, nrows, stratified, label, params) {
|
||||
# - For classification, need to convert y labels to factor before making the folds,
|
||||
# and then do stratification by factor levels.
|
||||
# - For regression, leave y numeric and do stratification by quantiles.
|
||||
if (exists('objective', where = params) &&
|
||||
is.character(params$objective)) {
|
||||
# If 'objective' provided in params, assume that y is a classification label
|
||||
# unless objective is reg:squarederror
|
||||
if (params$objective != 'reg:squarederror')
|
||||
y <- factor(y)
|
||||
if (is.character(objective)) {
|
||||
y <- convert.labels(y, params$objective)
|
||||
} else {
|
||||
# If no 'objective' given in params, it means that user either wants to
|
||||
# use the default 'reg:squarederror' objective or has provided a custom
|
||||
# obj function. Here, assume classification setting when y has 5 or less
|
||||
# unique values:
|
||||
if (length(unique(y)) <= 5)
|
||||
if (length(unique(y)) <= 5) {
|
||||
y <- factor(y)
|
||||
}
|
||||
}
|
||||
folds <- xgb.createFolds(y, nfold)
|
||||
} else {
|
||||
@@ -349,6 +361,7 @@ NULL
|
||||
#' # Save as a stand-alone file (JSON); load it with xgb.load()
|
||||
#' xgb.save(bst, 'xgb.model.json')
|
||||
#' bst2 <- xgb.load('xgb.model.json')
|
||||
#' if (file.exists('xgb.model.json')) file.remove('xgb.model.json')
|
||||
#'
|
||||
#' # Save as a raw byte vector; load it with xgb.load.raw()
|
||||
#' xgb_bytes <- xgb.save.raw(bst)
|
||||
@@ -364,6 +377,7 @@ NULL
|
||||
#' obj2 <- readRDS('my_object.rds')
|
||||
#' # Re-construct xgb.Booster object from the bytes
|
||||
#' bst2 <- xgb.load.raw(obj2$xgb_model_bytes)
|
||||
#' if (file.exists('my_object.rds')) file.remove('my_object.rds')
|
||||
#'
|
||||
#' @name a-compatibility-note-for-saveRDS-save
|
||||
NULL
|
||||
|
||||
@@ -357,7 +357,7 @@ slice.xgb.DMatrix <- function(object, idxset, ...) {
|
||||
#' @export
|
||||
print.xgb.DMatrix <- function(x, verbose = FALSE, ...) {
|
||||
cat('xgb.DMatrix dim:', nrow(x), 'x', ncol(x), ' info: ')
|
||||
infos <- c()
|
||||
infos <- character(0)
|
||||
if (length(getinfo(x, 'label')) > 0) infos <- 'label'
|
||||
if (length(getinfo(x, 'weight')) > 0) infos <- c(infos, 'weight')
|
||||
if (length(getinfo(x, 'base_margin')) > 0) infos <- c(infos, 'base_margin')
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#' \item \code{error} binary classification error rate
|
||||
#' \item \code{rmse} Rooted mean square error
|
||||
#' \item \code{logloss} negative log-likelihood function
|
||||
#' \item \code{mae} Mean absolute error
|
||||
#' \item \code{mape} Mean absolute percentage error
|
||||
#' \item \code{auc} Area under curve
|
||||
#' \item \code{aucpr} Area under PR curve
|
||||
#' \item \code{merror} Exact matching error, used to evaluate multi-class classification
|
||||
@@ -79,7 +81,7 @@
|
||||
#'
|
||||
#' All observations are used for both training and validation.
|
||||
#'
|
||||
#' Adapted from \url{http://en.wikipedia.org/wiki/Cross-validation_\%28statistics\%29#k-fold_cross-validation}
|
||||
#' Adapted from \url{https://en.wikipedia.org/wiki/Cross-validation_\%28statistics\%29}
|
||||
#'
|
||||
#' @return
|
||||
#' An object of class \code{xgb.cv.synchronous} with the following elements:
|
||||
|
||||
@@ -56,10 +56,10 @@ xgb.dump <- function(model, fname = NULL, fmap = "", with_stats=FALSE,
|
||||
as.character(dump_format))
|
||||
|
||||
if (is.null(fname))
|
||||
model_dump <- stri_replace_all_regex(model_dump, '\t', '')
|
||||
model_dump <- gsub('\t', '', model_dump, fixed = TRUE)
|
||||
|
||||
if (dump_format == "text")
|
||||
model_dump <- unlist(stri_split_regex(model_dump, '\n'))
|
||||
model_dump <- unlist(strsplit(model_dump, '\n', fixed = TRUE))
|
||||
|
||||
model_dump <- grep('^\\s*$', model_dump, invert = TRUE, value = TRUE)
|
||||
|
||||
|
||||
@@ -99,6 +99,84 @@ xgb.ggplot.deepness <- function(model = NULL, which = c("2x1", "max.depth", "med
|
||||
}
|
||||
}
|
||||
|
||||
#' @rdname xgb.plot.shap.summary
|
||||
#' @export
|
||||
xgb.ggplot.shap.summary <- function(data, shap_contrib = NULL, features = NULL, top_n = 10, model = NULL,
|
||||
trees = NULL, target_class = NULL, approxcontrib = FALSE, subsample = NULL) {
|
||||
data_list <- xgb.shap.data(
|
||||
data = data,
|
||||
shap_contrib = shap_contrib,
|
||||
features = features,
|
||||
top_n = top_n,
|
||||
model = model,
|
||||
trees = trees,
|
||||
target_class = target_class,
|
||||
approxcontrib = approxcontrib,
|
||||
subsample = subsample,
|
||||
max_observations = 10000 # 10,000 samples per feature.
|
||||
)
|
||||
p_data <- prepare.ggplot.shap.data(data_list, normalize = TRUE)
|
||||
# Reverse factor levels so that the first level is at the top of the plot
|
||||
p_data[, "feature" := factor(feature, rev(levels(feature)))]
|
||||
p <- ggplot2::ggplot(p_data, ggplot2::aes(x = feature, y = p_data$shap_value, colour = p_data$feature_value)) +
|
||||
ggplot2::geom_jitter(alpha = 0.5, width = 0.1) +
|
||||
ggplot2::scale_colour_viridis_c(limits = c(-3, 3), option = "plasma", direction = -1) +
|
||||
ggplot2::geom_abline(slope = 0, intercept = 0, colour = "darkgrey") +
|
||||
ggplot2::coord_flip()
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
#' Combine and melt feature values and SHAP contributions for sample
|
||||
#' observations.
|
||||
#'
|
||||
#' Conforms to data format required for ggplot functions.
|
||||
#'
|
||||
#' Internal utility function.
|
||||
#'
|
||||
#' @param data_list List containing 'data' and 'shap_contrib' returned by
|
||||
#' \code{xgb.shap.data()}.
|
||||
#' @param normalize Whether to standardize feature values to have mean 0 and
|
||||
#' standard deviation 1 (useful for comparing multiple features on the same
|
||||
#' plot). Default \code{FALSE}.
|
||||
#'
|
||||
#' @return A data.table containing the observation ID, the feature name, the
|
||||
#' feature value (normalized if specified), and the SHAP contribution value.
|
||||
prepare.ggplot.shap.data <- function(data_list, normalize = FALSE) {
|
||||
data <- data_list[["data"]]
|
||||
shap_contrib <- data_list[["shap_contrib"]]
|
||||
|
||||
data <- data.table::as.data.table(as.matrix(data))
|
||||
if (normalize) {
|
||||
data[, (names(data)) := lapply(.SD, normalize)]
|
||||
}
|
||||
data[, "id" := seq_len(nrow(data))]
|
||||
data_m <- data.table::melt.data.table(data, id.vars = "id", variable.name = "feature", value.name = "feature_value")
|
||||
|
||||
shap_contrib <- data.table::as.data.table(as.matrix(shap_contrib))
|
||||
shap_contrib[, "id" := seq_len(nrow(shap_contrib))]
|
||||
shap_contrib_m <- data.table::melt.data.table(shap_contrib, id.vars = "id", variable.name = "feature", value.name = "shap_value")
|
||||
|
||||
p_data <- data.table::merge.data.table(data_m, shap_contrib_m, by = c("id", "feature"))
|
||||
|
||||
p_data
|
||||
}
|
||||
|
||||
#' Scale feature value to have mean 0, standard deviation 1
|
||||
#'
|
||||
#' This is used to compare multiple features on the same plot.
|
||||
#' Internal utility function
|
||||
#'
|
||||
#' @param x Numeric vector
|
||||
#'
|
||||
#' @return Numeric vector with mean 0 and sd 1.
|
||||
normalize <- function(x) {
|
||||
loc <- mean(x, na.rm = TRUE)
|
||||
scale <- stats::sd(x, na.rm = TRUE)
|
||||
|
||||
(x - loc) / scale
|
||||
}
|
||||
|
||||
# Plot multiple ggplot graph aligned by rows and columns.
|
||||
# ... the plots
|
||||
# cols number of columns
|
||||
@@ -131,5 +209,5 @@ multiplot <- function(..., cols = 1) {
|
||||
|
||||
globalVariables(c(
|
||||
"Cluster", "ggplot", "aes", "geom_bar", "coord_flip", "xlab", "ylab", "ggtitle", "theme",
|
||||
"element_blank", "element_text", "V1", "Weight"
|
||||
"element_blank", "element_text", "V1", "Weight", "feature"
|
||||
))
|
||||
|
||||
@@ -87,11 +87,11 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
}
|
||||
|
||||
if (length(text) < 2 ||
|
||||
sum(stri_detect_regex(text, 'yes=(\\d+),no=(\\d+)')) < 1) {
|
||||
sum(grepl('yes=(\\d+),no=(\\d+)', text)) < 1) {
|
||||
stop("Non-tree model detected! This function can only be used with tree models.")
|
||||
}
|
||||
|
||||
position <- which(!is.na(stri_match_first_regex(text, "booster")))
|
||||
position <- which(grepl("booster", text, fixed = TRUE))
|
||||
|
||||
add.tree.id <- function(node, tree) if (use_int_id) node else paste(tree, node, sep = "-")
|
||||
|
||||
@@ -108,9 +108,9 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
}
|
||||
td <- td[Tree %in% trees & !grepl('^booster', t)]
|
||||
|
||||
td[, Node := stri_match_first_regex(t, "(\\d+):")[, 2] %>% as.integer]
|
||||
td[, Node := as.integer(sub("^([0-9]+):.*", "\\1", t))]
|
||||
if (!use_int_id) td[, ID := add.tree.id(Node, Tree)]
|
||||
td[, isLeaf := !is.na(stri_match_first_regex(t, "leaf"))]
|
||||
td[, isLeaf := grepl("leaf", t, fixed = TRUE)]
|
||||
|
||||
# parse branch lines
|
||||
branch_rx <- paste0("f(\\d+)<(", anynumber_regex, ")\\] yes=(\\d+),no=(\\d+),missing=(\\d+),",
|
||||
@@ -118,10 +118,11 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
branch_cols <- c("Feature", "Split", "Yes", "No", "Missing", "Quality", "Cover")
|
||||
td[isLeaf == FALSE,
|
||||
(branch_cols) := {
|
||||
# skip some indices with spurious capture groups from anynumber_regex
|
||||
xtr <- stri_match_first_regex(t, branch_rx)[, c(2, 3, 5, 6, 7, 8, 10), drop = FALSE]
|
||||
xtr[, 3:5] <- add.tree.id(xtr[, 3:5], Tree)
|
||||
lapply(seq_len(ncol(xtr)), function(i) xtr[, i])
|
||||
matches <- regmatches(t, regexec(branch_rx, t))
|
||||
# skip some indices with spurious capture groups from anynumber_regex
|
||||
xtr <- do.call(rbind, matches)[, c(2, 3, 5, 6, 7, 8, 10), drop = FALSE]
|
||||
xtr[, 3:5] <- add.tree.id(xtr[, 3:5], Tree)
|
||||
as.data.table(xtr)
|
||||
}]
|
||||
# assign feature_names when available
|
||||
if (!is.null(feature_names)) {
|
||||
@@ -135,8 +136,9 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
leaf_cols <- c("Feature", "Quality", "Cover")
|
||||
td[isLeaf == TRUE,
|
||||
(leaf_cols) := {
|
||||
xtr <- stri_match_first_regex(t, leaf_rx)[, c(2, 4)]
|
||||
c("Leaf", lapply(seq_len(ncol(xtr)), function(i) xtr[, i]))
|
||||
matches <- regmatches(t, regexec(leaf_rx, t))
|
||||
xtr <- do.call(rbind, matches)[, c(2, 4)]
|
||||
c("Leaf", as.data.table(xtr))
|
||||
}]
|
||||
|
||||
# convert some columns to numeric
|
||||
|
||||
@@ -99,21 +99,20 @@ xgb.plot.importance <- function(importance_matrix = NULL, top_n = NULL, measure
|
||||
}
|
||||
|
||||
if (plot) {
|
||||
op <- par(no.readonly = TRUE)
|
||||
mar <- op$mar
|
||||
original_mar <- par()$mar
|
||||
|
||||
# reset margins so this function doesn't have side effects
|
||||
on.exit({par(mar = original_mar)})
|
||||
|
||||
mar <- original_mar
|
||||
if (!is.null(left_margin))
|
||||
mar[2] <- left_margin
|
||||
par(mar = mar)
|
||||
|
||||
# reverse the order of rows to have the highest ranked at the top
|
||||
importance_matrix[nrow(importance_matrix):1,
|
||||
importance_matrix[rev(seq_len(nrow(importance_matrix))),
|
||||
barplot(Importance, horiz = TRUE, border = NA, cex.names = cex,
|
||||
names.arg = Feature, las = 1, ...)]
|
||||
grid(NULL, NA)
|
||||
# redraw over the grid
|
||||
importance_matrix[nrow(importance_matrix):1,
|
||||
barplot(Importance, horiz = TRUE, border = NA, add = TRUE)]
|
||||
par(op)
|
||||
}
|
||||
|
||||
invisible(importance_matrix)
|
||||
|
||||
@@ -67,7 +67,7 @@ xgb.plot.multi.trees <- function(model, feature_names = NULL, features_keep = 5,
|
||||
|
||||
# first number of the path represents the tree, then the following numbers are related to the path to follow
|
||||
# root init
|
||||
root.nodes <- tree.matrix[stri_detect_regex(ID, "\\d+-0"), ID]
|
||||
root.nodes <- tree.matrix[Node == 0, ID]
|
||||
tree.matrix[ID %in% root.nodes, abs.node.position := root.nodes]
|
||||
|
||||
precedent.nodes <- root.nodes
|
||||
@@ -86,11 +86,8 @@ xgb.plot.multi.trees <- function(model, feature_names = NULL, features_keep = 5,
|
||||
tree.matrix[!is.na(Yes), Yes := paste0(abs.node.position, "_0")]
|
||||
tree.matrix[!is.na(No), No := paste0(abs.node.position, "_1")]
|
||||
|
||||
remove.tree <- . %>% stri_replace_first_regex(pattern = "^\\d+-", replacement = "")
|
||||
|
||||
tree.matrix[, `:=`(abs.node.position = remove.tree(abs.node.position),
|
||||
Yes = remove.tree(Yes),
|
||||
No = remove.tree(No))]
|
||||
for (nm in c("abs.node.position", "Yes", "No"))
|
||||
data.table::set(tree.matrix, j = nm, value = sub("^\\d+-", "", tree.matrix[[nm]]))
|
||||
|
||||
nodes.dt <- tree.matrix[
|
||||
, .(Quality = sum(Quality))
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#' xgb.plot.shap(agaricus.test$data, model = bst, features = "odor=none")
|
||||
#' contr <- predict(bst, agaricus.test$data, predcontrib = TRUE)
|
||||
#' xgb.plot.shap(agaricus.test$data, contr, model = bst, top_n = 12, n_col = 3)
|
||||
#' xgb.ggplot.shap.summary(agaricus.test$data, contr, model = bst, top_n = 12) # Summary plot
|
||||
#'
|
||||
#' # multiclass example - plots for each class separately:
|
||||
#' nclass <- 3
|
||||
@@ -99,6 +100,7 @@
|
||||
#' n_col = 2, col = col, pch = 16, pch_NA = 17)
|
||||
#' xgb.plot.shap(x, model = mbst, trees = trees0 + 2, target_class = 2, top_n = 4,
|
||||
#' n_col = 2, col = col, pch = 16, pch_NA = 17)
|
||||
#' xgb.ggplot.shap.summary(x, model = mbst, target_class = 0, top_n = 4) # Summary plot
|
||||
#'
|
||||
#' @rdname xgb.plot.shap
|
||||
#' @export
|
||||
@@ -109,69 +111,33 @@ xgb.plot.shap <- function(data, shap_contrib = NULL, features = NULL, top_n = 1,
|
||||
plot_NA = TRUE, col_NA = rgb(0.7, 0, 1, 0.6), pch_NA = '.', pos_NA = 1.07,
|
||||
plot_loess = TRUE, col_loess = 2, span_loess = 0.5,
|
||||
which = c("1d", "2d"), plot = TRUE, ...) {
|
||||
|
||||
if (!is.matrix(data) && !inherits(data, "dgCMatrix"))
|
||||
stop("data: must be either matrix or dgCMatrix")
|
||||
|
||||
if (is.null(shap_contrib) && (is.null(model) || !inherits(model, "xgb.Booster")))
|
||||
stop("when shap_contrib is not provided, one must provide an xgb.Booster model")
|
||||
|
||||
if (is.null(features) && (is.null(model) || !inherits(model, "xgb.Booster")))
|
||||
stop("when features are not provided, one must provide an xgb.Booster model to rank the features")
|
||||
|
||||
if (!is.null(shap_contrib) &&
|
||||
(!is.matrix(shap_contrib) || nrow(shap_contrib) != nrow(data) || ncol(shap_contrib) != ncol(data) + 1))
|
||||
stop("shap_contrib is not compatible with the provided data")
|
||||
|
||||
nsample <- if (is.null(subsample)) min(100000, nrow(data)) else as.integer(subsample * nrow(data))
|
||||
idx <- sample(1:nrow(data), nsample)
|
||||
data <- data[idx, ]
|
||||
|
||||
if (is.null(shap_contrib)) {
|
||||
shap_contrib <- predict(model, data, predcontrib = TRUE, approxcontrib = approxcontrib)
|
||||
} else {
|
||||
shap_contrib <- shap_contrib[idx, ]
|
||||
}
|
||||
data_list <- xgb.shap.data(
|
||||
data = data,
|
||||
shap_contrib = shap_contrib,
|
||||
features = features,
|
||||
top_n = top_n,
|
||||
model = model,
|
||||
trees = trees,
|
||||
target_class = target_class,
|
||||
approxcontrib = approxcontrib,
|
||||
subsample = subsample,
|
||||
max_observations = 100000
|
||||
)
|
||||
data <- data_list[["data"]]
|
||||
shap_contrib <- data_list[["shap_contrib"]]
|
||||
features <- colnames(data)
|
||||
|
||||
which <- match.arg(which)
|
||||
if (which == "2d")
|
||||
stop("2D plots are not implemented yet")
|
||||
|
||||
if (is.null(features)) {
|
||||
imp <- xgb.importance(model = model, trees = trees)
|
||||
top_n <- as.integer(top_n[1])
|
||||
if (top_n < 1 && top_n > 100)
|
||||
stop("top_n: must be an integer within [1, 100]")
|
||||
features <- imp$Feature[1:min(top_n, NROW(imp))]
|
||||
}
|
||||
|
||||
if (is.character(features)) {
|
||||
if (is.null(colnames(data)))
|
||||
stop("Either provide `data` with column names or provide `features` as column indices")
|
||||
features <- match(features, colnames(data))
|
||||
}
|
||||
|
||||
if (n_col > length(features)) n_col <- length(features)
|
||||
|
||||
if (is.list(shap_contrib)) { # multiclass: either choose a class or merge
|
||||
shap_contrib <- if (!is.null(target_class)) shap_contrib[[target_class + 1]]
|
||||
else Reduce("+", lapply(shap_contrib, abs))
|
||||
}
|
||||
|
||||
shap_contrib <- shap_contrib[, features, drop = FALSE]
|
||||
data <- data[, features, drop = FALSE]
|
||||
cols <- colnames(data)
|
||||
if (is.null(cols)) cols <- colnames(shap_contrib)
|
||||
if (is.null(cols)) cols <- paste0('X', 1:ncol(data))
|
||||
colnames(data) <- cols
|
||||
colnames(shap_contrib) <- cols
|
||||
|
||||
if (plot && which == "1d") {
|
||||
op <- par(mfrow = c(ceiling(length(features) / n_col), n_col),
|
||||
oma = c(0, 0, 0, 0) + 0.2,
|
||||
mar = c(3.5, 3.5, 0, 0) + 0.1,
|
||||
mgp = c(1.7, 0.6, 0))
|
||||
for (f in cols) {
|
||||
for (f in features) {
|
||||
ord <- order(data[, f])
|
||||
x <- data[, f][ord]
|
||||
y <- shap_contrib[, f][ord]
|
||||
@@ -216,3 +182,108 @@ xgb.plot.shap <- function(data, shap_contrib = NULL, features = NULL, top_n = 1,
|
||||
}
|
||||
invisible(list(data = data, shap_contrib = shap_contrib))
|
||||
}
|
||||
|
||||
#' SHAP contribution dependency summary plot
|
||||
#'
|
||||
#' Compare SHAP contributions of different features.
|
||||
#'
|
||||
#' A point plot (each point representing one sample from \code{data}) is
|
||||
#' produced for each feature, with the points plotted on the SHAP value axis.
|
||||
#' Each point (observation) is coloured based on its feature value. The plot
|
||||
#' hence allows us to see which features have a negative / positive contribution
|
||||
#' on the model prediction, and whether the contribution is different for larger
|
||||
#' or smaller values of the feature. We effectively try to replicate the
|
||||
#' \code{summary_plot} function from https://github.com/slundberg/shap.
|
||||
#'
|
||||
#' @inheritParams xgb.plot.shap
|
||||
#'
|
||||
#' @return A \code{ggplot2} object.
|
||||
#' @export
|
||||
#'
|
||||
#' @examples # See \code{\link{xgb.plot.shap}}.
|
||||
#' @seealso \code{\link{xgb.plot.shap}}, \code{\link{xgb.ggplot.shap.summary}},
|
||||
#' \url{https://github.com/slundberg/shap}
|
||||
xgb.plot.shap.summary <- function(data, shap_contrib = NULL, features = NULL, top_n = 10, model = NULL,
|
||||
trees = NULL, target_class = NULL, approxcontrib = FALSE, subsample = NULL) {
|
||||
# Only ggplot implementation is available.
|
||||
xgb.ggplot.shap.summary(data, shap_contrib, features, top_n, model, trees, target_class, approxcontrib, subsample)
|
||||
}
|
||||
|
||||
#' Prepare data for SHAP plots. To be used in xgb.plot.shap, xgb.plot.shap.summary, etc.
|
||||
#' Internal utility function.
|
||||
#'
|
||||
#' @inheritParams xgb.plot.shap
|
||||
#' @keywords internal
|
||||
#'
|
||||
#' @return A list containing: 'data', a matrix containing sample observations
|
||||
#' and their feature values; 'shap_contrib', a matrix containing the SHAP contribution
|
||||
#' values for these observations.
|
||||
xgb.shap.data <- function(data, shap_contrib = NULL, features = NULL, top_n = 1, model = NULL,
|
||||
trees = NULL, target_class = NULL, approxcontrib = FALSE,
|
||||
subsample = NULL, max_observations = 100000) {
|
||||
if (!is.matrix(data) && !inherits(data, "dgCMatrix"))
|
||||
stop("data: must be either matrix or dgCMatrix")
|
||||
|
||||
if (is.null(shap_contrib) && (is.null(model) || !inherits(model, "xgb.Booster")))
|
||||
stop("when shap_contrib is not provided, one must provide an xgb.Booster model")
|
||||
|
||||
if (is.null(features) && (is.null(model) || !inherits(model, "xgb.Booster")))
|
||||
stop("when features are not provided, one must provide an xgb.Booster model to rank the features")
|
||||
|
||||
if (!is.null(shap_contrib) &&
|
||||
(!is.matrix(shap_contrib) || nrow(shap_contrib) != nrow(data) || ncol(shap_contrib) != ncol(data) + 1))
|
||||
stop("shap_contrib is not compatible with the provided data")
|
||||
|
||||
if (is.character(features) && is.null(colnames(data)))
|
||||
stop("either provide `data` with column names or provide `features` as column indices")
|
||||
|
||||
if (is.null(model$feature_names) && model$nfeatures != ncol(data))
|
||||
stop("if model has no feature_names, columns in `data` must match features in model")
|
||||
|
||||
if (!is.null(subsample)) {
|
||||
idx <- sample(x = seq_len(nrow(data)), size = as.integer(subsample * nrow(data)), replace = FALSE)
|
||||
} else {
|
||||
idx <- seq_len(min(nrow(data), max_observations))
|
||||
}
|
||||
data <- data[idx, ]
|
||||
if (is.null(colnames(data))) {
|
||||
colnames(data) <- paste0("X", seq_len(ncol(data)))
|
||||
}
|
||||
|
||||
if (!is.null(shap_contrib)) {
|
||||
if (is.list(shap_contrib)) { # multiclass: either choose a class or merge
|
||||
shap_contrib <- if (!is.null(target_class)) shap_contrib[[target_class + 1]] else Reduce("+", lapply(shap_contrib, abs))
|
||||
}
|
||||
shap_contrib <- shap_contrib[idx, ]
|
||||
if (is.null(colnames(shap_contrib))) {
|
||||
colnames(shap_contrib) <- paste0("X", seq_len(ncol(data)))
|
||||
}
|
||||
} else {
|
||||
shap_contrib <- predict(model, newdata = data, predcontrib = TRUE, approxcontrib = approxcontrib)
|
||||
if (is.list(shap_contrib)) { # multiclass: either choose a class or merge
|
||||
shap_contrib <- if (!is.null(target_class)) shap_contrib[[target_class + 1]] else Reduce("+", lapply(shap_contrib, abs))
|
||||
}
|
||||
}
|
||||
|
||||
if (is.null(features)) {
|
||||
if (!is.null(model$feature_names)) {
|
||||
imp <- xgb.importance(model = model, trees = trees)
|
||||
} else {
|
||||
imp <- xgb.importance(model = model, trees = trees, feature_names = colnames(data))
|
||||
}
|
||||
top_n <- top_n[1]
|
||||
if (top_n < 1 | top_n > 100) stop("top_n: must be an integer within [1, 100]")
|
||||
features <- imp$Feature[1:min(top_n, NROW(imp))]
|
||||
}
|
||||
if (is.character(features)) {
|
||||
features <- match(features, colnames(data))
|
||||
}
|
||||
|
||||
shap_contrib <- shap_contrib[, features, drop = FALSE]
|
||||
data <- data[, features, drop = FALSE]
|
||||
|
||||
list(
|
||||
data = data,
|
||||
shap_contrib = shap_contrib
|
||||
)
|
||||
}
|
||||
|
||||
@@ -130,16 +130,18 @@
|
||||
#' Note that when using a customized metric, only this single metric can be used.
|
||||
#' The following is the list of built-in metrics for which Xgboost provides optimized implementation:
|
||||
#' \itemize{
|
||||
#' \item \code{rmse} root mean square error. \url{http://en.wikipedia.org/wiki/Root_mean_square_error}
|
||||
#' \item \code{logloss} negative log-likelihood. \url{http://en.wikipedia.org/wiki/Log-likelihood}
|
||||
#' \item \code{mlogloss} multiclass logloss. \url{http://wiki.fast.ai/index.php/Log_Loss}
|
||||
#' \item \code{rmse} root mean square error. \url{https://en.wikipedia.org/wiki/Root_mean_square_error}
|
||||
#' \item \code{logloss} negative log-likelihood. \url{https://en.wikipedia.org/wiki/Log-likelihood}
|
||||
#' \item \code{mlogloss} multiclass logloss. \url{https://scikit-learn.org/stable/modules/generated/sklearn.metrics.log_loss.html}
|
||||
#' \item \code{error} Binary classification error rate. It is calculated as \code{(# wrong cases) / (# all cases)}.
|
||||
#' By default, it uses the 0.5 threshold for predicted values to define negative and positive instances.
|
||||
#' Different threshold (e.g., 0.) could be specified as "error@0."
|
||||
#' \item \code{merror} Multiclass classification error rate. It is calculated as \code{(# wrong cases) / (# all cases)}.
|
||||
#' \item \code{auc} Area under the curve. \url{http://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.
|
||||
#' \item \code{mae} Mean absolute error
|
||||
#' \item \code{mape} Mean absolute percentage error
|
||||
#' \item \code{auc} Area under the curve. \url{https://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.
|
||||
#' \item \code{aucpr} Area under the PR curve. \url{https://en.wikipedia.org/wiki/Precision_and_recall} for ranking evaluation.
|
||||
#' \item \code{ndcg} Normalized Discounted Cumulative Gain (for ranking task). \url{http://en.wikipedia.org/wiki/NDCG}
|
||||
#' \item \code{ndcg} Normalized Discounted Cumulative Gain (for ranking task). \url{https://en.wikipedia.org/wiki/NDCG}
|
||||
#' }
|
||||
#'
|
||||
#' The following callbacks are automatically created when certain parameters are set:
|
||||
|
||||
@@ -91,11 +91,6 @@ NULL
|
||||
#' @importFrom data.table setkeyv
|
||||
#' @importFrom data.table setnames
|
||||
#' @importFrom magrittr %>%
|
||||
#' @importFrom stringi stri_detect_regex
|
||||
#' @importFrom stringi stri_match_first_regex
|
||||
#' @importFrom stringi stri_replace_first_regex
|
||||
#' @importFrom stringi stri_replace_all_regex
|
||||
#' @importFrom stringi stri_split_regex
|
||||
#' @importFrom utils object.size str tail
|
||||
#' @importFrom stats predict
|
||||
#' @importFrom stats median
|
||||
|
||||
2
R-package/configure
vendored
2
R-package/configure
vendored
@@ -2732,7 +2732,7 @@ $as_echo "${ac_pkg_openmp}" >&6; }
|
||||
OPENMP_CXXFLAGS=''
|
||||
OPENMP_LIB=''
|
||||
echo '*****************************************************************************************'
|
||||
echo 'WARNING: OpenMP is unavailable on this Mac OSX system. Training speed may be suboptimal.'
|
||||
echo ' OpenMP is unavailable on this Mac OSX system. Training speed may be suboptimal.'
|
||||
echo ' To use all CPU cores for training jobs, you should install OpenMP by running\n'
|
||||
echo ' brew install libomp'
|
||||
echo '*****************************************************************************************'
|
||||
|
||||
@@ -39,7 +39,7 @@ then
|
||||
OPENMP_CXXFLAGS=''
|
||||
OPENMP_LIB=''
|
||||
echo '*****************************************************************************************'
|
||||
echo 'WARNING: OpenMP is unavailable on this Mac OSX system. Training speed may be suboptimal.'
|
||||
echo ' OpenMP is unavailable on this Mac OSX system. Training speed may be suboptimal.'
|
||||
echo ' To use all CPU cores for training jobs, you should install OpenMP by running\n'
|
||||
echo ' brew install libomp'
|
||||
echo '*****************************************************************************************'
|
||||
@@ -52,4 +52,3 @@ AC_SUBST(ENDIAN_FLAG)
|
||||
AC_SUBST(BACKTRACE_LIB)
|
||||
AC_CONFIG_FILES([src/Makevars])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ treeInteractions <- function(input_tree, input_max_depth) {
|
||||
interaction_trees <- trees[!is.na(Split) & !is.na(parent_1),
|
||||
c('Feature', paste0('parent_feat_', 1:(input_max_depth - 1))),
|
||||
with = FALSE]
|
||||
interaction_trees_split <- split(interaction_trees, 1:nrow(interaction_trees))
|
||||
interaction_trees_split <- split(interaction_trees, seq_len(nrow(interaction_trees)))
|
||||
interaction_list <- lapply(interaction_trees_split, as.character)
|
||||
|
||||
# Remove NAs (no parent interaction)
|
||||
@@ -101,8 +101,8 @@ bst3_interactions <- treeInteractions(bst3_tree, 4)
|
||||
|
||||
# Show monotonic constraints still apply by checking scores after incrementing V1
|
||||
x1 <- sort(unique(x[['V1']]))
|
||||
for (i in 1:length(x1)){
|
||||
testdata <- copy(x[, -c('V1')])
|
||||
for (i in seq_along(x1)){
|
||||
testdata <- copy(x[, - ('V1')])
|
||||
testdata[['V1']] <- x1[i]
|
||||
testdata <- testdata[, paste0('V', 1:10), with = FALSE]
|
||||
pred <- predict(bst3, as.matrix(testdata))
|
||||
|
||||
@@ -43,6 +43,7 @@ bst2 <- xgb.load('xgb.model')
|
||||
# Save as a stand-alone file (JSON); load it with xgb.load()
|
||||
xgb.save(bst, 'xgb.model.json')
|
||||
bst2 <- xgb.load('xgb.model.json')
|
||||
if (file.exists('xgb.model.json')) file.remove('xgb.model.json')
|
||||
|
||||
# Save as a raw byte vector; load it with xgb.load.raw()
|
||||
xgb_bytes <- xgb.save.raw(bst)
|
||||
@@ -58,5 +59,6 @@ saveRDS(obj, 'my_object.rds')
|
||||
obj2 <- readRDS('my_object.rds')
|
||||
# Re-construct xgb.Booster object from the bytes
|
||||
bst2 <- xgb.load.raw(obj2$xgb_model_bytes)
|
||||
if (file.exists('my_object.rds')) file.remove('my_object.rds')
|
||||
|
||||
}
|
||||
|
||||
18
R-package/man/normalize.Rd
Normal file
18
R-package/man/normalize.Rd
Normal file
@@ -0,0 +1,18 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/xgb.ggplot.R
|
||||
\name{normalize}
|
||||
\alias{normalize}
|
||||
\title{Scale feature value to have mean 0, standard deviation 1}
|
||||
\usage{
|
||||
normalize(x)
|
||||
}
|
||||
\arguments{
|
||||
\item{x}{Numeric vector}
|
||||
}
|
||||
\value{
|
||||
Numeric vector with mean 0 and sd 1.
|
||||
}
|
||||
\description{
|
||||
This is used to compare multiple features on the same plot.
|
||||
Internal utility function
|
||||
}
|
||||
27
R-package/man/prepare.ggplot.shap.data.Rd
Normal file
27
R-package/man/prepare.ggplot.shap.data.Rd
Normal file
@@ -0,0 +1,27 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/xgb.ggplot.R
|
||||
\name{prepare.ggplot.shap.data}
|
||||
\alias{prepare.ggplot.shap.data}
|
||||
\title{Combine and melt feature values and SHAP contributions for sample
|
||||
observations.}
|
||||
\usage{
|
||||
prepare.ggplot.shap.data(data_list, normalize = FALSE)
|
||||
}
|
||||
\arguments{
|
||||
\item{data_list}{List containing 'data' and 'shap_contrib' returned by
|
||||
\code{xgb.shap.data()}.}
|
||||
|
||||
\item{normalize}{Whether to standardize feature values to have mean 0 and
|
||||
standard deviation 1 (useful for comparing multiple features on the same
|
||||
plot). Default \code{FALSE}.}
|
||||
}
|
||||
\value{
|
||||
A data.table containing the observation ID, the feature name, the
|
||||
feature value (normalized if specified), and the SHAP contribution value.
|
||||
}
|
||||
\description{
|
||||
Conforms to data format required for ggplot functions.
|
||||
}
|
||||
\details{
|
||||
Internal utility function.
|
||||
}
|
||||
@@ -70,6 +70,8 @@ from each CV model. This parameter engages the \code{\link{cb.cv.predict}} callb
|
||||
\item \code{error} binary classification error rate
|
||||
\item \code{rmse} Rooted mean square error
|
||||
\item \code{logloss} negative log-likelihood function
|
||||
\item \code{mae} Mean absolute error
|
||||
\item \code{mape} Mean absolute percentage error
|
||||
\item \code{auc} Area under curve
|
||||
\item \code{aucpr} Area under PR curve
|
||||
\item \code{merror} Exact matching error, used to evaluate multi-class classification
|
||||
@@ -154,7 +156,7 @@ The cross-validation process is then repeated \code{nrounds} times, with each of
|
||||
|
||||
All observations are used for both training and validation.
|
||||
|
||||
Adapted from \url{http://en.wikipedia.org/wiki/Cross-validation_\%28statistics\%29#k-fold_cross-validation}
|
||||
Adapted from \url{https://en.wikipedia.org/wiki/Cross-validation_\%28statistics\%29}
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
|
||||
@@ -131,6 +131,7 @@ bst <- xgboost(agaricus.train$data, agaricus.train$label, nrounds = 50,
|
||||
xgb.plot.shap(agaricus.test$data, model = bst, features = "odor=none")
|
||||
contr <- predict(bst, agaricus.test$data, predcontrib = TRUE)
|
||||
xgb.plot.shap(agaricus.test$data, contr, model = bst, top_n = 12, n_col = 3)
|
||||
xgb.ggplot.shap.summary(agaricus.test$data, contr, model = bst, top_n = 12) # Summary plot
|
||||
|
||||
# multiclass example - plots for each class separately:
|
||||
nclass <- 3
|
||||
@@ -149,6 +150,7 @@ xgb.plot.shap(x, model = mbst, trees = trees0 + 1, target_class = 1, top_n = 4,
|
||||
n_col = 2, col = col, pch = 16, pch_NA = 17)
|
||||
xgb.plot.shap(x, model = mbst, trees = trees0 + 2, target_class = 2, top_n = 4,
|
||||
n_col = 2, col = col, pch = 16, pch_NA = 17)
|
||||
xgb.ggplot.shap.summary(x, model = mbst, target_class = 0, top_n = 4) # Summary plot
|
||||
|
||||
}
|
||||
\references{
|
||||
|
||||
78
R-package/man/xgb.plot.shap.summary.Rd
Normal file
78
R-package/man/xgb.plot.shap.summary.Rd
Normal file
@@ -0,0 +1,78 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/xgb.ggplot.R, R/xgb.plot.shap.R
|
||||
\name{xgb.ggplot.shap.summary}
|
||||
\alias{xgb.ggplot.shap.summary}
|
||||
\alias{xgb.plot.shap.summary}
|
||||
\title{SHAP contribution dependency summary plot}
|
||||
\usage{
|
||||
xgb.ggplot.shap.summary(
|
||||
data,
|
||||
shap_contrib = NULL,
|
||||
features = NULL,
|
||||
top_n = 10,
|
||||
model = NULL,
|
||||
trees = NULL,
|
||||
target_class = NULL,
|
||||
approxcontrib = FALSE,
|
||||
subsample = NULL
|
||||
)
|
||||
|
||||
xgb.plot.shap.summary(
|
||||
data,
|
||||
shap_contrib = NULL,
|
||||
features = NULL,
|
||||
top_n = 10,
|
||||
model = NULL,
|
||||
trees = NULL,
|
||||
target_class = NULL,
|
||||
approxcontrib = FALSE,
|
||||
subsample = NULL
|
||||
)
|
||||
}
|
||||
\arguments{
|
||||
\item{data}{data as a \code{matrix} or \code{dgCMatrix}.}
|
||||
|
||||
\item{shap_contrib}{a matrix of SHAP contributions that was computed earlier for the above
|
||||
\code{data}. When it is NULL, it is computed internally using \code{model} and \code{data}.}
|
||||
|
||||
\item{features}{a vector of either column indices or of feature names to plot. When it is NULL,
|
||||
feature importance is calculated, and \code{top_n} high ranked features are taken.}
|
||||
|
||||
\item{top_n}{when \code{features} is NULL, top_n [1, 100] most important features in a model are taken.}
|
||||
|
||||
\item{model}{an \code{xgb.Booster} model. It has to be provided when either \code{shap_contrib}
|
||||
or \code{features} is missing.}
|
||||
|
||||
\item{trees}{passed to \code{\link{xgb.importance}} when \code{features = NULL}.}
|
||||
|
||||
\item{target_class}{is only relevant for multiclass models. When it is set to a 0-based class index,
|
||||
only SHAP contributions for that specific class are used.
|
||||
If it is not set, SHAP importances are averaged over all classes.}
|
||||
|
||||
\item{approxcontrib}{passed to \code{\link{predict.xgb.Booster}} when \code{shap_contrib = NULL}.}
|
||||
|
||||
\item{subsample}{a random fraction of data points to use for plotting. When it is NULL,
|
||||
it is set so that up to 100K data points are used.}
|
||||
}
|
||||
\value{
|
||||
A \code{ggplot2} object.
|
||||
}
|
||||
\description{
|
||||
Compare SHAP contributions of different features.
|
||||
}
|
||||
\details{
|
||||
A point plot (each point representing one sample from \code{data}) is
|
||||
produced for each feature, with the points plotted on the SHAP value axis.
|
||||
Each point (observation) is coloured based on its feature value. The plot
|
||||
hence allows us to see which features have a negative / positive contribution
|
||||
on the model prediction, and whether the contribution is different for larger
|
||||
or smaller values of the feature. We effectively try to replicate the
|
||||
\code{summary_plot} function from https://github.com/slundberg/shap.
|
||||
}
|
||||
\examples{
|
||||
# See \code{\link{xgb.plot.shap}}.
|
||||
}
|
||||
\seealso{
|
||||
\code{\link{xgb.plot.shap}}, \code{\link{xgb.ggplot.shap.summary}},
|
||||
\url{https://github.com/slundberg/shap}
|
||||
}
|
||||
55
R-package/man/xgb.shap.data.Rd
Normal file
55
R-package/man/xgb.shap.data.Rd
Normal file
@@ -0,0 +1,55 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/xgb.plot.shap.R
|
||||
\name{xgb.shap.data}
|
||||
\alias{xgb.shap.data}
|
||||
\title{Prepare data for SHAP plots. To be used in xgb.plot.shap, xgb.plot.shap.summary, etc.
|
||||
Internal utility function.}
|
||||
\usage{
|
||||
xgb.shap.data(
|
||||
data,
|
||||
shap_contrib = NULL,
|
||||
features = NULL,
|
||||
top_n = 1,
|
||||
model = NULL,
|
||||
trees = NULL,
|
||||
target_class = NULL,
|
||||
approxcontrib = FALSE,
|
||||
subsample = NULL,
|
||||
max_observations = 1e+05
|
||||
)
|
||||
}
|
||||
\arguments{
|
||||
\item{data}{data as a \code{matrix} or \code{dgCMatrix}.}
|
||||
|
||||
\item{shap_contrib}{a matrix of SHAP contributions that was computed earlier for the above
|
||||
\code{data}. When it is NULL, it is computed internally using \code{model} and \code{data}.}
|
||||
|
||||
\item{features}{a vector of either column indices or of feature names to plot. When it is NULL,
|
||||
feature importance is calculated, and \code{top_n} high ranked features are taken.}
|
||||
|
||||
\item{top_n}{when \code{features} is NULL, top_n [1, 100] most important features in a model are taken.}
|
||||
|
||||
\item{model}{an \code{xgb.Booster} model. It has to be provided when either \code{shap_contrib}
|
||||
or \code{features} is missing.}
|
||||
|
||||
\item{trees}{passed to \code{\link{xgb.importance}} when \code{features = NULL}.}
|
||||
|
||||
\item{target_class}{is only relevant for multiclass models. When it is set to a 0-based class index,
|
||||
only SHAP contributions for that specific class are used.
|
||||
If it is not set, SHAP importances are averaged over all classes.}
|
||||
|
||||
\item{approxcontrib}{passed to \code{\link{predict.xgb.Booster}} when \code{shap_contrib = NULL}.}
|
||||
|
||||
\item{subsample}{a random fraction of data points to use for plotting. When it is NULL,
|
||||
it is set so that up to 100K data points are used.}
|
||||
}
|
||||
\value{
|
||||
A list containing: 'data', a matrix containing sample observations
|
||||
and their feature values; 'shap_contrib', a matrix containing the SHAP contribution
|
||||
values for these observations.
|
||||
}
|
||||
\description{
|
||||
Prepare data for SHAP plots. To be used in xgb.plot.shap, xgb.plot.shap.summary, etc.
|
||||
Internal utility function.
|
||||
}
|
||||
\keyword{internal}
|
||||
@@ -215,16 +215,18 @@ User may set one or several \code{eval_metric} parameters.
|
||||
Note that when using a customized metric, only this single metric can be used.
|
||||
The following is the list of built-in metrics for which Xgboost provides optimized implementation:
|
||||
\itemize{
|
||||
\item \code{rmse} root mean square error. \url{http://en.wikipedia.org/wiki/Root_mean_square_error}
|
||||
\item \code{logloss} negative log-likelihood. \url{http://en.wikipedia.org/wiki/Log-likelihood}
|
||||
\item \code{mlogloss} multiclass logloss. \url{http://wiki.fast.ai/index.php/Log_Loss}
|
||||
\item \code{rmse} root mean square error. \url{https://en.wikipedia.org/wiki/Root_mean_square_error}
|
||||
\item \code{logloss} negative log-likelihood. \url{https://en.wikipedia.org/wiki/Log-likelihood}
|
||||
\item \code{mlogloss} multiclass logloss. \url{https://scikit-learn.org/stable/modules/generated/sklearn.metrics.log_loss.html}
|
||||
\item \code{error} Binary classification error rate. It is calculated as \code{(# wrong cases) / (# all cases)}.
|
||||
By default, it uses the 0.5 threshold for predicted values to define negative and positive instances.
|
||||
Different threshold (e.g., 0.) could be specified as "error@0."
|
||||
\item \code{merror} Multiclass classification error rate. It is calculated as \code{(# wrong cases) / (# all cases)}.
|
||||
\item \code{auc} Area under the curve. \url{http://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.
|
||||
\item \code{mae} Mean absolute error
|
||||
\item \code{mape} Mean absolute percentage error
|
||||
\item \code{auc} Area under the curve. \url{https://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.
|
||||
\item \code{aucpr} Area under the PR curve. \url{https://en.wikipedia.org/wiki/Precision_and_recall} for ranking evaluation.
|
||||
\item \code{ndcg} Normalized Discounted Cumulative Gain (for ranking task). \url{http://en.wikipedia.org/wiki/NDCG}
|
||||
\item \code{ndcg} Normalized Discounted Cumulative Gain (for ranking task). \url{https://en.wikipedia.org/wiki/NDCG}
|
||||
}
|
||||
|
||||
The following callbacks are automatically created when certain parameters are set:
|
||||
|
||||
@@ -8,7 +8,7 @@ CXX_STD = CXX14
|
||||
XGB_RFLAGS = -DXGBOOST_STRICT_R_MODE=1 -DDMLC_LOG_BEFORE_THROW=0\
|
||||
-DDMLC_ENABLE_STD_THREAD=$(ENABLE_STD_THREAD) -DDMLC_DISABLE_STDIN=1\
|
||||
-DDMLC_LOG_CUSTOMIZE=1 -DXGBOOST_CUSTOMIZE_LOGGER=1\
|
||||
-DRABIT_CUSTOMIZE_MSG_ -DRABIT_STRICT_CXX98_
|
||||
-DRABIT_CUSTOMIZE_MSG_
|
||||
|
||||
# disable the use of thread_local for 32 bit windows:
|
||||
ifeq ($(R_OSTYPE)$(WIN),windows)
|
||||
@@ -19,6 +19,7 @@ $(foreach v, $(XGB_RFLAGS), $(warning $(v)))
|
||||
PKG_CPPFLAGS= -I$(PKGROOT)/include -I$(PKGROOT)/dmlc-core/include -I$(PKGROOT)/rabit/include -I$(PKGROOT) $(XGB_RFLAGS)
|
||||
PKG_CXXFLAGS= @OPENMP_CXXFLAGS@ @ENDIAN_FLAG@ -pthread
|
||||
PKG_LIBS = @OPENMP_CXXFLAGS@ @OPENMP_LIB@ @ENDIAN_FLAG@ @BACKTRACE_LIB@ -pthread
|
||||
OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o\
|
||||
$(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o\
|
||||
$(PKGROOT)/rabit/src/engine_empty.o $(PKGROOT)/rabit/src/c_api.o
|
||||
OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o \
|
||||
$(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o \
|
||||
$(PKGROOT)/rabit/src/engine.o $(PKGROOT)/rabit/src/c_api.o \
|
||||
$(PKGROOT)/rabit/src/allreduce_base.o
|
||||
|
||||
@@ -20,7 +20,7 @@ CXX_STD = CXX14
|
||||
XGB_RFLAGS = -DXGBOOST_STRICT_R_MODE=1 -DDMLC_LOG_BEFORE_THROW=0\
|
||||
-DDMLC_ENABLE_STD_THREAD=$(ENABLE_STD_THREAD) -DDMLC_DISABLE_STDIN=1\
|
||||
-DDMLC_LOG_CUSTOMIZE=1 -DXGBOOST_CUSTOMIZE_LOGGER=1\
|
||||
-DRABIT_CUSTOMIZE_MSG_ -DRABIT_STRICT_CXX98_
|
||||
-DRABIT_CUSTOMIZE_MSG_
|
||||
|
||||
# disable the use of thread_local for 32 bit windows:
|
||||
ifeq ($(R_OSTYPE)$(WIN),windows)
|
||||
@@ -31,8 +31,9 @@ $(foreach v, $(XGB_RFLAGS), $(warning $(v)))
|
||||
PKG_CPPFLAGS= -I$(PKGROOT)/include -I$(PKGROOT)/dmlc-core/include -I$(PKGROOT)/rabit/include -I$(PKGROOT) $(XGB_RFLAGS)
|
||||
PKG_CXXFLAGS= $(SHLIB_OPENMP_CXXFLAGS) $(SHLIB_PTHREAD_FLAGS)
|
||||
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(SHLIB_PTHREAD_FLAGS)
|
||||
OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o\
|
||||
$(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o\
|
||||
$(PKGROOT)/rabit/src/engine_empty.o $(PKGROOT)/rabit/src/c_api.o
|
||||
OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o \
|
||||
$(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o \
|
||||
$(PKGROOT)/rabit/src/engine.o $(PKGROOT)/rabit/src/c_api.o \
|
||||
$(PKGROOT)/rabit/src/allreduce_base.o
|
||||
|
||||
$(OBJECTS) : xgblib
|
||||
|
||||
@@ -13,23 +13,6 @@ void CustomLogMessage::Log(const std::string& msg) {
|
||||
}
|
||||
} // namespace dmlc
|
||||
|
||||
// implements rabit error handling.
|
||||
extern "C" {
|
||||
void XGBoostAssert_R(int exp, const char *fmt, ...);
|
||||
void XGBoostCheck_R(int exp, const char *fmt, ...);
|
||||
}
|
||||
|
||||
namespace rabit {
|
||||
namespace utils {
|
||||
extern "C" {
|
||||
void (*Printf)(const char *fmt, ...) = Rprintf;
|
||||
void (*Assert)(int exp, const char *fmt, ...) = XGBoostAssert_R;
|
||||
void (*Check)(int exp, const char *fmt, ...) = XGBoostCheck_R;
|
||||
void (*Error)(const char *fmt, ...) = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace xgboost {
|
||||
ConsoleLogger::~ConsoleLogger() {
|
||||
if (cur_verbosity_ == LogVerbosity::kIgnore ||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
model_generator_metadata <- function() {
|
||||
return (list(
|
||||
kRounds = 2,
|
||||
kRows = 1000,
|
||||
kCols = 4,
|
||||
kForests = 2,
|
||||
kMaxDepth = 2,
|
||||
kClasses = 3
|
||||
))
|
||||
}
|
||||
@@ -2,10 +2,16 @@
|
||||
# of saved model files from XGBoost version 0.90 and 1.0.x.
|
||||
library(xgboost)
|
||||
library(Matrix)
|
||||
source('./generate_models_params.R')
|
||||
|
||||
set.seed(0)
|
||||
metadata <- model_generator_metadata()
|
||||
metadata <- list(
|
||||
kRounds = 2,
|
||||
kRows = 1000,
|
||||
kCols = 4,
|
||||
kForests = 2,
|
||||
kMaxDepth = 2,
|
||||
kClasses = 3
|
||||
)
|
||||
X <- Matrix(data = rnorm(metadata$kRows * metadata$kCols), nrow = metadata$kRows,
|
||||
ncol = metadata$kCols, sparse = TRUE)
|
||||
w <- runif(metadata$kRows)
|
||||
@@ -46,11 +52,16 @@ generate_logistic_model <- function () {
|
||||
y <- sample(0:1, size = metadata$kRows, replace = TRUE)
|
||||
stopifnot(max(y) == 1, min(y) == 0)
|
||||
|
||||
data <- xgb.DMatrix(X, label = y, weight = w)
|
||||
params <- list(tree_method = 'hist', num_parallel_tree = metadata$kForests,
|
||||
max_depth = metadata$kMaxDepth, objective = 'binary:logistic')
|
||||
booster <- xgb.train(params, data, nrounds = metadata$kRounds)
|
||||
save_booster(booster, 'logit')
|
||||
objective <- c('binary:logistic', 'binary:logitraw')
|
||||
name <- c('logit', 'logitraw')
|
||||
|
||||
for (i in seq_len(length(objective))) {
|
||||
data <- xgb.DMatrix(X, label = y, weight = w)
|
||||
params <- list(tree_method = 'hist', num_parallel_tree = metadata$kForests,
|
||||
max_depth = metadata$kMaxDepth, objective = objective[i])
|
||||
booster <- xgb.train(params, data, nrounds = metadata$kRounds)
|
||||
save_booster(booster, name[i])
|
||||
}
|
||||
}
|
||||
|
||||
generate_classification_model <- function () {
|
||||
@@ -6,21 +6,21 @@ my_linters <- list(
|
||||
assignment_linter = lintr::assignment_linter,
|
||||
closed_curly_linter = lintr::closed_curly_linter,
|
||||
commas_linter = lintr::commas_linter,
|
||||
# commented_code_linter = lintr::commented_code_linter,
|
||||
equals_na = lintr::equals_na_linter,
|
||||
infix_spaces_linter = lintr::infix_spaces_linter,
|
||||
line_length_linter = lintr::line_length_linter,
|
||||
no_tab_linter = lintr::no_tab_linter,
|
||||
object_usage_linter = lintr::object_usage_linter,
|
||||
# snake_case_linter = lintr::snake_case_linter,
|
||||
# multiple_dots_linter = lintr::multiple_dots_linter,
|
||||
object_length_linter = lintr::object_length_linter,
|
||||
open_curly_linter = lintr::open_curly_linter,
|
||||
# single_quotes_linter = lintr::single_quotes_linter,
|
||||
semicolon = lintr::semicolon_terminator_linter,
|
||||
seq = lintr::seq_linter,
|
||||
spaces_inside_linter = lintr::spaces_inside_linter,
|
||||
spaces_left_parentheses_linter = lintr::spaces_left_parentheses_linter,
|
||||
trailing_blank_lines_linter = lintr::trailing_blank_lines_linter,
|
||||
trailing_whitespace_linter = lintr::trailing_whitespace_linter,
|
||||
true_false = lintr::T_and_F_symbol_linter
|
||||
true_false = lintr::T_and_F_symbol_linter,
|
||||
unneeded_concatenation = lintr::unneeded_concatenation_linter
|
||||
)
|
||||
|
||||
results <- lapply(
|
||||
@@ -17,7 +17,8 @@ test_that("train and predict binary classification", {
|
||||
nrounds <- 2
|
||||
expect_output(
|
||||
bst <- xgboost(data = train$data, label = train$label, max_depth = 2,
|
||||
eta = 1, nthread = 2, nrounds = nrounds, objective = "binary:logistic")
|
||||
eta = 1, nthread = 2, nrounds = nrounds, objective = "binary:logistic",
|
||||
eval_metric = "error")
|
||||
, "train-error")
|
||||
expect_equal(class(bst), "xgb.Booster")
|
||||
expect_equal(bst$niter, nrounds)
|
||||
@@ -122,7 +123,7 @@ test_that("train and predict softprob", {
|
||||
expect_output(
|
||||
bst <- xgboost(data = as.matrix(iris[, -5]), label = lb,
|
||||
max_depth = 3, eta = 0.5, nthread = 2, nrounds = 5,
|
||||
objective = "multi:softprob", num_class = 3)
|
||||
objective = "multi:softprob", num_class = 3, eval_metric = "merror")
|
||||
, "train-merror")
|
||||
expect_false(is.null(bst$evaluation_log))
|
||||
expect_lt(bst$evaluation_log[, min(train_merror)], 0.025)
|
||||
@@ -150,7 +151,7 @@ test_that("train and predict softmax", {
|
||||
expect_output(
|
||||
bst <- xgboost(data = as.matrix(iris[, -5]), label = lb,
|
||||
max_depth = 3, eta = 0.5, nthread = 2, nrounds = 5,
|
||||
objective = "multi:softmax", num_class = 3)
|
||||
objective = "multi:softmax", num_class = 3, eval_metric = "merror")
|
||||
, "train-merror")
|
||||
expect_false(is.null(bst$evaluation_log))
|
||||
expect_lt(bst$evaluation_log[, min(train_merror)], 0.025)
|
||||
@@ -167,7 +168,7 @@ test_that("train and predict RF", {
|
||||
lb <- train$label
|
||||
# single iteration
|
||||
bst <- xgboost(data = train$data, label = lb, max_depth = 5,
|
||||
nthread = 2, nrounds = 1, objective = "binary:logistic",
|
||||
nthread = 2, nrounds = 1, objective = "binary:logistic", eval_metric = "error",
|
||||
num_parallel_tree = 20, subsample = 0.6, colsample_bytree = 0.1)
|
||||
expect_equal(bst$niter, 1)
|
||||
expect_equal(xgb.ntree(bst), 20)
|
||||
@@ -193,7 +194,8 @@ test_that("train and predict RF with softprob", {
|
||||
set.seed(11)
|
||||
bst <- xgboost(data = as.matrix(iris[, -5]), label = lb,
|
||||
max_depth = 3, eta = 0.9, nthread = 2, nrounds = nrounds,
|
||||
objective = "multi:softprob", num_class = 3, verbose = 0,
|
||||
objective = "multi:softprob", eval_metric = "merror",
|
||||
num_class = 3, verbose = 0,
|
||||
num_parallel_tree = 4, subsample = 0.5, colsample_bytree = 0.5)
|
||||
expect_equal(bst$niter, 15)
|
||||
expect_equal(xgb.ntree(bst), 15 * 3 * 4)
|
||||
@@ -245,11 +247,12 @@ test_that("training continuation works", {
|
||||
expect_equal(bst$raw, bst2$raw)
|
||||
expect_equal(dim(bst2$evaluation_log), c(2, 2))
|
||||
# test continuing from a model in file
|
||||
xgb.save(bst1, "xgboost.model")
|
||||
bst2 <- xgb.train(param, dtrain, nrounds = 2, watchlist, verbose = 0, xgb_model = "xgboost.model")
|
||||
xgb.save(bst1, "xgboost.json")
|
||||
bst2 <- xgb.train(param, dtrain, nrounds = 2, watchlist, verbose = 0, xgb_model = "xgboost.json")
|
||||
if (!windows_flag && !solaris_flag)
|
||||
expect_equal(bst$raw, bst2$raw)
|
||||
expect_equal(dim(bst2$evaluation_log), c(2, 2))
|
||||
file.remove("xgboost.json")
|
||||
})
|
||||
|
||||
test_that("model serialization works", {
|
||||
@@ -273,7 +276,7 @@ test_that("xgb.cv works", {
|
||||
expect_output(
|
||||
cv <- xgb.cv(data = train$data, label = train$label, max_depth = 2, nfold = 5,
|
||||
eta = 1., nthread = 2, nrounds = 2, objective = "binary:logistic",
|
||||
verbose = TRUE)
|
||||
eval_metric = "error", verbose = TRUE)
|
||||
, "train-error:")
|
||||
expect_is(cv, 'xgb.cv.synchronous')
|
||||
expect_false(is.null(cv$evaluation_log))
|
||||
@@ -298,7 +301,7 @@ test_that("xgb.cv works with stratified folds", {
|
||||
eta = 1., nthread = 2, nrounds = 2, objective = "binary:logistic",
|
||||
verbose = TRUE, stratified = TRUE)
|
||||
# Stratified folds should result in a different evaluation logs
|
||||
expect_true(all(cv$evaluation_log[, test_error_mean] != cv2$evaluation_log[, test_error_mean]))
|
||||
expect_true(all(cv$evaluation_log[, test_logloss_mean] != cv2$evaluation_log[, test_logloss_mean]))
|
||||
})
|
||||
|
||||
test_that("train and predict with non-strict classes", {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
require(xgboost)
|
||||
require(data.table)
|
||||
require(titanic)
|
||||
|
||||
context("callbacks")
|
||||
|
||||
@@ -26,7 +27,8 @@ watchlist <- list(train = dtrain, test = dtest)
|
||||
|
||||
err <- function(label, pr) sum((pr > 0.5) != label) / length(label)
|
||||
|
||||
param <- list(objective = "binary:logistic", max_depth = 2, nthread = 2)
|
||||
param <- list(objective = "binary:logistic", eval_metric = "error",
|
||||
max_depth = 2, nthread = 2)
|
||||
|
||||
|
||||
test_that("cb.print.evaluation works as expected", {
|
||||
@@ -105,7 +107,8 @@ test_that("cb.evaluation.log works as expected", {
|
||||
})
|
||||
|
||||
|
||||
param <- list(objective = "binary:logistic", max_depth = 4, nthread = 2)
|
||||
param <- list(objective = "binary:logistic", eval_metric = "error",
|
||||
max_depth = 4, nthread = 2)
|
||||
|
||||
test_that("can store evaluation_log without printing", {
|
||||
expect_silent(
|
||||
@@ -173,16 +176,16 @@ test_that("cb.reset.parameters works as expected", {
|
||||
})
|
||||
|
||||
test_that("cb.save.model works as expected", {
|
||||
files <- c('xgboost_01.model', 'xgboost_02.model', 'xgboost.model')
|
||||
files <- c('xgboost_01.json', 'xgboost_02.json', 'xgboost.json')
|
||||
for (f in files) if (file.exists(f)) file.remove(f)
|
||||
|
||||
bst <- xgb.train(param, dtrain, nrounds = 2, watchlist, eta = 1, verbose = 0,
|
||||
save_period = 1, save_name = "xgboost_%02d.model")
|
||||
expect_true(file.exists('xgboost_01.model'))
|
||||
expect_true(file.exists('xgboost_02.model'))
|
||||
b1 <- xgb.load('xgboost_01.model')
|
||||
save_period = 1, save_name = "xgboost_%02d.json")
|
||||
expect_true(file.exists('xgboost_01.json'))
|
||||
expect_true(file.exists('xgboost_02.json'))
|
||||
b1 <- xgb.load('xgboost_01.json')
|
||||
expect_equal(xgb.ntree(b1), 1)
|
||||
b2 <- xgb.load('xgboost_02.model')
|
||||
b2 <- xgb.load('xgboost_02.json')
|
||||
expect_equal(xgb.ntree(b2), 2)
|
||||
|
||||
xgb.config(b2) <- xgb.config(bst)
|
||||
@@ -191,9 +194,9 @@ test_that("cb.save.model works as expected", {
|
||||
|
||||
# save_period = 0 saves the last iteration's model
|
||||
bst <- xgb.train(param, dtrain, nrounds = 2, watchlist, eta = 1, verbose = 0,
|
||||
save_period = 0)
|
||||
expect_true(file.exists('xgboost.model'))
|
||||
b2 <- xgb.load('xgboost.model')
|
||||
save_period = 0, save_name = 'xgboost.json')
|
||||
expect_true(file.exists('xgboost.json'))
|
||||
b2 <- xgb.load('xgboost.json')
|
||||
xgb.config(b2) <- xgb.config(bst)
|
||||
expect_equal(bst$raw, b2$raw)
|
||||
|
||||
@@ -236,7 +239,7 @@ test_that("early stopping xgb.train works", {
|
||||
test_that("early stopping using a specific metric works", {
|
||||
set.seed(11)
|
||||
expect_output(
|
||||
bst <- xgb.train(param, dtrain, nrounds = 20, watchlist, eta = 0.6,
|
||||
bst <- xgb.train(param[-2], dtrain, nrounds = 20, watchlist, eta = 0.6,
|
||||
eval_metric = "logloss", eval_metric = "auc",
|
||||
callbacks = list(cb.early.stop(stopping_rounds = 3, maximize = FALSE,
|
||||
metric_name = 'test_logloss')))
|
||||
@@ -252,6 +255,26 @@ test_that("early stopping using a specific metric works", {
|
||||
expect_equal(logloss_log, logloss_pred, tolerance = 1e-5)
|
||||
})
|
||||
|
||||
test_that("early stopping works with titanic", {
|
||||
# This test was inspired by https://github.com/dmlc/xgboost/issues/5935
|
||||
# It catches possible issues on noLD R
|
||||
titanic <- titanic::titanic_train
|
||||
titanic$Pclass <- as.factor(titanic$Pclass)
|
||||
dtx <- model.matrix(~ 0 + ., data = titanic[, c("Pclass", "Sex")])
|
||||
dty <- titanic$Survived
|
||||
|
||||
xgboost::xgboost(
|
||||
data = dtx,
|
||||
label = dty,
|
||||
objective = "binary:logistic",
|
||||
eval_metric = "auc",
|
||||
nrounds = 100,
|
||||
early_stopping_rounds = 3
|
||||
)
|
||||
|
||||
expect_true(TRUE) # should not crash
|
||||
})
|
||||
|
||||
test_that("early stopping xgb.cv works", {
|
||||
set.seed(11)
|
||||
expect_output(
|
||||
|
||||
@@ -47,7 +47,7 @@ test_that("custom objective with early stop works", {
|
||||
bst <- xgb.train(param, dtrain, 10, watchlist)
|
||||
expect_equal(class(bst), "xgb.Booster")
|
||||
train_log <- bst$evaluation_log$train_error
|
||||
expect_true(all(diff(train_log)) <= 0)
|
||||
expect_true(all(diff(train_log) <= 0))
|
||||
})
|
||||
|
||||
test_that("custom objective using DMatrix attr works", {
|
||||
|
||||
@@ -64,8 +64,8 @@ test_that("xgb.DMatrix: getinfo & setinfo", {
|
||||
expect_true(setinfo(dtest, 'group', c(50, 50)))
|
||||
expect_error(setinfo(dtest, 'group', test_label))
|
||||
|
||||
# providing character values will give a warning
|
||||
expect_warning(setinfo(dtest, 'weight', rep('a', nrow(test_data))))
|
||||
# providing character values will give an error
|
||||
expect_error(setinfo(dtest, 'weight', rep('a', nrow(test_data))))
|
||||
|
||||
# any other label should error
|
||||
expect_error(setinfo(dtest, 'asdf', test_label))
|
||||
@@ -99,7 +99,7 @@ test_that("xgb.DMatrix: colnames", {
|
||||
dtest <- xgb.DMatrix(test_data, label = test_label)
|
||||
expect_equal(colnames(dtest), colnames(test_data))
|
||||
expect_error(colnames(dtest) <- 'asdf')
|
||||
new_names <- make.names(1:ncol(test_data))
|
||||
new_names <- make.names(seq_len(ncol(test_data)))
|
||||
expect_silent(colnames(dtest) <- new_names)
|
||||
expect_equal(colnames(dtest), new_names)
|
||||
expect_silent(colnames(dtest) <- NULL)
|
||||
|
||||
@@ -9,7 +9,8 @@ test_that("train and prediction when gctorture is on", {
|
||||
test <- agaricus.test
|
||||
gctorture(TRUE)
|
||||
bst <- xgboost(data = train$data, label = train$label, max.depth = 2,
|
||||
eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic")
|
||||
eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic")
|
||||
pred <- predict(bst, test$data)
|
||||
gctorture(FALSE)
|
||||
expect_length(pred, length(test$label))
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ test_that("gblinear works", {
|
||||
dtrain <- xgb.DMatrix(agaricus.train$data, label = agaricus.train$label)
|
||||
dtest <- xgb.DMatrix(agaricus.test$data, label = agaricus.test$label)
|
||||
|
||||
param <- list(objective = "binary:logistic", booster = "gblinear",
|
||||
param <- list(objective = "binary:logistic", eval_metric = "error", booster = "gblinear",
|
||||
nthread = 2, eta = 0.8, alpha = 0.0001, lambda = 0.0001)
|
||||
watchlist <- list(eval = dtest, train = dtrain)
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ test_that("SHAPs sum to predictions, with or without DART", {
|
||||
|
||||
expect_equal(rowSums(shap), pred, tol = tol)
|
||||
expect_equal(apply(shapi, 1, sum), pred, tol = tol)
|
||||
for (i in 1 : nrow(d))
|
||||
for (i in seq_len(nrow(d)))
|
||||
for (f in list(rowSums, colSums))
|
||||
expect_equal(f(shapi[i, , ]), shap[i, ], tol = tol)
|
||||
}
|
||||
@@ -335,8 +335,8 @@ test_that("xgb.model.dt.tree and xgb.importance work with a single split model",
|
||||
})
|
||||
|
||||
test_that("xgb.plot.tree works with and without feature names", {
|
||||
xgb.plot.tree(feature_names = feature.names, model = bst.Tree)
|
||||
xgb.plot.tree(model = bst.Tree)
|
||||
expect_silent(xgb.plot.tree(feature_names = feature.names, model = bst.Tree))
|
||||
expect_silent(xgb.plot.tree(model = bst.Tree))
|
||||
})
|
||||
|
||||
test_that("xgb.plot.multi.trees works with and without feature names", {
|
||||
@@ -351,11 +351,47 @@ test_that("xgb.plot.deepness works", {
|
||||
xgb.ggplot.deepness(model = bst.Tree)
|
||||
})
|
||||
|
||||
test_that("xgb.shap.data works when top_n is provided", {
|
||||
data_list <- xgb.shap.data(data = sparse_matrix, model = bst.Tree, top_n = 2)
|
||||
expect_equal(names(data_list), c("data", "shap_contrib"))
|
||||
expect_equal(NCOL(data_list$data), 2)
|
||||
expect_equal(NCOL(data_list$shap_contrib), 2)
|
||||
expect_equal(NROW(data_list$data), NROW(data_list$shap_contrib))
|
||||
expect_gt(length(colnames(data_list$data)), 0)
|
||||
expect_gt(length(colnames(data_list$shap_contrib)), 0)
|
||||
|
||||
# for multiclass without target class provided
|
||||
data_list <- xgb.shap.data(data = as.matrix(iris[, -5]), model = mbst.Tree, top_n = 2)
|
||||
expect_equal(dim(data_list$shap_contrib), c(nrow(iris), 2))
|
||||
# for multiclass with target class provided
|
||||
data_list <- xgb.shap.data(data = as.matrix(iris[, -5]), model = mbst.Tree, top_n = 2, target_class = 0)
|
||||
expect_equal(dim(data_list$shap_contrib), c(nrow(iris), 2))
|
||||
})
|
||||
|
||||
test_that("xgb.shap.data works with subsampling", {
|
||||
data_list <- xgb.shap.data(data = sparse_matrix, model = bst.Tree, top_n = 2, subsample = 0.8)
|
||||
expect_equal(NROW(data_list$data), as.integer(0.8 * nrow(sparse_matrix)))
|
||||
expect_equal(NROW(data_list$data), NROW(data_list$shap_contrib))
|
||||
})
|
||||
|
||||
test_that("prepare.ggplot.shap.data works", {
|
||||
data_list <- xgb.shap.data(data = sparse_matrix, model = bst.Tree, top_n = 2)
|
||||
plot_data <- prepare.ggplot.shap.data(data_list, normalize = TRUE)
|
||||
expect_s3_class(plot_data, "data.frame")
|
||||
expect_equal(names(plot_data), c("id", "feature", "feature_value", "shap_value"))
|
||||
expect_s3_class(plot_data$feature, "factor")
|
||||
# Each observation should have 1 row for each feature
|
||||
expect_equal(nrow(plot_data), nrow(sparse_matrix) * 2)
|
||||
})
|
||||
|
||||
test_that("xgb.plot.shap works", {
|
||||
sh <- xgb.plot.shap(data = sparse_matrix, model = bst.Tree, top_n = 2, col = 4)
|
||||
expect_equal(names(sh), c("data", "shap_contrib"))
|
||||
expect_equal(NCOL(sh$data), 2)
|
||||
expect_equal(NCOL(sh$shap_contrib), 2)
|
||||
})
|
||||
|
||||
test_that("xgb.plot.shap.summary works", {
|
||||
expect_silent(xgb.plot.shap.summary(data = sparse_matrix, model = bst.Tree, top_n = 2))
|
||||
expect_silent(xgb.ggplot.shap.summary(data = sparse_matrix, model = bst.Tree, top_n = 2))
|
||||
})
|
||||
|
||||
test_that("check.deprecation works", {
|
||||
@@ -374,3 +410,26 @@ test_that("check.deprecation works", {
|
||||
, "\'dumm\' was partially matched to \'dummy\'")
|
||||
expect_equal(res, list(a = 1, DUMMY = 22))
|
||||
})
|
||||
|
||||
test_that('convert.labels works', {
|
||||
y <- c(0, 1, 0, 0, 1)
|
||||
for (objective in c('binary:logistic', 'binary:logitraw', 'binary:hinge')) {
|
||||
res <- xgboost:::convert.labels(y, objective_name = objective)
|
||||
expect_s3_class(res, 'factor')
|
||||
expect_equal(res, factor(res))
|
||||
}
|
||||
y <- c(0, 1, 3, 2, 1, 4)
|
||||
for (objective in c('multi:softmax', 'multi:softprob', 'rank:pairwise', 'rank:ndcg',
|
||||
'rank:map')) {
|
||||
res <- xgboost:::convert.labels(y, objective_name = objective)
|
||||
expect_s3_class(res, 'factor')
|
||||
expect_equal(res, factor(res))
|
||||
}
|
||||
y <- c(1.2, 3.0, -1.0, 10.0)
|
||||
for (objective in c('reg:squarederror', 'reg:squaredlogerror', 'reg:logistic',
|
||||
'reg:pseudohubererror', 'count:poisson', 'survival:cox', 'survival:aft',
|
||||
'reg:gamma', 'reg:tweedie')) {
|
||||
res <- xgboost:::convert.labels(y, objective_name = objective)
|
||||
expect_equal(class(res), 'numeric')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
require(xgboost)
|
||||
require(jsonlite)
|
||||
source('../generate_models_params.R')
|
||||
|
||||
context("Models from previous versions of XGBoost can be loaded")
|
||||
|
||||
metadata <- model_generator_metadata()
|
||||
metadata <- list(
|
||||
kRounds = 2,
|
||||
kRows = 1000,
|
||||
kCols = 4,
|
||||
kForests = 2,
|
||||
kMaxDepth = 2,
|
||||
kClasses = 3
|
||||
)
|
||||
|
||||
run_model_param_check <- function (config) {
|
||||
testthat::expect_equal(config$learner$learner_model_param$num_feature, '4')
|
||||
@@ -33,6 +39,10 @@ run_booster_check <- function (booster, name) {
|
||||
testthat::expect_equal(config$learner$learner_train_param$objective, 'multi:softmax')
|
||||
testthat::expect_equal(as.numeric(config$learner$learner_model_param$num_class),
|
||||
metadata$kClasses)
|
||||
} else if (name == 'logitraw') {
|
||||
testthat::expect_equal(get_num_tree(booster), metadata$kForests * metadata$kRounds)
|
||||
testthat::expect_equal(as.numeric(config$learner$learner_model_param$num_class), 0)
|
||||
testthat::expect_equal(config$learner$learner_train_param$objective, 'binary:logitraw')
|
||||
} else if (name == 'logit') {
|
||||
testthat::expect_equal(get_num_tree(booster), metadata$kForests * metadata$kRounds)
|
||||
testthat::expect_equal(as.numeric(config$learner$learner_model_param$num_class), 0)
|
||||
@@ -55,7 +65,7 @@ test_that("Models from previous versions of XGBoost can be loaded", {
|
||||
zipfile <- file.path(getwd(), file_name)
|
||||
model_dir <- file.path(getwd(), 'models')
|
||||
download.file(paste('https://', bucket, '.s3-', region, '.amazonaws.com/', file_name, sep = ''),
|
||||
destfile = zipfile, mode = 'wb')
|
||||
destfile = zipfile, mode = 'wb', quiet = TRUE)
|
||||
unzip(zipfile, overwrite = TRUE)
|
||||
|
||||
pred_data <- xgb.DMatrix(matrix(c(0, 0, 0, 0), nrow = 1, ncol = 4))
|
||||
@@ -66,13 +76,34 @@ test_that("Models from previous versions of XGBoost can be loaded", {
|
||||
m <- regmatches(model_file, m)[[1]]
|
||||
model_xgb_ver <- m[2]
|
||||
name <- m[3]
|
||||
is_rds <- endsWith(model_file, '.rds')
|
||||
|
||||
if (endsWith(model_file, '.rds')) {
|
||||
booster <- readRDS(model_file)
|
||||
} else {
|
||||
booster <- xgb.load(model_file)
|
||||
cpp_warning <- capture.output({
|
||||
# Expect an R warning when a model is loaded from RDS and it was generated by version < 1.1.x
|
||||
if (is_rds && compareVersion(model_xgb_ver, '1.1.1.1') < 0) {
|
||||
booster <- readRDS(model_file)
|
||||
expect_warning(predict(booster, newdata = pred_data))
|
||||
expect_warning(run_booster_check(booster, name))
|
||||
} else {
|
||||
if (is_rds) {
|
||||
booster <- readRDS(model_file)
|
||||
} else {
|
||||
booster <- xgb.load(model_file)
|
||||
}
|
||||
predict(booster, newdata = pred_data)
|
||||
run_booster_check(booster, name)
|
||||
}
|
||||
})
|
||||
if (compareVersion(model_xgb_ver, '1.0.0.0') < 0) {
|
||||
# Expect a C++ warning when a model was generated in version < 1.0.x
|
||||
m <- grepl(paste0('.*Loading model from XGBoost < 1\\.0\\.0, consider saving it again for ',
|
||||
'improved compatibility.*'), cpp_warning, perl = TRUE)
|
||||
expect_true(length(m) > 0 && all(m))
|
||||
} else if (is_rds && model_xgb_ver == '1.1.1.1') {
|
||||
# Expect a C++ warning when a model is loaded from RDS and it was generated by version 1.1.x
|
||||
m <- grepl(paste0('.*Attempted to load internal configuration for a model file that was ',
|
||||
'generated by a previous version of XGBoost.*'), cpp_warning, perl = TRUE)
|
||||
expect_true(length(m) > 0 && all(m))
|
||||
}
|
||||
predict(booster, newdata = pred_data)
|
||||
run_booster_check(booster, name)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -57,7 +57,7 @@ To answer the question above we will convert *categorical* variables to `numeric
|
||||
|
||||
In this Vignette we will see how to transform a *dense* `data.frame` (*dense* = few zeroes in the matrix) with *categorical* variables to a very *sparse* matrix (*sparse* = lots of zero in the matrix) of `numeric` features.
|
||||
|
||||
The method we are going to see is usually called [one-hot encoding](http://en.wikipedia.org/wiki/One-hot).
|
||||
The method we are going to see is usually called [one-hot encoding](https://en.wikipedia.org/wiki/One-hot).
|
||||
|
||||
The first step is to load `Arthritis` dataset in memory and wrap it with `data.table` package.
|
||||
|
||||
@@ -66,7 +66,7 @@ data(Arthritis)
|
||||
df <- data.table(Arthritis, keep.rownames = FALSE)
|
||||
```
|
||||
|
||||
> `data.table` is 100% compliant with **R** `data.frame` but its syntax is more consistent and its performance for large dataset is [best in class](http://stackoverflow.com/questions/21435339/data-table-vs-dplyr-can-one-do-something-well-the-other-cant-or-does-poorly) (`dplyr` from **R** and `Pandas` from **Python** [included](https://github.com/Rdatatable/data.table/wiki/Benchmarks-%3A-Grouping)). Some parts of **Xgboost** **R** package use `data.table`.
|
||||
> `data.table` is 100% compliant with **R** `data.frame` but its syntax is more consistent and its performance for large dataset is [best in class](https://stackoverflow.com/questions/21435339/data-table-vs-dplyr-can-one-do-something-well-the-other-cant-or-does-poorly) (`dplyr` from **R** and `Pandas` from **Python** [included](https://github.com/Rdatatable/data.table/wiki/Benchmarks-%3A-Grouping)). Some parts of **Xgboost** **R** package use `data.table`.
|
||||
|
||||
The first thing we want to do is to have a look to the first few lines of the `data.table`:
|
||||
|
||||
@@ -137,8 +137,8 @@ levels(df[,Treatment])
|
||||
#### Encoding categorical features
|
||||
|
||||
Next step, we will transform the categorical data to dummy variables.
|
||||
Several encoding methods exist, e.g., [one-hot encoding](http://en.wikipedia.org/wiki/One-hot) is a common approach.
|
||||
We will use the [dummy contrast coding](http://www.ats.ucla.edu/stat/r/library/contrast_coding.htm#dummy) which is popular because it produces "full rank" encoding (also see [this blog post by Max Kuhn](http://appliedpredictivemodeling.com/blog/2013/10/23/the-basics-of-encoding-categorical-data-for-predictive-models)).
|
||||
Several encoding methods exist, e.g., [one-hot encoding](https://en.wikipedia.org/wiki/One-hot) is a common approach.
|
||||
We will use the [dummy contrast coding](https://stats.idre.ucla.edu/r/library/r-library-contrast-coding-systems-for-categorical-variables/) which is popular because it produces "full rank" encoding (also see [this blog post by Max Kuhn](http://appliedpredictivemodeling.com/blog/2013/10/23/the-basics-of-encoding-categorical-data-for-predictive-models)).
|
||||
|
||||
The purpose is to transform each value of each *categorical* feature into a *binary* feature `{0, 1}`.
|
||||
|
||||
@@ -176,7 +176,7 @@ bst <- xgboost(data = sparse_matrix, label = output_vector, max_depth = 4,
|
||||
|
||||
You can see some `train-error: 0.XXXXX` lines followed by a number. It decreases. Each line shows how well the model explains your data. Lower is better.
|
||||
|
||||
A model which fits too well may [overfit](http://en.wikipedia.org/wiki/Overfitting) (meaning it copy/paste too much the past, and won't be that good to predict the future).
|
||||
A model which fits too well may [overfit](https://en.wikipedia.org/wiki/Overfitting) (meaning it copy/paste too much the past, and won't be that good to predict the future).
|
||||
|
||||
> Here you can see the numbers decrease until line 7 and then increase.
|
||||
>
|
||||
@@ -304,7 +304,7 @@ Linear model may not be that smart in this scenario.
|
||||
Special Note: What about Random Forests™?
|
||||
-----------------------------------------
|
||||
|
||||
As you may know, [Random Forests™](http://en.wikipedia.org/wiki/Random_forest) algorithm is cousin with boosting and both are part of the [ensemble learning](http://en.wikipedia.org/wiki/Ensemble_learning) family.
|
||||
As you may know, [Random Forests™](https://en.wikipedia.org/wiki/Random_forest) algorithm is cousin with boosting and both are part of the [ensemble learning](https://en.wikipedia.org/wiki/Ensemble_learning) family.
|
||||
|
||||
Both trains several decision trees for one dataset. The *main* difference is that in Random Forests™, trees are independent and in boosting, the tree `N+1` focus its learning on the loss (<=> what has not been well modeled by the tree `N`).
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
author = "K. Bache and M. Lichman",
|
||||
year = "2013",
|
||||
title = "{UCI} Machine Learning Repository",
|
||||
url = "http://archive.ics.uci.edu/ml",
|
||||
url = "http://archive.ics.uci.edu/ml/",
|
||||
institution = "University of California, Irvine, School of Information and Computer Sciences"
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ The version 0.4-2 is on CRAN, and you can install it by:
|
||||
install.packages("xgboost")
|
||||
```
|
||||
|
||||
Formerly available versions can be obtained from the CRAN [archive](https://cran.r-project.org/src/contrib/Archive/xgboost)
|
||||
Formerly available versions can be obtained from the CRAN [archive](https://cran.r-project.org/src/contrib/Archive/xgboost/)
|
||||
|
||||
## Learning
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<img src=https://raw.githubusercontent.com/dmlc/dmlc.github.io/master/img/logo-m/xgboost.png width=135/> eXtreme Gradient Boosting
|
||||
===========
|
||||
[](https://xgboost-ci.net/blue/organizations/jenkins/xgboost/activity)
|
||||
[](https://xgboost-ci.net/blue/organizations/jenkins/xgboost/activity)
|
||||
[](https://travis-ci.org/dmlc/xgboost)
|
||||
[](https://ci.appveyor.com/project/tqchen/xgboost)
|
||||
[](https://github.com/dmlc/xgboost/actions)
|
||||
[](https://xgboost.readthedocs.org)
|
||||
[](./LICENSE)
|
||||
[](http://cran.r-project.org/web/packages/xgboost)
|
||||
[](https://pypi.python.org/pypi/xgboost/)
|
||||
[](https://optuna.org)
|
||||
[](https://twitter.com/XGBoostProject)
|
||||
|
||||
[Community](https://xgboost.ai/community) |
|
||||
[Documentation](https://xgboost.readthedocs.org) |
|
||||
|
||||
@@ -12,5 +12,3 @@
|
||||
#include "../dmlc-core/src/data.cc"
|
||||
#include "../dmlc-core/src/io.cc"
|
||||
#include "../dmlc-core/src/recordio.cc"
|
||||
|
||||
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
|
||||
#if DMLC_ENABLE_STD_THREAD
|
||||
#include "../src/data/sparse_page_dmatrix.cc"
|
||||
#include "../src/data/sparse_page_source.cc"
|
||||
#endif
|
||||
|
||||
// trees
|
||||
#include "../src/tree/param.cc"
|
||||
#include "../src/tree/split_evaluator.cc"
|
||||
#include "../src/tree/tree_model.cc"
|
||||
#include "../src/tree/tree_updater.cc"
|
||||
#include "../src/tree/updater_colmaker.cc"
|
||||
@@ -57,7 +57,6 @@
|
||||
#include "../src/tree/updater_refresh.cc"
|
||||
#include "../src/tree/updater_sync.cc"
|
||||
#include "../src/tree/updater_histmaker.cc"
|
||||
#include "../src/tree/updater_skmaker.cc"
|
||||
#include "../src/tree/constraints.cc"
|
||||
|
||||
// linear
|
||||
@@ -69,8 +68,10 @@
|
||||
#include "../src/learner.cc"
|
||||
#include "../src/logging.cc"
|
||||
#include "../src/common/common.cc"
|
||||
#include "../src/common/random.cc"
|
||||
#include "../src/common/charconv.cc"
|
||||
#include "../src/common/timer.cc"
|
||||
#include "../src/common/quantile.cc"
|
||||
#include "../src/common/host_device_vector.cc"
|
||||
#include "../src/common/hist_util.cc"
|
||||
#include "../src/common/json.cc"
|
||||
|
||||
@@ -1 +1 @@
|
||||
@xgboost_VERSION_MAJOR@.@xgboost_VERSION_MINOR@.@xgboost_VERSION_PATCH@-SNAPSHOT
|
||||
@xgboost_VERSION_MAJOR@.@xgboost_VERSION_MINOR@.@xgboost_VERSION_PATCH@
|
||||
|
||||
@@ -6,11 +6,11 @@ function(setup_rpackage_install_target rlib_target build_dir)
|
||||
install(
|
||||
DIRECTORY "${xgboost_SOURCE_DIR}/R-package"
|
||||
DESTINATION "${build_dir}"
|
||||
REGEX "src/*" EXCLUDE
|
||||
REGEX "R-package/configure" EXCLUDE
|
||||
PATTERN "src/*" EXCLUDE
|
||||
PATTERN "R-package/configure" EXCLUDE
|
||||
)
|
||||
install(TARGETS ${rlib_target}
|
||||
LIBRARY DESTINATION "${build_dir}/R-package/src/"
|
||||
RUNTIME DESTINATION "${build_dir}/R-package/src/")
|
||||
install(SCRIPT ${PROJECT_BINARY_DIR}/RPackageInstall.cmake)
|
||||
endfunction()
|
||||
endfunction()
|
||||
|
||||
@@ -6,24 +6,32 @@
|
||||
# Add flags
|
||||
macro(enable_sanitizer sanitizer)
|
||||
if(${sanitizer} MATCHES "address")
|
||||
find_package(ASan REQUIRED)
|
||||
find_package(ASan)
|
||||
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=address")
|
||||
link_libraries(${ASan_LIBRARY})
|
||||
if (ASan_FOUND)
|
||||
link_libraries(${ASan_LIBRARY})
|
||||
endif (ASan_FOUND)
|
||||
|
||||
elseif(${sanitizer} MATCHES "thread")
|
||||
find_package(TSan REQUIRED)
|
||||
find_package(TSan)
|
||||
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=thread")
|
||||
link_libraries(${TSan_LIBRARY})
|
||||
if (TSan_FOUND)
|
||||
link_libraries(${TSan_LIBRARY})
|
||||
endif (TSan_FOUND)
|
||||
|
||||
elseif(${sanitizer} MATCHES "leak")
|
||||
find_package(LSan REQUIRED)
|
||||
find_package(LSan)
|
||||
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=leak")
|
||||
link_libraries(${LSan_LIBRARY})
|
||||
if (LSan_FOUND)
|
||||
link_libraries(${LSan_LIBRARY})
|
||||
endif (LSan_FOUND)
|
||||
|
||||
elseif(${sanitizer} MATCHES "undefined")
|
||||
find_package(UBSan REQUIRED)
|
||||
find_package(UBSan)
|
||||
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=undefined -fno-sanitize-recover=undefined")
|
||||
link_libraries(${UBSan_LIBRARY})
|
||||
if (UBSan_FOUND)
|
||||
link_libraries(${UBSan_LIBRARY})
|
||||
endif (UBSan_FOUND)
|
||||
|
||||
else()
|
||||
message(FATAL_ERROR "Santizer ${sanitizer} not supported.")
|
||||
|
||||
@@ -54,23 +54,22 @@ endfunction(msvc_use_static_runtime)
|
||||
|
||||
# Set output directory of target, ignoring debug or release
|
||||
function(set_output_directory target dir)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${dir}
|
||||
)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${dir}
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${dir}
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${dir}
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${dir})
|
||||
endfunction(set_output_directory)
|
||||
|
||||
# Set a default build type to release if none was specified
|
||||
@@ -91,7 +90,9 @@ function(format_gencode_flags flags out)
|
||||
endif()
|
||||
# Set up architecture flags
|
||||
if(NOT flags)
|
||||
if(CUDA_VERSION VERSION_GREATER_EQUAL "10.0")
|
||||
if (CUDA_VERSION VERSION_GREATER_EQUAL "11.0")
|
||||
set(flags "35;50;52;60;61;70;75;80")
|
||||
elseif(CUDA_VERSION VERSION_GREATER_EQUAL "10.0")
|
||||
set(flags "35;50;52;60;61;70;75")
|
||||
elseif(CUDA_VERSION VERSION_GREATER_EQUAL "9.0")
|
||||
set(flags "35;50;52;60;61;70")
|
||||
@@ -99,15 +100,25 @@ function(format_gencode_flags flags out)
|
||||
set(flags "35;50;52;60;61")
|
||||
endif()
|
||||
endif()
|
||||
# Generate SASS
|
||||
foreach(ver ${flags})
|
||||
set(${out} "${${out}}--generate-code=arch=compute_${ver},code=sm_${ver};")
|
||||
endforeach()
|
||||
# Generate PTX for last architecture
|
||||
list(GET flags -1 ver)
|
||||
set(${out} "${${out}}--generate-code=arch=compute_${ver},code=compute_${ver};")
|
||||
|
||||
set(${out} "${${out}}" PARENT_SCOPE)
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
||||
cmake_policy(SET CMP0104 NEW)
|
||||
foreach(ver ${flags})
|
||||
set(CMAKE_CUDA_ARCHITECTURES "${ver}-real;${ver}-virtual;${CMAKE_CUDA_ARCHITECTURES}")
|
||||
endforeach()
|
||||
set(CMAKE_CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}" PARENT_SCOPE)
|
||||
message(STATUS "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}")
|
||||
else()
|
||||
# Generate SASS
|
||||
foreach(ver ${flags})
|
||||
set(${out} "${${out}}--generate-code=arch=compute_${ver},code=sm_${ver};")
|
||||
endforeach()
|
||||
# Generate PTX for last architecture
|
||||
list(GET flags -1 ver)
|
||||
set(${out} "${${out}}--generate-code=arch=compute_${ver},code=compute_${ver};")
|
||||
set(${out} "${${out}}" PARENT_SCOPE)
|
||||
message(STATUS "CUDA GEN_CODE: ${GEN_CODE}")
|
||||
endif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
||||
endfunction(format_gencode_flags flags)
|
||||
|
||||
macro(enable_nvtx target)
|
||||
@@ -116,3 +127,56 @@ macro(enable_nvtx target)
|
||||
target_link_libraries(${target} PRIVATE "${NVTX_LIBRARY}")
|
||||
target_compile_definitions(${target} PRIVATE -DXGBOOST_USE_NVTX=1)
|
||||
endmacro()
|
||||
|
||||
# Set CUDA related flags to target. Must be used after code `format_gencode_flags`.
|
||||
function(xgboost_set_cuda_flags target)
|
||||
find_package(OpenMP REQUIRED)
|
||||
target_link_libraries(${target} PUBLIC OpenMP::OpenMP_CXX)
|
||||
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:--expt-extended-lambda>
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:${GEN_CODE}>
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${OpenMP_CXX_FLAGS}>)
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
||||
set_property(TARGET ${target} PROPERTY CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES})
|
||||
endif (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
||||
|
||||
if (USE_DEVICE_DEBUG)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<AND:$<CONFIG:DEBUG>,$<COMPILE_LANGUAGE:CUDA>>:-G;-src-in-ptx>)
|
||||
else (USE_DEVICE_DEBUG)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:-lineinfo>)
|
||||
endif (USE_DEVICE_DEBUG)
|
||||
|
||||
if (USE_NVTX)
|
||||
enable_nvtx(${target})
|
||||
endif (USE_NVTX)
|
||||
|
||||
target_compile_definitions(${target} PRIVATE -DXGBOOST_USE_CUDA=1 -DTHRUST_IGNORE_CUB_VERSION_CHECK=1)
|
||||
target_include_directories(${target} PRIVATE ${xgboost_SOURCE_DIR}/cub/)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/utf-8>)
|
||||
endif (MSVC)
|
||||
|
||||
set_target_properties(${target} PROPERTIES
|
||||
CUDA_STANDARD 14
|
||||
CUDA_STANDARD_REQUIRED ON
|
||||
CUDA_SEPARABLE_COMPILATION OFF)
|
||||
|
||||
if (HIDE_CXX_SYMBOLS)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-fvisibility=hidden>)
|
||||
endif (HIDE_CXX_SYMBOLS)
|
||||
|
||||
if (USE_NCCL)
|
||||
find_package(Nccl REQUIRED)
|
||||
target_include_directories(${target} PRIVATE ${NCCL_INCLUDE_DIR})
|
||||
target_compile_definitions(${target} PRIVATE -DXGBOOST_USE_NCCL=1)
|
||||
target_link_libraries(${target} PUBLIC ${NCCL_LIBRARY})
|
||||
endif (USE_NCCL)
|
||||
endfunction(xgboost_set_cuda_flags)
|
||||
|
||||
@@ -22,19 +22,24 @@
|
||||
#
|
||||
# NCCL_ROOT - When set, this path is inspected instead of standard library
|
||||
# locations as the root of the NCCL installation.
|
||||
# The environment variable NCCL_ROOT overrides this veriable.
|
||||
# The environment variable NCCL_ROOT overrides this variable.
|
||||
#
|
||||
# This module defines
|
||||
# Nccl_FOUND, whether nccl has been found
|
||||
# NCCL_INCLUDE_DIR, directory containing header
|
||||
# NCCL_LIBRARY, directory containing nccl library
|
||||
# NCCL_LIB_NAME, nccl library name
|
||||
# USE_NCCL_LIB_PATH, when set, NCCL_LIBRARY path is also inspected for the
|
||||
# location of the nccl library. This would disable
|
||||
# switching between static and shared.
|
||||
#
|
||||
# This module assumes that the user has already called find_package(CUDA)
|
||||
|
||||
if (NCCL_LIBRARY)
|
||||
# Don't cache NCCL_LIBRARY to enable switching between static and shared.
|
||||
unset(NCCL_LIBRARY CACHE)
|
||||
if(NOT USE_NCCL_LIB_PATH)
|
||||
# Don't cache NCCL_LIBRARY to enable switching between static and shared.
|
||||
unset(NCCL_LIBRARY CACHE)
|
||||
endif(NOT USE_NCCL_LIB_PATH)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_SHARED_NCCL)
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
set(USE_OPENMP @USE_OPENMP@)
|
||||
set(USE_CUDA @USE_CUDA@)
|
||||
set(USE_NCCL @USE_NCCL@)
|
||||
|
||||
find_dependency(Threads)
|
||||
if(USE_OPENMP)
|
||||
find_dependency(OpenMP)
|
||||
endif()
|
||||
if(USE_CUDA)
|
||||
find_dependency(CUDA)
|
||||
endif()
|
||||
if(USE_NCCL)
|
||||
find_dependency(Nccl)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET xgboost::xgboost)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/XGBoostTargets.cmake)
|
||||
endif()
|
||||
|
||||
message(STATUS "Found XGBoost (found version \"${xgboost_VERSION}\")")
|
||||
|
||||
2
cub
2
cub
Submodule cub updated: c3cceac115...af39ee264f
@@ -62,7 +62,7 @@ test:data = "agaricus.txt.test"
|
||||
We use the tree booster and logistic regression objective in our setting. This indicates that we accomplish our task using classic gradient boosting regression tree(GBRT), which is a promising method for binary classification.
|
||||
|
||||
The parameters shown in the example gives the most common ones that are needed to use xgboost.
|
||||
If you are interested in more parameter settings, the complete parameter settings and detailed descriptions are [here](../../doc/parameter.rst). Besides putting the parameters in the configuration file, we can set them by passing them as arguments as below:
|
||||
If you are interested in more parameter settings, the complete parameter settings and detailed descriptions are [here](https://xgboost.readthedocs.io/en/stable/parameter.html). Besides putting the parameters in the configuration file, we can set them by passing them as arguments as below:
|
||||
|
||||
```
|
||||
../../xgboost mushroom.conf max_depth=6
|
||||
@@ -161,4 +161,3 @@ Eg. ```nthread=10```
|
||||
|
||||
Set nthread to be the number of your real cpu (On Unix, this can be found using ```lscpu```)
|
||||
Some systems will have ```Thread(s) per core = 2```, for example, a 4 core cpu with 8 threads, in such case set ```nthread=4``` and not 8.
|
||||
|
||||
@@ -18,7 +18,7 @@ max_depth = 3
|
||||
# the number of round to do boosting
|
||||
num_round = 2
|
||||
# 0 means do not save any model except the final round model
|
||||
save_period = 0
|
||||
save_period = 2
|
||||
# The path of training data
|
||||
data = "agaricus.txt.train"
|
||||
# The path of validation data, used to monitor training process, here [test] sets name of the validation set
|
||||
@@ -3,13 +3,15 @@
|
||||
python mapfeat.py
|
||||
# split train and test
|
||||
python mknfold.py agaricus.txt 1
|
||||
# training and output the models
|
||||
../../xgboost mushroom.conf
|
||||
# output prediction task=pred
|
||||
../../xgboost mushroom.conf task=pred model_in=0002.model
|
||||
# print the boosters of 00002.model in dump.raw.txt
|
||||
../../xgboost mushroom.conf task=dump model_in=0002.model name_dump=dump.raw.txt
|
||||
# use the feature map in printing for better visualization
|
||||
../../xgboost mushroom.conf task=dump model_in=0002.model fmap=featmap.txt name_dump=dump.nice.txt
|
||||
cat dump.nice.txt
|
||||
|
||||
XGBOOST=../../../xgboost
|
||||
|
||||
# training and output the models
|
||||
$XGBOOST mushroom.conf
|
||||
# output prediction task=pred
|
||||
$XGBOOST mushroom.conf task=pred model_in=0002.model
|
||||
# print the boosters of 00002.model in dump.raw.txt
|
||||
$XGBOOST mushroom.conf task=dump model_in=0002.model name_dump=dump.raw.txt
|
||||
# use the feature map in printing for better visualization
|
||||
$XGBOOST mushroom.conf task=dump model_in=0002.model fmap=featmap.txt name_dump=dump.nice.txt
|
||||
cat dump.nice.txt
|
||||
11
demo/CLI/distributed-training/run_aws.sh
Normal file
11
demo/CLI/distributed-training/run_aws.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
# This is the example script to run distributed xgboost on AWS.
|
||||
# Change the following two lines for configuration
|
||||
|
||||
export BUCKET=mybucket
|
||||
|
||||
# submit the job to YARN
|
||||
../../../dmlc-core/tracker/dmlc-submit --cluster=yarn --num-workers=2 --worker-cores=2\
|
||||
../../../xgboost mushroom.aws.conf nthread=2\
|
||||
data=s3://${BUCKET}/xgb-demo/train\
|
||||
eval[test]=s3://${BUCKET}/xgb-demo/test\
|
||||
model_dir=s3://${BUCKET}/xgb-demo/model
|
||||
@@ -1,6 +1,6 @@
|
||||
Regression
|
||||
====
|
||||
Using XGBoost for regression is very similar to using it for binary classification. We suggest that you can refer to the [binary classification demo](../binary_classification) first. In XGBoost if we use negative log likelihood as the loss function for regression, the training procedure is same as training binary classifier of XGBoost.
|
||||
Using XGBoost for regression is very similar to using it for binary classification. We suggest that you can refer to the [binary classification demo](../binary_classification) first. In XGBoost if we use negative log likelihood as the loss function for regression, the training procedure is same as training binary classifier of XGBoost.
|
||||
|
||||
### Tutorial
|
||||
The dataset we used is the [computer hardware dataset from UCI repository](https://archive.ics.uci.edu/ml/datasets/Computer+Hardware). The demo for regression is almost the same as the [binary classification demo](../binary_classification), except a little difference in general parameter:
|
||||
@@ -14,4 +14,3 @@ objective = reg:squarederror
|
||||
```
|
||||
|
||||
The input format is same as binary classification, except that the label is now the target regression values. We use linear regression here, if we want use objective = reg:logistic logistic regression, the label needed to be pre-scaled into [0,1].
|
||||
|
||||
33
demo/CLI/regression/mapfeat.py
Executable file
33
demo/CLI/regression/mapfeat.py
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
fo = open('machine.txt', 'w')
|
||||
cnt = 6
|
||||
fmap = {}
|
||||
for l in open('machine.data'):
|
||||
arr = l.split(',')
|
||||
fo.write(arr[8])
|
||||
for i in range(0, 6):
|
||||
fo.write(' %d:%s' % (i, arr[i + 2]))
|
||||
|
||||
if arr[0] not in fmap:
|
||||
fmap[arr[0]] = cnt
|
||||
cnt += 1
|
||||
|
||||
fo.write(' %d:1' % fmap[arr[0]])
|
||||
fo.write('\n')
|
||||
|
||||
fo.close()
|
||||
|
||||
# create feature map for machine data
|
||||
fo = open('featmap.txt', 'w')
|
||||
# list from machine.names
|
||||
names = [
|
||||
'vendor', 'MYCT', 'MMIN', 'MMAX', 'CACH', 'CHMIN', 'CHMAX', 'PRP', 'ERP'
|
||||
]
|
||||
|
||||
for i in range(0, 6):
|
||||
fo.write('%d\t%s\tint\n' % (i, names[i + 1]))
|
||||
|
||||
for v, k in sorted(fmap.items(), key=lambda x: x[1]):
|
||||
fo.write('%d\tvendor=%s\ti\n' % (k, v))
|
||||
fo.close()
|
||||
28
demo/CLI/regression/mknfold.py
Executable file
28
demo/CLI/regression/mknfold.py
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
import random
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print('Usage:<filename> <k> [nfold = 5]')
|
||||
exit(0)
|
||||
|
||||
random.seed(10)
|
||||
|
||||
k = int(sys.argv[2])
|
||||
if len(sys.argv) > 3:
|
||||
nfold = int(sys.argv[3])
|
||||
else:
|
||||
nfold = 5
|
||||
|
||||
fi = open(sys.argv[1], 'r')
|
||||
ftr = open(sys.argv[1] + '.train', 'w')
|
||||
fte = open(sys.argv[1] + '.test', 'w')
|
||||
for l in fi:
|
||||
if random.randint(1, nfold) == k:
|
||||
fte.write(l)
|
||||
else:
|
||||
ftr.write(l)
|
||||
|
||||
fi.close()
|
||||
ftr.close()
|
||||
fte.close()
|
||||
@@ -1,14 +1,9 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print 'Usage: <csv> <libsvm>'
|
||||
print 'convert a all numerical csv to libsvm'
|
||||
|
||||
fo = open(sys.argv[2], 'w')
|
||||
|
||||
for l in open(sys.argv[1]):
|
||||
arr = l.split(',')
|
||||
fo.write('%s' % arr[0])
|
||||
for i in xrange(len(arr) - 1):
|
||||
for i in range(len(arr) - 1):
|
||||
fo.write(' %d:%s' % (i, arr[i+1]))
|
||||
fo.close()
|
||||
@@ -14,4 +14,4 @@ python csv2libsvm.py YearPredictionMSD.txt yearpredMSD.libsvm
|
||||
head -n 463715 yearpredMSD.libsvm > yearpredMSD.libsvm.train
|
||||
tail -n 51630 yearpredMSD.libsvm > yearpredMSD.libsvm.test
|
||||
echo "finish making the data"
|
||||
../../xgboost yearpredMSD.conf
|
||||
../../../xgboost yearpredMSD.conf
|
||||
@@ -60,9 +60,9 @@ This is a list of short codes introducing different functionalities of xgboost p
|
||||
Most of examples in this section are based on CLI or python version.
|
||||
However, the parameter settings can be applied to all versions
|
||||
|
||||
- [Binary classification](binary_classification)
|
||||
- [Binary classification](CLI/binary_classification)
|
||||
- [Multiclass classification](multiclass_classification)
|
||||
- [Regression](regression)
|
||||
- [Regression](CLI/regression)
|
||||
- [Learning to Rank](rank)
|
||||
|
||||
### Benchmarks
|
||||
@@ -78,6 +78,14 @@ XGBoost is extensively used by machine learning practitioners to create state of
|
||||
this is a list of machine learning winning solutions with XGBoost.
|
||||
Please send pull requests if you find ones that are missing here.
|
||||
|
||||
|
||||
- Benedikt Schifferer, Gilberto Titericz, Chris Deotte, Christof Henkel, Kazuki Onodera, Jiwei Liu, Bojan Tunguz, Even Oldridge, Gabriel De Souza Pereira Moreira and Ahmet Erdem, 1st place winner of [Twitter RecSys Challenge 2020](https://recsys-twitter.com/) conducted from June,20-August,20. [GPU Accelerated Feature Engineering and Training for Recommender Systems](https://medium.com/rapids-ai/winning-solution-of-recsys2020-challenge-gpu-accelerated-feature-engineering-and-training-for-cd67c5a87b1f)
|
||||
- Eugene Khvedchenya,Jessica Fridrich, Jan Butora, Yassine Yousfi 1st place winner in [ALASKA2 Image Steganalysis](https://www.kaggle.com/c/alaska2-image-steganalysis/overview). Link to [discussion](https://www.kaggle.com/c/alaska2-image-steganalysis/discussion/168546)
|
||||
- Dan Ofer, Seffi Cohen, Noa Dagan, Nurit, 1st place in WiDS Datathon 2020. Link to [discussion](https://www.kaggle.com/c/widsdatathon2020/discussion/133189)
|
||||
- Chris Deotte, Konstantin Yakovlev 1st place in [IEEE-CIS Fraud Detection](https://www.kaggle.com/c/ieee-fraud-detection/overview). Link to [discussion](https://www.kaggle.com/c/ieee-fraud-detection/discussion/111308)
|
||||
- Giba, Lucasz, 1st place winner in [Santander Value Prediction Challenge](https://www.kaggle.com/c/santander-value-prediction-challenge) organized on August,2018. Solution [discussion](https://www.kaggle.com/c/santander-value-prediction-challenge/discussion/65272) and [code](https://www.kaggle.com/titericz/winner-model-giba-single-xgb-lb0-5178/comments)
|
||||
- Beluga, 2nd place and Evgeny Nekrasov, 3rd place winner in Statoil/C-CORE Iceberg Classifier Challenge'2018. Link to [discussion](https://www.kaggle.com/c/statoil-iceberg-classifier-challenge/discussion/48294)
|
||||
- Radek Osmulski, 1st place of the [iMaterialist Challenge (Fashion) at FGVC5](https://www.kaggle.com/c/imaterialist-challenge-fashion-2018/overview). Link to [the winning solution](https://www.kaggle.com/c/imaterialist-challenge-fashion-2018/discussion/57944).
|
||||
- Maksims Volkovs, Guangwei Yu and Tomi Poutanen, 1st place of the [2017 ACM RecSys challenge](http://2017.recsyschallenge.com/). Link to [paper](http://www.cs.toronto.edu/~mvolkovs/recsys2017_challenge.pdf).
|
||||
- Vlad Sandulescu, Mihai Chiru, 1st place of the [KDD Cup 2016 competition](https://kddcup2016.azurewebsites.net). Link to [the arxiv paper](http://arxiv.org/abs/1609.02728).
|
||||
- Marios Michailidis, Mathias Müller and HJ van Veen, 1st place of the [Dato Truely Native? competition](https://www.kaggle.com/c/dato-native). Link to [the Kaggle interview](http://blog.kaggle.com/2015/12/03/dato-winners-interview-1st-place-mad-professors/).
|
||||
@@ -91,6 +99,11 @@ Please send pull requests if you find ones that are missing here.
|
||||
- Owen Zhang, 1st place of the [Avito Context Ad Clicks competition](https://www.kaggle.com/c/avito-context-ad-clicks). Link to [the Kaggle interview](http://blog.kaggle.com/2015/08/26/avito-winners-interview-1st-place-owen-zhang/).
|
||||
- Keiichi Kuroyanagi, 2nd place of the [Airbnb New User Bookings](https://www.kaggle.com/c/airbnb-recruiting-new-user-bookings). Link to [the Kaggle interview](http://blog.kaggle.com/2016/03/17/airbnb-new-user-bookings-winners-interview-2nd-place-keiichi-kuroyanagi-keiku/).
|
||||
- Marios Michailidis, Mathias Müller and Ning Situ, 1st place [Homesite Quote Conversion](https://www.kaggle.com/c/homesite-quote-conversion). Link to [the Kaggle interview](http://blog.kaggle.com/2016/04/08/homesite-quote-conversion-winners-write-up-1st-place-kazanova-faron-clobber/).
|
||||
- Gilberto Titericz, Stanislav Semenov, 1st place in challenge to classify products into the correct category organized by Otto Group in 2015. Link to [challenge](https://www.kaggle.com/c/otto-group-product-classification-challenge). Link to [kaggle winning solution](https://www.kaggle.com/c/otto-group-product-classification-challenge/discussion/14335)
|
||||
- Darius Barušauskas, 1st place winner in [Predicting Red Hat Business Value](https://www.kaggle.com/c/predicting-red-hat-business-value). Link to [interview](https://medium.com/kaggle-blog/red-hat-business-value-competition-1st-place-winners-interview-darius-baru%C5%A1auskas-646692a2841b). Link to [discussion](https://www.kaggle.com/c/predicting-red-hat-business-value/discussion/23786)
|
||||
- David Austin, Weimin Wang, 1st place winner in [Iceberg-classifier-challenge](https://www.kaggle.com/c/statoil-iceberg-classifier-challenge/leaderboard) Link to [discussion](https://www.kaggle.com/c/statoil-iceberg-classifier-challenge/discussion/48241)
|
||||
- Kazuki Onodera, Kazuki Fujikawa, 2nd place winner in [OpenVaccine: COVID-19 mRNA Vaccine Degradation Prediction](https://www.kaggle.com/c/stanford-covid-vaccine/overview) Link to [Discussion](https://www.kaggle.com/c/stanford-covid-vaccine/discussion/189709)
|
||||
- Prarthana Bhat, 2nd place winner in [DYD Competition](https://datahack.analyticsvidhya.com/contest/date-your-data/). Link to [Solution](https://github.com/analyticsvidhya/DateYourData/blob/master/Prathna_Bhat_Model.R).
|
||||
|
||||
## Talks
|
||||
- [XGBoost: A Scalable Tree Boosting System](http://datascience.la/xgboost-workshop-and-meetup-talk-with-tianqi-chen/) (video+slides) by Tianqi Chen at the Los Angeles Data Science meetup
|
||||
@@ -138,6 +151,7 @@ Send a PR to add a one sentence description:)
|
||||
Open source integrations with XGBoost:
|
||||
* [Neptune.ai](http://neptune.ai/) - Experiment management and collaboration tool for ML/DL/RL specialists. Integration has a form of the [XGBoost callback](https://docs.neptune.ai/integrations/xgboost.html) that automatically logs training and evaluation metrics, as well as saved model (booster), feature importance chart and visualized trees.
|
||||
* [Optuna](https://optuna.org/) - An open source hyperparameter optimization framework to automate hyperparameter search. Optuna integrates with XGBoost in the [XGBoostPruningCallback](https://optuna.readthedocs.io/en/stable/reference/integration.html#optuna.integration.XGBoostPruningCallback) that let users easily prune unpromising trials.
|
||||
* [dtreeviz](https://github.com/parrt/dtreeviz) - A python library for decision tree visualization and model interpretation. Starting from version 1.0, dtreeviz is able to visualize tree ensembles produced by XGBoost.
|
||||
|
||||
## Awards
|
||||
- [John Chambers Award](http://stat-computing.org/awards/jmc/winners.html) - 2016 Winner: XGBoost R Package, by Tong He (Simon Fraser University) and Tianqi Chen (University of Washington)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(api-demo LANGUAGES C CXX VERSION 0.0.1)
|
||||
find_package(xgboost REQUIRED)
|
||||
add_executable(api-demo c-api-demo.c)
|
||||
target_link_libraries(api-demo xgboost::xgboost)
|
||||
target_link_libraries(api-demo PRIVATE xgboost::xgboost)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* \brief A simple example of using xgboost C API.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <xgboost/c_api.h>
|
||||
@@ -62,7 +63,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
bst_ulong num_feature = 0;
|
||||
safe_xgboost(XGBoosterGetNumFeature(booster, &num_feature));
|
||||
printf("num_feature: %llu\n", num_feature);
|
||||
printf("num_feature: %lu\n", (unsigned long)(num_feature));
|
||||
|
||||
// predict
|
||||
bst_ulong out_len = 0;
|
||||
@@ -84,6 +85,86 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
{
|
||||
printf("Dense Matrix Example (XGDMatrixCreateFromMat): ");
|
||||
|
||||
const float values[] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
|
||||
1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0};
|
||||
|
||||
DMatrixHandle dmat;
|
||||
safe_xgboost(XGDMatrixCreateFromMat(values, 1, 127, 0.0, &dmat));
|
||||
|
||||
bst_ulong out_len = 0;
|
||||
const float* out_result = NULL;
|
||||
|
||||
safe_xgboost(XGBoosterPredict(booster, dmat, 0, 0, 0, &out_len,
|
||||
&out_result));
|
||||
assert(out_len == 1);
|
||||
|
||||
printf("%1.4f \n", out_result[0]);
|
||||
safe_xgboost(XGDMatrixFree(dmat));
|
||||
}
|
||||
|
||||
{
|
||||
printf("Sparse Matrix Example (XGDMatrixCreateFromCSREx): ");
|
||||
|
||||
const size_t indptr[] = {0, 22};
|
||||
const unsigned indices[] = {1, 9, 19, 21, 24, 34, 36, 39, 42, 53, 56, 65,
|
||||
69, 77, 86, 88, 92, 95, 102, 106, 117, 122};
|
||||
const float data[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
DMatrixHandle dmat;
|
||||
safe_xgboost(XGDMatrixCreateFromCSREx(indptr, indices, data, 2, 22, 127,
|
||||
&dmat));
|
||||
|
||||
bst_ulong out_len = 0;
|
||||
const float* out_result = NULL;
|
||||
|
||||
safe_xgboost(XGBoosterPredict(booster, dmat, 0, 0, 0, &out_len,
|
||||
&out_result));
|
||||
assert(out_len == 1);
|
||||
|
||||
printf("%1.4f \n", out_result[0]);
|
||||
safe_xgboost(XGDMatrixFree(dmat));
|
||||
}
|
||||
|
||||
{
|
||||
printf("Sparse Matrix Example (XGDMatrixCreateFromCSCEx): ");
|
||||
|
||||
const size_t col_ptr[] = {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8,
|
||||
8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18,
|
||||
18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22};
|
||||
|
||||
const unsigned indices[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0};
|
||||
|
||||
const float data[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
||||
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
DMatrixHandle dmat;
|
||||
safe_xgboost(XGDMatrixCreateFromCSCEx(col_ptr, indices, data, 128, 22, 1,
|
||||
&dmat));
|
||||
|
||||
bst_ulong out_len = 0;
|
||||
const float* out_result = NULL;
|
||||
|
||||
safe_xgboost(XGBoosterPredict(booster, dmat, 0, 0, 0, &out_len,
|
||||
&out_result));
|
||||
assert(out_len == 1);
|
||||
|
||||
printf("%1.4f \n", out_result[0]);
|
||||
safe_xgboost(XGDMatrixFree(dmat));
|
||||
}
|
||||
|
||||
// free everything
|
||||
safe_xgboost(XGBoosterFree(booster));
|
||||
safe_xgboost(XGDMatrixFree(dtrain));
|
||||
|
||||
@@ -2,16 +2,13 @@ from dask_cuda import LocalCUDACluster
|
||||
from dask.distributed import Client
|
||||
from dask import array as da
|
||||
import xgboost as xgb
|
||||
from xgboost import dask as dxgb
|
||||
from xgboost.dask import DaskDMatrix
|
||||
import cupy as cp
|
||||
import argparse
|
||||
|
||||
|
||||
def main(client):
|
||||
# generate some random data for demonstration
|
||||
m = 100000
|
||||
n = 100
|
||||
X = da.random.random(size=(m, n), chunks=100)
|
||||
y = da.random.random(size=(m, ), chunks=100)
|
||||
|
||||
def using_dask_matrix(client: Client, X, y):
|
||||
# DaskDMatrix acts like normal DMatrix, works as a proxy for local
|
||||
# DMatrix scatter around workers.
|
||||
dtrain = DaskDMatrix(client, X, y)
|
||||
@@ -31,15 +28,56 @@ def main(client):
|
||||
|
||||
# you can pass output directly into `predict` too.
|
||||
prediction = xgb.dask.predict(client, bst, dtrain)
|
||||
prediction = prediction.compute()
|
||||
print('Evaluation history:', history)
|
||||
return prediction
|
||||
|
||||
|
||||
def using_quantile_device_dmatrix(client: Client, X, y):
|
||||
'''`DaskDeviceQuantileDMatrix` is a data type specialized for `gpu_hist`, tree
|
||||
method that reduces memory overhead. When training on GPU pipeline, it's
|
||||
preferred over `DaskDMatrix`.
|
||||
|
||||
.. versionadded:: 1.2.0
|
||||
|
||||
'''
|
||||
# Input must be on GPU for `DaskDeviceQuantileDMatrix`.
|
||||
X = X.map_blocks(cp.array)
|
||||
y = y.map_blocks(cp.array)
|
||||
|
||||
# `DaskDeviceQuantileDMatrix` is used instead of `DaskDMatrix`, be careful
|
||||
# that it can not be used for anything else than training.
|
||||
dtrain = dxgb.DaskDeviceQuantileDMatrix(client, X, y)
|
||||
output = xgb.dask.train(client,
|
||||
{'verbosity': 2,
|
||||
'tree_method': 'gpu_hist'},
|
||||
dtrain,
|
||||
num_boost_round=4)
|
||||
|
||||
prediction = xgb.dask.predict(client, output, X)
|
||||
return prediction
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--ddqdm', choices=[0, 1], type=int, default=1,
|
||||
help='''Whether should we use `DaskDeviceQuantileDMatrix`''')
|
||||
args = parser.parse_args()
|
||||
|
||||
# `LocalCUDACluster` is used for assigning GPU to XGBoost processes. Here
|
||||
# `n_workers` represents the number of GPUs since we use one GPU per worker
|
||||
# process.
|
||||
with LocalCUDACluster(n_workers=2, threads_per_worker=4) as cluster:
|
||||
with Client(cluster) as client:
|
||||
main(client)
|
||||
# generate some random data for demonstration
|
||||
m = 100000
|
||||
n = 100
|
||||
X = da.random.random(size=(m, n), chunks=100)
|
||||
y = da.random.random(size=(m, ), chunks=100)
|
||||
|
||||
if args.ddqdm == 1:
|
||||
print('Using DaskDeviceQuantileDMatrix')
|
||||
from_ddqdm = using_quantile_device_dmatrix(client, X, y)
|
||||
else:
|
||||
print('Using DMatrix')
|
||||
from_dmatrix = using_dask_matrix(client, X, y)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# This is the example script to run distributed xgboost on AWS.
|
||||
# Change the following two lines for configuration
|
||||
|
||||
export BUCKET=mybucket
|
||||
|
||||
# submit the job to YARN
|
||||
../../dmlc-core/tracker/dmlc-submit --cluster=yarn --num-workers=2 --worker-cores=2\
|
||||
../../xgboost mushroom.aws.conf nthread=2\
|
||||
data=s3://${BUCKET}/xgb-demo/train\
|
||||
eval[test]=s3://${BUCKET}/xgb-demo/test\
|
||||
model_dir=s3://${BUCKET}/xgb-demo/model
|
||||
@@ -1,3 +1,5 @@
|
||||
# GPU Acceleration Demo
|
||||
|
||||
`cover_type.py` shows how to train a model on the [forest cover type](https://archive.ics.uci.edu/ml/datasets/covertype) dataset using GPU acceleration. The forest cover type dataset has 581,012 rows and 54 features, making it time consuming to process. We compare the run-time and accuracy of the GPU and CPU histogram algorithms.
|
||||
`cover_type.py` shows how to train a model on the [forest cover type](https://archive.ics.uci.edu/ml/datasets/covertype) dataset using GPU acceleration. The forest cover type dataset has 581,012 rows and 54 features, making it time consuming to process. We compare the run-time and accuracy of the GPU and CPU histogram algorithms.
|
||||
|
||||
`shap.ipynb` demonstrates using GPU acceleration to compute SHAP values for feature importance.
|
||||
|
||||
211
demo/gpu_acceleration/shap.ipynb
Normal file
211
demo/gpu_acceleration/shap.ipynb
Normal file
File diff suppressed because one or more lines are too long
130
demo/guide-python/callbacks.py
Normal file
130
demo/guide-python/callbacks.py
Normal file
@@ -0,0 +1,130 @@
|
||||
'''
|
||||
Demo for using and defining callback functions.
|
||||
|
||||
.. versionadded:: 1.3.0
|
||||
'''
|
||||
import xgboost as xgb
|
||||
import tempfile
|
||||
import os
|
||||
import numpy as np
|
||||
from sklearn.datasets import load_breast_cancer
|
||||
from sklearn.model_selection import train_test_split
|
||||
from matplotlib import pyplot as plt
|
||||
import argparse
|
||||
|
||||
|
||||
class Plotting(xgb.callback.TrainingCallback):
|
||||
'''Plot evaluation result during training. Only for demonstration purpose as it's quite
|
||||
slow to draw.
|
||||
|
||||
'''
|
||||
def __init__(self, rounds):
|
||||
self.fig = plt.figure()
|
||||
self.ax = self.fig.add_subplot(111)
|
||||
self.rounds = rounds
|
||||
self.lines = {}
|
||||
self.fig.show()
|
||||
self.x = np.linspace(0, self.rounds, self.rounds)
|
||||
plt.ion()
|
||||
|
||||
def _get_key(self, data, metric):
|
||||
return f'{data}-{metric}'
|
||||
|
||||
def after_iteration(self, model, epoch, evals_log):
|
||||
'''Update the plot.'''
|
||||
if not self.lines:
|
||||
for data, metric in evals_log.items():
|
||||
for metric_name, log in metric.items():
|
||||
key = self._get_key(data, metric_name)
|
||||
expanded = log + [0] * (self.rounds - len(log))
|
||||
self.lines[key], = self.ax.plot(self.x, expanded, label=key)
|
||||
self.ax.legend()
|
||||
else:
|
||||
# https://pythonspot.com/matplotlib-update-plot/
|
||||
for data, metric in evals_log.items():
|
||||
for metric_name, log in metric.items():
|
||||
key = self._get_key(data, metric_name)
|
||||
expanded = log + [0] * (self.rounds - len(log))
|
||||
self.lines[key].set_ydata(expanded)
|
||||
self.fig.canvas.draw()
|
||||
# False to indicate training should not stop.
|
||||
return False
|
||||
|
||||
|
||||
def custom_callback():
|
||||
'''Demo for defining a custom callback function that plots evaluation result during
|
||||
training.'''
|
||||
X, y = load_breast_cancer(return_X_y=True)
|
||||
X_train, X_valid, y_train, y_valid = train_test_split(X, y, random_state=0)
|
||||
|
||||
D_train = xgb.DMatrix(X_train, y_train)
|
||||
D_valid = xgb.DMatrix(X_valid, y_valid)
|
||||
|
||||
num_boost_round = 100
|
||||
plotting = Plotting(num_boost_round)
|
||||
|
||||
# Pass it to the `callbacks` parameter as a list.
|
||||
xgb.train(
|
||||
{
|
||||
'objective': 'binary:logistic',
|
||||
'eval_metric': ['error', 'rmse'],
|
||||
'tree_method': 'gpu_hist'
|
||||
},
|
||||
D_train,
|
||||
evals=[(D_train, 'Train'), (D_valid, 'Valid')],
|
||||
num_boost_round=num_boost_round,
|
||||
callbacks=[plotting])
|
||||
|
||||
|
||||
def check_point_callback():
|
||||
# only for demo, set a larger value (like 100) in practice as checkpointing is quite
|
||||
# slow.
|
||||
rounds = 2
|
||||
|
||||
def check(as_pickle):
|
||||
for i in range(0, 10, rounds):
|
||||
if i == 0:
|
||||
continue
|
||||
if as_pickle:
|
||||
path = os.path.join(tmpdir, 'model_' + str(i) + '.pkl')
|
||||
else:
|
||||
path = os.path.join(tmpdir, 'model_' + str(i) + '.json')
|
||||
assert(os.path.exists(path))
|
||||
|
||||
X, y = load_breast_cancer(return_X_y=True)
|
||||
m = xgb.DMatrix(X, y)
|
||||
# Check point to a temporary directory for demo
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
# Use callback class from xgboost.callback
|
||||
# Feel free to subclass/customize it to suit your need.
|
||||
check_point = xgb.callback.TrainingCheckPoint(directory=tmpdir,
|
||||
iterations=rounds,
|
||||
name='model')
|
||||
xgb.train({'objective': 'binary:logistic'}, m,
|
||||
num_boost_round=10,
|
||||
verbose_eval=False,
|
||||
callbacks=[check_point])
|
||||
check(False)
|
||||
|
||||
# This version of checkpoint saves everything including parameters and
|
||||
# model. See: doc/tutorials/saving_model.rst
|
||||
check_point = xgb.callback.TrainingCheckPoint(directory=tmpdir,
|
||||
iterations=rounds,
|
||||
as_pickle=True,
|
||||
name='model')
|
||||
xgb.train({'objective': 'binary:logistic'}, m,
|
||||
num_boost_round=10,
|
||||
verbose_eval=False,
|
||||
callbacks=[check_point])
|
||||
check(True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--plot', default=1, type=int)
|
||||
args = parser.parse_args()
|
||||
|
||||
check_point_callback()
|
||||
|
||||
if args.plot:
|
||||
custom_callback()
|
||||
@@ -14,15 +14,15 @@ print('running cross validation')
|
||||
# std_value is standard deviation of the metric
|
||||
xgb.cv(param, dtrain, num_round, nfold=5,
|
||||
metrics={'error'}, seed=0,
|
||||
callbacks=[xgb.callback.print_evaluation(show_stdv=True)])
|
||||
callbacks=[xgb.callback.EvaluationMonitor(show_stdv=True)])
|
||||
|
||||
print('running cross validation, disable standard deviation display')
|
||||
# do cross validation, this will print result out as
|
||||
# [iteration] metric_name:mean_value
|
||||
res = xgb.cv(param, dtrain, num_boost_round=10, nfold=5,
|
||||
metrics={'error'}, seed=0,
|
||||
callbacks=[xgb.callback.print_evaluation(show_stdv=False),
|
||||
xgb.callback.early_stop(3)])
|
||||
callbacks=[xgb.callback.EvaluationMonitor(show_stdv=False),
|
||||
xgb.callback.EarlyStopping(3)])
|
||||
print(res)
|
||||
print('running cross validation, with preprocessing function')
|
||||
# define the preprocessing function
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import xgboost as xgb
|
||||
###
|
||||
# advanced: customized loss function
|
||||
#
|
||||
import os
|
||||
import numpy as np
|
||||
import xgboost as xgb
|
||||
|
||||
print('start running example to used customized objective function')
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
dtrain = xgb.DMatrix(os.path.join(CURRENT_DIR, '../data/agaricus.txt.train'))
|
||||
dtest = xgb.DMatrix(os.path.join(CURRENT_DIR, '../data/agaricus.txt.test'))
|
||||
|
||||
# note: for customized objective function, we leave objective as default
|
||||
# note: what we are getting is margin value in prediction
|
||||
# you must know what you are doing
|
||||
param = {'max_depth': 2, 'eta': 1}
|
||||
# note: what we are getting is margin value in prediction you must know what
|
||||
# you are doing
|
||||
param = {'max_depth': 2, 'eta': 1, 'objective': 'reg:logistic'}
|
||||
watchlist = [(dtest, 'eval'), (dtrain, 'train')]
|
||||
num_round = 2
|
||||
num_round = 10
|
||||
|
||||
|
||||
# user define objective function, given prediction, return gradient and second
|
||||
# order gradient this is log likelihood loss
|
||||
def logregobj(preds, dtrain):
|
||||
labels = dtrain.get_label()
|
||||
preds = 1.0 / (1.0 + np.exp(-preds))
|
||||
preds = 1.0 / (1.0 + np.exp(-preds)) # transform raw leaf weight
|
||||
grad = preds - labels
|
||||
hess = preds * (1.0 - preds)
|
||||
return grad, hess
|
||||
@@ -31,20 +31,31 @@ def logregobj(preds, dtrain):
|
||||
# user defined evaluation function, return a pair metric_name, result
|
||||
|
||||
# NOTE: when you do customized loss function, the default prediction value is
|
||||
# margin. this may make builtin evaluation metric not function properly for
|
||||
# example, we are doing logistic loss, the prediction is score before logistic
|
||||
# transformation the builtin evaluation error assumes input is after logistic
|
||||
# transformation Take this in mind when you use the customization, and maybe
|
||||
# you need write customized evaluation function
|
||||
# margin, which means the prediction is score before logistic transformation.
|
||||
def evalerror(preds, dtrain):
|
||||
labels = dtrain.get_label()
|
||||
preds = 1.0 / (1.0 + np.exp(-preds)) # transform raw leaf weight
|
||||
# return a pair metric_name, result. The metric name must not contain a
|
||||
# colon (:) or a space since preds are margin(before logistic
|
||||
# transformation, cutoff at 0)
|
||||
return 'my-error', float(sum(labels != (preds > 0.0))) / len(labels)
|
||||
# colon (:) or a space
|
||||
return 'my-error', float(sum(labels != (preds > 0.5))) / len(labels)
|
||||
|
||||
|
||||
py_evals_result = {}
|
||||
|
||||
# training with customized objective, we can also do step by step training
|
||||
# simply look at xgboost.py's implementation of train
|
||||
bst = xgb.train(param, dtrain, num_round, watchlist, obj=logregobj,
|
||||
feval=evalerror)
|
||||
# simply look at training.py's implementation of train
|
||||
py_params = param.copy()
|
||||
py_params.update({'disable_default_eval_metric': True})
|
||||
py_logreg = xgb.train(py_params, dtrain, num_round, watchlist, obj=logregobj,
|
||||
feval=evalerror, evals_result=py_evals_result)
|
||||
|
||||
evals_result = {}
|
||||
params = param.copy()
|
||||
params.update({'eval_metric': 'error'})
|
||||
logreg = xgb.train(params, dtrain, num_boost_round=num_round, evals=watchlist,
|
||||
evals_result=evals_result)
|
||||
|
||||
|
||||
for i in range(len(py_evals_result['train']['my-error'])):
|
||||
np.testing.assert_almost_equal(py_evals_result['train']['my-error'],
|
||||
evals_result['train']['error'])
|
||||
|
||||
@@ -142,7 +142,8 @@ def main(args):
|
||||
|
||||
native_results = {}
|
||||
# Use the same objective function defined in XGBoost.
|
||||
booster_native = xgb.train({'num_class': kClasses},
|
||||
booster_native = xgb.train({'num_class': kClasses,
|
||||
'eval_metric': 'merror'},
|
||||
m,
|
||||
num_boost_round=kRounds,
|
||||
evals_result=native_results,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'''A demo for defining data iterator.
|
||||
|
||||
.. versionadded:: 1.2.0
|
||||
|
||||
The demo that defines a customized iterator for passing batches of data into
|
||||
`xgboost.DeviceQuantileDMatrix` and use this `DeviceQuantileDMatrix` for
|
||||
training. The feature is used primarily designed to reduce the required GPU
|
||||
@@ -39,7 +41,7 @@ class IterForDMatrixDemo(xgboost.core.DataIter):
|
||||
rng = cupy.random.RandomState(1994)
|
||||
self._data = [rng.randn(self.rows, self.cols)] * BATCHES
|
||||
self._labels = [rng.randn(self.rows)] * BATCHES
|
||||
self._weights = [rng.randn(self.rows)] * BATCHES
|
||||
self._weights = [rng.uniform(size=self.rows)] * BATCHES
|
||||
|
||||
self.it = 0 # set iterator to 0
|
||||
super().__init__()
|
||||
|
||||
@@ -7,8 +7,8 @@ import xgboost as xgb
|
||||
# several cache file with the prefix will be generated
|
||||
# currently only support convert from libsvm file
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
dtrain = xgb.DMatrix(os.path.join(CURRENT_DIR, '../data/agaricus.txt.train'))
|
||||
dtest = xgb.DMatrix(os.path.join(CURRENT_DIR, '../data/agaricus.txt.test'))
|
||||
dtrain = xgb.DMatrix(os.path.join(CURRENT_DIR, '../data/agaricus.txt.train#dtrain.cache'))
|
||||
dtest = xgb.DMatrix(os.path.join(CURRENT_DIR, '../data/agaricus.txt.test#dtest.cache'))
|
||||
|
||||
# specify validations set to watch performance
|
||||
param = {'max_depth':2, 'eta':1, 'objective':'binary:logistic'}
|
||||
|
||||
49
demo/guide-python/feature_weights.py
Normal file
49
demo/guide-python/feature_weights.py
Normal file
@@ -0,0 +1,49 @@
|
||||
'''Using feature weight to change column sampling.
|
||||
|
||||
.. versionadded:: 1.3.0
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
import xgboost
|
||||
from matplotlib import pyplot as plt
|
||||
import argparse
|
||||
|
||||
|
||||
def main(args):
|
||||
rng = np.random.RandomState(1994)
|
||||
|
||||
kRows = 1000
|
||||
kCols = 10
|
||||
|
||||
X = rng.randn(kRows, kCols)
|
||||
y = rng.randn(kRows)
|
||||
fw = np.ones(shape=(kCols,))
|
||||
for i in range(kCols):
|
||||
fw[i] *= float(i)
|
||||
|
||||
dtrain = xgboost.DMatrix(X, y)
|
||||
dtrain.set_info(feature_weights=fw)
|
||||
|
||||
bst = xgboost.train({'tree_method': 'hist',
|
||||
'colsample_bynode': 0.5},
|
||||
dtrain, num_boost_round=10,
|
||||
evals=[(dtrain, 'd')])
|
||||
featue_map = bst.get_fscore()
|
||||
# feature zero has 0 weight
|
||||
assert featue_map.get('f0', None) is None
|
||||
assert max(featue_map.values()) == featue_map.get('f9')
|
||||
|
||||
if args.plot:
|
||||
xgboost.plot_importance(bst)
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--plot',
|
||||
type=int,
|
||||
default=1,
|
||||
help='Set to 0 to disable plotting the evaluation history.')
|
||||
args = parser.parse_args()
|
||||
main(args)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user