in gbdt-rs/src/decision_tree.rs [1758:1842]
fn add_node_from_json(&mut self, index: TreeIndex, node: &serde_json::Value) -> Result<()> {
{
let node_ref = self
.tree
.get_node_mut(index)
.expect("node should not be empty!");
// This is the leaf node
if let serde_json::Value::Number(pred) = &node["leaf"] {
let leaf_value = pred.as_f64().ok_or_else(|| "parse 'leaf' error")?;
node_ref.value.pred = leaf_value as ValueType;
node_ref.value.is_leaf = true;
return Ok(());
} else {
// feature value
let feature_value = node["split_condition"]
.as_f64()
.ok_or_else(|| "parse 'split condition' error")?;
node_ref.value.feature_value = feature_value as ValueType;
// feature index
let feature_index = match node["split"].as_i64() {
Some(v) => v,
None => {
let feature_name = node["split"]
.as_str()
.ok_or_else(|| "parse 'split' error")?;
let feature_str: String = feature_name.chars().skip(3).collect();
feature_str.parse::<i64>()?
}
};
node_ref.value.feature_index = feature_index as usize;
// handle unknown feature
let missing = node["missing"]
.as_i64()
.ok_or_else(|| "parse 'missing' error")?;
let left_child = node["yes"].as_i64().ok_or_else(|| "parse 'yes' error")?;
let right_child = node["no"].as_i64().ok_or_else(|| "parse 'no' error")?;
if missing == left_child {
node_ref.value.missing = -1;
} else if missing == right_child {
node_ref.value.missing = 1;
} else {
return Err(GbdtError::NotSupportExtraMissingNode);
}
}
}
// ids for children
let left_child = node["yes"].as_i64().ok_or_else(|| "parse 'yes' error")?;
let right_child = node["no"].as_i64().ok_or_else(|| "parse 'no' error")?;
let children = node["children"]
.as_array()
.ok_or_else(|| "parse 'children' error")?;
let mut find_left = false;
let mut find_right = false;
for child in children.iter() {
let node_id = child["nodeid"]
.as_i64()
.ok_or_else(|| "parse 'nodeid' error")?;
// build left child
if node_id == left_child {
find_left = true;
let left_index = self
.tree
.add_left_node(index, BinaryTreeNode::new(DTNode::new()));
self.add_node_from_json(left_index, child)?;
}
// build right child
if node_id == right_child {
find_right = true;
let right_index = self
.tree
.add_right_node(index, BinaryTreeNode::new(DTNode::new()));
self.add_node_from_json(right_index, child)?;
}
}
if (!find_left) || (!find_right) {
return Err(GbdtError::ChildrenNotFound);
}
Ok(())
}