This page shows the chapter notebook with its saved results. Constructed examples do not measure competition gains.
Chapter 8: The Five-Stage Feature Engineering Process
Try the decision first
When the target is multiplicative and skewed, does fitting log1p(y) help, and does the answer depend on the metric and on how the prediction is brought back to the raw scale?
Write your expectation before opening the worked results. Use the chapter activity to compare supported inputs. To change the calculation itself, run the notebook on GitHub.
Your answers stay on this page until you download them. They are not sent to a server.
Worked notebook and saved results
When the target is multiplicative and skewed, does fitting log1p(y) help, and does the answer depend on the metric and on how the prediction is brought back to the raw scale?
A skewed target tempts a log transform, but the chapter warns that exponentiating a mean log prediction need not recover the raw-scale conditional mean. Measuring both metrics on the same new rows shows which policy each metric rewards.
Constructed data with log-normal noise; the sizes of these gaps are properties of this generator. No policy wins every metric, and with this multiplicative noise the raw-target fit is never a clear winner.
The experiment
A constructed regression with 5 features and a log-normal target, y = exp(f(x) + s * noise), where the noise spread s is the control. A histogram gradient boosting regressor is trained on 6,000 rows under three policies: fit y directly; fit log1p(y) and take expm1 of the prediction; and fit log1p(y) with a smearing correction that averages expm1(m + e) over cross-fitted log residuals e. A constant (the training mean) is the simple predictor. Each is scored on 8,000 new rows from the same generator by raw-scale RMSE and by RMSLE, the square root of the mean squared difference of log1p values. Every score is the mean over 8 constructed datasets.
Calculation code
import numpy as np
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import KFold
from kaggle_companion.activities._common import clean
SEED = 8
REPLICATES = 8 # independent constructed datasets; every score is their mean
N_TRAIN, N_NEW = 6000, 8000
def generate(n, sigma, rng):
"""Five features; the target is multiplicative: y = exp(f(x) + sigma * noise). exp(f) is its median."""
X = rng.normal(size=(n, 5))
f = 3.0 + 0.8 * X[:, 0] + 0.5 * X[:, 1] - 0.4 * X[:, 2] + 0.3 * X[:, 0] * X[:, 1]
y = np.exp(f + sigma * rng.normal(size=n))
return X, y, f
def model():
return HistGradientBoostingRegressor(max_iter=100, learning_rate=0.08, max_depth=3, min_samples_leaf=30, random_state=0)
def rmse(y, p):
return float(np.sqrt(np.mean((y - p) ** 2)))
def rmsle(y, p):
return float(np.sqrt(np.mean((np.log1p(y) - np.log1p(np.maximum(p, 0))) ** 2)))
def one_dataset(sigma, seed):
rng = np.random.default_rng(seed)
X, y, _ = generate(N_TRAIN, sigma, rng)
X_new, y_new, f_new = generate(N_NEW, sigma, rng)
raw = model().fit(X, y).predict(X_new) # policy 1: fit y directly, squared error on the raw scale
log_y = np.log1p(y) # policy 2: fit log1p(y), then undo the transform
m_new = model().fit(X, log_y).predict(X_new) # predicted mean of log1p(y)
naive = np.expm1(m_new) # exponentiate the mean log prediction
oof = np.zeros(N_TRAIN) # policy 3: smearing. Cross-fitted log residuals e_i give
for a, b in KFold(5, shuffle=True, random_state=0).split(X): # mean(expm1(m + e_i)) = exp(m) * mean(exp(e_i)) - 1
oof[b] = model().fit(X[a], log_y[a]).predict(X[b])
smear = np.exp(m_new) * np.mean(np.exp(log_y - oof)) - 1.0
policies = {"raw_fit": raw, "log_naive": naive, "log_smeared": smear, "constant": np.full(N_NEW, y.mean())}
out = {k: {"rmse": rmse(y_new, p), "rmsle": rmsle(y_new, p), "mean_prediction": float(np.mean(p))}
for k, p in policies.items()}
out["known_mean"] = {"rmse": rmse(y_new, np.exp(f_new + sigma ** 2 / 2)), "rmsle": rmsle(y_new, np.exp(f_new + sigma ** 2 / 2))}
out["known_median"] = {"rmse": rmse(y_new, np.exp(f_new)), "rmsle": rmsle(y_new, np.exp(f_new))}
out["mean_target"] = float(np.mean(y_new))
return out
def run(sigma):
sets = [one_dataset(sigma, SEED * 100 + i) for i in range(REPLICATES)]
result = {"sigma": sigma, "replicates": REPLICATES, "training_rows": N_TRAIN, "new_rows": N_NEW,
"mean_target": float(np.mean([s["mean_target"] for s in sets]))}
for name in ("raw_fit", "log_naive", "log_smeared", "constant", "known_mean", "known_median"):
result[name] = {m: float(np.mean([s[name][m] for s in sets])) for m in sets[0][name]}
result[name]["rmse_per_set"] = [s[name]["rmse"] for s in sets]
result[name]["rmsle_per_set"] = [s[name]["rmsle"] for s in sets]
return clean(result)
Measure it across the control
The control is multiplicative noise spread s (standard deviation of the log-scale noise). Each value below runs the whole experiment from the generator up.
Calculation code
import pandas as pd
from kaggle_companion.activities.ch08 import explain
VALUES = [0.3, 0.8, 1.2, 1.6]
results = {value: run(value) for value in VALUES}
table = pd.DataFrame({str(v): explain(results[v], v)['metrics'] for v in VALUES})
print(table.to_string())0.3 0.8 1.2 1.6 RMSLE, plain log fit 0.297 0.749 1.099 1.433 RMSLE, raw-target fit 0.679 1.034 1.468 2.014 RMSE, plain log fit 93.8 213.1 530.5 1864.3 RMSE, smeared log fit 92.0 203.4 510.0 1829.3 RMSE, raw-target fit 102.9 214.3 524.2 1854.9 Mean prediction, plain log fit 38.8 39.2 39.7 40.7
Look at it
The figure shows the default setting, multiplicative noise spread s (standard deviation of the log-scale noise) = 0.8.
Calculation code
import matplotlib.pyplot as plt
from kaggle_companion.activities.ch08 import draw, NCOLS, HEIGHT
DEFAULT = 0.8
fig, axes = plt.subplots(1, NCOLS, figsize=(6.6 if NCOLS == 1 else 10.4, HEIGHT), layout='constrained')
draw(axes, results[DEFAULT], DEFAULT)
plt.show()What the result says
At noise spread 0.8, the plain log fit scores RMSLE 0.749 (raw-target fit 1.034) but its predictions average 39.2 against a target mean of 58.6, so 39.2 / 58.6 = 0.669 of the mean is recovered. The smearing correction lowers RMSE from 213.1 to 203.4 and raises RMSLE from 0.749 to 0.804. The raw-target fit has RMSE 214.3 and the constant 256.7.
- Mean recovered by the plain back-transform: 39.2 / 58.6 = 0.669.
- Gain of smearing on RMSE: 213.1 - 203.4 = +9.7 (positive means smearing is better).
- Cost of smearing on RMSLE: 0.804 - 0.749 = +0.055 (positive means smearing is worse).
- Raw-target fit against the plain log fit on RMSLE: 1.034 - 0.749 = +0.286.
Apply this to your competition
- Read which metric scores the competition before deciding whether to transform the target at all.
- If the metric is RMSLE or another log-scale loss, fit log1p(y) and invert it plainly; if it is raw-scale RMSE, test a smearing-style correction.
- Check the average of your predictions against the average of the training target; a large shortfall means the inverse policy is off.
- Keep a raw-target fit and a constant predictor as comparators, and choose the transform inside development, not on the assessment rows.
Book location: Chapter 8, Stage 4: Target Transforms.
Apply a lesson from this chapter
Select a lesson whose conditions match your project. State how you would test it and what would make you reject it.
Cache repeated feature work in a columnar format
Conditions
- large click datasets are repeatedly loaded during feature experiments
Action
- Proposed adaptation of source observation: Benchmark and cache stable datasets and features in a columnar format.
Check
- Proposed verification: Verify dtype, row-order and null-value equivalence and measure repeated read time.
Limits
- The speed claim is qualitative and tied to the author’s environment.
Use binary-group sums and sparse interactions as explicit hypotheses
Conditions
- small anonymized binary data suggest structured interactions
Action
- Proposed adaptation of source observation: Compare grouped sums and a bounded set of interactions against the original-feature baseline.
Check
- Proposed verification: Perform selection within folds and test arbitrary frequency thresholds and assumed grouping.
Limits
- Feature-name groups and process explanations are hypotheses, not verified subprocess identities.
Turn simulation outputs into learned proxy features
Conditions
- simulation labels are too noisy to use directly as targets
- external simulation labels may have nonlinear bias and quality mismatch
Action
- Proposed conditional application: Train proxy models on simulation results and feed their predictions as tabular features for the final model.
- Proposed adaptation of source observation: Compare model-predicted simulation features with direct noisy labels and evaluate target quality on trusted host labels.
Check
- Proposed check: Generate proxy predictions independently of held-out host labels and ablate them on fixed host-domain folds, including simulation and serving cost.
- Proposed verification: Keep simulation predictors OOF where trained on matching samples and use the same host folds for alternatives.
Limits
- Reported improvement is small; simulation setup and proxy training are substantial and simulation reliability is uncertain.
- The packet does not detail first-stage isolation; external-label gains do not prove simulation correctness.
Compare business-level pooling of photo features
Conditions
- multiple restaurant photos map to one business label
Action
- Proposed adaptation of source observation: Compare mean pooling with encoded photo-set representations using fixed photo features.
Check
- Proposed verification: Split validation by business and compare aggregation methods on identical photo sets.
Limits
- The packet describes pipeline alternatives without selected settings or ablations.
Preserve fluctuations before grouping repeated records
Conditions
- aggregation by identifier discards within-group variation
Action
- Proposed conditional application: Compute fractions and differences before grouping, then aggregate with mean, sum, min, max, standard deviation, percentiles and median.
Check
- Proposed check: Compare grouped means with pre-group difference/ratio statistics on identifier-separated holdouts; ensure records exist at prediction time.
Limits
- Grouping may pool unavailable future records; undefined claimed boost is not exported as numeric evidence.
Hash raw values and selected feature interactions consistently
Conditions
- categorical or discretized values require a bounded feature index space
Action
- Proposed: encode field identity with values and hash selected pairwise interactions using a reproducible hash.
Check
- Proposed: use a stable hash or persist the hashing environment and verify train/inference indices; compare interaction selection and collisions on an independent validation split.
Limits
- Stable hashing is a proposed correction. Numeric inputs are treated as categorical strings, repeated column positions can yield repeated interaction slots, and no improvement or memory measurement is supplied.
Evaluate compression before photo-set descriptor construction
Conditions
- set descriptors consume high-dimensional image embeddings
Action
- Proposed adaptation of source observation: Evaluate feature normalization and training-fitted PCA before constructing image-set descriptors.
Check
- Proposed verification: Fit compression on training data and report descriptor memory, runtime and held-out loss.
Limits
- PCA dimensions and fitting procedure are absent; preprocessing effectiveness is not quantified.
Pool small categorical groups before fitting
Conditions
- categorical predictors contain rare levels with limited support
Action
- Proposed adaptation of source observation: Evaluate pooling rare training categories into a shared level.
Check
- Proposed verification: Choose thresholds within training folds and check minority-category performance.
Limits
- The source does not specify pooling thresholds or give a controlled comparison.
- Source author Jeremy Howard explicitly disclaims prize eligibility; prize winner is Quan Sun. First-place model rank remains unverified source metadata, distinct from prize award.
Verify feature construction on a small dataset before scaling
Conditions
- feature generation on a very large click dataset is expensive
Action
- Proposed adaptation of source observation: Exercise each new feature generator on a small representative fixture before generating the full feature cache.
Check
- Proposed verification: Check row counts, types, missing values and grouping boundaries before scaling.
Limits
- A small fixture can miss rare full-data failure modes; the source does not quantify saved compute.
Keep labels out of unsupervised filtering
Conditions
- anomaly filtering is applied to labeled tabular rows
Action
- Proposed: fit anomaly detection on predictor columns and audit which classes are removed.
Check
- Proposed: compare feature-only filtering with the observed label-inclusive filtering on an untouched held-out set and report class removal rates.
Limits
- Feature-only fitting is proposed corrective synthesis. The source includes target labels in anomaly fitting and provides no evidence of improved generalization.
Reuse fitted clipping thresholds at inference
Conditions
- tabular predictors have extreme upper tails
Action
- Proposed: fit clipping quantiles on training predictors and reuse the same thresholds for inference.
Check
- Proposed: fit thresholds inside each validation fold and compare clipping with no clipping; persist column order and thresholds.
Limits
- The script independently recodes categories and imputes using each dataset statistics. The clipping consistency does not make its entire preprocessing consistent.
Fit feature preprocessing only on the training partition
Conditions
- numeric scaling and category encoding precede validation and test predictions
Action
- Proposed: fit one preprocessing pipeline on training rows and reuse its transform for all other partitions.
Check
- Proposed: persist fitted column/category order and define unknown-category handling; assert partition IDs are disjoint.
Limits
- The random splits are stratified by state and do not establish temporal generalization. OneHotEncoder has no shown unknown-category handling.
Construct target summary features inside validation folds
Conditions
- entity aggregates summarize the prediction target
Action
- Proposed: fit target aggregates using training-fold labels only and define unseen-entity fallbacks.
Check
- Proposed: rebuild aggregate features per fold and compare against the global-feature CV; preserve test/train membership explicitly instead of inferring it from zero quantity.
Limits
- Fold-local aggregates are proposed correction. Invoice total price and quantity also include the target; transductive text fitting and target-zero split membership require separate audits.
Fit imputation only on training data
Conditions
- train and test need missing-value handling
Action
- Proposed conditional application: Fit the imputer on training only and apply it to both training and test sets.
Check
- Proposed check: Assert fit indices exclude validation/test rows and repeat fitting separately inside each CV fold.
Limits
- Training-only fitting does not by itself prevent patient or temporal leakage.
Audit subgroup target rates to locate date and missingness signals
Conditions
- tabular application data contain calendar and missingness patterns
Action
- Proposed adaptation of source observation: Inspect target rates by calendar group and missingness state to generate candidate features.
Check
- Proposed verification: Require sufficient group support and verify effects on a held-out period before selecting them.
Limits
- Exploratory target-rate inspection is not held-out evidence; application processing features require an availability check.
- Source author Jeremy Howard explicitly disclaims prize eligibility; prize winner is Quan Sun. First-place model rank remains unverified source metadata, distinct from prize award.
Separate a continuous value’s missingness from its imputed level
Conditions
- missingness itself may predict the target
Action
- Proposed adaptation of source observation: Keep a binary missingness indicator while imputing the numeric value with a training-fitted median.
Check
- Proposed verification: Fit imputation inside each fold and compare against imputation alone.
Limits
- No isolated gain is reported and deployment missingness may differ.
- Source author Jeremy Howard explicitly disclaims prize eligibility; prize winner is Quan Sun. First-place model rank remains unverified source metadata, distinct from prize award.
Compress the tail of count features
Conditions
- heavy-tailed count features in hashed categorical inputs
Action
- Proposed: keep small exact counts and use integer logarithm buckets for larger counts.
Check
- Proposed: compare exact and log-bucketed counts on time-matched validation, tracking hashed feature cardinality.
Limits
- The boundary and logarithm base are implementation choices, not validated universal defaults.
Audit sample retention after feature joins
Conditions
- multiple auxiliary tables do not cover every prediction entity
Action
- Proposed: preserve the base entity manifest and check missing or duplicated rows at every merge.
Check
- Proposed: use explicit ID joins for output, assert uniqueness and count missing entities after each merge, and decide missing-feature fallback deliberately.
Limits
- Base-manifest preservation is proposed. Inner joins may drop inactive users, and auxiliary date availability is not established.
Audit availability of label-history features
Conditions
- transaction features use nearby known fraud labels
Action
- Proposed: restrict label-history features to information available before prediction and reconstruct them within validation folds.
Check
- Proposed: reconstruct features on a forward-time holdout using only labels that would have been known at each prediction time; remove next-fraud features for prospective deployment.
Limits
- This is a proposed audit of source code, not an observed leakage-safe implementation. The shown code also contains malformed indentation and undefined dependencies; no reliable execution or gain is inferred.
Condition identifier detail on observed frequency
Conditions
- high-cardinality device identifiers with sparse counts
Action
- Proposed: retain frequent identifier tokens while replacing rare identifiers with count-based tokens.
Check
- Proposed: compute counts using an allowed training history; compare thresholds on forward-time validation and inspect unseen identifiers.
Limits
- Thresholds are source-specific examples and upstream count construction is not shown. No isolated improvement is documented.
Inspect record ordering in auxiliary event tables
Conditions
- multiple anonymized log tables accompany a prediction task
Action
- Proposed conditional application: Test whether auxiliary record order encodes useful chronology or grouping, then audit that ordering is available in future data.
Check
- Proposed check: Shuffle auxiliary-table order, test timestamp/order features under future-time validation, and verify ordering survives the production ingest.
Limits
- File order may be a competition artifact or leakage; source gives no exact order-feature formula.
Keep transformations defined beyond fitted minima
Conditions
- new physical data extends below the original normalization minimum
Action
- Proposed conditional application: Use a signed log-like branch below the reference minimum instead of an undefined ordinary log, preserving old normalization constants.
Check
- Proposed check: Test domain, continuity, finite values and gradients around threshold/extremes; compare old/new-data distributions.
Limits
- Fixed constants preserve compatibility but can misnormalize shifted distributions; eager inactive branches need numerical checks.