Evaluate fitted cells and select response-level deliveries
predictModel.RdRun trainRegressionModel() in evaluation mode, collect its point
predictions and OOF metrics, select one response–dataset cell per response,
and add matching signed OOF-residual offsets. This is the first delivery
selector. The later aggregateResponses() selector has a different
candidate set and grouping rule.
Usage
predictModel(.path.train, .path.model, .path.metrics,
.path.response, .path.summary, .path.export, .file.index = NULL,
METHODS, PPROC = NULL, probs = c(0.50, 0.90, 0.95),
.min = -Inf, .max = Inf, .ensemble = "ensemble.R2",
.deliverable_datasets = NULL, .responses = NULL)Arguments
- .path.train
Path to an existing split directory. Training files are discovered non-recursively by the suffix
_TRAIN.csv. Their first two underscore-separated fields are interpreted as response and dataset, so those identifiers cannot contain underscores.- .path.model
Existing directory containing the fitted model files required by
trainRegressionModel()evaluation mode.- .path.metrics
Existing writable directory for cell metric CSVs. Evaluation can overwrite assigned files; this helper then reads every CSV in the directory and overwrites
metrics.csvunder.path.summarywith their unique union.- .path.response
Existing writable directory for cell response CSVs. Evaluation can overwrite assigned files; matching files are then read to assemble the long prediction table.
- .path.summary
Summary-output directory. It is created non-recursively when absent, so its parent must exist. A compatible
prediction_quantiles.csvfromauditQuantiles()must already exist.- .path.export
Export directory. It is created non-recursively when absent, so its parent must exist. Assigned dataset CSVs are overwritten.
- .file.index
NULL, a nonexistent path, or a CSV index path. When an existing file is supplied, its first column is the join key used to rewrite every CSV under.path.summaryand.path.exportthat contains that name.- METHODS
Non-empty character vector of fitted caret method identifiers. Duplicates are removed and order is randomized before evaluation.
- PPROC
Forwarded as
.preProcessto evaluation mode. The currenttrainRegressionModel()evaluation path does not use preprocessing.- probs
Numeric vector of offset probabilities. Each value is converted to an integer percentage with
as.integer(100 * p)and requires a matchingq_XXcolumn inprediction_quantiles.csv. The standard producer writes only 0.50, 0.90, and 0.95.- .min, .max
Numeric response bounds. Base point predictions are projected by the evaluation engine; each point-plus-offset value is projected again. Bound order and finiteness are not validated.
- .ensemble
A value in
c("ensemble.R2", "ensemble.RMSE"). It selects both the metric and method label used by the response-level selector. The default is"ensemble.R2".- .deliverable_datasets
NULL, or a character vector restricting dataset eligibility only for response-level selection. It does not change split discovery, evaluation, long outputs, or the list of dataset-named files considered for export.- .responses
NULL, or a character vector restricting discovered responses before evaluation.NULLuses all parsed responses.
Value
Invisibly, a list with DTL, the unadjusted long point table;
DTW, the selected wide point-plus-offset table; and
DT.metrics, the deduplicated union of metric CSVs before any index
rewrite.
Evaluation and assembly
Discovered response and dataset names are deduplicated independently and
passed to trainRegressionModel() with TRAIN = FALSE. The method
vector is sampled with R's current random-number generator, so this call
advances RNG state even though fitted models are reused. The engine
reconstructs OOF metrics and predicts unseen split rows according to its
accepted reference contract. Because this wrapper does not override the
engine's PARALLEL argument, evaluation registers a PSOCK backend with
at most two workers, stops it on exit, and leaves foreach sequential. A
restricted environment that forbids local server sockets can therefore fail
before evaluation even though no model is fitted.
Every existing metric CSV is row-bound and deduplicated into
DT.metrics. Every existing
response_dataset.csv under .path.response is read,
deduplicated, and tagged with set = "response_dataset". Their union,
DTL, retains base-method and both ensemble point predictions. Missing
response files are skipped. If none is read, cleanup of the never-created
intermediate can error before a result is written.
Response-level selector and offsets
Let \(r\) index a response, \(d\) a dataset cell, \(x\) one unseen
predictor row, and \(\mathcal D_r\) the eligible metric rows for
response \(r\). Eligibility includes the requested ensemble label and,
when supplied, membership in .deliverable_datasets.
For the RMSE ensemble the selected row is
$$d_r^{RMSE}=\operatorname*{first\,argmin}_{d\in\mathcal D_r}
\mathrm{RMSE}_{rd},$$
among rows labeled ensemble.RMSE. For the R2 ensemble it is
$$d_r^{R2}=\operatorname*{first\,argmax}_{d\in\mathcal D_r}R^2_{rd},$$
among rows labeled ensemble.R2. Missing scores are ignored when a
non-missing score exists, and an extremum tie selects the first metric row.
If every score in a response group is missing, or filtering leaves no row
for that response, the selector contributes no selected row for it. Later
offset assembly and reshaping can consequently omit that response or fail
when no usable selection remains.
For the selected response and dataset, let \(\hat y_r(x)\) be the
matching ensemble point prediction and let \(q_{p,rd}\) be the signed,
cell-pooled OOF-residual offset at requested probability \(p\), written by
auditQuantiles(). Let \(a\) and \(b\) be bounds in response units,
supplied by .min and .max, respectively. When \(a\le b\),
interval projection is
\(\Pi_{[a,b]}(z)=\min\{b,\max\{a,z\}\}\) for real \(z\). The delivered
value is
$$Q_{p,r}(x)=\Pi_{[a,b]}\{\hat y_r(x)+q_{p,rd}\}.$$
This is a projected point-plus-residual-offset estimate. It is not a
predictive-distribution quantile and carries no conditional, marginal, or
conformal coverage guarantee. Exactly one matching offset row is required
for every selected cell. Rows with any missing field are removed before
wide reshaping. Bound order and finiteness are not checked; with invalid
bounds the nested minimum/maximum remains the executed operation but is not
an interval projection.
Files, index joins, and return
The helper overwrites metrics.csv with DT.metrics and
response_long.csv with the unadjusted long point table DTL.
For each discovered dataset, it finds sample IDs occurring in long-table set
names ending in _dataset and writes a dataset-named CSV when at least
one selected wide row has such an ID. Dataset names enter an unescaped
regular expression. Each wide file has one row per retained
sample/probability, a SampleID column, one column per selected
response, and p. Existing assigned files are overwritten.
If an index file is supplied, every CSV currently present under both output directories is read. Files containing the index's first column are replaced by the index-to-file data.table join, which can add columns, change order, or duplicate rows when the key is not unique. This includes pre-existing CSVs not created by the current call. In-memory return tables precede these joins.
Errors from evaluation, absent quantile files or columns, non-unique selected rows, malformed schemas, empty casts, joins, and file operations can occur after earlier assigned files were written; there is no transactional rollback. Progress uses ssel's debug channel.
References
Hyndman, R. J., and Fan, Y. (1996). Sample quantiles in statistical packages. The American Statistician, 50(4), 361–365. doi:10.1080/00031305.1996.10473566 .
Parikh, N., and Boyd, S. (2014). Proximal Algorithms. Foundations and Trends in Optimization, 1(3), 127–239. doi:10.1561/2400000003 .
See also
trainRegressionModel() for evaluation and ensemble point
predictions, auditQuantiles() for the offset estimator, and
aggregateResponses() for the later RMSE-candidate rowwise selector.
Examples
# \donttest{
root <- tempfile("ssel-predict-")
train_dir <- file.path(root, "train")
model_dir <- file.path(root, "model")
metrics_dir <- file.path(root, "metrics")
response_dir <- file.path(root, "response")
summary_dir <- file.path(root, "summary")
export_dir <- file.path(root, "export")
for (path in c(train_dir, model_dir, metrics_dir, response_dir,
summary_dir, export_dir)) {
dir.create(path, recursive = TRUE)
}
train <- data.frame(
x = 1:6,
y = c(1, 2, 2, 4, 5, 7)
)
test <- data.frame(x = c(7, 8), SampleID = c("P1", "P2"))
utils::write.csv(train, file.path(train_dir, "target_demo_TRAIN.csv"),
row.names = FALSE)
utils::write.csv(test, file.path(train_dir, "target_demo_TEST.csv"),
row.names = FALSE)
fit <- stats::lm(y ~ x, data = train)
fit$pred <- data.frame(
intercept = TRUE,
pred = c(1.5, 1.5, 3, 3, 6, 6),
obs = train$y,
rowIndex = 1:6
)
fit$bestTune <- data.frame(intercept = TRUE)
saveRDS(fit, file.path(model_dir, "lm_target_demo.Rds"))
data.table::fwrite(
data.table::data.table(
response = "target", dataset = "demo", n = 6L,
q_50 = 0, q_90 = 0.5, q_95 = 1
),
file.path(summary_dir, "prediction_quantiles.csv")
)
set.seed(2026)
result <- suppressMessages(predictModel(
.path.train = train_dir,
.path.model = model_dir,
.path.metrics = metrics_dir,
.path.response = response_dir,
.path.summary = summary_dir,
.path.export = export_dir,
METHODS = "lm",
.ensemble = "ensemble.RMSE"
))
result$DTW
#> Index: <SampleID>
#> SampleID target p
#> <char> <num> <num>
#> 1: P1 7.600000 0.50
#> 2: P2 8.771429 0.50
#> 3: P1 8.100000 0.90
#> 4: P2 9.271429 0.90
#> 5: P1 8.600000 0.95
#> 6: P2 9.771429 0.95
# p identifies three signed-residual offsets around one selected cell.
unlink(root, recursive = TRUE)
# }