Calibrate a Frozen Workflow
calibrate_workflow.RdAdds an Inductive Venn-Abers calibrator to an already fitted classification or
regression workflow and fits only that calibrator, on the workflow's final
predictions; the complete workflow, including learned preprocessing and any
learned postprocessor, is retained unchanged. It needs the fitted workflow and
new calibration data that played no part in its training, tuning or selection.
Choose it when the workflow is final or expensive to refit; use
calibrated_workflow when the package should train the workflow
and create the calibration split itself.
Usage
calibrate_workflow(fitted_workflow, data_calibration, outcome, ...,
classification = "binary", event_level = "first", precision = NULL,
loss = "log", m = NULL, epsilon = NULL, schema = NULL)
# S3 method for class 'vennabers_frozen'
predict(object, new_data, type = NULL, ...,
loss = NULL)
# S3 method for class 'vennabers_frozen'
print(x, ...)Arguments
- fitted_workflow
A fully fitted classification or regression workflow. Single parsnip fits, extracted engines and unfitted workflows are rejected.
- data_calibration
A nonempty data frame in the original learned input format, including the outcome. Do not pre-bake the data. Missing predictor values are allowed only if the stored prediction path handles them.
- outcome
One column name matching the trained outcome. Calibration truth must be a nonmissing factor with exactly the trained class universe. Factor levels may be reordered; the stored workflow fixes the output class order. Binary calibration may observe only one class. OvO/OvR must observe every stored class globally. Regression truth must be a finite numeric vector, including when all values are 0/1; the workflow fixes the mode.
- classification
Exactly
"binary"(default),"ovo"or"ovr". Choose OvO/OvR explicitly or through the training schema, including for a two-class matrix problem.- event_level
Exactly
"first"or"second", selecting the event by the trained class order. Only accepted explicitly for binary calibration.- precision
NULL or a finite numeric whole number. Only calibration probabilities are rounded, following
venn_abers. New probabilities are never rounded. Changing this option or the event requires a new calibrator, but no new base workflow fit.- loss
Constructor: exactly
"log"or"brier", saved as the prediction default. Predict andvenn_abers_details(): omit to retain that default, or override without refitting or changing stored state. Explicit NULL is invalid at prediction. Only classification accepts loss or precision. Regression rejects explicit classification, event_level, precision and loss options, including explicit defaults or NULL.- m, epsilon
Regression moderation. With both NULL, use m = 1. Otherwise supply exactly one non-NULL value: a whole number with 1 <= m <= floor((k-1)/2), or 0 < epsilon < 1 giving m = floor(epsilon*(k+1)/2) within that same range, where k is the calibration size. At least three observations are needed. Requested values and effective m and epsilon = 2*m/(k+1) are retained. Classification rejects these options.
- schema
NULL for an originally named workflow, or the fixed
venn_abers_schemaused to encode the original training data. With a schema, explicitly encode calibration and prediction data usingvenn_abers_encode(data, schema)and useschema$encoded_outcome. Omitted classification and binary event options inherit the schema; explicit options must agree. The workflow mode, input columns, class order and ordered factor status must match. A schema does not rename an existing workflow.- object, x
A fitted predictor returned by
calibrate_workflow().- new_data
A data frame in the learned input format. The outcome is not needed and, if present, is removed before the original workflow predicts.
- type
NULL selects
"prob"for classification and"numeric"for regression. Classification also accepts"class". Regression returns only numeric points;"conf_int"and"pred_int"are unsupported.- ...
Must be empty. Constructor argument names must be exact. Unknown, training, split, Cross and full-model options are rejected.
Value
An already fitted vennabers_frozen predictor, also inheriting
vennabers_fit. It is not a trainable workflow or a specification for
fit_resamples(). The object retains complete workflows in models,
the calibrator, schema, class_levels, event_class, input column
metadata, calibration size, requested/effective parameters, and relevant
R, package and engine versions. No additional complete copy of new raw
calibration data is stored; data already retained by the original workflow remain.
Prediction returns a tibble with named .pred_<class> probabilities in
trained class order, or a factor .pred_class, ordered exactly when the
trained outcome is ordered. The event wins at probability
0.5 in binary calibration. OvO/OvR ties choose the first stored level.
Regression returns one double .pred column.
venn_abers_details() returns the same prediction table and binary
lower/upper bounds and points with row, Inductive fold and event identity;
OvO/OvR add class-pair or class-against-rest identities. Regression details
contain row, fold, prediction, lower and upper. IVAR bounds concern regularized
conditional expectations, not confidence or prediction intervals.
Zero and one row preserve types and columns; zero rows do not call the base engine.
Print reports the adoption without base fits, the one retained workflow, the
number of calibration rows and the Inductive fold-to-model mapping.
plot.vennabers_fit draws the stored calibration map.
Details
Calibration uses the complete public workflow predict(type = "prob")
or predict(type = "numeric") path, including its existing postprocessor
exactly once. Missing, extra,
duplicate or unknown class columns, nonfinite/out-of-range probabilities,
invalid row sums and changed row counts cause errors. Multiclass matrices
are normalized only within the existing 1e-8 row-sum tolerance, by the manual
core. OvO zero pair sums, coupling, OvR normalization and calibration-only
rounding use those same cores. Regression requires finite final numeric values. Failures retain original
class/input names and prediction-stage context. No learned state is renamed,
refitted or bypassed through an extracted engine or a raw fallback.
The user is responsible for keeping the new calibration data outside all earlier
model, preprocessing, postprocessing and parameter-selection data. Assessment
data must also be separate from calibration and selection. This history is not
automatically verified. Frozen adoption is an R extension, neither Cross
calibration nor full-model transfer. calibrated_workflow is the
separate path that trains new base workflows on its own split.
Native fit_resamples() and last_fit() evaluate the base workflow
itself. Their fitted workflows, from tune::extract_workflow() or saved
extracts, can be adopted with calibration rows outside both their analysis and
assessment data; the adoption then learns only the calibrator. The returned
predictor is not itself a tune input.
To choose between the Log and Brier rules after adoption, compare
predict(fitted, validation, type = "prob", loss = ...) with yardstick
metrics on separate, previously unused validation rows, then pass the chosen
loss explicitly when predicting. Neither the workflow nor the calibrator
is refitted, and no further helper is needed. Validation rows remain selection
data; final assessment uses other rows. Automatic search with new training
belongs to calibrated_workflow() tuning.
saveRDS() and readRDS() preserve prediction and diagnostics without
learning for the tested GLM, multinomial and linear workflows, including recipes
and Tailor, in fresh R processes and parallel workers. Required
packages must be available in the new R process. Engines with external resources
retain their own storage contracts; no universal portability is promised.
The integration dependencies are optional; manual cores work without them.
The installed examples/frozen-binary.R demonstrates earlier model/recipe
and postprocessor learning, separate calibration, the loss-only choice on
validation rows and independent assessment.
examples/frozen-multiclass-regression.R demonstrates learned multinomial
and linear postprocessing with OvO/OvR and IVAR. The original workflow must
support the requested batch size: for example, the tested probably 1.2.0
multinomial smooth=FALSE path fails on one row; smooth=TRUE supports it.
Original prediction failures propagate without modifying the workflow.
For encoded training, retain the original schema together with the fitted
workflow. No schema is learned from later calibration data. Inputs must carry
the encoded names; valid reordered input columns and factor levels are matched
by identity. Predictions and details carry the schema binding and remain
encoded. venn_abers_decode() returns the existing roles with original
names and classes, including diagnostics; it invents neither outer identities
nor Cross aggregates for these Inductive methods. See the installed
examples/frozen-schema.R for all four paths with learned postprocessing.
Bindings retained on the workflow, its original recipe template, or incoming
data are checked, along with learned metadata. Workflows and table operations
can discard attributes: matching detached codes alone cannot prove which schema
was used during training. The caller must supply the actually associated schema.
An originally named workflow must continue receiving its original inputs with
schema = NULL. Creating a schema afterward does not authorize recipe
rewriting, refitting or encoded input substitution. An old workflow whose
complete prediction path fails on reserved names reports the stage, names and
underlying cause. The limited binary GLM raw-response probe without a
postprocessor is not a product fallback; no engine or postprocessor is bypassed.
See also
vignette("workflows", package = "vennabers") for frozen
workflows in context, vignette("method", package = "vennabers") for the
theory and its guarantees, and vennabers_examples for annotated
installed scripts.
calibrated_workflow, venn_abers_details,
venn_abers_schema, venn_abers, venn_abers_regression
Examples
if (all(vapply(c("parsnip", "workflows", "hardhat", "rsample", "recipes",
"rlang", "tibble", "withr", "generics", "tidyselect"),
requireNamespace, logical(1), quietly = TRUE))) {
d <- data.frame(x = sin(1:80), truth = factor(rep(c("yes", "no", "no", "yes"), 20)))
base <- workflows::workflow() |>
workflows::add_formula(truth ~ x) |>
workflows::add_model(parsnip::logistic_reg(engine = "glm"))
earlier <- generics::fit(base, d[1:40, ])
calibrated <- calibrate_workflow(earlier, d[41:60, ], "truth")
predict(calibrated, d[61:80, "x", drop = FALSE])
}
#> # A tibble: 20 × 2
#> .pred_no .pred_yes
#> <dbl> <dbl>
#> 1 0.412 0.588
#> 2 0.438 0.562
#> 3 0.455 0.545
#> 4 0.571 0.429
#> 5 0.571 0.429
#> 6 0.438 0.562
#> 7 0.438 0.562
#> 8 0.438 0.562
#> 9 0.438 0.562
#> 10 0.571 0.429
#> 11 0.571 0.429
#> 12 0.455 0.545
#> 13 0.438 0.562
#> 14 0.412 0.588
#> 15 0.438 0.562
#> 16 0.526 0.474
#> 17 0.7 0.3
#> 18 0.526 0.474
#> 19 0.438 0.562
#> 20 0.412 0.588