Preprocessing placement and leakage
Use this guide to decide where a preprocessing node belongs relative to the Train-Test Split node. It covers 62 registered preprocessing IDs: 60 transformations and two row-split registrations. Aliases have separate entries because older saved pipelines can contain either spelling.
Placement depends on the configured operation, not just the node's display name. The same node can apply a fixed formula in one configuration and learn a statistic in another. These rules describe supported implementations and parameter modes; they do not guarantee that an arbitrary dataset or experiment is leakage-free.
Start with the training boundary
A practical linear pipeline is:
Loader -> Fixed rules -> Train-Test Split -> Learned preprocessing -> Train / Tune
Learned preprocessing must fit using training rows only. Apply the resulting state to validation, test and inference rows without fitting it again. Examples include scaling statistics, imputation values, category vocabularies, feature selection, bin edges, target statistics and group lookup tables.
Cross-validation introduces an inner boundary. Fit learned preprocessing again inside each training fold, then apply it to that fold's validation rows. A scaler fitted once on the whole outer training set has already seen the inner validation folds. Putting it after the outer split alone does not resolve that problem.
Resampling is stricter: oversampling and undersampling act only on training rows, including the training partition of each CV fold. Do not resample the validation or test population.
Feature-Target Split is not Train-Test Split. Separating X from y does not
reserve any rows for evaluation. TrainTestSplitter and its legacy Split alias
create the row boundary checked by the leakage gate.
Prediction row alignment
SkyulfPipeline.predict() and deployment prediction require one result per
submitted row. If an applied step filters or adds rows, prediction stops with
the step name and before/after counts. For example, an IQR step that reduces
[2, 1000, 4] to two rows cannot return an ambiguous two-element prediction list.
Use row-preserving handling such as Winsorize, or filter the raw input yourself
and retain its row mapping before submitting it.
LagFeatures and RollingAggregate can reorder rows through sort_by. Prediction
also rejects a batch whose order changes in either built-in step; sort the input
as required before submitting it. Temporary position checks stay outside feature
columns and are removed before the next step. Custom transformers remain
responsible for preserving order; the generic guard checks their row counts.
Ordinary FeatureEngineer.transform() and CV/threshold scoring retain configured
filtering and sorting. The prediction guard uses preserve_rows=True and does
not change training, fitted artifacts or validation-label alignment. Existing
splitter, resampling, Deduplicate and DropMissingRows inference skips remain.
Read the placement labels
| Label | Meaning | What to do |
|---|---|---|
| Before split (fixed) | Uses configured rules, schema or a pretrained model without fitting the current dataset. | May precede the split when its inputs and configuration are valid for prediction. |
| Depends on operation | Some configurations are fixed; others learn from data. | Inspect every configured operation and selection rule. |
| After split | Active preprocessing learns state or is conservatively gated. | Fit on training rows and refit inside CV training folds. Resampling is training-only. |
| Time/history review | Uses neighboring or earlier rows without fitting a distribution. | Check ordering, entity groups, horizon, history availability and split strategy. |
| Creates row split | Establishes the train/test row boundary. | Place learned feature preprocessing downstream and choose an appropriate split protocol. |
"Before split" is permission to apply a fixed operation, not a universal safety claim. A ratio that includes the answer, a timestamp recorded after an outcome, or a manual threshold chosen from test results can leak even though the operation fits no statistic. Reporting statistics is not feature fitting, but using test reports to select features or tune a model contaminates the evaluation.
Configuration changes that change placement
General Transformation and Power Transformer
Fixed logarithms, square roots and squares do not fit a parameter from the dataset. Yeo-Johnson and Box-Cox do. Put those learned methods after the row split and fit them within each CV training fold. Turning off standardization does not make the power parameter fixed.
Inspect the entire transformation list. If one entry learns, the mixed node learns. The name "General Transformation" alone cannot establish its placement.
Polynomial Features and its alias
PolynomialFeatures and PolynomialFeaturesNode build a fixed mathematical
basis, but their optional automatic column selection learns from the fitting rows.
| Configuration | Placement |
|---|---|
auto_detect: true, with columns omitted or [] |
After the row split: discover eligible columns from training data only. |
Explicit nonempty columns, even with auto_detect: true |
Before split is allowed: column selection and polynomial math are fixed. |
auto_detect omitted or false |
Before split is allowed: automatic discovery is disabled. |
The registry conservatively marks both aliases as learned; the configured
operation determines placement. FeatureInteraction is a separate fixed node
and does not inherit this automatic-selection rule.
Feature Generation and its aliases
Arithmetic, ratios, similarity and datetime extraction are fixed calculations.
group_agg fits a group lookup on training rows and reuses it on held-out rows.
Unknown groups become missing instead of obtaining statistics from the test batch;
add suitable downstream missing-value handling when needed.
This distinction applies to FeatureGeneration, FeatureGenerationNode and
FeatureMath. A mixed operation list containing a learned group aggregate belongs
after the split, even when its other entries are arithmetic. Fixed expressions
still require inputs that exist at prediction time.
Casting, imputation and column deletion
| Configuration | Placement reason |
|---|---|
| Casting numeric/string/datetime values | Fixed conversion. |
Casting to category/categorical |
Fits a training vocabulary; unseen categories become missing. Resolve per-column overrides first. |
| Simple Imputer with a configured constant | Fixed fill rule. |
| Simple Imputer with mean, median or most-frequent strategy | Fits training statistics. |
| Drop Missing Columns without a positive threshold | Fixed configured deletion. |
Drop Missing Columns with positive missing_threshold |
Learns which columns to remove, even with explicit candidate columns. |
Column selection is part of the operation
Do not treat omitted columns, null and [] as interchangeable:
| Node | Omitted/null selection | Explicit empty selection | Explicit nonempty selection |
|---|---|---|---|
| Custom Binning | Value-based column discovery; learned. | Fixed/no-op. | Configured columns and edges are fixed. |
| Hash Encoder | Automatic selection; conservatively gated. | Fixed/no-op. | Fixed hashing of selected columns. |
| Missing Indicator | Discovers columns containing missing values; learned. | Also automatic discovery; learned. | Fixed indicator columns. |
| Label Encoder | Available target only, or no-op. | Available target only, or no-op. | Feature columns learn mappings; exact known-target selection is exempt. |
| Ordinal Encoder | Discovers and learns feature categories. | Target-only/no-op. | Feature encoding remains learned, including configured category orders; exact known-target selection is exempt. |
| Count and TF-IDF Vectorizers | No-op; no automatic text discovery. | No-op. | Feature text learns vocabulary and, for TF-IDF, IDF. |
| Hashing Vectorizer, Tokenizer, Sentence Embedder | No-op. | No-op. | Fixed processing or pretrained embeddings. |
| Text Cleaning | Discovers text dtypes for fixed cleaning. | No-op. | Fixed cleaning of selected text columns. |
Target-only exemptions require an authoritative target in the current pipeline or branch. A target name from an unrelated branch is not evidence that an encoder is operating only on labels. Text feature processing excludes the authoritative target.
An explicit [] is also a supported no-op for OneHotEncoder, DummyEncoder,
TargetEncoder, WOEEncoder, PowerTransformer, StandardScaler, MinMaxScaler,
MaxAbsScaler, RobustScaler, SimpleImputer, KNNImputer, IterativeImputer,
GeneralBinning, KBinsDiscretizer, CustomBinning, IQR, ZScore, Winsorize
and EllipticEnvelope. This is a specific implementation contract, not a rule to
apply to other nodes. Selectors, resamplers and Missing Indicator do not receive a
general empty-list exemption.
Target encoders, lags and rolling windows
TargetEncoder learns target statistics. Training rows in the pipeline receive
out-of-fold encodings; held-out and inference rows use the full-training artifact.
Unknown categories fall back to the training prior. WOEEncoder uses complement-fold
mappings for training rows and the full-training mapping for held-out rows, with the
configured unknown-category fallback, currently zero. These protections do not remove
the need for the outer row boundary and CV preprocessing refits.
WOE smoothing adds regularization (default 0.5) to every observed category's
count in each target class. Each class total therefore includes
regularization * number_of_observed_categories; missing feature values count as
a category. Cross-fitting uses only the categories in each training complement.
The corrected WOE and Information Value calculations apply to new fits; existing
saved mappings retain their values. Refit the pipeline to use the correction.
LagFeatures and RollingAggregate do not fit a distribution, but they depend on
other rows. Use the correct time ordering, entity groups, prediction horizon and
history protocol. A rolling aggregate includes the current row: a current-target
input can expose the answer directly. A lagged target is useful only when that
target observation is actually available at the intended prediction time. Merely
moving a temporal node after a random split does not establish a valid protocol.
Newly fitted DateFeatures steps extract calendar parts in UTC. For example,
2024-01-01 00:30+02:00 produces year 2023, day 31 and hour 22. Naive dates
are interpreted as UTC without moving their clock time; mixed offsets and DST
transitions follow the same rule on both engines. The original column remains
unchanged unless drop_original is enabled. Saved older artifacts retain their
original engine-specific behavior so an existing model's features do not change
on reload. Refit the complete pipeline to adopt UTC for those models.
Complete registered-node catalog
The placement of learned entries below describes active feature processing. The explicit-empty and target-only exceptions above still apply. Aliases remain separate.
| Registered ID | Placement | Behavior and practical rule |
|---|---|---|
AliasReplacement |
Before split (fixed) | Apply configured/domain aliases to each value; no fitted vocabulary. |
Casting |
Depends on operation | Fixed casts may precede split; categorical vocabularies fit on train. Resolve per-column overrides. |
CorrelationThreshold |
After split | Learn retained columns from training correlations; empty selection still invokes discovery. |
CustomBinning |
Depends on operation | Explicit columns and configured edges are fixed; omitted/null columns learn value-based selection. |
DataSnapshot |
Before split (fixed) | Report a snapshot without changing modeling data; do not tune from held-out reports. |
DatasetProfile |
Before split (fixed) | Report statistics while preserving data; held-out-driven modeling decisions can still leak. |
DateFeatures |
Before split (fixed) | Extract configured calendar fields from each timestamp. |
Deduplicate |
After split | Conservatively gated cross-row filtering. Separately prevent duplicate entities from crossing evaluation splits. |
DropMissingColumns |
Depends on operation | Positive missing threshold learns deletion; otherwise use fixed configured columns. |
DropMissingRows |
Before split (fixed) | Apply fixed per-row missingness rules. Removing evaluation rows changes the scored population. |
DummyEncoder |
After split | Learn training categories and fixed indicator schema; unknown categories yield zeros. |
EllipticEnvelope |
After split | Fit training outlier estimator and reuse it. Filtering held-out rows changes evaluation coverage. |
FeatureGeneration |
Depends on operation | Fixed arithmetic/ratio/similarity/datetime; group_agg learns training lookup. |
FeatureGenerationNode |
Depends on operation | Feature-generation alias with the same mixed-operation rules. |
FeatureInteraction |
Before split (fixed) | Build a polynomial basis from schema and configured options. |
FeatureMath |
Depends on operation | Feature-generation alias; any learned group aggregate makes the node learned. |
GeneralBinning |
After split | Learn bin edges or discretization state on training values and replay them. |
GeneralTransformation |
Depends on operation | Fixed math may precede split; Yeo-Johnson/Box-Cox fit parameters. Inspect all rules. |
GeoDistance |
Before split (fixed) | Compute configured distances from each row's coordinates. |
H3Index |
Before split (fixed) | Map coordinates to cells at a configured resolution. |
HashEncoder |
Depends on operation | Explicit columns use fixed hashing; automatic selection is conservatively gated. |
IQR |
After split | Learn training quartiles and bounds; held-out outliers cannot move them. |
InvalidValueReplacement |
Before split (fixed) | Apply configured invalid-value replacement rules. |
IterativeImputer |
After split | Fit imputation models on training data and reuse them. |
KBinsDiscretizer |
After split | Binning alias; active data-derived modes learn training edges/state. |
KNNImputer |
After split | Fit/store training reference rows; do not use held-out rows as fitting references. |
LabelEncoder |
Depends on operation | Default/empty target-only or no-op; explicit feature columns learn category mappings. |
LagFeatures |
Time/history review | Positive lags require valid ordering, groups, available history and prediction horizon. |
ManualBounds |
Before split (fixed) | Apply supplied bounds; do not choose them by inspecting test outcomes. |
MaxAbsScaler |
After split | Fit training maximum absolute values and reuse the scale. |
MinMaxScaler |
After split | Fit training extrema; held-out extrema cannot redefine the range. |
MissingIndicator |
Depends on operation | Nonempty explicit columns are fixed; omitted/null/[] learns missing-column discovery. |
ModelBasedSelection |
After split | Fit selector/model on training features and targets as required. |
OneHotEncoder |
After split | Fit categories/frequency grouping and preserve the training output schema. |
OrdinalEncoder |
Depends on operation | Default learns feature categories; explicit [] or exact known-target selection is exempt. |
Oversampling |
After split, training only | Resample each training partition only, never validation or test rows. |
PolynomialFeatures |
Depends on operation | auto_detect: true with omitted/empty columns learns column selection; otherwise fixed polynomial math. |
PolynomialFeaturesNode |
Depends on operation | Same automatic-selection rule as PolynomialFeatures; explicit nonempty columns remain fixed. |
PowerTransformer |
After split | Fit Yeo-Johnson/Box-Cox parameters even when standardization is disabled. |
RobustScaler |
After split | Fit robust training location and scale statistics. |
RollingAggregate |
Time/history review | Ordered/grouped rolling features include the current row; current-target input can leak directly. |
SimpleImputer |
Depends on operation | Configured constant is fixed; mean/median/most-frequent fits training statistics. |
SimpleTransformation |
Before split (fixed) | Apply configured simple math without fitting power parameters. |
Split |
Creates row split | Legacy alias of TrainTestSplitter. |
StandardScaler |
After split | Fit training centering/scaling statistics and refit within CV folds. |
TargetEncoder |
After split | OOF training encoding; full-training artifact for held-out/inference, training prior for unknowns. |
TextCleaning |
Before split (fixed) | Fixed per-value cleaning; omitted/null detects text dtypes, [] does nothing. |
TrainTestSplitter |
Creates row split | Create the actual train/test row boundary with a suitable split protocol. |
Undersampling |
After split, training only | Preserve the original validation and test populations. |
UnivariateSelection |
After split | Fit feature scores/selection on training rows and targets as required. |
ValueReplacement |
Before split (fixed) | Apply explicitly configured value replacements. |
VarianceThreshold |
After split | Fit feature variances and selection; [] is not a general no-op exemption. |
WOEEncoder |
After split | Complement-fold training mappings; full-training held-out mapping and configured unknown fallback. |
Winsorize |
After split | Fit training clipping limits; held-out extreme values cannot change them. |
ZScore |
After split | Fit training location/scale and reuse the stored outlier rule. |
count_vectorizer |
Depends on operation | Nonempty feature selection learns vocabulary; omitted/null/[] is no-op. |
feature_selection |
After split | Dispatch to configured learned selector; preserve training-only and fold-refit boundaries. |
feature_target_split |
Before split (fixed) | Separate X from y; this is not a train/test row boundary. |
hashing_vectorizer |
Before split (fixed) | Fixed hash space; explicit nonempty text columns required. |
sentence_embedder |
Before split (fixed) | Apply pretrained embeddings; explicit nonempty columns required, external model provenance remains separate. |
tfidf_vectorizer |
Depends on operation | Nonempty feature selection learns vocabulary/IDF; omitted/null/[] is no-op. |
tokenizer |
Before split (fixed) | Fixed tokenization; explicit nonempty text columns required. |
Supported graph shapes and current policy
Prefer a linear chain when the feature operations are sequential. Backend fold reconstruction also supports these branch forms when their requirements hold:
- A common row splitter forks into linear transformer branches that preserve row alignment and join directly into the model. Avoid additional splitters, nested merges and disallowed row-changing steps in the branches.
- Genuinely fixed branches from a shared loader merge at the first row splitter, followed by a reconstructable downstream chain. The resolver retains merged raw input and outer training row selection for fold-local fitting.
Supported topology does not establish correct feature ownership. Preserve intended column selection and merge order; overlapping outputs can replace earlier branch columns. A join into an intermediate encoder is not the same supported form as a direct join into the model. See the core/backend guide for diagrams and exact reconstruction requirements.
With the default raise policy, a detected definite preprocessing-placement
violation is rejected by the backend admission gate with HTTP 400 and no jobs
created. Unsupported fold reconstruction involving learned preprocessing also
stops execution by default, but that capability failure can occur after a job has
been created. These are separate outcomes.
Explicit metadata.on_leakage="warn" or "ignore" can permit the legacy fallback
to pre-transformed data. Its CV scores can be optimistically biased, and its
fold_refit_fallback diagnostic describes the missing guarantee. Choosing a weaker
policy does not make the graph reconstructable or repair the statistical problem.
Read the Leakage Gate and Fold Refit Audit separately. Green results provide evidence for the checks performed, not proof of feature provenance, entity independence, valid temporal assumptions or an untouched test-selection process.
Core-only CV callers must fit a fresh pipeline on each fold's raw training partition; cross-validating an estimator over a globally preprocessed matrix does not automatically refit the core preprocessing steps.
Where to use this reference
The canvas How pipelines work dialog contains a searchable Preprocessing & Leakage tab with the same registered-node coverage. Search by display name, registry ID, category or operation, and filter by placement.
For implementation evidence and the exact fit/apply contracts, see the preprocessing leakage audit. For graph diagrams, admission and fold-reconstruction details, see Leakage: core and backend.