Closed AltamashRafiq closed 11 months ago
For some context, there are two models here: one that passes the test and one that fails. The only difference is depth of 2 in the passing model vs 3 in the failing model.
Hi there, thank you for raising the issue. I will take a look when I have time.
Thank you so much! I've been digging into this and here is some insight for one sample observation
Observation: 0 0:0.9 1:66.40000000000001 2:60 3:5.92 4:5.86 5:3.91 10:1 14:1 23:1
For this sample, only one tree in the forest gives an output that is different to python's xgboost. This tree (leaf node below) returns -0.302633077 instead of 0.0803299546. As we can see, it splits on feature 5 here and the split condition is approximately equal to the raw value of the feature. As 3.91 < 3.91000009, we should go to 0.0803299546 but it is incorrectly interpreted as a value greater than or equal to the threshold. My suspicion is that the threshold 3.91000009 is being accidentally rounded down here.
Problematic leaf node: { "nodeid": 5, "depth": 2, "split": "f5", "split_condition": 3.91000009, "yes": 11, "no": 12, "missing": 11 , "children": [{ "nodeid": 11, "leaf": -0.302633077 }, { "nodeid": 12, "leaf": 0.0803299546 }]}
This issue is solved! Turns out the problem originates from xgboost in python, not the xgboost-go library. Xgboost's C++ library internally stores the trees as float32 but dumps the trees as float64 in Python. This means that split conditions like 3.91 become 3.91000009 when dumped to json, eventually leading to differences between this library's and xgboost python's results. This problem can be replicated in numpy as well (see attached).
XGBoost's c++ library uses float32 for all values. May be worth considering using float32 instead of float64 within xgboost-go for inference parity.
I'm not aware of an issue wrt casting the float64 values in the json to float32 in code. In theory it should reverse the damage done by casting float32's to float64 in the python xgboost lib.
@Elvenson Thoughts?
I think you guys are right, let me update the code when I have time. Thanks you guys for your insights!
@Elvenson @jcronq PR for this change created here: https://github.com/Elvenson/xgboost-go/pull/13
Thanks for your contribution @AltamashRafiq ! I have merged the code and will close this issue now.
Hi! I have a failing test case for this library that I am trying to understand. This uses the open source diamonds dataset. Could you weigh in on why this is a failing case and what might be going wrong? XGBoost version 1.6.2 which I have tested dumps the same json tree and predictions as version 1.2.0.
Python file for generating the test files:
Test file in Go: