| Type: | Package |
| Title: | Multi-Task Learning with Orthogonal Constraints |
| Version: | 0.1.0 |
| Description: | Fits regularised multi-task learning models where relationships between tasks are controlled via orthogonality or disjoint-support constraints. Supports regression, binary classification, and censored survival data. In survival mode, time-to-event outcomes are converted into binary labels at user-defined thresholds, enabling the discovery of features with time-varying effects that standard proportional-hazards models cannot detect. Implements the penalty described in Vervier et al. (2014) https://hal.science/hal-00985654. |
| License: | GPL-3 |
| Encoding: | UTF-8 |
| Imports: | parallel, doParallel, foreach, ggplot2, rlang, stats |
| VignetteBuilder: | knitr |
| Suggests: | knitr, glmnet, testthat (≥ 3.0.0), survival, rmarkdown |
| RoxygenNote: | 7.3.3 |
| Depends: | R (≥ 4.0.0) |
| NeedsCompilation: | no |
| Packaged: | 2026-08-07 13:45:33 UTC; Shadow |
| Author: | Kevin Vervier [aut, cre], Novartis Pharma AG [cph, fnd] |
| Maintainer: | Kevin Vervier <kevin.vervier@novartis.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-08-23 10:10:02 UTC |
orthoMTL: Multi-Task Learning with Orthogonal Constraints
Description
Fits regularised multi-task learning models where relationships between tasks are controlled via orthogonality or disjoint-support constraints. Supports regression, classification, and censored survival data.
Overview
orthoMTL implements a penalised multi-task learning framework where the columns of the coefficient matrix are encouraged to be orthogonal (or have disjoint supports). In survival mode, time-to-event data is converted into binary classification tasks at user-defined thresholds, with censored observations masked in the loss computation.
The package is the successor to the orthopen package and extends
it with survival analysis, elastic-net sparsity, cross-validation,
bootstrap inference, and a visualisation suite.
Key Functions
Modelling:
-
orthoMTL— Core solver (regression, classification, survival) -
predict.orthoMTL— Predictions with column alignment and monotonicity projection -
coef.orthoMTL— Extract coefficient matrix
Survival Utilities:
-
create_longitudinal_labels— Survival to binary label conversion -
create_indicator_matrix— Censoring indicator matrix -
create_constraint_matrix— Diffusion constraint matrix for temporal tasks
Cross-Validation and Inference:
-
cv_orthoMTL— Parallel hyperparameter grid search -
bootstrap_orthoMTL— Bootstrap coefficient variability and null comparison -
cindex_mtl— Concordance index for multi-task predictions
Visualisation:
-
plot_heatmap— Coefficient heatmap -
plot_correlation— Task distance map -
plot_prediction— Prediction swimmer plot -
plot_bootstrap— Bootstrap real vs null comparison
Simulation:
-
simulate_mtl— Simulated survival data with time-varying effects
Algorithm
The core optimisation problem is:
\min_W \frac{1}{2n}\|XW - Y\|^2_{obs} +
\lambda\left[\frac{1-\alpha}{2}\sum_{s,t} K_{st}|W_s^\top W_t| +
\alpha\|W\|_1\right]
where the loss is computed only on non-censored entries, K encodes
task relationships, \lambda controls the penalty strength, and
\alpha \in [0,1] mixes the orthogonality penalty (\alpha=0)
with Lasso sparsity (\alpha=1).
Getting Started
See vignette("introduction", package = "orthoMTL") for a complete
worked example using simulated data.
Author(s)
Maintainer: Kevin Vervier kevin.vervier@novartis.com
Other contributors:
Novartis Pharma AG [copyright holder, funder]
References
Vervier, K., Mahe, P., d'Aspremont, A., Veyrieras, J.-B., and Vert, J.-P. (2014). On Learning Matrices with Orthogonal Columns or Disjoint Supports. ECML-PKDD 2014. https://hal.science/hal-00985654
Build a normalised effect template vector
Description
Build a normalised effect template vector
Usage
.make_template(type, n_tasks)
Arguments
type |
Template type: "early", "late", "constant", "increasing", "decreasing". |
n_tasks |
Number of tasks/thresholds. |
Value
Numeric vector of length n_tasks, normalised so
max(abs(values)) == 1.
Classification Accuracy for Multi-Task Predictions
Description
Pooled fraction of correctly classified non-NA cells, for
orthoMTL fits in classification mode (logistic = TRUE).
A cell is positive when its true label is > 0 and predicted
positive when its score is > 0. This works for both the
\{-1, +1\} encoding the solver optimises and a \{0, 1\}
encoding, and for raw "link" scores or "response"
probabilities (threshold 0.5 corresponds to a link of 0... see note).
Usage
accuracy_mtl(true.label.mat, pred.label.mat, threshold = 0)
Arguments
true.label.mat |
A numeric matrix of true responses
( |
pred.label.mat |
A numeric matrix of predictions of the same
dimensions (as produced by |
threshold |
Decision threshold applied to |
Value
A single numeric value in [0, 1] (higher is better).
See Also
Examples
set.seed(1)
Y <- matrix(sample(c(-1, 1), 30, replace = TRUE), 10, 3)
P <- Y * abs(matrix(rnorm(30), 10, 3)) # mostly correct signs
accuracy_mtl(Y, P)
Area Under the ROC Curve for Multi-Task Predictions
Description
Pooled AUC over every non-NA cell, computed via the
Mann-Whitney U statistic (with 0.5 credit for ties), for
orthoMTL fits in classification mode. The positive class is
defined by true label > 0. AUC is invariant to monotone
transforms, so raw "link" scores and "response"
probabilities give identical results.
Usage
auc_mtl(true.label.mat, pred.label.mat)
Arguments
true.label.mat |
A numeric matrix of true responses
( |
pred.label.mat |
A numeric matrix of predictions of the same
dimensions (as produced by |
Value
A single numeric value in [0, 1] (higher is better;
0.5 = random).
See Also
Examples
set.seed(1)
Y <- matrix(sample(c(-1, 1), 30, replace = TRUE), 10, 3)
P <- Y + matrix(rnorm(30), 10, 3)
auc_mtl(Y, P)
Bootstrap Inference for orthoMTL Coefficients
Description
Estimates coefficient variability and statistical relevance by comparing bootstrapped models (real signal) against null models (permuted outcomes). This two-pronged approach answers: (1) how stable is each coefficient across resamples, and (2) is each coefficient distinguishable from what would be obtained by chance.
Usage
bootstrap_orthoMTL(
X,
Y,
lambda = 1,
alpha = 0,
step_size = 0.1,
K = NULL,
disjoint = FALSE,
schedule = c("sqrt", "log", "const", "linear"),
survival = FALSE,
censored.mat = NULL,
n_repeats = 100,
n_cores = 2,
seed = NULL,
verbose = TRUE
)
Arguments
X |
A numeric matrix of predictor variables with dimensions
|
Y |
A numeric matrix of response labels with dimensions
|
lambda |
Regularisation parameter for the orthogonal penalty. |
alpha |
Elastic-net mixing parameter in |
step_size |
Step size for gradient descent. Default: |
K |
Constraint matrix of dimensions
|
disjoint |
Logical. Enforce disjoint supports? Default:
|
schedule |
Character; the gradient-step decay schedule passed to
|
survival |
Logical. Use censored survival loss? Default:
|
censored.mat |
A numeric indicator matrix of dimensions
|
n_repeats |
Number of bootstrap/permutation repeats. Default:
|
n_cores |
Number of cores for parallel execution. Default:
|
seed |
Optional base random seed. Default: |
verbose |
Logical. Print progress information? Default:
|
Details
Real bootstrap: For each repeat, rows of X, Y,
and censored.mat are resampled with replacement. The
model is refit with identical hyperparameters. This produces a
distribution of coefficient values reflecting estimation variability.
Null permutation: For each repeat, rows of Y and
censored.mat are permuted without replacement while
X remains fixed. This breaks the association between features
and outcomes, producing a null distribution of coefficients.
Comparing real vs null distributions for each feature and task
indicates whether observed coefficients are distinguishable from
noise. Visualise with plot_bootstrap.
Value
An object of class "bootstrap_orthoMTL" containing:
- results
A tidy
data.framewith columnsid(feature name),time(task/threshold),coeff(coefficient value),group("real"or"null"), andrepeat_id(integer).- coefficients_real
A list of
n_repeatscoefficient matrices (eachp x numTasks).- coefficients_null
A list of
n_repeatscoefficient matrices from permuted outcomes.- obj_real
Numeric vector of final objective values for real bootstrap models.
- obj_null
Numeric vector of final objective values for null permutation models.
- n_repeats
Number of repeats.
- n_features
Number of features.
- n_tasks
Number of tasks.
- feature_names
Character vector of feature names.
- task_names
Character vector of task names.
- call
The matched function call.
See Also
Examples
set.seed(42)
n <- 30; p <- 5; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
SurvTime <- rexp(n, rate = 0.1)
Event <- rbinom(n, 1, 0.7)
thresholds <- c(4, 6, 10)
Y <- create_longitudinal_labels(SurvTime, Event, thresholds)
W <- create_indicator_matrix(Y)
K <- create_constraint_matrix(n_tasks)
boot_res <- bootstrap_orthoMTL(
X = X, Y = Y, lambda = 1e-3, step_size = 0.1,
K = K, survival = TRUE, censored.mat = W,
n_repeats = 5, n_cores = 1, verbose = FALSE
)
print(boot_res)
head(boot_res$results)
Concordance Index for Multi-Task Predictions
Description
Computes a concordance index (C-index) adapted for the multi-task survival framework. Predictions across tasks are aggregated by row-sum to produce a single score per patient, then concordance is evaluated over pairs where at least one member has a fully observed outcome.
Usage
cindex_mtl(true.label.mat, pred.label.mat)
Arguments
true.label.mat |
A numeric matrix of true response labels with
dimensions |
pred.label.mat |
A numeric matrix of predicted response values
with dimensions |
Details
The effective survival time for each patient is derived as the highest task index where the true label is positive (i.e., the last threshold at which the patient was progression-free).
A patient is considered "uncensored" only if all task labels are
non-NA. Concordant pairs require both a correct ordering
of effective survival times and a matching ordering of predicted
scores.
Value
A numeric value between 0 and 1 (higher is better). A value of 0.5 indicates random concordance.
Known limitations
The following limitations are documented and flagged for future investigation:
No credit for tied predictions or tied survival times
Strict censoring: uncensored requires all tasks observed
Equal weighting of all tasks in the row-sum aggregation
See Also
predict.orthoMTL for generating the
prediction matrix.
Examples
# Simulate a small multi-task prediction scenario
set.seed(42)
n <- 30; n_tasks <- 4
SurvTime <- rexp(n, rate = 0.1)
Event <- rbinom(n, 1, 0.7)
thresholds <- c(4, 6, 10, 15)
Y <- create_longitudinal_labels(SurvTime, Event, thresholds)
# Simulate imperfect predictions (add noise to true labels)
pred <- Y
pred[is.na(pred)] <- 0.5
pred <- pred + matrix(rnorm(n * n_tasks, sd = 0.3), n, n_tasks)
cindex_mtl(Y, pred)
Extract Coefficients from an orthoMTL Model
Description
Returns the coefficient matrix from a fitted orthoMTL model.
Usage
## S3 method for class 'orthoMTL'
coef(object, ...)
Arguments
object |
A fitted model object of class |
... |
Additional arguments (currently ignored). |
Value
A numeric matrix of regression coefficients with dimensions
n_features x n_tasks. Row names correspond to feature names
and column names to task names, if available.
Examples
set.seed(42)
n <- 100; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
Y <- X %*% matrix(rnorm(p * n_tasks), p) + matrix(rnorm(n * n_tasks), n) * 0.1
K <- matrix(1, n_tasks, n_tasks); diag(K) <- 0.5
fit <- orthoMTL(X, Y, lambda = 1e-3, K = K)
coef(fit)
Create Diffusion Constraint Matrix
Description
Builds a square constraint matrix K encoding the prior belief
that temporally distant tasks should have more orthogonal coefficients.
Off-diagonal entries accumulate weight proportional to the distance
between task indices, implementing a diffusion-like pattern.
Usage
create_constraint_matrix(numTasks, diag_val = 0.5)
Arguments
numTasks |
An integer specifying the number of tasks. |
diag_val |
A numeric value for the diagonal of |
Details
This matrix is passed to orthoMTL via the K
argument to control the orthogonality penalty between tasks.
The construction rule: for each distance level h from
1 to numTasks, add 1 to all entries where
|row - col| > h. This produces a matrix where nearby tasks
(adjacent thresholds) share more support, while distant tasks
are pushed toward orthogonality.
For survival analysis with time thresholds, this encodes the assumption that the set of predictive features changes gradually over time rather than abruptly.
Value
A numeric square matrix of dimensions
numTasks x numTasks. Off-diagonal entry K[i,j]
is larger when tasks i and j are further apart.
Diagonal entries are set to diag_val.
See Also
Examples
# 5-task constraint matrix
K <- create_constraint_matrix(5)
K
# Override diagonal for a specific penalty balance
K <- create_constraint_matrix(7, diag_val = 6)
K
Create Censoring Indicator Matrix
Description
Converts NA entries in a longitudinal label matrix (as produced
by create_longitudinal_labels) into a binary indicator
matrix. This indicator is used by orthoMTL to mask
censored observations in the loss computation.
Usage
create_indicator_matrix(Y)
Arguments
Y |
A numeric matrix of dimensions |
Value
A numeric matrix of the same dimensions as Y.
1 = label is observed (known), 0 = label is censored
(unknown).
See Also
Examples
set.seed(42)
SurvTime <- rexp(10, rate = 0.1)
Event <- rbinom(10, 1, 0.7)
Y <- create_longitudinal_labels(SurvTime, Event, c(4, 6, 10))
W <- create_indicator_matrix(Y)
W # 1 = observed, 0 = censored
Convert Survival Data to Longitudinal Binary Labels
Description
Transforms time-to-event survival data into a matrix of binary labels at user-defined time thresholds. This is the core data transformation that enables survival analysis within the multi-task learning framework.
Usage
create_longitudinal_labels(SurvTime, Event, thresholds = c(4, 6))
Arguments
SurvTime |
A numeric vector of length |
Event |
A numeric vector of length |
thresholds |
A numeric vector of length |
Details
The encoding logic for each patient at each threshold is:
-
1— patient is progression-free at this threshold (survival time exceeds threshold, regardless of event status) -
0— patient experienced an event before this threshold (survival time < threshold AND event observed) -
NA— patient was censored before this threshold (survival time < threshold AND no event observed); label is unknown
Value
A numeric matrix of dimensions n x numTasks. Column
names are set to the threshold values. Contains 1, 0,
and NA values as described above.
See Also
create_indicator_matrix to convert NA
values into a binary censoring indicator matrix.
Examples
# Simulate 10 patients
set.seed(42)
SurvTime <- rexp(10, rate = 0.1)
Event <- rbinom(10, 1, 0.7)
thresholds <- c(4, 6, 10, 15)
Y <- create_longitudinal_labels(SurvTime, Event, thresholds)
Y # 1 = progression-free, 0 = event, NA = censored
Cross-Validation for orthoMTL Hyperparameter Selection
Description
Performs a parallelised grid search over hyperparameters for
orthoMTL, evaluating each configuration via
cross-validated concordance index. Returns the best configuration
without retraining a final model (that is the caller's responsibility).
Usage
cv_orthoMTL(
X.train,
Y.train,
W.train = NULL,
K = NULL,
lambdas = c(0.001, 0.01),
alphas = 0,
stepsizes = c(0.1, 0.5),
diag_vals = c(0.5, 1),
survival = TRUE,
logistic = FALSE,
metric = NULL,
disjoint = FALSE,
schedule = c("sqrt", "log", "const", "linear"),
folds = NULL,
n_cores = 2,
seed = NULL,
verbose = TRUE
)
Arguments
X.train |
A numeric matrix of training features with dimensions
|
Y.train |
A numeric matrix of training labels with dimensions
|
W.train |
A numeric indicator matrix of dimensions
|
K |
A square constraint matrix of dimensions
|
lambdas |
A numeric vector of regularisation parameters to search. |
alphas |
A numeric vector of elastic-net mixing parameters in
|
stepsizes |
A numeric vector of gradient descent step sizes to search. |
diag_vals |
A numeric vector of diagonal values for the
constraint matrix |
survival |
Logical. Use censored survival loss? Default:
|
logistic |
Logical. Fit logistic (classification) models?
Passed through to |
metric |
Character; the scoring metric maximised/minimised over
the grid, or |
disjoint |
Logical. Enforce disjoint supports? Default:
|
schedule |
Character; the gradient-step decay schedule passed to
|
folds |
An integer vector of length |
n_cores |
Integer. Number of cores for parallel execution.
Default: |
seed |
Optional integer random seed for reproducibility. Default:
|
verbose |
Logical. Print progress information? Default:
|
Details
The grid is constructed as the full Cartesian product of
lambdas, alphas, stepsizes, and
diag_vals. Each configuration is evaluated independently
in parallel across cores. Within each configuration, folds are
evaluated sequentially and the per-fold C-indices are averaged.
The best configuration is selected by joint maximisation of the mean CV C-index over the entire flattened grid (not greedy sequential search).
This function does not retrain a final model. Use the
returned hyperparameters to train via orthoMTL.
Value
An object of class "cv_orthoMTL" containing:
- best
A list with the best hyperparameters:
lambda,alpha,stepsize,diag_val, and the correspondingcv_score.- results
A
data.frameof all configurations with their mean CV C-index, sorted descending bycv_score.- folds
The fold assignment vector used.
- n_configs
Total number of configurations tested.
- n_folds
Number of unique folds.
- call
The matched function call.
See Also
Examples
set.seed(42)
n <- 50; p <- 5; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
SurvTime <- rexp(n, rate = 0.1)
Event <- rbinom(n, 1, 0.7)
thresholds <- c(4, 6, 10)
Y <- create_longitudinal_labels(SurvTime, Event, thresholds)
W <- create_indicator_matrix(Y)
K <- create_constraint_matrix(n_tasks)
folds <- rep(1:2, length.out = n)
cv_res <- cv_orthoMTL(
X.train = X, Y.train = Y, W.train = W, K = K,
lambdas = c(1e-3, 1e-2), alphas = 0,
stepsizes = c(0.1), diag_vals = c(0.5, 1),
survival = TRUE, disjoint = FALSE,
folds = folds, n_cores = 1, seed = 42, verbose = FALSE
)
print(cv_res)
cv_res$best
Project a Vector onto Non-Negative Non-Increasing Space
Description
Applies an isotonic regression-style projection to enforce that the
output vector is non-negative and non-increasing. Used internally
by predict.orthoMTL to ensure survival predictions
are monotonically decreasing across time thresholds.
Usage
nnmaxheap_C(m)
Arguments
m |
A numeric vector to project. |
Details
This function implements a pool-adjacent-violators style algorithm.
It replaces the external Iso package dependency used in the
predecessor orthopen package.
Value
A numeric vector of the same length as m, projected
onto the non-negative non-increasing constraint space.
Examples
# Project a vector onto the non-negative non-increasing space
nnmaxheap_C(c(3, 1, 2, -1))
# Already valid input: returned unchanged
nnmaxheap_C(c(5, 3, 3, 1))
Multi-task learning with orthogonal constraints
Description
This function solves a multi-task problem where relationships between tasks can be complex
Usage
orthoMTL(
X,
Y,
lambda = 1,
step_size = 0.1,
tol = 1e-05,
stop_no_improve = 100,
max_iter = 1e+06,
W_0 = NULL,
seed = NULL,
K = NULL,
disjoint = FALSE,
logistic = FALSE,
alpha = 0,
schedule = c("sqrt", "log", "const", "linear"),
survival = FALSE,
censored.mat = NULL,
verbose = 0
)
Arguments
X |
a matrix of predictor variables with dimensions n x p |
Y |
a matrix of response variables with dimensions n x numTasks, where numTasks is the number of response variables. NAs can be used for censored data. |
lambda |
the regularization parameter for the OrthoPen penalty, default is 1 |
step_size |
the step size for updating the regression coefficients in gradient descent, default is 0.1 |
tol |
Convergence tolerance. The algorithm stops when the
improvement in the objective function is less than |
stop_no_improve |
the number of iterations without improvement in the objective function to trigger convergence, default is 100 |
max_iter |
the maximum number of iterations, default is 1e+06 |
W_0 |
a matrix of initial values for the regression coefficients, default is NULL, as not provided and will be randomly attributed |
seed |
an optional random seed for reproducibility, default is
|
K |
a constraint matrix of weights to adjust the OrthoPen penalty, default is an identity matrix with dimensions numTasks x numTasks |
disjoint |
a logical value indicating whether the response variables should have disjoint supports, default is FALSE |
logistic |
a logical value indicating whether logistic regression should be used instead of linear regression, default is FALSE |
alpha |
the elastic-net mixing parameter in |
schedule |
Character; the gradient-step decay schedule – how the
per-iteration scale grows with the iteration index
The default |
survival |
a logical value indicating whether survival analysis should be performed, default is FALSE |
censored.mat |
a matrix indicating whether observations are censored, used only if survival=TRUE |
verbose |
the level of verbosity, default is 0 (no messages) |
Value
a list containing the following elements:
B |
a matrix of regression coefficients with dimensions p x numTasks |
obj |
the final objective function when algorithms stops |
imax |
the number of iterations |
References
Kevin Vervier, Pierre Mahé, Alexandre d’Aspremont, Jean-Baptiste Veyrieras, Jean-Philippe Vert (2014). On learning matrices with orthogonal columns or disjoint supports. https://hal.science/hal-00985654/file/learningDisjointSupports.pdf
Examples
# Regression with orthogonal columns
set.seed(42)
n <- 100; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
W_true <- qr.Q(qr(matrix(rnorm(p * n_tasks), p, n_tasks)))
Y <- X %*% W_true + matrix(rnorm(n * n_tasks), n) * 0.1
K <- matrix(1, n_tasks, n_tasks)
diag(K) <- 0.5
fit <- orthoMTL(X, Y, lambda = 1e-3, K = K, disjoint = FALSE)
fit$B # coefficient matrix
fit$converged # did optimisation converge?
Bootstrap Coefficient Comparison Plot
Description
Displays faceted line plots comparing real (bootstrapped) vs null (permuted) coefficient trajectories across tasks for selected or all features. Each panel shows the mean and standard error of the coefficient at each task/threshold.
Usage
plot_bootstrap(x, features = NULL, batch_size = 9)
Arguments
x |
Either a |
features |
A character vector of feature names to plot. If
|
batch_size |
Number of features per facet page. Default:
|
Details
Blue lines show coefficients from models fitted on bootstrapped (resampled) data — reflecting estimation variability under real signal. Grey lines show coefficients from models fitted on permuted outcomes — reflecting the null distribution.
When the blue (real) band is clearly separated from the grey (null) band, the feature's coefficient is distinguishable from noise at that task/threshold.
Value
A list of ggplot2 objects, one per batch/page.
See Also
Examples
set.seed(42)
n <- 30; p <- 5; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
SurvTime <- rexp(n, rate = 0.1)
Event <- rbinom(n, 1, 0.7)
thresholds <- c(4, 6, 10)
Y <- create_longitudinal_labels(SurvTime, Event, thresholds)
W <- create_indicator_matrix(Y)
K <- create_constraint_matrix(n_tasks)
boot_res <- bootstrap_orthoMTL(
X = X, Y = Y, lambda = 1e-3, step_size = 0.1,
K = K, survival = TRUE, censored.mat = W,
n_repeats = 5, n_cores = 1, verbose = FALSE
)
plots <- plot_bootstrap(boot_res)
plots[[1]]
Task Correlation Map for orthoMTL
Description
Displays pairwise distances between task coefficient vectors as a
heatmap. Distance is computed as 1 - cosine_similarity.
Values near 0 indicate similar coefficient profiles; values near 1
indicate orthogonal profiles.
Usage
plot_correlation(x, midpoint = 0.5, limits = c(0, 1))
Arguments
x |
Either a fitted |
midpoint |
Midpoint for the colour scale. Default: |
limits |
Numeric vector of length 2 for the colour scale limits.
Default: |
Value
A ggplot2 object.
See Also
Examples
set.seed(42)
n <- 100; p <- 10; n_tasks <- 4
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
Y <- X %*% matrix(rnorm(p * n_tasks), p) + matrix(rnorm(n * n_tasks), n) * 0.1
colnames(Y) <- c("T1", "T2", "T3", "T4")
K <- matrix(1, n_tasks, n_tasks); diag(K) <- 0.5
fit <- orthoMTL(X, Y, lambda = 1e-3, K = K)
plot_correlation(fit)
Coefficient Heatmap for orthoMTL
Description
Displays the coefficient matrix as a heatmap. Features (rows) can optionally be reordered by their mean coefficient across tasks.
Usage
plot_heatmap(x, reorder = TRUE)
Arguments
x |
Either a fitted |
reorder |
Logical. If |
Value
A ggplot2 object.
See Also
coef.orthoMTL, plot_correlation
Examples
set.seed(42)
n <- 100; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
Y <- X %*% matrix(rnorm(p * n_tasks), p) + matrix(rnorm(n * n_tasks), n) * 0.1
colnames(Y) <- c("T1", "T2", "T3")
K <- matrix(1, n_tasks, n_tasks); diag(K) <- 0.5
fit <- orthoMTL(X, Y, lambda = 1e-3, K = K)
# From fitted object
plot_heatmap(fit)
# From raw matrix
plot_heatmap(coef(fit), reorder = FALSE)
Prediction Swimmer Plot for orthoMTL
Description
Displays a prediction matrix as a heatmap (swimmer plot), where rows are patients and columns are tasks/thresholds.
Usage
plot_prediction(x)
Arguments
x |
A numeric prediction matrix with dimensions
|
Value
A ggplot2 object.
See Also
Examples
set.seed(42)
n <- 50; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
Y <- X %*% matrix(rnorm(p * n_tasks), p) + matrix(rnorm(n * n_tasks), n) * 0.1
colnames(Y) <- c("T1", "T2", "T3")
K <- matrix(1, n_tasks, n_tasks); diag(K) <- 0.5
fit <- orthoMTL(X, Y, lambda = 1e-3, K = K)
preds <- predict(fit, newdata = X)
plot_prediction(preds)
Predict from an orthoMTL Model
Description
Generate predictions from a fitted orthoMTL model for new
observations. In survival mode, predictions are projected onto the
non-negative non-increasing space to ensure monotonicity across tasks.
Usage
## S3 method for class 'orthoMTL'
predict(object, newdata, type = c("link", "response", "class"), ...)
Arguments
object |
A fitted model object of class |
newdata |
A numeric matrix of new observations with dimensions
|
type |
Character; scale of the returned predictions. One of:
|
... |
Additional arguments (currently ignored). |
Details
If the fitted object contains feature_names (i.e., the training
matrix X had column names), newdata columns are aligned
to match. Missing features cause an error. Extra features trigger a
warning and are dropped.
In survival mode (object$hyperparameters$survival == TRUE),
each row of the raw prediction matrix is projected via
nnmaxheap_C() to enforce non-negative, non-increasing values
across tasks (time thresholds).
Value
A numeric matrix of predictions with dimensions
n_new x n_tasks. Column names correspond to task names
if available.
References
Vervier, K., Mahe, P., d'Aspremont, A., Veyrieras, J.-B., and Vert, J.-P. (2014). On Learning Matrices with Orthogonal Columns or Disjoint Supports. ECML-PKDD 2014. https://hal.science/hal-00985654
Examples
set.seed(42)
n <- 100; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
W_true <- qr.Q(qr(matrix(rnorm(p * n_tasks), p, n_tasks)))
Y <- X %*% W_true + matrix(rnorm(n * n_tasks), n) * 0.1
K <- matrix(1, n_tasks, n_tasks); diag(K) <- 0.5
fit <- orthoMTL(X, Y, lambda = 1e-3, K = K, disjoint = FALSE)
X_new <- matrix(rnorm(20 * p), 20, p)
colnames(X_new) <- paste0("V", seq_len(p))
preds <- predict(fit, newdata = X_new)
dim(preds)
Print Bootstrap Inference Results
Description
Displays a summary of bootstrap inference results from
bootstrap_orthoMTL.
Usage
## S3 method for class 'bootstrap_orthoMTL'
print(x, ...)
Arguments
x |
An object of class |
... |
Additional arguments (currently ignored). |
Value
Invisibly returns x.
Examples
# See ?bootstrap_orthoMTL for a full example
Print Cross-Validation Results
Description
Displays a summary of cross-validation results from
cv_orthoMTL.
Usage
## S3 method for class 'cv_orthoMTL'
print(x, n_top = 5, ...)
Arguments
x |
An object of class |
n_top |
Number of top configurations to display. Default: 5. |
... |
Additional arguments (currently ignored). |
Value
Invisibly returns x.
Examples
# See ?cv_orthoMTL for a full example
Print an orthoMTL Object
Description
Displays a compact summary of a fitted orthoMTL model.
Usage
## S3 method for class 'orthoMTL'
print(x, ...)
Arguments
x |
A fitted model object of class |
... |
Additional arguments (currently ignored). |
Value
Invisibly returns x.
Examples
set.seed(42)
n <- 100; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
Y <- X %*% matrix(rnorm(p * n_tasks), p) + matrix(rnorm(n * n_tasks), n) * 0.1
fit <- orthoMTL(X, Y, lambda = 1e-3)
print(fit)
Print Simulated Multi-Task Data
Description
Displays a summary of a simulated dataset from
simulate_mtl.
Usage
## S3 method for class 'simulated_mtl'
print(x, ...)
Arguments
x |
An object of class |
... |
Additional arguments (currently ignored). |
Value
Invisibly returns x.
Examples
sim <- simulate_mtl(n = 100, p = 20, n_signals = 4)
print(sim)
Projection onto Disjoint Support Feasible Set
Description
Projects weight and constraint matrices ...
Usage
proj_disjoint(w, v)
Arguments
w |
Numeric matrix of weights used in the loss function. |
v |
Numeric matrix of constraints used for projection. |
Value
A list with projected matrices w and v.
Coefficient of Determination (R-squared) for Multi-Task Regression
Description
Pooled R^2 = 1 - SS_{res} / SS_{tot} over every non-NA
cell, for orthoMTL fits in regression mode. SS_{tot} uses
the global mean of the pooled true values.
Usage
r2_mtl(true.label.mat, pred.label.mat)
Arguments
true.label.mat |
A numeric matrix of true responses
( |
pred.label.mat |
A numeric matrix of predictions of the same
dimensions (as produced by |
Value
A single numeric value (higher is better; 1 = perfect). Can be negative when predictions are worse than the mean.
See Also
Examples
set.seed(1)
Y <- matrix(rnorm(30), 10, 3)
P <- Y + matrix(rnorm(30, sd = 0.1), 10, 3)
r2_mtl(Y, P)
Root Mean Squared Error for Multi-Task Regression
Description
Pooled RMSE over every non-NA cell of the true/predicted
matrices, for orthoMTL fits in regression mode
(logistic = FALSE, survival = FALSE).
Usage
rmse_mtl(true.label.mat, pred.label.mat)
Arguments
true.label.mat |
A numeric matrix of true responses
( |
pred.label.mat |
A numeric matrix of predictions of the same
dimensions (as produced by |
Value
A single non-negative numeric value (lower is better).
See Also
Examples
set.seed(1)
Y <- matrix(rnorm(30), 10, 3)
P <- Y + matrix(rnorm(30, sd = 0.1), 10, 3)
rmse_mtl(Y, P)
Simulate Multi-Task Data with Time-Varying Effects
Description
Generates a realistic simulated dataset with binary and continuous
features and a known ground-truth coefficient structure. The
mode argument selects the response type: piecewise-exponential
survival times (default), multi-task regression
targets, or multi-task binary classification labels. Designed
for demonstrating and testing orthoMTL.
Usage
simulate_mtl(
n = 200,
p = 30,
n_signals = 5,
n_continuous = 1,
thresholds = c(4, 6, 10, 15),
mode = c("survival", "regression", "classification"),
noise_sd = 1,
censoring_max = 25,
baseline_hazard = 0.05,
effect_strength = 0.8,
treatment_effect = -0.3,
seed = NULL
)
Arguments
n |
Number of patients. Default: |
p |
Number of features excluding the treatment column.
Default: |
n_signals |
Number of features with true non-zero effects.
Default: |
n_continuous |
Number of continuous features (placed first
in the feature matrix). Default: |
thresholds |
Numeric vector of time thresholds defining the
task structure. Default: |
mode |
Character; the response type to generate. One of
|
noise_sd |
Standard deviation of the Gaussian noise added in
|
censoring_max |
Maximum censoring time. Censoring times are
drawn from |
baseline_hazard |
Baseline hazard rate per interval. Default:
|
effect_strength |
Multiplier controlling the magnitude of
feature effects. Default: |
treatment_effect |
Effect of treatment on the log-hazard
(negative = protective). Default: |
seed |
Optional random seed for reproducibility. Default:
|
Details
Feature structure:
Continuous features are drawn from
N(0, 1).Binary features have prevalences drawn from
Beta(2, 10), producing a realistic range (~5-30%).Treatment is balanced 1:1 via random assignment.
Effect templates: Each signal feature is assigned one of five temporal patterns:
-
"early": strong effect at early thresholds, fading to zero at late. -
"late": zero at early thresholds, emerging at late. -
"constant": equal effect across all thresholds (detectable by standard Cox models). -
"increasing": effect grows over time. -
"decreasing": effect shrinks over time.
Templates are assigned cyclically across signal features with random sign (risk-increasing or protective).
Survival time generation:
Uses a piecewise-exponential model where the hazard in each
interval is
h_k(i) = baseline_hazard * exp(X[i, ] %*% beta[, k]).
Patients progress through intervals sequentially; an event
occurs when the simulated time within an interval is shorter
than the interval width.
Censoring:
Independent of event times. C ~ Unif(0, censoring_max).
Observed time = min(T, C), event indicator = T <= C.
Value
An object of class "simulated_mtl" containing:
- mode
The response type generated.
- Y
For
mode = "regression"/"classification", then x length(thresholds)response matrix.NULLin survival mode (useSurvTime/Eventinstead).- SurvTime, Event
Survival mode only (
NULLotherwise): observed times and event indicators.- X
Numeric matrix of dimensions
n x (p + 1). Columns includen_continuouscontinuous features (standard normal),p - n_continuousbinary features (prevalences drawn fromBeta(2, 10)), and atreatmentcolumn (balanced 1:1).- SurvTime
Numeric vector of observed survival times.
- Event
Binary vector:
1= event observed,0= censored.- treatment
Binary vector (also present as last column of
X).- feature_names
Character vector of column names of
X.- ground_truth
A list containing:
- coefficients
Matrix of true coefficients with dimensions
(p + 1) x length(thresholds).- signal_features
Names of features with non-zero effects.
- null_features
Names of features with zero effects.
- effect_types
Named character vector mapping signal features to their temporal effect template.
- thresholds
The thresholds used.
- baseline_hazard
The baseline hazard used.
- n, p, n_signals, n_continuous, thresholds, seed
Input parameters stored for reference.
- call
The matched function call.
See Also
create_longitudinal_labels,
orthoMTL
Examples
# Generate simulated data
sim <- simulate_mtl(n = 100, p = 20, n_signals = 4, seed = 42)
sim
# Inspect ground truth
sim$ground_truth$signal_features
sim$ground_truth$effect_types
sim$ground_truth$coefficients[sim$ground_truth$signal_features, ]
# Use in orthoMTL workflow
thresholds <- c(4, 6, 10, 15)
Y <- create_longitudinal_labels(sim$SurvTime, sim$Event, thresholds)
W <- create_indicator_matrix(Y)
K <- create_constraint_matrix(length(thresholds))
fit <- orthoMTL(sim$X, Y, lambda = 1e-3, K = K,
survival = TRUE, censored.mat = W)
summary(fit)
Summarise an orthoMTL Object
Description
Displays a detailed summary of a fitted orthoMTL model,
including hyperparameters, coefficient matrix statistics, and
top features by mean absolute coefficient.
Usage
## S3 method for class 'orthoMTL'
summary(object, n_top = 5, ...)
Arguments
object |
A fitted model object of class |
n_top |
Number of top features to display. Default: 5. |
... |
Additional arguments (currently ignored). |
Value
Invisibly returns object.
Examples
set.seed(42)
n <- 100; p <- 10; n_tasks <- 3
X <- matrix(rnorm(n * p), n, p)
colnames(X) <- paste0("V", seq_len(p))
Y <- X %*% matrix(rnorm(p * n_tasks), p) + matrix(rnorm(n * n_tasks), n) * 0.1
fit <- orthoMTL(X, Y, lambda = 1e-3)
summary(fit)