Suffolk University • Sawyer Business School

Feature Engineering & Leak-Proof Pipelines

Encoders, scalers, imputers, and the scikit-learn Pipeline — the machinery that turns a messy table into a model input without ever peeking at the test set

Session 3 of 13 · Mon Sep 28
Module: Data & Features
150 Minutes
Mondays 5:00 PM
Hands-On Learning
01 // LEARNING OBJECTIVES

What You'll Learn Today

By the end of tonight you'll have both the concept and the working code — every objective maps to a cell you run yourself.

01

Build a ColumnTransformer + Pipeline

Numeric columns get imputed and scaled, categorical columns get encoded, and the model sits at the end — one object that fits on train and transforms test, so leakage becomes structurally impossible.

02

Choose the Right Encoder

One-hot for a handful of categories, ordinal when order is real, target encoding for 3,000 zip codes — and why the last one must be fit inside cross-validation.

03

Know When Scaling Matters

Logistic regression, kNN, and SVMs care about scale; trees do not. Scale where it counts, and always after the split.

04

Engineer Features From Domain Knowledge

Ratios (charges per month of tenure), buckets, datetime parts, and interaction terms — the features a good analyst invents are usually worth more than the algorithm choice.

02 // SESSION AGENDA

Today's Journey

A business question, a dataset, a model — and the judgment to evaluate it.

5:00 PM - 5:20 PM

The Wrong Way, Live

20 minutes

Where the Churn Detective left off: the columns you would not know on sign-up day, and why that matters. Then the classic mistake live: scale the whole dataset, then split. The score looks great. It is a lie.

  • Anything that learns from data — a scaler, an imputer, an encoder — is a model and must be fit on training data only
  • Rule of the semester: split first, then fit everything on the training fold
5:20 PM - 5:40 PM

Meet the Data: Bank Marketing

20 minutes

45,211 phone calls from a Portuguese bank's term-deposit campaign, 16 features, 11.7% said yes. Numeric and categorical columns mixed together, one column ('duration') that is pure leakage — and a business question: who should the call center dial first?

  • Call duration is known only after the call ends — the outcome is already decided. Drop it
  • Ten categorical columns: job, marital, education, contact, month, outcome of the previous campaign…
5:40 PM - 6:05 PM

Encoders: One-Hot, Ordinal, Target

25 minutes

Categories are text; models need numbers. OneHotEncoder for 'job' (12 values), OrdinalEncoder for education (order is real), and TargetEncoder for high-cardinality columns — with the cross-fitting trick that keeps it from leaking the label.

  • handle_unknown='ignore': production will always show you a category you never saw
  • TargetEncoder in scikit-learn ≥ 1.3 cross-fits internally — that is why it is safe inside a pipeline and a hand-rolled groupby mean is not
6:05 PM - 6:15 PM

Break

10 minutes

Stretch, coffee, compare notes on the Churn Detective and HW1 (due next Monday).

6:15 PM - 6:45 PM

The Pipeline, Assembled

30 minutes

ColumnTransformer routes each column to its transformer; Pipeline chains preprocessing to the model; cross_val_score evaluates the whole thing honestly. One object, one fit call, zero leakage — and set_output(transform='pandas') keeps column names readable.

  • The HTML display of a fitted pipeline shows every branch — read it like a wiring diagram
  • Swap the last step from LogisticRegression to HistGradientBoosting and nothing else changes: that is the payoff
6:45 PM - 7:15 PM

Feature Engineering From Domain Knowledge

30 minutes

Back to Telco: charges-per-tenure-month, a 'new customer' flag, a count of add-on services, contract × payment interactions. Each one is a hypothesis about why customers leave. We add them with FunctionTransformer and measure whether AUC moves.

  • A feature is a hypothesis: 'customers on month-to-month contracts paying by electronic check churn more' becomes a column
  • skrub's TableVectorizer: the 2025 shortcut that guesses sensible encoders for every column
7:15 PM - 7:30 PM

Wrap-Up & Next Week

15 minutes

The reusable template: ColumnTransformer → Pipeline → cross_val_score. Next week we point it at 30,000 credit-card customers and learn to predict who defaults.

  • Practice item: rebuild your HW1 model as a Pipeline and confirm the score does not change
  • Reading for Session 4: ISLP Chapter 4 (Classification), 4.1–4.3
03 // INTERACTIVE RESOURCES

Tools & Learning Materials

Notebooks, readings, explorers, and the stories behind the methods.

Hands-On

Session 3 Notebook — Leak-Proof Feature Pipelines

The wrong way and the right way side by side, then the full ColumnTransformer + Pipeline on Bank Marketing, target encoding, and engineered Telco features with before/after AUC.

Open in Colab
In Class

Session 3 Class Notebook — What We Type Together

Tonight's live notebook: pandas continued from where Session 2 stopped — describe, value_counts, sorting, loc/iloc, new columns, missing values, groupby — on Titanic first, then the same moves on Telco through to who to call first.

Open in Colab
Hands-On

The Churn Detective — a self-checking case file (HW1 companion)

Seven case files on the Telco data, one per part of Homework 1: the tampered TotalCharges column, groupby interrogations, engineered clues, the sign-up-day time machine, a model that beats the baseline, and framing your own prediction problem. Guess before you run, then a check cell prints ✓. 60–90 minutes; ends with a scorecard.

Open in Colab
Reading

scikit-learn User Guide — Preprocessing Data

The reference for every transformer we use tonight: StandardScaler, OneHotEncoder, OrdinalEncoder, TargetEncoder, and the imputers. Bookmark it.

Open the guide
Reading

Inria scikit-learn MOOC — Handling Categorical Data & Pipelines

The course taught by scikit-learn's own developers. The 'Predictive modeling pipeline' module is the best free walkthrough of ColumnTransformer that exists.

Open the MOOC
Go Deeper

Kaggle Learn — Feature Engineering

Four short lessons: mutual information, creating features, k-means features, and target encoding. Ninety minutes, free, with exercises.

Start the course
Tool

skrub — Machine Learning With Dataframes

TableVectorizer picks an encoder for every column automatically; the Cleaner handles dates and dirty strings. The 2025 answer to 'I have a table, give me features.'

See the docs
Story

Story: Why Call Duration Is the Most Famous Leak in ML

The Bank Marketing dataset's own documentation warns that 'duration' should be discarded for a realistic model — the outcome is known once the call ends. A leak so well known it comes with a label.

Read the dataset notes
Video

StatQuest — One-Hot Encoding & Feature Scaling

Search the StatQuest index for 'one-hot' and 'standardization'. Ten minutes each, and the pictures stick.

Open the index
Refresher

Refresher: Data Visualization With matplotlib & seaborn (ISOM 730 notebook)

Prof. Arslan's earlier notebook on line plots, scatter plots, histograms, and seaborn pair plots — the tools you use to decide which features to engineer. Hosted in the course repo — opens in Colab with one click.

Open in Colab
04 // HANDS-ON ACTIVITIES

Learning by Doing

Open the notebook and build it with us.

Activity 1

One Pipeline to Rule Them All

Build a single scikit-learn object that imputes and scales the numeric columns, one-hot encodes the categoricals, and fits a logistic regression on the Bank Marketing data — then evaluate it with 5-fold cross-validation without leaking a single row.

1

Separate the column types

select_dtypes(include='number') for numeric, the rest for categorical. Drop 'duration' — it is known only after the outcome.

2

Wire the ColumnTransformer

Numeric branch: SimpleImputer(median) → StandardScaler. Categorical branch: OneHotEncoder(handle_unknown='ignore').

3

Chain the model

Pipeline([('prep', preprocessor), ('model', LogisticRegression(max_iter=1000))]). Display it — read the wiring diagram.

4

Evaluate honestly

cross_val_score with StratifiedKFold(5) and scoring='roc_auc'. Every fold fits the scaler and encoder on its own training portion.

python
from sklearn.datasets import fetch_openml
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score, StratifiedKFold

bank = fetch_openml('bank-marketing', version=1, as_frame=True)
X, y = bank.data, (bank.target == '2').astype(int)   # '2' = subscribed
X = X.drop(columns=['V12'])                          # V12 = call duration: leakage

num = X.select_dtypes(include='number').columns
cat = X.columns.difference(num)

prep = ColumnTransformer([
    ('num', Pipeline([('imp', SimpleImputer(strategy='median')), ('sc', StandardScaler())]), num),
    ('cat', OneHotEncoder(handle_unknown='ignore'), cat),
])
model = Pipeline([('prep', prep), ('clf', LogisticRegression(max_iter=1000))])

scores = cross_val_score(model, X, y, cv=StratifiedKFold(5, shuffle=True, random_state=835), scoring='roc_auc')
print(f'AUC: {scores.mean():.3f} ± {scores.std():.3f}')

Notice that the model line is the least interesting part. Swap LogisticRegression for HistGradientBoostingClassifier and every other line stays put — the pipeline is the asset, the model is a parameter. And notice what dropping duration costs: AUC falls from the low 0.90s to the high 0.70s. The honest number is the one you can act on before the phone rings.

05 // KEY TAKEAWAYS

What to Remember

Every preprocessing step that learns from data — scalers, imputers, encoders — is a model. Fit it on the training fold only, and let a Pipeline enforce that for you.

Encoders are choices, not defaults: one-hot for few categories, ordinal when order is real, target encoding (cross-fit) for many categories. handle_unknown='ignore' because production will surprise you.

A feature is a hypothesis about the business. Charges per tenure-month, add-on counts, contract × payment interactions — the features you invent from domain knowledge usually move the score more than the algorithm you pick.

06 // HOMEWORK

Before Next Session

Complete these before next Monday — they are the practice that makes the next session land.

Practice (ungraded) + Reading Before Session 4 (Mon Oct 5): rebuild your HW1 Telco model as a Pipeline with a ColumnTransformer and confirm the cross-validated AUC matches what you reported. Then add three engineered features of your own design (at least one ratio, at least one interaction) and note whether AUC moves. Read ISLP Chapter 4 (Classification), sections 4.1–4.3 — we predict who defaults on a credit card next week.
07 // PRACTICE

Test Yourself

Exam-style questions for the ideas in this session — Data & Leak-Proof Features. Every wrong answer names the misconception behind it.

Q07 The feature that makes your model brilliant offline and useless live. Q08 One-hot, ordinal, or target encoding for 3,000 zip codes? Q09 A column with too many categories — keep it, drop it, or encode it smarter? Q10 Six candidate features for a readmission model. One of them is from the future. Q11 Two students, same scaler, different order of operations. One of them leaked. Q12 The blanks default at 31%. What do you do with a missing value that talks?

All of Features →

Coming Next

Session 4: Classification — Predicting Yes/No

Logistic regression as odds, kNN and Naive Bayes as contrasts, the confusion matrix in depth, precision vs. recall, ROC vs. PR curves, and what to do when only 22% of your credit-card customers default.

ClassificationLogistic RegressionROC & PR