The reward_model, contextual_policy, and
best_arm arguments of kpe(),
train_eval(), and papd() each accept either a
character string naming a built-in learner or a user-supplied object
that implements the required fit / predict
methods.
Prerequisites
See vignette("getting-started", package = "kpe") for
installation and the full learner/backend table. The runnable example
below uses only base-R learners ("linear",
"simple") plus a user-supplied reward object, so it needs
no extra packages. The optional xgboost snippet near the
end requires the xgboost package.
Built-in strings
| slot | strings |
|---|---|
reward_model |
"random_forest", "linear",
"ridge", "lasso"
|
contextual_policy |
"policy_tree", "policy_forest",
"linear"
|
best_arm |
"ips", "simple"
|
User-supplied-object contracts
A user-supplied learner must be an R list with
fit and predict elements matching the
following signatures.
# Reward model
list(
fit = function(X, y) { ... ; invisible(NULL) },
predict = function(X) numeric_vector
)
# X is an (n, d + 1) numeric matrix whose last column is the observed
# action. predict returns a length-n numeric vector of predicted
# outcomes.
# Contextual policy
list(
fit = function(X, A, Y, n_actions) { ... ; invisible(NULL) },
predict = function(X) integer_vector
)
# predict returns a length-n integer vector of actions in
# {0, ..., n_actions - 1}.
# Best-arm (non-contextual)
list(
fit = function(A, Y, propensities, n_actions) { ... ; invisible(NULL) },
predict = function() integer_scalar
)
# predict returns a single integer action in {0, ..., n_actions - 1}.The same list instance is reused across folds, so
fit should reset any state it needs from the training
arguments — for example via a closure that assigns into its parent
environment with <<-.
Example: a user-supplied reward model
The learner below records the mean of y at fit time and
returns it as the reward prediction at predict time. It has no
statistical value; it is the minimal object that satisfies the
reward-model contract.
byo_reward <- local({
mu <- NULL
list(
fit = function(X, y) { mu <<- mean(y); invisible(NULL) },
predict = function(X) rep(mu, nrow(as.matrix(X)))
)
})
set.seed(0)
n <- 300
X <- matrix(runif(n * 2, -1, 1), ncol = 2)
A <- rbinom(n, 1, 0.5)
Y <- ifelse(X[, 1] >= 0, A, 0.5 * (1 - A)) + rnorm(n, sd = 0.3)
fit <- kpe(X, A, Y, propensity = 0.5,
n_shuffles = 4, n_folds = 6,
reward_model = byo_reward,
contextual_policy = "linear",
best_arm = "simple",
seed = 0)
print(fit)## K-Fold Personalization Estimator (kpe)
## n_samples = 300
## n_shuffles = 4, n_folds = 6
## psi = 0.2586 (SE 0.03006)
## 95% CI = [0.1997, 0.3175]
## p-value = 2.248e-16 (one-sided)
## policy stability = 0.9933
Example: wrapping an external regressor as a reward model
Any regressor that exposes fit(X, y) and
predict(X) can be adapted by assigning its fitted state in
the closure and calling predict at prediction time. The
snippet below wraps xgboost::xgboost (not a hard dependency
of kpe; load separately if required).
library(xgboost)
byo_xgb <- local({
model <- NULL
list(
fit = function(X, y) {
model <<- xgboost::xgboost(data = as.matrix(X), label = y,
nrounds = 50, verbose = 0)
invisible(NULL)
},
predict = function(X) {
as.numeric(stats::predict(model, as.matrix(X)))
}
)
})
fit <- kpe(X, A, Y, propensity = 0.5,
reward_model = byo_xgb, seed = 0)The same construction applies to a user-supplied
contextual_policy (providing
fit(X, A, Y, n_actions) and predict(X)
returning integer actions in {0, ..., n_actions - 1}) or a
user-supplied best_arm (providing
fit(A, Y, propensities, n_actions) and
predict() returning a single integer action).