【发布时间】:2022-11-10 16:54:47
【问题描述】:
我一直在查看booster.save_model("model.json") 的输出,但我无法理解输出。似乎model.json 中的所有信息实际上几乎都没有用于预测,实际上 - 非常少。作为参考,一个这样的 model.json 看起来像这样:
j={"learner": {
"attributes": {},
"feature_names": [],
"feature_types": [],
"gradient_booster": {"model": {"gbtree_model_param": {"num_trees": "1", "size_leaf_vector": "0"}, "tree_info": [0], "trees": [<a single tree>]}, "name": "gbtree"},
"learner_model_param": {"base_score": "5E-1", "num_class": "0", "num_feature": "5"},
"objective": {"name": "reg:squarederror", "reg_loss_param": {"scale_pos_weight": "1"}}},
"version": [1, 4, 2]}
j['learner']['gradient_booster']['model']['trees'] 下的单棵树是
{
"base_weights": [-0.4984156, -1.2707391, 0.37819964, -2.128702, -0.5379327, -0.41528815, 1.2452325, -2.9461422, -1.3161767, -1.317807, 0.3579243, -1.2447615, 0.33945537, 0.5203166, 2.272548],
"categories": [],
"categories_nodes": [],
"categories_segments": [],
"categories_sizes": [],
"default_left": [true, true, true, true, true, true, true, false, false, false, false, false, false, false, false],
"id": 0,
"left_children": [1, 3, 5, 7, 9, 11, 13, -1, -1, -1, -1, -1, -1, -1, -1],
"loss_changes": [6771.463, 3341.7627, 3223.7031, 1622.7256, 2004.9153, 1532.3413, 1666.2395, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
"parents": [2147483647, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6],
"right_children": [2, 4, 6, 8, 10, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1],
"split_conditions": [0.073486, -0.11132032, 0.041045856, -0.011401389, 0.104938895, -0.05693599, 0.19832665, -0.8838427, -0.39485303, -0.3953421, 0.1073773, -0.37342846, 0.101836614, 0.15609498, 0.6817644],
"split_indices": [3, 4, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
"split_type": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"sum_hessian": [10000.0, 5316.0, 4684.0, 2448.0, 2868.0, 2446.0, 2238.0, 1219.0, 1229.0, 1533.0, 1335.0, 1165.0, 1281.0, 1313.0, 925.0],
"tree_param": {"num_deleted": "0", "num_feature": "5", "num_nodes": "15", "size_leaf_vector": "0"}
}
问题 1:作为其输入和这些参数的函数,助推器做出预测的确切公式是什么?
我本来希望通过从 base_score 开始并在每次遍历期间添加 base_weights 的相关值来形成预测,但这似乎并非如此,事实上,预测的值似乎没有依赖base_weights(或loss_changes或sum_hessian)!这是一个简短的演示(使用xgboost.__version__=1.4.2 和python 3.9.7):
import numpy as np, xgboost, json
def new_model():
return xgboost.XGBRegressor(n_estimators=1, max_depth=3, base_score=0.5)
def save_model(model, path):
model.get_booster().save_model(path)
def load_model(path):
model = new_model()
model.load_model(path)
return model
x = np.random.standard_normal((10000, 5))
y = x.sum(1)
m0 = new_model()
m0.fit(x, y)
pred0 = m0.predict(x)
p0 = '/tmp/m0.json'
save_model(m0, p0)
np.testing.assert_array_equal(pred0, load_model(p0).predict(x)) # test save->load
with open(p0) as f:
j = json.load(f)
trees = j['learner']['gradient_booster']['model']['trees']
for field in ['base_weights', 'loss_changes', 'sum_hessian']:
trees[0][field] = np.random.random(len(trees[0][field])).tolist()
p1 = '/tmp/m2.json'
with open(p1, 'w') as f:
json.dump(j, f)
np.testing.assert_array_equal(pred0, load_model(p1).predict(x)) # this assertion passes! Unexpected!
确实,似乎正在使用的唯一浮点数据是split_indices,但我认为这远远不足以描述回归树。因此,如果问题 1 太细而无法在这里回答,那么仍然...
问题2:模型预测怎么可能只依赖于这个浮点向量split_conditions?
【问题讨论】:
-
这个问题要问两个问题。您可能会得到更好或更快的答复,将其分为两个问题。
标签: python machine-learning xgboost