Skip to content

Commit

Permalink
merge classif.liblinear
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Sonabend committed Oct 21, 2020
1 parent 340443c commit 5a18705
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 11 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export(LearnerClassifJ48)
export(LearnerClassifJRip)
export(LearnerClassifKSVM)
export(LearnerClassifLMT)
export(LearnerClassifLiblineaR)
export(LearnerClassifLiblineaRL1L2SVC)
export(LearnerClassifLiblineaRL1LogReg)
export(LearnerClassifLiblineaRL2L1SVC)
Expand Down
96 changes: 96 additions & 0 deletions R/learner_LiblineaR_classif_liblinear.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#' @title LiblineaR Classification Learner
#' @author be-marc
#' @name mlr_learners_classif.liblinear
#'
#' @template class_learner
#' @templateVar id classif.liblinear
#' @templateVar caller LiblineaR
#'
#' @details Type of SVC depends on `type` argument:
#'
#' * `0` – L2-regularized logistic regression (primal)
#' * `1` - L2-regularized L2-loss support vector classification (dual)
#' * `3` - L2-regularized L1-loss support vector classification (dual)
#' * `2` – L2-regularized L2-loss support vector classification (primal)
#' * `4` – Support vector classification by Crammer and Singer
#' * `5` - L1-regularized L2-loss support vector classification
#' * `6` - L1-regularized logistic regression
#' * `7` - L2-regularized logistic regression (dual)
#'
#' If number of records > number of features, `type = 2` is faster than `type = 1`
#' (Hsu et al. 2003).
#'
#' The default `epsilon` value depends on the `type` parameter, see [LiblineaR::LiblineaR].
#'
#' @export
#' @template seealso_learner
#' @template example
LearnerClassifLiblineaR = R6Class("LearnerClassifLiblineaR", # nolint
inherit = LearnerClassif,
public = list(

#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

ps = ParamSet$new(
params = list(
ParamInt$new(id = "type", default = 0, lower = 0, upper = 7, tags = "train"),
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
ParamDbl$new(id = "epsilon", lower = 0, tags = "train"),
ParamDbl$new(id = "bias", default = 1, tags = "train"),
ParamInt$new(id = "cross", default = 0L, lower = 0L, tags = "train"),
ParamLgl$new(id = "verbose", default = FALSE, tags = "train"),
ParamUty$new(id = "wi", default = NULL, tags = "train"),
ParamLgl$new(id = "findC", default = FALSE, tags = "train"),
ParamLgl$new(id = "useInitC", default = TRUE, tags = "train")
)
)

# 50 is an arbitrary choice here
ps$add_dep("findC", "cross", CondAnyOf$new(seq(2:50)))
ps$add_dep("useInitC", "findC", CondEqual$new(TRUE))

super$initialize(
id = "classif.liblinear",
packages = "LiblineaR",
feature_types = "numeric",
predict_types = c("response", "prob"),
param_set = ps,
properties = c("twoclass", "multiclass"),
man = "mlr3extralearners::mlr_learners_classif.liblinear"
)
}
),
private = list(
.train = function(task) {
pars = self$param_set$get_values(tags = "train")
data = task$data()
train = task$data(cols = task$feature_names)
target = task$truth()

type = ifelse(is.null(pars$type), 0, pars$type)
pars = pars[names(pars) != "type"]

invoke(LiblineaR::LiblineaR, data = train, target = target, type = type, .args = pars)
},

.predict = function(task) {
newdata = task$data(cols = task$feature_names)

type = ifelse(is.null(self$param_set$values$type), 0, self$param_set$values$type)

if (type %nin% c(0, 6, 7) && self$predict_type == "prob") {
stop("'prob' predict_type only possible if `type` is `0`, `6`, or `7`.")
}

if (self$predict_type == "prob") {
return(list(prob = invoke(predict, self$model, newx = newdata, proba = TRUE)$probabilities))
} else {
return(list(response = invoke(predict, self$model, newx = newdata)$predictions))
}
}
)
)

.extralrns_dict$add("classif.liblinear", LearnerClassifLiblineaR)
3 changes: 3 additions & 0 deletions R/learner_LiblineaR_classif_liblinearl1l2svc.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ LearnerClassifLiblineaRL1L2SVC = R6Class("LearnerClassifLiblineaRL1L2SVC",
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `classif.liblinear` with `type = 5`.") # nolint

ps = ParamSet$new(
params = list(
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
Expand Down
3 changes: 3 additions & 0 deletions R/learner_LiblineaR_classif_liblinearl1logreg.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ LearnerClassifLiblineaRL1LogReg = R6Class("LearnerClassifLiblineaRL1LogReg", # n
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `classif.liblinear` with `type = 6`.") # nolint

ps = ParamSet$new(
params = list(
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
Expand Down
3 changes: 3 additions & 0 deletions R/learner_LiblineaR_classif_liblinearl2l1svc.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ LearnerClassifLiblineaRL2L1SVC = R6Class("LearnerClassifLiblineaRL2L1SVC",
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `classif.liblinear` with `type = 3`.") # nolint

ps = ParamSet$new(
params = list(
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
Expand Down
3 changes: 3 additions & 0 deletions R/learner_LiblineaR_classif_liblinearl2l2svc.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ LearnerClassifLiblineaRL2L2SVC = R6Class("LearnerClassifLiblineaRL2L2SVC", # nol
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `classif.liblinear` with `type = 1` or `2`.") # nolint

ps = ParamSet$new(
params = list(
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
Expand Down
3 changes: 3 additions & 0 deletions R/learner_LiblineaR_classif_liblinearl2logreg.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ LearnerClassifLiblineaRL2LogReg = R6Class("LearnerClassifLiblineaRL2LogReg", # n
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `classif.liblinear` with `type = 0`.") # nolint

ps = ParamSet$new(
params = list(
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
Expand Down
2 changes: 2 additions & 0 deletions R/learner_LiblineaR_classif_liblinearmulticlasssvc.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ LearnerClassifLiblineaRMultiClassSVC = R6Class("LearnerClassifLiblineaRMultiClas
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `classif.liblinear` with `type = 4`.") # nolint

ps = ParamSet$new(
params = list(
ParamDbl$new(id = "cost", default = 1, lower = 0, tags = "train"),
Expand Down
6 changes: 1 addition & 5 deletions R/learner_LiblineaR_regr_liblinear.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,7 @@ LearnerRegrLiblineaR = R6Class("LearnerRegrLiblineaR",
train = task$data(cols = task$feature_names)
target = task$truth()

if (is.null(pars$type)) {
type = 11
} else {
type = as.numeric(pars$type)
}
type = ifelse(is.null(pars$type), 11, pars$type)
pars = pars[names(pars) != "type"]

invoke(LiblineaR::LiblineaR, data = train, target = target, type = type, .args = pars)
Expand Down
2 changes: 1 addition & 1 deletion R/learner_LiblineaR_regr_liblinearl2l1svr.R
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ LearnerRegrLiblineaRL2L1SVR = R6Class("LearnerRegrLiblineaRL2L1SVR",
#' Creates a new instance of this [R6][R6::R6Class] class.
initialize = function() {

warning("Deprecated. In the future please use `regr.liblinear` with `type = 11` or `type = 12`.") # nolint
warning("Deprecated. In the future please use `regr.liblinear` with `type = 13`.") # nolint

ps = ParamSet$new(
params = list(
Expand Down
33 changes: 33 additions & 0 deletions inst/paramtest/test_paramtest_LiblineaR_classif_liblinear.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
library(mlr3extralearners)
install_learners("classif.liblinear")

test_that("classif.liblinear", {
learner = lrn("classif.liblinear")
fun = LiblineaR::LiblineaR
exclude = c(
"data", # handled by mlr3
"target", # handled by mlr3
"svr_eps" # only for regression
)

ParamTest = run_paramtest(learner, fun, exclude)
expect_true(ParamTest, info = paste0(
"Missing parameters:",
paste0("- '", ParamTest$missing, "'", collapse = "")))
})

test_that("classif.liblinear predict", {
learner = lrn("classif.liblinear")
fun = LiblineaR:::predict.LiblineaR
exclude = c(
"object", # handled internally
"newx", # handled internally
"proba", # handled internally
"decisionValues" # handled internally
)

ParamTest = run_paramtest(learner, fun, exclude)
expect_true(ParamTest, info = paste0(
"Missing parameters:",
paste0("- '", ParamTest$missing, "'", collapse = "")))
})
23 changes: 18 additions & 5 deletions inst/paramtest/test_paramtest_LiblineaR_regr_liblinear.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@ test_that("regr.liblinear", {

ParamTest = run_paramtest(learner, fun, exclude)
expect_true(ParamTest, info = paste0(
"
Missing parameters:
",
paste0("- '", ParamTest$missing, "'", collapse = "
")))
"Missing parameters:",
paste0("- '", ParamTest$missing, "'", collapse = "")))
})

test_that("regr.liblinear predict", {
learner = lrn("regr.liblinear")
fun = LiblineaR:::predict.LiblineaR
exclude = c(
"object", # handled internally
"newx", # handled internally
"proba", # classif only
"decisionValues" # classif only
)

ParamTest = run_paramtest(learner, fun, exclude)
expect_true(ParamTest, info = paste0(
"Missing parameters:",
paste0("- '", ParamTest$missing, "'", collapse = "")))
})
111 changes: 111 additions & 0 deletions man/mlr_learners_classif.liblinear.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/testthat/test_LiblineaR_classif_liblinear.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
install_learners("classif.liblinear")

test_that("autotest", {
learner = LearnerClassifLiblineaR$new()
expect_learner(learner)
result = run_autotest(learner)
expect_true(result, info = result$error)
})

0 comments on commit 5a18705

Please sign in to comment.