Computes leak-free target encoding statistics (mean, std, min, max) using nested inner KFold within each outer CV fold, preventing target leakage that occurs with naive groupby-based encoding.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add wenmin-wu/ds-skills --skill inner-kfold-target-encoding --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Inner Kfold Target Encoding?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/wenmin-wu-inner-kfold-target-encoding)More formats (shields.io, HTML) on the badges page.
---
name: tabular-inner-kfold-target-encoding
description: >
Computes leak-free target encoding statistics (mean, std, min, max) using nested inner KFold within each outer CV fold, preventing target leakage that occurs with naive groupby-based encoding.
---
# Inner KFold Target Encoding
## Overview
Naive target encoding leaks information because the target statistics for a row's category include that row's own target value. This skill uses a nested (inner) KFold loop: within each outer training fold, an inner 5-fold CV computes category-level aggregates only on held-in data, then applies them to the held-out inner fold. The result is a leak-free set of TE features (mean via sklearn, std/min/max via groupby).
## Quick Start
```python
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import TargetEncoder
import pandas as pd
outer_cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
inner_cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for train_idx, val_idx in outer_cv.split(X, y):
X_tr, X_val = X.iloc[train_idx], X.iloc[val_idx]
y_tr = y.iloc[train_idx]
# Mean TE via sklearn (handles inner CV internally)
te = TargetEncoder(cv=5, smooth="auto")
X_tr_te = te.fit_transform(X_tr[cat_cols], y_tr)
X_val_te = te.transform(X_val[cat_cols])
# Std/Min/Max TE via inner KFold
for col in cat_cols:
oof_stats = pd.DataFrame(index=X_tr.index)
for in_tr, in_val in inner_cv.split(X_tr, y_tr):
stats = X_tr.iloc[in_tr].groupby(col)[target].agg(['std','min','max'])
mapped = X_tr.iloc[in_val][[col]].join(stats, on=col)
oof_stats.loc[mapped.index] = mapped[['std','min','max']].values
# Val/test: use full outer-fold training stats
full_stats = X_tr.groupby(col)[target].agg(['std','min','max'])
X_val[[f'{col}_std', f'{col}_min', f'{col}_max']] = \
X_val[[col]].join(full_stats, on=col)[['std','min','max']].values
```
## Workflow
1. Define outer `StratifiedKFold(n_splits=5)` for model evaluation
2. For each outer fold, split into train/val
3. Run inner `StratifiedKFold(n_splits=5)` on the outer training set
4. Inner folds: `groupby(cat_col)[target].agg(['std','min','max'])` on held-in, apply to held-out
5. For val/test: compute stats on the full outer training set and map
6. Use `sklearn.TargetEncoder(cv=5)` for mean TE (it does its own internal CV)
7. Concatenate all TE features with original features for model training
## Key Decisions
- **Why nested CV?** Single-fold groupby leaks target info into training rows, inflating CV scores
- **Why std/min/max separately from mean?** sklearn's TargetEncoder only provides mean; additional statistics add signal for tree models
- **Fill NaN stats** with global target mean/std for unseen categories
- **Inner folds = 5** balances computation cost with stable estimates
## References
- Source: "S6E3 Detail EDA + Baseline XGB" (Kaggle Playground Series S6E3)
- sklearn TargetEncoder docs: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.TargetEncoder.html
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!