xgb.plot.tree узел цветовой заливки и текстовые улучшения - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь сделать дерево, созданное с помощью xgboost, более читабельным. Я нашел несколько других постов, предлагающих использовать пакет «chartmer» для изменения характеристик шрифта и цвета, но я нашел только для установки этих параметров при создании нового графика.

Кроме того, я нашел этот пост, но когда я попытался отредактировать исходный код функции xgb.plot.tree, он выдавал ошибку, что не смог найти функцию «проверить устаревание», которая находится внутри источника код.

макет дерева xgb.plot.t в r

Вот исходный код

xgb.plot.tree <- function(feature_names = NULL, model = NULL, trees = NULL, 
plot_width = NULL, plot_height = NULL,
                      render = TRUE, show_node_id = FALSE, ...){
check.deprecation(...)
if (!inherits(model, "xgb.Booster")) {
stop("model: Has to be an object of class xgb.Booster")
}

if (!requireNamespace("DiagrammeR", quietly = TRUE)) {
stop("DiagrammeR package is required for xgb.plot.tree", call. = FALSE)
}

dt <- xgb.model.dt.tree(feature_names = feature_names, model = model, trees 
= trees)

dt[, label:= paste0(Feature, "\nCover: ", Cover, ifelse(Feature == "Leaf", 
"\nValue: ", "\nGain: "), Quality)]
if (show_node_id)
dt[, label := paste0(ID, ": ", label)]
dt[Node == 0, label := paste0("Tree ", Tree, "\n", label)]
dt[, shape:= "rectangle"][Feature == "Leaf", shape:= "oval"]
dt[, filledcolor:= "Beige"][Feature == "Leaf", filledcolor:= "Khaki"]
# in order to draw the first tree on top:
dt <- dt[order(-Tree)]

nodes <- DiagrammeR::create_node_df(
n         = nrow(dt),
ID        = dt$ID,
label     = dt$label,
fillcolor = dt$filledcolor,
shape     = dt$shape,
data      = dt$Feature,
fontcolor = "black")

edges <- DiagrammeR::create_edge_df(
from  = match(dt[Feature != "Leaf", c(ID)] %>% rep(2), dt$ID),
to    = match(dt[Feature != "Leaf", c(Yes, No)], dt$ID),
label = dt[Feature != "Leaf", paste("<", Split)] %>%
        c(rep("", nrow(dt[Feature != "Leaf"]))),
style = dt[Feature != "Leaf", ifelse(Missing == Yes, "bold", "solid")] %>%
        c(dt[Feature != "Leaf", ifelse(Missing == No, "bold", "solid")]),
rel   = "leading_to")

graph <- DiagrammeR::create_graph(
  nodes_df = nodes,
  edges_df = edges,
  attr_theme = NULL
  ) %>%
DiagrammeR::add_global_graph_attrs(
  attr_type = "graph",
  attr  = c("layout", "rankdir"),
  value = c("dot", "LR")
  ) %>%
DiagrammeR::add_global_graph_attrs(
  attr_type = "node",
  attr  = c("color", "style", "fontname"),
  value = c("DimGray", "filled", "Helvetica")
  ) %>%
DiagrammeR::add_global_graph_attrs(
  attr_type = "edge",
  attr  = c("color", "arrowsize", "arrowhead", "fontname"),
  value = c("DimGray", "1.5", "vee", "Helvetica"))

if (!render) return(invisible(graph))

DiagrammeR::render_graph(graph, width = plot_width, height = plot_height)
}

и я просто добавил черный и серый вместо бежевого и хаки, чтобы посмотреть, поможет ли это.

xgb.plot.tree <- function(feature_names = NULL, model = NULL, trees = NULL, 
plot_width = NULL, plot_height = NULL,
                      render = TRUE, show_node_id = FALSE, ...){
check.deprecation(...)
if (!inherits(model, "xgb.Booster")) {
stop("model: Has to be an object of class xgb.Booster")
}

if (!requireNamespace("DiagrammeR", quietly = TRUE)) {
stop("DiagrammeR package is required for xgb.plot.tree", call. = FALSE)
}

dt <- xgb.model.dt.tree(feature_names = feature_names, model = model, trees 
= trees)

dt[, label:= paste0(Feature, "\nCover: ", Cover, ifelse(Feature == "Leaf", 
"\nValue: ", "\nGain: "), Quality)]
if (show_node_id)
dt[, label := paste0(ID, ": ", label)]
dt[Node == 0, label := paste0("Tree ", Tree, "\n", label)]
dt[, shape:= "rectangle"][Feature == "Leaf", shape:= "oval"]
dt[, filledcolor:= "Black"][Feature == "Leaf", filledcolor:= "Grey"]
# in order to draw the first tree on top:
dt <- dt[order(-Tree)]

nodes <- DiagrammeR::create_node_df(
n         = nrow(dt),
ID        = dt$ID,
label     = dt$label,
fillcolor = dt$filledcolor,
shape     = dt$shape,
data      = dt$Feature,
fontcolor = "black")

edges <- DiagrammeR::create_edge_df(
from  = match(dt[Feature != "Leaf", c(ID)] %>% rep(2), dt$ID),
to    = match(dt[Feature != "Leaf", c(Yes, No)], dt$ID),
label = dt[Feature != "Leaf", paste("<", Split)] %>%
        c(rep("", nrow(dt[Feature != "Leaf"]))),
style = dt[Feature != "Leaf", ifelse(Missing == Yes, "bold", "solid")] %>%
        c(dt[Feature != "Leaf", ifelse(Missing == No, "bold", "solid")]),
rel   = "leading_to")

graph <- DiagrammeR::create_graph(
  nodes_df = nodes,
  edges_df = edges,
  attr_theme = NULL
  ) %>%
DiagrammeR::add_global_graph_attrs(
  attr_type = "graph",
  attr  = c("layout", "rankdir"),
  value = c("dot", "LR")
  ) %>%
DiagrammeR::add_global_graph_attrs(
  attr_type = "node",
  attr  = c("color", "style", "fontname"),
  value = c("DimGray", "filled", "Helvetica")
  ) %>%
DiagrammeR::add_global_graph_attrs(
  attr_type = "edge",
  attr  = c("color", "arrowsize", "arrowhead", "fontname"),
  value = c("DimGray", "1.5", "vee", "Helvetica"))

if (!render) return(invisible(graph))

DiagrammeR::render_graph(graph, width = plot_width, height = plot_height)
}

Любая помощь будет потрясающей, спасибо!

...