Nothing
context("GraphLearner")
test_that("basic graphlearner tests", {
skip_if_not_installed("rpart")
skip_on_cran() # takes too long
task = mlr_tasks$get("iris")
lrn = mlr_learners$get("classif.rpart")
gr = PipeOpLearner$new(lrn)
glrn = GraphLearner$new(gr)
glrn$properties = setdiff(glrn$properties, "weights") # FIXME: workaround until weights handling does not need to be part of the paramset
if ("use_weights" %in% names(glrn)) { # FIXME: condition can be removed when mlr3 weights update, mlr3-org/mlr3#1124 is on CRAN
glrn$use_weights = "error" # also need to update use_weights now
}
expect_true(run_experiment(task, glrn)$ok)
glrn$properties = c(glrn$properties, "weights")
glrn = GraphLearner$new(gr)
expect_learner(glrn)
glrn$train(task)
expect_prediction_classif({
graphpred = glrn$predict(task)
})
expect_equal(graphpred,
lrn$train(task)$predict(task))
expect_prediction_classif({
graphpred = glrn$predict(task)
})
expect_equal(graphpred, lrn$predict(task))
set.seed(1)
lrn = mlr_learners$get("classif.rpart")
resgraphlrn = resample(task, lrn, mlr_resamplings$get("cv"))
set.seed(1)
resjustlrn = resample(task, lrn, mlr_resamplings$get("cv"))
expect_equal(resgraphlrn$prediction(), resjustlrn$prediction())
gr2 = PipeOpScale$new() %>>% PipeOpLearner$new(lrn)
glrn2 = GraphLearner$new(gr2)
glrn2_clone = glrn2$clone(deep = TRUE)
expect_learner(glrn2)
glrn2$properties = setdiff(glrn2$properties, "weights") # FIXME: see above
if ("use_weights" %in% names(glrn2)) { # FIXME: see above
glrn2$use_weights = "error" # see above
}
expect_true(run_experiment(task, glrn2)$ok)
glrn2$properties = c(glrn2$properties, "weights") # reset changes
if ("use_weights" %in% names(glrn2)) { # FIXME: see above
glrn2$use_weights = "use" # reset changes
}
glrn2$train(task)
glrn2_clone$state = glrn2$state
# glrn2_clone$state$log = glrn2_clone$state$log$clone(deep = TRUE) # FIXME: this can go when mlr-org/mlr3#343 is fixed
# glrn2_clone$state$model$classif.rpart$log = glrn2_clone$state$model$classif.rpart$log$clone(deep = TRUE) # FIXME: this can go when mlr-org/mlr3#343 is fixed
expect_deep_clone(glrn2_clone, glrn2$clone(deep = TRUE))
expect_prediction_classif({
graphpred2 = glrn2$predict(task)
})
expect_equal(glrn2$predict(task), glrn2_clone$predict(task))
scidf = cbind(scale(iris[1:4]), iris[5])
scalediris = TaskClassif$new("scalediris", as_data_backend(scidf), "Species")
dblrn = mlr_learners$get("classif.debug")
dblrn$param_set$values$save_tasks = TRUE
dbgr = GraphLearner$new(PipeOpScale$new() %>>% PipeOpLearner$new(dblrn))
expect_equal(dbgr$train(task), dbgr)
# debuglearner predict() modifies model, but PipeOpLearner does not accept
# model changes in predict phase, so would ordinarily discard the change.
# Here we swap the debuglearner model by an environment, which gets updated
# by-reference, so we can get the $task_predict slot eventually.
dbmodels = as.environment(dbgr$model$classif.debug$model)
dbgr$state$model$classif.debug$model = dbmodels
dbgr$predict(task)
expect_equal(dbmodels$task_train$data(), scalediris$data())
expect_equal(dbmodels$task_predict$data(), scalediris$data())
})
test_that("GraphLearner clone_graph FALSE", {
skip_if_not_installed("rpart")
# prepare graph
gr1 = po("pca") %>>% lrn("classif.rpart")
gr1$train(tsk("iris"))
expect_true(gr1$is_trained)
gl = GraphLearner$new(gr1, clone_graph = FALSE)
# graph is not cloned
expect_identical(gl$graph, gr1)
# GraphLearner$initialize resets graph state
expect_false(gr1$is_trained)
# compare result of training with a subset of iris
gl$train(tsk("iris")$filter(1:110))
# gr1 state is not set by this
expect_false(gr1$is_trained)
# train gr1 with a *different* task than gl
gr1$train(tsk("iris"))
# simulate pipeline with iris subset to get expected GraphLearner prediction result
pp = po("pca")
expected_prediction = lrn("classif.rpart")$train(pp$train(list(tsk("iris")$filter(1:110)))[[1]])$predict(pp$predict(list(tsk("iris")))[[1]])
# check that predicting on iris subset gives different result from gr1$predict()
expect_false(isTRUE(all.equal(gr1$predict(tsk("iris"))[[1]], expected_prediction)))
expect_true(gr1$is_trained)
# check that the GraphLearner predicts what we expect
expect_true(isTRUE(all.equal(gl$predict(tsk("iris")), expected_prediction)))
expect_false(gr1$is_trained) # predicting with GraphLearner resets Graph state
expect_identical(gl$graph, gr1)
# check that as_learner respects `clone` now
gl = as_learner(gr1, clone = FALSE)
expect_identical(gl$graph, gr1)
})
test_that("graphlearner parameters behave as they should", {
dblrn = mlr_learners$get("classif.debug")
dblrn$param_set$values$save_tasks = TRUE
# Graph ParamSet
dbgr = PipeOpScale$new() %>>% PipeOpLearner$new(dblrn)
expect_subset(c("scale.center", "scale.scale", "classif.debug.x"), dbgr$param_set$ids())
dbgr$param_set$values$classif.debug.x = 1
expect_equal(dbgr$param_set$values$classif.debug.x, 1)
expect_equal(dbgr$pipeops$classif.debug$param_set$values$x, 1)
expect_equal(dbgr$pipeops$classif.debug$learner$param_set$values$x, 1)
dbgr$pipeops$classif.debug$param_set$values$x = 0
expect_equal(dbgr$param_set$values$classif.debug.x, 0)
expect_equal(dbgr$pipeops$classif.debug$param_set$values$x, 0)
expect_equal(dbgr$pipeops$classif.debug$learner$param_set$values$x, 0)
dbgr$pipeops$classif.debug$learner$param_set$values$x = 0.5
expect_equal(dbgr$param_set$values$classif.debug.x, 0.5)
expect_equal(dbgr$pipeops$classif.debug$param_set$values$x, 0.5)
expect_equal(dbgr$pipeops$classif.debug$learner$param_set$values$x, 0.5)
expect_error({
dbgr$param_set$values$classif.debug.x = "a"
})
expect_error({
dbgr$pipeops$classif.debug$param_set$values$x = "a"
})
expect_error({
dbgr$pipeops$classif.debug$learner$param_set$values$x = "a"
})
expect_equal(dbgr$param_set$values$classif.debug.x, 0.5)
expect_equal(dbgr$pipeops$classif.debug$param_set$values$x, 0.5)
expect_equal(dbgr$pipeops$classif.debug$learner$param_set$values$x, 0.5)
# Graph Learner ParamSet
dblrn = mlr_learners$get("classif.debug")
dblrn$param_set$values$message_train = 1
dblrn$param_set$values$message_predict = 1
dblrn$param_set$values$warning_train = 1
dblrn$param_set$values$warning_predict = 1
pol = PipeOpLearner$new(dblrn, param_vals = list(message_predict = 0, warning_train = 0, warning_predict = 0))
gl = GraphLearner$new(pol, param_vals = list(classif.debug.warning_train = 1, classif.debug.warning_predict = 1))
gl$param_set$values$classif.debug.warning_predict = 0
expect_mapequal(gl$param_set$values,
list(classif.debug.message_predict = 0, classif.debug.message_train = 1, classif.debug.warning_predict = 0, classif.debug.warning_train = 1))
# GraphLearner AB shortcuts
gl = GraphLearner$new(dbgr)
# GraphLearner AB $pipeops
expect_no_error({gl$pipeops$classif.debug$param_set$values$x = 0.5})
expect_equal(gl$pipeops$classif.debug$param_set$values$x, 0.5)
expect_equal(gl$graph_model$pipeops$classif.debug$param_set$values$x, 0.5)
# GraphLearner AB $pipeops_param_set
expect_no_error({gl$pipeops_param_set$classif.debug$values$x = 0})
expect_equal(gl$pipeops_param_set$classif.debug$values$x, 0)
expect_equal(gl$graph_model$pipeops$classif.debug$param_set$values$x, 0)
# GraphLearner AB $pipeops_param_set_values
expect_no_error({gl$pipeops_param_set_values$classif.debug$x = 1})
expect_equal(gl$pipeops_param_set_values$classif.debug$x, 1)
expect_equal(gl$graph_model$pipeops$classif.debug$param_set$values$x, 1)
# Change param_set pointer should throw error
expect_error({gl$pipeops$scale$param_set = ps()})
expect_error({gl$pipeops_param_set$scale = ps()})
# Lists with wrong properties should not be accepted
expect_error({gl$pipeops_param_set_values = list()})
expect_error({gl$pipeops_param_set_values = list(x = 5)})
})
test_that("graphlearner type inference", {
skip_if_not_installed("rpart")
skip_on_cran() # takes too long
# default: classif
lrn = GraphLearner$new(mlr_pipeops$get("nop"))
expect_equal(lrn$task_type, "classif")
expect_equal(lrn$predict_type, "response")
###########
# classif #
###########
# inference from pipeoplearner
lrn = GraphLearner$new(mlr_pipeops$get("learner", lrn("classif.rpart")))
expect_equal(lrn$task_type, "classif")
expect_equal(lrn$predict_type, "response")
# inference from output only
lrn = GraphLearner$new(mlr_pipeops$get("copy", 1) %>>% mlr_pipeops$get("learner", lrn("classif.rpart")))
expect_equal(lrn$task_type, "classif")
expect_equal(lrn$predict_type, "response")
# inference from input only
lrn = GraphLearner$new(mlr_pipeops$get("learner", lrn("classif.rpart")) %>>% mlr_pipeops$get("copy", 1))
expect_equal(lrn$task_type, "classif")
expect_equal(lrn$predict_type, "response")
# inference when multiple input, but one is a Task
# inference when multiple input, but one is a Task
lrn = GraphLearner$new(gunion(list(mlr_pipeops$get("learner", lrn("regr.rpart")), mlr_pipeops$get("nop"))) %>>% mlr_pipeops$get("unbranch"))
expect_equal(lrn$task_type, "regr")
# expect_equal(lrn$predict_type, "response")
###########
# Errors #
###########
# input, output mismatching types
gr = gunion(list(mlr_pipeops$get("learner", lrn("regr.rpart")), mlr_pipeops$get("nop"))) %>>% mlr_pipeops$get("unbranch") %>>% mlr_pipeops$get("learner", lrn("classif.rpart"))
expect_error(GraphLearner$new(gr), "multiple possibilities")
gr = gunion(list(mlr_pipeops$get("learner", lrn("classif.rpart")), mlr_pipeops$get("nop"))) %>>% mlr_pipeops$get("unbranch") %>>% mlr_pipeops$get("learner", lrn("regr.rpart"))
expect_error(GraphLearner$new(gr), "multiple possibilities")
# input two mismatching types
gr = gunion(list(mlr_pipeops$get("learner", lrn("classif.rpart")), mlr_pipeops$get("learner", lrn("regr.rpart")))) %>>% mlr_pipeops$get("unbranch")
expect_error(GraphLearner$new(gr), "multiple possibilities")
# input two mismatching types
expect_error(GraphLearner$new(PipeOpScale$new()), "output type not.*Prediction.*or compatible")
###########################
# Target Transformations #
###########################
lrn = GraphLearner$new(ppl("targettrafo", graph = lrn("classif.rpart"), trafo_pipeop = PipeOpTargetMutate$new()))
expect_equal(lrn$task_type, "classif")
expect_equal(lrn$predict_type, "response")
lrn = GraphLearner$new(ppl("targettrafo", graph = lrn("regr.rpart"), trafo_pipeop = PipeOpTargetMutate$new()))
expect_equal(lrn$task_type, "regr")
expect_equal(lrn$predict_type, "response")
lrn = GraphLearner$new(ppl("targettrafo", graph = lrn("regr.rpart"), trafo_pipeop = PipeOpTargetTrafoScaleRange$new()))
expect_equal(lrn$task_type, "regr")
expect_equal(lrn$predict_type, "response")
###########################
# Synthetic examples #
###########################
# these construct broken graphs on purpose; if this gets caught somewhere else
# in the future we might have to adjust the tests
# The point here is that there could at some point be "legal" graphs that
# end up using the fallback target type inference.
g = po("branch", 2) %>>% gunion(list(mlr_pipeops$get("learner", lrn("regr.rpart")), mlr_pipeops$get("nop"))) %>>% mlr_pipeops$get("unbranch")
g$pipeops$regr.rpart$output$predict = "*"
expect_equal(as_learner(g)$task_type, "regr")
g$pipeops$regr.rpart$input$train = "*"
g$pipeops$regr.rpart$input$predict = "*"
expect_equal(as_learner(g)$task_type, "regr")
g$train(tsk("boston_housing"))
expect_equal(as_learner(g)$task_type, "regr") # should use base_learner inference
g = po("replicate", reps = 2) %>>% lrn("regr.rpart") %>>% po("regravg", collect_multiplicity = TRUE)
g$pipeops$regravg$input$predict = "[*]"
g$pipeops$regravg$output$predict = "*"
g$pipeops$regr.rpart$output$predict = "*"
g$pipeops$regr.rpart$input$train = "*"
g$pipeops$regr.rpart$input$predict = "*"
expect_equal(as_learner(g)$task_type, "regr")
expect_equal(as_learner(g)$task_type, "regr") # should use base_learner inference
g$train(tsk("boston_housing"))
expect_equal(as_learner(g)$task_type, "regr") # should not fail because of multiplicity in the graph
g_branch = ppl("branch", list(rpart = lrn("classif.rpart"), debug = lrn("classif.debug")))
l_branch = as_learner(g_branch)
expect_equal(l_branch$predict_type, "response")
l_branch$graph$pipeops$classif.debug$predict_type = "prob"
expect_equal(l_branch$predict_type, "response")
l_branch$param_set$values$branch.selection = "debug"
expect_equal(l_branch$predict_type, "prob")
l_branch$predict_type = "prob"
expect_equal(l_branch$graph$pipeops$classif.debug$learner$predict_type, "prob")
expect_equal(l_branch$predict_type, "prob")
l_branch$param_set$values$branch.selection = "rpart"
expect_equal(l_branch$predict_type, "prob")
})
test_that("graphlearner type inference - branched", {
skip_if_not_installed("rpart")
skip_on_cran() # takes too long
# default: classif
lrn = GraphLearner$new(gunion(list(
mlr_pipeops$get(id = "l1", "learner", lrn("classif.rpart")),
po("nop") %>>% mlr_pipeops$get(id = "l2", "learner", lrn("classif.rpart"))
)) %>>%
po("classifavg") %>>%
po(id = "n2", "nop"))
expect_equal(lrn$task_type, "classif")
expect_equal(lrn$predict_type, "response")
###########
# regr #
###########
# inference from pipeoplearner
lrn = GraphLearner$new(mlr_pipeops$get("learner", lrn("regr.rpart")))
expect_equal(lrn$task_type, "regr")
expect_equal(lrn$predict_type, "response")
# inference from output only
lrn = GraphLearner$new(mlr_pipeops$get("copy", 1) %>>% mlr_pipeops$get("learner", lrn("regr.rpart")))
expect_equal(lrn$task_type, "regr")
expect_equal(lrn$predict_type, "response")
# inference from input only
lrn = GraphLearner$new(mlr_pipeops$get("learner", lrn("regr.rpart")) %>>% mlr_pipeops$get("copy", 1))
expect_equal(lrn$task_type, "regr")
expect_equal(lrn$predict_type, "response")
# inference when multiple input, but one is a Task
lrn = GraphLearner$new(gunion(list(
mlr_pipeops$get(id = "l1", "learner", lrn("regr.rpart")),
po("nop") %>>% mlr_pipeops$get(id = "l2", "learner", lrn("regr.rpart"))
)) %>>%
po("regravg") %>>%
po(id = "n2", "nop"))
expect_equal(lrn$task_type, "regr")
expect_equal(lrn$predict_type, "response")
###########
# Errors #
###########
# input, output mismatching types
gr = gunion(list(mlr_pipeops$get("learner", lrn("regr.rpart")), mlr_pipeops$get("nop"))) %>>% mlr_pipeops$get("unbranch") %>>% mlr_pipeops$get("learner", lrn("classif.rpart"))
expect_error(GraphLearner$new(gr), "multiple possibilities")
gr = gunion(list(mlr_pipeops$get("learner", lrn("classif.rpart")), mlr_pipeops$get("nop"))) %>>% mlr_pipeops$get("unbranch") %>>% mlr_pipeops$get("learner", lrn("regr.rpart"))
expect_error(GraphLearner$new(gr), "multiple possibilities")
# input two mismatching types
gr = gunion(list(mlr_pipeops$get("learner", lrn("classif.rpart")), mlr_pipeops$get("learner", lrn("regr.rpart")))) %>>% mlr_pipeops$get("unbranch")
expect_error(GraphLearner$new(gr), "multiple possibilities")
# input two mismatching types
expect_error(GraphLearner$new(PipeOpScale$new()), "output type not.*Prediction.*or compatible")
})
test_that("graphlearner predict type inference", {
skip_if_not_installed("rpart")
skip_on_cran() # takes too long
# Getter:
# Classification
lrp = po(lrn("classif.rpart", predict_type = "prob"))
lrr = po(lrn("classif.rpart"))
lfp = po(lrn("classif.featureless", predict_type = "prob"))
lfr = po(lrn("classif.featureless"))
nop = po("nop")
# linear
lrn = GraphLearner$new(lrp)
expect_equal(lrn$predict_type, "prob")
lrn = GraphLearner$new(lrr)
expect_equal(lrn$predict_type, "response")
lrn = GraphLearner$new(lrp %>>% nop)
expect_equal(lrn$predict_type, "prob")
# averager
lrn = GraphLearner$new(pipeline_greplicate(po("subsample") %>>% lrr, 3L) %>>% po("classifavg"))
expect_equal(lrn$predict_type, "response")
lrn = GraphLearner$new(pipeline_greplicate(po("subsample") %>>% lrp, 3L) %>>% po("classifavg"))
expect_equal(lrn$predict_type, "prob")
# branching
lrn = GraphLearner$new(po("branch", 2) %>>% gunion(list(lrp, lfp)) %>>% po("unbranch"))
expect_equal(lrn$predict_type, "prob")
lrn = GraphLearner$new(po("branch", 2) %>>% gunion(list(lrr, lfr)) %>>% po("unbranch"))
expect_equal(lrn$predict_type, "response")
lrn = GraphLearner$new(po("branch", 2) %>>% gunion(list(lrp, lfr)) %>>% po("unbranch"))
expect_equal(lrn$predict_type, "prob")
lrn$param_set$values$branch.selection = 2
expect_equal(lrn$predict_type, "response")
# with additional NOP in branch
lrn = GraphLearner$new(po("branch", 2) %>>% gunion(list(lrp %>>% nop, lfp)) %>>% po("unbranch"))
expect_equal(lrn$predict_type, "prob")
# Regression
lrrp = po(lrn("regr.featureless", predict_type = "se"))
lrrr = po(lrn("regr.rpart"))
lrn = GraphLearner$new(pipeline_greplicate(po("subsample") %>>% lrrr, 3L) %>>% po("regravg"))
expect_equal(lrn$predict_type, "response")
lrn = GraphLearner$new(pipeline_greplicate(po("subsample") %>>% lrrp, 3L) %>>% po("regravg"))
expect_equal(lrn$predict_type, "se")
lrn = GraphLearner$new(lrrp %>>% nop)
expect_equal(lrn$predict_type, "se")
# Setter:
lrp = po(lrn("classif.rpart", predict_type = "prob"))
lrn = GraphLearner$new(lrp)
lrn$predict_type = "prob"
expect_equal(lrn$predict_type, "prob")
expect_equal(lrn$graph$pipeops[[lrp$id]]$predict_type, "prob")
lrn = GraphLearner$new(lrp)
lrn$predict_type = "response"
expect_equal(lrn$predict_type, "response")
expect_equal(lrn$graph$pipeops[[lrp$id]]$predict_type, "response")
lrn = GraphLearner$new(lrp)
lrn$predict_type = "prob"
expect_equal(lrn$predict_type, "prob")
expect_equal(lrn$graph$pipeops[[lrp$id]]$predict_type, "prob")
lrn = GraphLearner$new(lrp %>>% po("nop"))
lrn$predict_type = "response"
expect_equal(lrn$predict_type, "response")
expect_equal(lrn$graph$pipeops[[lrp$id]]$predict_type, "response")
# averager
lrn = GraphLearner$new(pipeline_greplicate(po("subsample") %>>% lrp %>>% nop, 3L) %>>% po("classifavg"))
lrn$predict_type = "response"
expect_equal(lrn$predict_type, "response")
expect_true(all(map_chr(lrn$graph$pipeops[paste(lrp$id, 1:3, sep = "_")], "predict_type") == "response"))
# branching
lrn = GraphLearner$new(po("branch", 2) %>>% gunion(list(lrp, lfp %>>% nop)) %>>% po("unbranch"))
expect_equal(lrn$predict_type, "prob")
lrn$predict_type = "response"
expect_equal(lrn$predict_type, "response")
expect_equal(lrn$graph$pipeops[[lrp$id]]$predict_type, "response")
expect_equal(lrn$graph$pipeops[[lfp$id]]$predict_type, "response")
# Setter on construction
lrn = GraphLearner$new(lrr, predict_type = "prob")
expect_equal(lrr$predict_type, "response")
expect_equal(lrn$predict_type, "prob")
expect_equal(lrn$graph$pipeops[[lrr$id]]$predict_type, "prob")
# Errors:
expect_error({lrrp = po(lrn("classif.featureless", predict_type = "se"))})
})
test_that("GraphLearner model", {
skip_if_not_installed("rpart")
graph = po("pca") %>>% lrn("classif.rpart")
graph2 = graph$clone(deep = TRUE)
graph_orig = graph$clone(deep = TRUE)
lr = GraphLearner$new(graph)
expect_equal(lr$graph, graph)
expect_equal(lr$graph_model, graph)
graph2$train(tsk("iris"))
lr$train(tsk("iris"))
expect_equal(graph, graph_orig)
expect_null(graph$state$pca)
# behind-the-scenes param_set cache ruins expect_equal if we don't do this:
graph_orig$param_set
expect_equal(lr$graph, graph_orig)
graph2$state$classif.rpart$train_time = 0
lr$state$model$classif.rpart$train_time = 0
expect_equal(lr$graph_model, graph2)
imp = graph2$pipeops$classif.rpart$learner_model$importance()
expect_equal(lr$graph_model$pipeops$classif.rpart$learner_model$importance(), imp)
})
test_that("predict() function for Graph", {
skip_if_not_installed("rpart")
lx = as_graph(lrn("classif.rpart"))
lx$train(tsk("iris"))
p1 = lx$pipeops$classif.rpart$learner_model$predict(tsk("iris"))
expect_equal(predict(lx, tsk("iris")), p1)
expect_error(predict(lx, iris[1:4]), "Could not create a classif-task for plain prediction data")
lx = as_graph(lrn("regr.rpart"))
lx$train(tsk("boston_housing_classic"))
p1 = lx$pipeops$regr.rpart$learner_model$predict(tsk("boston_housing_classic"))
expect_equal(predict(lx, tsk("boston_housing_classic")), p1)
expect_equal(
predict(lx, tsk("boston_housing_classic")$data(cols = tsk("boston_housing_classic")$feature_names)),
p1$response
)
})
test_that("base_learner() works", {
skip_on_cran()
skip_if_not_installed("rpart")
# graph containing single PipeOpLearner
x = as_learner(as_graph(lrn("classif.rpart")))
# untrained
expect_learner(x$base_learner())
expect_identical(x$base_learner(0), x)
expect_identical(x$base_learner(1), x$base_learner())
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
# trained:
x$train(tsk("iris"))
expect_learner(x$base_learner())
expect_identical(x$base_learner(0), x)
expect_identical(x$base_learner(1), x$base_learner())
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
# graph consisting of PCA, rpart, threshold
x = as_learner(po("pca") %>>% lrn("classif.rpart") %>>% po("threshold"))
expect_learner(x$base_learner())
expect_identical(x$base_learner(0), x)
expect_identical(x$base_learner(1), x$base_learner())
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
# trained:
x$train(tsk("iris"))
expect_learner(x$base_learner())
expect_identical(x$base_learner(0), x)
expect_identical(x$base_learner(1), x$base_learner())
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
# graph inside a graph
x = as_learner(po("pca") %>>% as_learner(po("scale") %>>% lrn("classif.rpart")) %>>% po("threshold"))
expect_learner(x$base_learner())
expect_identical(x$base_learner(0), x)
expect_identical(x$base_learner(1), x$graph_model$pipeops$scale.classif.rpart$learner_model)
expect_identical(x$base_learner(2), x$base_learner())
expect_identical(x$base_learner(), x$graph_model$pipeops$scale.classif.rpart$learner_model$graph_model$pipeops$classif.rpart$learner_model)
x$train(tsk("iris"))
expect_learner(x$base_learner())
expect_identical(x$base_learner(0), x)
expect_identical(x$base_learner(1), x$graph_model$pipeops$scale.classif.rpart$learner_model)
expect_identical(x$base_learner(2), x$base_learner())
expect_identical(x$base_learner(), x$graph_model$pipeops$scale.classif.rpart$learner_model$graph_model$pipeops$classif.rpart$learner_model)
# branching: now supported
branching_learner = as_learner(ppl("branch", lrns(c("classif.rpart", "classif.debug"))))
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.rpart$learner_model)
branching_learner$param_set$values$branch.selection = "classif.debug"
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.debug$learner_model)
#
branching_learner = as_learner(ppl("branch", pos(c("pca", "ica")), prefix_branchops = "brunch") %>>% ppl("branch", lrns(c("classif.rpart", "classif.debug"))))
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.rpart$learner_model)
branching_learner$param_set$values$branch.selection = "classif.debug"
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.debug$learner_model)
# with '...' inputs in unbranch
branching_learner = as_learner(po("branch", c("classif.rpart", "classif.debug")) %>>% unname(lrns(c("classif.rpart", "classif.debug"))) %>>% po("unbranch"))
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.rpart$learner_model)
branching_learner$param_set$values$branch.selection = "classif.debug"
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.debug$learner_model)
#
branching_learner = as_learner(po("branch_1", c("pca", "ica")) %>>% unname(pos(c("pca", "ica"))) %>>% po("unbranch_1") %>>%
po("branch", c("classif.rpart", "classif.debug")) %>>% unname(lrns(c("classif.rpart", "classif.debug"))) %>>% po("unbranch"))
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.rpart$learner_model)
branching_learner$param_set$values$branch.selection = "classif.debug"
expect_identical(branching_learner$base_learner(), branching_learner$graph_model$pipeops$classif.debug$learner_model)
# unbranch with single input, without corresponding PipeOpBranch, is legal
x = as_learner(po("pca") %>>% lrn("classif.rpart") %>>% po("unbranch", 1))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
# unbranch with '...' input
x = as_learner(po("pca") %>>% lrn("classif.rpart") %>>% po("unbranch"))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
# ParamInt selection parameter
x = as_learner(ppl("branch", list(lrn("classif.rpart") %>>% po("unbranch", 1, id = "poub1"), lrn("classif.debug") %>>% po("unbranch", 1, id = "poub2"))))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
x$param_set$values$branch.selection = 2
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.debug$learner_model)
x$param_set$values$branch.selection = to_tune()
# TODO: update this once something smarter happens here
# expect_error(x$base_learner(), "Cannot infer active output.* PipeOpBranch branch.*non-numeric 'selection'")
x = as_learner(ppl("branch", list(classif.rpart = lrn("classif.rpart") %>>% po("unbranch", 1, id = "poub1"), classif.debug = lrn("classif.debug") %>>% po("unbranch", 1, id = "poub2"))))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
x$param_set$values$branch.selection = "classif.debug"
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.debug$learner_model)
expect_error(x$base_learner(return_po = TRUE), "recursive must be == 1 if return_po is TRUE")
expect_error(x$base_learner(return_po = TRUE, recursive = 0), "recursive must be == 1 if return_po is TRUE")
expect_error(x$base_learner(return_all = TRUE), "recursive must be <= 1 if return_all is TRUE")
expect_identical(x$base_learner(recursive = 1, return_po = TRUE), x$graph_model$pipeops$classif.debug)
expect_identical(x$base_learner(recursive = 1, return_all = TRUE),
list(x$graph_model$pipeops$classif.debug$learner_model))
expect_identical(x$base_learner(recursive = 1, return_po = TRUE, return_all = TRUE),
list(x$graph_model$pipeops$classif.debug))
expect_identical(x$base_learner(recursive = 1, return_po = TRUE, return_all = TRUE, resolve_branching = FALSE),
list(x$graph_model$pipeops$classif.rpart, x$graph_model$pipeops$classif.debug))
expect_identical(x$base_learner(recursive = 0), x)
expect_identical(x$base_learner(recursive = 0, return_all = TRUE), list(x))
# unbranch as very first operation works
x = as_learner(po("unbranch", 1, id = "dummyub1") %>>% ppl("branch", list(classif.rpart = lrn("classif.rpart") %>>% po("unbranch", 1, id = "poub1"), classif.debug = lrn("classif.debug") %>>% po("unbranch", 1, id = "poub2"))))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
x$param_set$values$branch.selection = "classif.debug"
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.debug$learner_model)
# branch with output connected to several pipeops
x = as_learner(ppl("branch", list(classif.rpart = list(po("nop"), po("nop_1")) %>>% po("featureunion") %>>% lrn("classif.rpart") %>>% po("unbranch", 1, id = "poub1"), classif.debug = lrn("classif.debug") %>>% po("unbranch", 1, id = "poub2"))))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
x$param_set$values$branch.selection = "classif.debug"
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.debug$learner_model)
x = as_learner(ppl("branch", list(classif.rpart = po("featureunion", 2) %>>% lrn("classif.rpart") %>>% po("unbranch", 1, id = "poub1"), classif.debug = lrn("classif.debug") %>>% po("unbranch", 1, id = "poub2"))))
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.rpart$learner_model)
x$param_set$values$branch.selection = "classif.debug"
expect_identical(x$base_learner(), x$graph_model$pipeops$classif.debug$learner_model)
x = as_learner(po("unbranch", 2, id = "dummyub1") %>>% ppl("branch", list(classif.rpart = lrn("classif.rpart") %>>% po("unbranch", 1, id = "poub1"), classif.debug = lrn("classif.debug") %>>% po("unbranch", 1, id = "poub2"))))
expect_error(x$base_learner(), "dummyub1 has multiple active inputs.*'input1'.*direct Graph input.*'input2'.*direct Graph input")
################################################################################
### The following graphs are bogus for multiple reasons. If our graph checks ###
### ever become more rigorous, these will have to be adjusted. ###
################################################################################
# pipeopbranch connected to unbranch through the same output in multiple routes.
g = (po("branch", c("classif.rpart", "classif.debug")) %>>% list(lrn("classif.rpart"), lrn("classif.debug")))$
add_pipeop(po("unbranch", 3))$
add_edge("classif.rpart", "unbranch", dst_channel = "input1")$
add_edge("classif.debug", "unbranch", dst_channel = "input2")$
add_edge("branch", "unbranch", src_channel = "classif.debug", dst_channel = "input3")
# classif.rpart route has only one connection --> works
expect_identical(as_learner(g)$base_learner(), g$pipeops$classif.rpart$learner_model)
g$param_set$values$branch.selection = "classif.debug"
expect_error(as_learner(g)$base_learner(), "PipeOpUnbranch unbranch.*multiple active inputs.*'input2'.*PipeOpBranch 'branch'.*'classif.debug'.*'input3'.*PipeOpBranch 'branch'.*'classif.debug'")
# live input from graph input is recognized correctly
g = (po("branch", c("classif.rpart", "classif.debug")) %>>% list(lrn("classif.rpart"), lrn("classif.debug")))$
add_pipeop(po("unbranch", 2, id = "poub1"))$
add_pipeop(po("unbranch", 1, id = "poub2"))$
add_pipeop(po("unbranch", 2))$
add_edge("classif.rpart", "poub1", dst_channel = "input1")$
add_edge("classif.debug", "poub2")$
add_edge("poub1", "unbranch", dst_channel = "input1")$
add_edge("poub2", "unbranch", dst_channel = "input2")
# error because poub1 gets two live inputs: from PipeOpBranch and from graph input
expect_error(as_learner(g)$base_learner(),
"poub1 has multiple active inputs.*'input1'.*active output 'classif.rpart'.*'input2'.*direct Graph input")
g$param_set$values$branch.selection = "classif.debug"
# now poub1 has only one live input, since PipeOpBranch's active output goes to classif.debug / poub2;
# however, the overall unbranch now has two active inputs
expect_error(as_learner(g)$base_learner(),
"PipeOpUnbranch unbranch has multiple active inputs.*'input1'.* from direct Graph input.* always active.*'input2'.* 'branch' active output 'classif.debug'")
g = Graph$new()$
add_pipeop(po("branch", c("classif.rpart", "classif.debug"), id = "branch1"))$
add_pipeop(po("branch", c("classif.rpart", "classif.debug"), id = "branch2"))$
add_pipeop(po("featureunion", id = "fu1"))$
add_pipeop(po("featureunion", id = "fu2"))$
add_pipeop(lrn("classif.rpart"))$
add_pipeop(lrn("classif.debug"))$
add_pipeop(po("unbranch", 2))$
add_edge("branch1", "fu1", src_channel = "classif.rpart")$
add_edge("branch2", "fu1", src_channel = "classif.rpart")$
add_edge("branch1", "fu2", src_channel = "classif.debug")$
add_edge("branch2", "fu2", src_channel = "classif.debug")$
add_edge("fu1", "classif.rpart")$
add_edge("fu2", "classif.debug")$
add_edge("classif.rpart", "unbranch", dst_channel = "input1")$
add_edge("classif.debug", "unbranch", dst_channel = "input2")
# this works as long as branch1 and branch2 flow in the same direction
expect_identical(as_learner(g)$base_learner(), g$pipeops$classif.rpart$learner_model)
g$param_set$set_values(branch1.selection = "classif.debug", branch2.selection = "classif.debug")
expect_identical(as_learner(g)$base_learner(), g$pipeops$classif.debug$learner_model)
g$param_set$set_values(branch1.selection = "classif.rpart", branch2.selection = "classif.debug")
## there are multiple possible error messages here: either at fu1, or at fu2.
## currently we find fu1 first because this is what the topological sort results in (fu1 gets checked first),
## but an error at fu2 would be equally valid.
expect_error(as_learner(g)$base_learner(),
"'branch2' inactive output.*'classif.rpart'.*'branch1' active output.*'classif.rpart'.*at PipeOp fu1|'branch1' inactive output.*'classif.debug'.*'branch2' active output.*'classif.debug'.*at PipeOp fu2")
g$add_pipeop(po("nop"))$add_edge("nop", "fu2")
g$param_set$set_values(branch1.selection = "classif.debug", branch2.selection = "classif.debug")
expect_identical(as_learner(g)$base_learner(), g$pipeops$classif.debug$learner_model)
g$param_set$set_values(branch1.selection = "classif.rpart", branch2.selection = "classif.rpart")
expect_error(as_learner(g)$base_learner(),
"'branch1' inactive output.*classif.debug.*'branch2' inactive output.*classif.debug.* in conflict with direct Graph input.*fu2")
# bogus GraphLearner with no PipeOpLearner inside.
expect_error(as_learner(po("nop"))$base_learner(), "No base learner found in Graph.")
bagger = as_learner(ppl("bagging", iterations = 1, lrn("classif.rpart"),
averager = po("classifavg", collect_multiplicity = TRUE)))
expect_identical(bagger$base_learner(), bagger$graph_model$pipeops$classif.rpart$learner_model)
bagger$train(tsk("iris"))
# ....$learner_model is a multiplicity, but base_learner() unpacks it.
expect_identical(bagger$base_learner(), bagger$graph_model$pipeops$classif.rpart$learner_model[[1]])
bagger$param_set$values$replicate.reps = 2
bagger$train(tsk("iris"))
expect_error(bagger$base_learner(), "Multiplicity that does not contain exactly one Learner")
metabagger = as_learner(ppl("bagging", iterations = 1,
ppl("bagging", iterations = 1, lrn("classif.rpart"),
averager = po("classifavg_1", collect_multiplicity = TRUE))$set_names(c("replicate", "subsample"), c("replicate_1", "subsample_1")),
averager = po("classifavg_2", collect_multiplicity = TRUE)))
expect_identical(metabagger$base_learner(), metabagger$graph_model$pipeops$classif.rpart$learner_model)
metabagger$train(tsk("iris"))
expect_identical(metabagger$base_learner(), metabagger$graph_model$pipeops$classif.rpart$learner_model[[1]][[1]])
metabagger$param_set$values$replicate.reps = 2
metabagger$train(tsk("iris"))
expect_error(metabagger$base_learner(), "Multiplicity that does not contain exactly one Learner")
metabagger$param_set$values$replicate.reps = 1
metabagger$train(tsk("iris"))
expect_identical(metabagger$base_learner(), metabagger$graph_model$pipeops$classif.rpart$learner_model[[1]][[1]])
metabagger$param_set$values$replicate_1.reps = 2
metabagger$train(tsk("iris"))
expect_error(metabagger$base_learner(), "Multiplicity that does not contain exactly one Learner")
# double-channel pipeop cascade: see there is no exponential explosion
gchain = chain_graphs(
lapply(1:20, function(i) ppl("branch", pos(paste0("nop_", c(2 * i, 2 * i + 1))), prefix_branchops = as.character(i))),
in_place = TRUE
)
glrn = as_learner(gchain %>>% ppl("branch", lrns(c("classif.rpart", "classif.debug"))))
expect_identical(glrn$base_learner(), glrn$graph_model$pipeops$classif.rpart$learner_model)
expect_identical(glrn$base_learner(recursive = 1, return_all = TRUE, resolve_branching = FALSE),
list(glrn$graph_model$pipeops$classif.rpart$learner_model, glrn$graph_model$pipeops$classif.debug$learner_model))
glrn = as_learner(ppl("branch", lrns(c("classif.rpart", "classif.debug"))) %>>% gchain)
expect_identical(glrn$base_learner(), glrn$graph_model$pipeops$classif.rpart$learner_model)
# without memoization the following would take a long time
expect_identical(glrn$base_learner(recursive = 1, return_all = TRUE, resolve_branching = FALSE),
list(glrn$graph_model$pipeops$classif.rpart$learner_model, glrn$graph_model$pipeops$classif.debug$learner_model))
glrn$base_learner()
# branch -> unbranch, unbranch -> unbranch
g = Graph$new()$
add_pipeop(po("branch", c("classif.rpart", "dummy1", "dummy2", "classif.debug"), id = "branch1"))$
add_pipeop(po("unbranch", 2, id = "unbranch1"))$
add_pipeop(po("unbranch", 2, id = "unbranch2"))$
add_pipeop(po("unbranch", 2, id = "unbranch3"))$
add_pipeop(lrn("classif.rpart"))$
add_pipeop(lrn("classif.debug"))$
add_edge("branch1", "classif.rpart", src_channel = "classif.rpart")$
add_edge("branch1", "classif.debug", src_channel = "classif.debug")$
add_edge("classif.rpart", "unbranch1", dst_channel = "input1")$
add_edge("classif.debug", "unbranch2", dst_channel = "input1")$
add_edge("unbranch1", "unbranch3", dst_channel = "input1")$
add_edge("unbranch2", "unbranch3", dst_channel = "input2")$
add_edge("branch1", "unbranch1", src_channel = "dummy1", dst_channel = "input2")$
add_edge("branch1", "unbranch2", src_channel = "dummy2", dst_channel = "input2")
expect_identical(as_learner(g)$base_learner(), g$pipeops$classif.rpart$learner_model)
g$param_set$values$branch1.selection = "classif.debug"
expect_identical(as_learner(g)$base_learner(), g$pipeops$classif.debug$learner_model)
g$param_set$values$branch1.selection = "dummy1"
expect_equal(g$train(1), list(unbranch3.output = 1))
expect_error(as_learner(g)$base_learner(), "No base learner found")
expect_identical(as_learner(g)$base_learner(recursive = 1, resolve_branching = FALSE, return_all = TRUE),
list(g$pipeops$classif.rpart$learner_model, g$pipeops$classif.debug$learner_model))
# infer task type and other things: use base_learner, but don't do that if things are given explicitly.
})
test_that("GraphLearner hashes", {
skip_if_not_installed("rpart")
learner1 = as_learner(ppl("robustify") %>>% lrn("regr.rpart"))
learner1dash = as_learner(ppl("robustify") %>>% lrn("regr.rpart"))
expect_string(learner1$hash)
expect_string(learner1$phash)
# to compare hashes, we need to set the function-valued hyperparameters equal;
# otherwise, they have different environments and may hash differently.
funparams = names(which(map_lgl(learner1$param_set$values, is.function)))
learner1dash$param_set$set_values(.values = learner1$param_set$values[funparams])
expect_equal(learner1$hash, learner1dash$hash)
expect_equal(learner1$phash, learner1dash$phash)
learner1dash$graph$pipeops$regr.rpart$param_set$values$xval = 1
expect_string(all.equal(learner1$hash, learner1dash$hash), "mismatch")
expect_equal(learner1$phash, learner1dash$phash)
learner2 = as_learner(po("pca") %>>% lrn("regr.rpart"))
expect_string(all.equal(learner1$hash, learner2$hash), "mismatch")
expect_string(all.equal(learner1$phash, learner2$phash), "mismatch")
learner1$id = "myid"
learner2$id = "myid"
expect_string(all.equal(learner1$hash, learner2$hash), "mismatch")
expect_string(all.equal(learner1$phash, learner2$phash), "mismatch")
# construction argument dependent hashes
expect_string(all.equal(po("copy", 2)$hash, po("copy", 3)$hash), "mismatch")
lr1 <- lrn("classif.rpart")
lr2 <- lrn("classif.rpart")$encapsulate("try", fallback = lrn("classif.rpart"))
expect_string(all.equal(lr1$hash, lr2$hash), "mismatch")
expect_string(all.equal(lr1$phash, lr2$phash), "mismatch")
lr1 <- as_learner(as_pipeop(lr1))
lr2 <- as_learner(as_pipeop(lr2))
expect_string(all.equal(lr1$hash, lr2$hash), "mismatch")
expect_string(all.equal(lr1$phash, lr2$phash), "mismatch")
lr1 <- as_learner(as_pipeop(lr1))
lr2 <- as_learner(as_pipeop(lr2))
expect_string(all.equal(lr1$hash, lr2$hash), "mismatch")
expect_string(all.equal(lr1$phash, lr2$phash), "mismatch")
})
test_that("validation, internal_valid_scores", {
skip_if_not_installed("rpart")
expect_error(as_pipeop(lrn("classif.debug", validate = 0.3)), "must either be")
# None of the Learners can do validation -> NULL
glrn1 = as_learner(as_graph(lrn("classif.rpart")))$train(tsk("iris"))
expect_false("validation" %in% glrn1$properties)
expect_null(glrn1$internal_valid_scores)
glrn2 = as_learner(as_graph(lrn("classif.debug")))
expect_true("validation" %in% glrn2$properties)
set_validate(glrn2, 0.2)
expect_equal(glrn2$validate, 0.2)
expect_equal(glrn2$graph$pipeops$classif.debug$learner$validate, "predefined")
glrn2$train(tsk("iris"))
expect_list(glrn2$internal_valid_scores, types = "numeric")
expect_equal(names(glrn2$internal_valid_scores), "classif.debug.acc")
set_validate(glrn2, NULL)
glrn2$train(tsk("iris"))
expect_null(glrn2$internal_valid_scores)
# No validation set specified --> No internal_valid_scores
expect_equal(
as_learner(as_graph(lrn("classif.debug")))$train(tsk("iris"))$internal_valid_scores,
NULL
)
glrn2 = as_learner(as_graph(lrn("classif.debug")))
})
test_that("internal_tuned_values", {
skip_if_not_installed("rpart")
# no internal tuning support -> NULL
task = tsk("iris")
glrn1 = as_learner(as_graph(lrn("classif.rpart")))$train(task)
expect_false("internal_tuning" %in% glrn1$properties)
expect_null(glrn1$internal_tuned_values)
# learner wQ
# ith internal tuning
glrn2 = as_learner(as_graph(lrn("classif.debug")))
expect_true("internal_tuning" %in% glrn2$properties)
expect_null(glrn2$internal_tuned_values)
glrn2$train(task)
expect_equal(glrn2$internal_tuned_values, named_list())
glrn2$param_set$set_values(classif.debug.early_stopping = TRUE, classif.debug.iter = 1000)
set_validate(glrn2, 0.2)
glrn2$train(task)
expect_equal(names(glrn2$internal_tuned_values), "classif.debug.iter")
})
test_that("set_validate", {
glrn = as_learner(as_pipeop(lrn("classif.debug", validate = "predefined")))
set_validate(glrn, "test")
expect_equal(glrn$validate, "test")
expect_equal(glrn$graph$pipeops$classif.debug$learner$validate, "predefined")
set_validate(glrn, NULL)
expect_null(glrn$validate)
expect_null(glrn$graph$pipeops$classif.debug$learner$validate)
set_validate(glrn, 0.2, ids = "classif.debug")
expect_equal(glrn$validate, 0.2)
expect_equal(glrn$graph$pipeops$classif.debug$learner$validate, "predefined")
glrn = as_learner(ppl("branch", list(lrn("classif.debug"), lrn("classif.debug", id = "final"), lrn("classif.featureless"))))
set_validate(glrn, 0.3, ids = c("classif.debug", "final"))
expect_equal(glrn$validate, 0.3)
expect_equal(glrn$graph$pipeops$classif.debug$learner$validate, "predefined")
expect_equal(glrn$graph$pipeops$final$learner$validate, "predefined")
expect_error(set_validate(glrn, 0.2, ids = "classif.featureless"))
glrn = as_learner(ppl("stacking", list(lrn("classif.debug"), lrn("classif.featureless")),
lrn("classif.debug", id = "final")))
glrn2 = as_learner(po("learner", glrn, id = "polearner"))
set_validate(glrn2, validate = 0.25, ids = "polearner", args = list(polearner = list(ids = "final")))
expect_equal(glrn2$validate, 0.25)
expect_equal(glrn2$graph$pipeops$polearner$learner$validate, "predefined")
expect_equal(glrn2$graph$pipeops$polearner$learner$graph$pipeops$final$learner$validate, "predefined")
expect_null(glrn2$graph$pipeops$polearner$learner$graph$pipeops$classif.debug$learner$validate)
# graphlearner in graphlearner: failure handling
glrn = as_learner(po("pca") %>>% lrn("classif.debug"))
po_glrn = as_pipeop(glrn)
po_glrn$id = "po_glrn"
gglrn = as_learner(po_glrn)
expect_error(
set_validate(gglrn, validate = "test", args = list(po_glrn = list(ids = "pca"))),
"Trying to heuristically reset"
)
expect_null(gglrn$validate)
# base_learner is not final learner
glrn = as_learner(lrn("classif.debug") %>>% po("nop"))
set_validate(glrn, 0.3)
expect_equal(glrn$graph$pipeops$classif.debug$validate, "predefined")
set_validate(glrn, NULL)
expect_null(glrn$graph$pipeops$classif.debug$validate)
expect_null(glrn$validate)
# args and args_all
bglrn = as_learner(ppl("branch", list(lrn("classif.debug", id = "d1"), lrn("classif.debug", id = "d2"))))
obj = as_pipeop(bglrn)
obj$id = "po_glrn"
gglrn = as_learner(obj)
# args
set_validate(gglrn, validate = 0.2, args = list(po_glrn = list(ids = "d1")))
expect_equal(gglrn$graph$pipeops[[1L]]$learner$graph$pipeops$d1$validate, "predefined")
expect_null(gglrn$graph$pipeops[[1L]]$learner$graph$pipeops$d2$validate)
# args all
gglrn = as_learner(obj)
set_validate(gglrn, validate = 0.2, args_all = list(ids = "d1"))
expect_equal(gglrn$graph$pipeops[[1L]]$learner$graph$pipeops$d1$validate, "predefined")
expect_null(gglrn$graph$pipeops[[1L]]$learner$graph$pipeops$d2$validate)
})
test_that("marshal", {
task = tsk("iris")
glrn = as_learner(as_graph(lrn("classif.debug")))
glrn$train(task)
p1 = glrn$predict(task)
glrn$marshal()
expect_true(glrn$marshaled)
expect_true(is_marshaled_model(glrn$state$model$marshaled$classif.debug))
glrn$unmarshal()
expect_false(is_marshaled_model(glrn$state$model$marshaled$classif.debug))
expect_class(glrn$model, "graph_learner_model")
expect_false(is_marshaled_model(glrn$state$model$marshaled$classif.debug$model))
p2 = glrn$predict(task)
expect_equal(p1$response, p2$response)
# checks that it is marshalable
glrn$train(task)
expect_learner(glrn, task)
})
test_that("marshal has no effect when nothing needed marshaling", {
skip_if_not_installed("rpart")
task = tsk("iris")
glrn = as_learner(as_graph(lrn("classif.rpart")))
glrn$train(task)
glrn$marshal()
expect_class(glrn$marshal()$model, "graph_learner_model")
expect_class(glrn$unmarshal()$model, "graph_learner_model")
expect_learner(glrn, task = task)
})
# in case Debug ever gets these properties, we remove them here.
DebugBasic = R6Class("DebugBasic", inherit = LearnerClassifDebug,
public = list(
initialize = function(...) {
super$initialize(...)
self$properties = setdiff(self$properties, c("importance", "selected_features", "loglik", "oob_error"))
},
importance = function() {
return(sapply(self$state$feature_names, function(i) 1))
}
))
test_that("GraphLearner Importance", {
DebugWithImportance = R6Class("DebugWithImportance", inherit = LearnerClassifDebug,
public = list(
initialize = function(...) {
super$initialize(...)
self$properties = c(setdiff(self$properties, c("importance", "selected_features", "loglik", "oob_error")), "importance")
},
importance = function() {
return(sapply(self$state$feature_names, function(i) 1))
}
))
g_basic = GraphLearner$new(Graph$new()$add_pipeop(DebugBasic$new()))
g_importance = GraphLearner$new(Graph$new()$add_pipeop(DebugWithImportance$new()))
expect_false("importance" %in% g_basic$properties)
expect_true("importance" %in% g_importance$properties)
expect_false(any(c("loglik", "oob_error") %in% g_basic$properties))
expect_false(any(c("loglik", "oob_error") %in% g_importance$properties))
expect_error(g_basic$importance(), "does not implement.*importance")
g_importance$train(tsk("iris"))
expect_equal(g_importance$importance(), c(Petal.Length = 1, Petal.Width = 1, Sepal.Length = 1, Sepal.Width = 1))
g_bagging = as_learner(ppl("bagging", DebugWithImportance$new(), averager = po("classifavg", collect_multiplicity = TRUE)))
expect_true("importance" %in% g_bagging$properties)
g_bagging$train(tsk("iris"))
expect_true("importance" %in% g_bagging$properties)
expect_error(g_bagging$importance(), "Multiplicity that does not contain exactly one Learner")
g_bagging$param_set$values$replicate.reps = 1
g_bagging$train(tsk("iris"))
expect_equal(g_bagging$importance(), c(Petal.Length = 1, Petal.Width = 1, Sepal.Length = 1, Sepal.Width = 1))
# * test importance with feature selection
g_fs = as_learner(po("select", selector = selector_grep("Sepal")) %>>% DebugWithImportance$new())
g_fs$train(tsk("iris"))
expect_equal(g_fs$importance(), c(Sepal.Length = 1, Sepal.Width = 1))
# branching
lbasic = DebugBasic$new()
lbasic$id = "basic"
g_branch = as_learner(ppl("branch", list(basic = lbasic, importance = DebugWithImportance$new())))
expect_true("importance" %in% g_branch$properties)
g_branch$train(tsk("iris"))
expect_error(g_branch$importance(), "does not implement.*importance")
g_branch$param_set$values$branch.selection = "importance"
g_branch$train(tsk("iris"))
expect_equal(g_branch$importance(), c(Petal.Length = 1, Petal.Width = 1, Sepal.Length = 1, Sepal.Width = 1))
g_nested = as_learner(as_graph(as_learner(as_graph(DebugWithImportance$new()))))
expect_equal(
g_nested$train(tsk("iris"))$importance(),
c(Petal.Length = 1, Petal.Width = 1, Sepal.Length = 1, Sepal.Width = 1)
)
expect_true("importance" %in% g_nested$properties)
g_nested_basic = as_learner(as_graph(as_learner(as_graph(DebugBasic$new()))))
expect_false("importance" %in% g_nested_basic$properties)
expect_false(any(c("loglik", "oob_error") %in% g_nested_basic$properties))
expect_false(any(c("loglik", "oob_error") %in% g_nested$properties))
})
test_that("GraphLearner Selected Features", {
DebugWithSelectedFeatures = R6Class("DebugWithFeatsel", inherit = LearnerClassifDebug,
public = list(
initialize = function(...) {
super$initialize(...)
self$properties = c(setdiff(self$properties, c("importance", "selected_features", "loglik", "oob_error")), "selected_features")
},
selected_features = function() {
return(self$state$feature_names[[1]])
}
))
g_basic = GraphLearner$new(Graph$new()$add_pipeop(DebugBasic$new()))
g_featsel = GraphLearner$new(Graph$new()$add_pipeop(DebugWithSelectedFeatures$new()))
expect_true("selected_features" %in% g_basic$properties)
expect_true("selected_features" %in% g_featsel$properties)
expect_false(any(c("importance", "loglik", "oob_error") %in% g_featsel$properties))
expect_false(any(c("importance", "loglik", "oob_error") %in% g_featsel$properties))
expect_error(g_basic$selected_features(), "does not implement.*selected_features.*impute_selected_features.*TRUE")
g_basic$impute_selected_features = TRUE
expect_error(g_basic$selected_features(), "No model stored.*classif.debug.*Graph.*classif.debug")
g_basic$train(tsk("iris"))
expect_equal(g_basic$selected_features(), tsk("iris")$feature_names)
g_featsel$train(tsk("iris"))
expect_equal(g_featsel$selected_features(), tsk("iris")$feature_names[[1]])
# does not accidentally impute if it doesn't need to
g_featsel$impute_selected_features = TRUE
expect_equal(g_featsel$selected_features(), tsk("iris")$feature_names[[1]])
g_bagging = as_learner(ppl("bagging", DebugWithSelectedFeatures$new(), averager = po("classifavg", collect_multiplicity = TRUE)))
expect_true("selected_features" %in% g_bagging$properties)
g_bagging$train(tsk("iris"))
expect_true("selected_features" %in% g_bagging$properties)
expect_equal(g_bagging$selected_features(), tsk("iris")$feature_names[[1]])
g_fs = as_learner(po("select", selector = selector_grep("Sepal")) %>>% DebugWithSelectedFeatures$new())
g_fs$train(tsk("iris"))
expect_equal(g_fs$selected_features(), "Sepal.Length")
g_fs_basic = as_learner(po("select", selector = selector_grep("Sepal")) %>>% DebugBasic$new())
g_fs_basic$train(tsk("iris"))
g_fs_basic$impute_selected_features = TRUE
expect_equal(g_fs_basic$selected_features(), c("Sepal.Length", "Sepal.Width"))
# branching
lbasic = DebugBasic$new()
lbasic$id = "basic"
g_branch = as_learner(ppl("branch", list(basic = lbasic, fs = DebugWithSelectedFeatures$new(), featureless = lrn("classif.featureless"))))
expect_true("selected_features" %in% g_branch$properties)
g_branch$train(tsk("iris"))
expect_error(g_branch$selected_features(), "does not implement.*selected_features.*impute_selected_features.*TRUE")
g_branch$impute_selected_features = TRUE
expect_equal(g_branch$selected_features(), tsk("iris")$feature_names)
g_branch$param_set$values$branch.selection = "fs"
g_branch$train(tsk("iris"))
expect_equal(g_branch$selected_features(), tsk("iris")$feature_names[[1]])
g_branch$param_set$values$branch.selection = "featureless"
g_branch$train(tsk("iris"))
expect_equal(g_branch$selected_features(), character(0))
g_nested = as_learner(as_graph(as_learner(as_graph(DebugWithSelectedFeatures$new()))))
expect_equal(
g_nested$train(tsk("iris"))$selected_features(),
tsk("iris")$feature_names[[1]]
)
g_nested = as_learner(as_graph(as_learner(as_graph(DebugBasic$new()))))
expect_error(g_nested$train(tsk("iris"))$selected_features(), " classif\\.debug .*selected_features.*impute_selected_features to TRUE")
# need to turn on imputation in the innermost graph
g_nested$graph$pipeops$classif.debug$learner$impute_selected_features = TRUE
expect_equal(
g_nested$train(tsk("iris"))$selected_features(),
tsk("iris")$feature_names
)
# feature union unions selected features
g_avg = as_learner(list(po("select", selector = selector_grep("Sepal")) %>>% lbasic, DebugWithSelectedFeatures$new(), lrn("classif.featureless")) %>>% po("classifavg", 3))
g_avg$train(tsk("iris"))
expect_error(g_avg$selected_features(), "does not implement.*selected_features.*impute_selected_features.*TRUE")
g_avg$impute_selected_features = TRUE
# Sepal.* from lbasic, Petal.Length from DebugWithSelectedFeatures, nothing from featureless
expect_equal(g_avg$selected_features(), c("Sepal.Length", "Sepal.Width", "Petal.Length"))
})
test_that("GraphLearner other properties", {
has_loglik = "loglik" %in% mlr_reflections$learner_properties[["classif"]]
if (!has_loglik) skip()
DebugWithProperties = R6Class("DebugWithProperties", inherit = LearnerClassifDebug,
public = list(
initialize = function(...) {
super$initialize(...)
self$properties = c(
setdiff(self$properties, c("importance", "selected_features", "loglik", "oob_error")),
"loglik", "oob_error")
},
loglik = function() {
1
},
oob_error = function() {
2
}
))
g_basic = GraphLearner$new(Graph$new()$add_pipeop(DebugBasic$new()))
g_properties = GraphLearner$new(Graph$new()$add_pipeop(DebugWithProperties$new()))
expect_false(any(c("loglik", "oob_error") %in% g_basic$properties))
expect_true(all(c("loglik", "oob_error") %in% g_properties$properties))
expect_error(g_basic$loglik(), "does not implement.*loglik")
expect_error(g_basic$oob_error(), "does not implement.*oob_error")
g_properties$train(tsk("iris"))
expect_equal(g_properties$loglik(), 1)
expect_equal(g_properties$oob_error(), 2)
g_bagging = as_learner(ppl("bagging", DebugWithProperties$new(), averager = po("classifavg", collect_multiplicity = TRUE)))
expect_true(all(c("loglik", "oob_error") %in% g_bagging$properties))
g_bagging$train(tsk("iris"))
expect_true(all(c("loglik", "oob_error") %in% g_bagging$properties))
expect_error(g_bagging$loglik(), "Multiplicity that does not contain exactly one Learner")
expect_error(g_bagging$oob_error(), "Multiplicity that does not contain exactly one Learner")
g_bagging$param_set$values$replicate.reps = 1
g_bagging$train(tsk("iris"))
expect_equal(g_bagging$loglik(), 1)
expect_equal(g_bagging$oob_error(), 2)
# branching
lbasic = DebugBasic$new()
lbasic$id = "basic"
g_branch = as_learner(ppl("branch", list(basic = lbasic, properties = DebugWithProperties$new())))
expect_true(all(c("loglik", "oob_error") %in% g_branch$properties))
g_branch$train(tsk("iris"))
expect_error(g_branch$loglik(), "does not implement.*loglik")
expect_error(g_branch$oob_error(), "does not implement.*oob_error")
g_branch$param_set$values$branch.selection = "properties"
g_branch$train(tsk("iris"))
expect_equal(g_branch$loglik(), 1)
expect_equal(g_branch$oob_error(), 2)
g_nested = as_learner(as_graph(as_learner(as_graph(DebugWithProperties$new()))))
expect_equal(
g_nested$train(tsk("iris"))$loglik(),
1
)
expect_equal(
g_nested$train(tsk("iris"))$oob_error(),
2
)
expect_true(all(c("loglik", "oob_error") %in% g_nested$properties))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.