By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A Hyper-Practical, Zero-Fluff Study Guide
You’re building a production-grade ML pipeline for a retail client. Your raw data has: - Numerical features (e.g., price, quantity) that need scaling.- Categorical features (e.g., product_category, region) that need one-hot encoding.- Text features (e.g., product_description) that need TF-IDF vectorization.- Missing values that need imputation.
price
quantity
product_category
region
product_description
If you process each feature manually, your code becomes: - Brittle: A single change in the data schema (e.g., a new column) breaks everything.- Hard to maintain: You’ll have 10+ lines of preprocessing logic scattered across notebooks.- Non-reproducible: Your training and inference pipelines diverge, leading to silent failures in production.
Enter Pipeline, ColumnTransformer, and FeatureUnion:- Pipeline: Chains preprocessing and modeling steps into a single object. Ensures consistent transformations during training and inference.- ColumnTransformer: Applies different transformations to different columns (e.g., scale numerics, encode categories). No more manual column splitting.- FeatureUnion: Combines multiple feature extraction steps (e.g., text + numerical features) into a single output.
Pipeline
ColumnTransformer
FeatureUnion
Why this matters in production:1. Avoids data leakage: Ensures preprocessing (e.g., scaling) is fitted only on training data, not the entire dataset.2. Simplifies deployment: Your entire preprocessing + model logic is a single pickle file.3. Enables CI/CD for ML: Pipelines can be versioned, tested, and deployed like any other code.
pickle
Real-world scenario:You inherit a legacy notebook where preprocessing is done in 50+ lines of pandas code. Your task: - Refactor it into a reusable, maintainable pipeline.- Deploy it to AWS SageMaker or FastAPI without breaking inference.
pandas
StandardScaler
OneHotEncoder
TfidfVectorizer
SimpleImputer
MinMaxScaler
handle_unknown="ignore"
FunctionTransformer
df["log_price"] = np.log(df["price"])
make_pipeline
make_column_transformer
("scaler", StandardScaler())
scikit-learn
numpy
pip install scikit-learn pandas numpy
Goal: Process a retail dataset with: - Numerical features: price, quantity - Categorical features: product_category, region - Text feature: product_description - Missing values in price and region
import pandas as pd # Sample data (replace with your CSV) data = { "price": [10, 20, None, 40, 50], "quantity": [1, 2, 3, 4, 5], "product_category": ["A", "B", "A", "C", "B"], "region": ["North", "South", None, "East", "West"], "product_description": ["great product", "okay product", "bad product", "awesome", "meh"] } df = pd.DataFrame(data) print(df.head())
from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline # Numerical pipeline: impute missing values + scale numeric_features = ["price", "quantity"] numeric_transformer = Pipeline([ ("imputer", SimpleImputer(strategy="median")), # Fill missing with median ("scaler", StandardScaler()) # Scale to mean=0, std=1 ]) # Categorical pipeline: impute missing + one-hot encode categorical_features = ["product_category", "region"] categorical_transformer = Pipeline([ ("imputer", SimpleImputer(strategy="most_frequent")), # Fill missing with mode ("encoder", OneHotEncoder(handle_unknown="ignore")) # Ignore new categories in prod ]) # Text pipeline: TF-IDF vectorization text_feature = "product_description" text_transformer = Pipeline([ ("tfidf", TfidfVectorizer(max_features=10)) # Limit to top 10 words ]) # Combine all transformers preprocessor = ColumnTransformer([ ("num", numeric_transformer, numeric_features), ("cat", categorical_transformer, categorical_features), ("text", text_transformer, text_feature) ])
from sklearn.ensemble import RandomForestClassifier # Full pipeline: preprocessing + model pipeline = Pipeline([ ("preprocessor", preprocessor), ("classifier", RandomForestClassifier()) ])
from sklearn.model_selection import train_test_split # Dummy target (replace with your actual target) y = [0, 1, 0, 1, 0] X_train, X_test, y_train, y_test = train_test_split(df, y, test_size=0.2, random_state=42) # Fit the pipeline pipeline.fit(X_train, y_train) # Score on test set print("Test accuracy:", pipeline.score(X_test, y_test))
import joblib # Save the pipeline joblib.dump(pipeline, "retail_pipeline.joblib") # Load and predict (e.g., in a FastAPI endpoint) loaded_pipeline = joblib.load("retail_pipeline.joblib") new_data = pd.DataFrame({ "price": [30], "quantity": [2], "product_category": ["A"], "region": ["North"], "product_description": ["amazing product"] }) print("Prediction:", loaded_pipeline.predict(new_data))
Expected Output:
Test accuracy: 1.0 # (or your actual score) Prediction: [0] # (or your actual prediction)
python-dotenv
token_pattern=r"\b\w+\b"
max_features
max_features=100
sparse=True
StandardScaler()
retail_pipeline_v1.joblib
print(pipeline.named_steps["preprocessor"].transformers_)
X_train.describe()
train_test_split
df[["col1", "col2"]]
NaN
validate=False
Answer: Use ColumnTransformer with separate pipelines for each feature type.
Trap Distinction:
Pipeline vs FeatureUnion:
Code Snippet Question: ```python from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.impute import SimpleImputer
pipeline = Pipeline([ ("imputer", SimpleImputer()), ("scaler", StandardScaler()) ]) `` - Question: What happens if you callpipeline.fit_transform(X)whereXhas missing values? - Answer:SimpleImputerfills missing values first, thenStandardScaler` scales the imputed data.
`` - Question: What happens if you call
where
has missing values? - Answer:
fills missing values first, then
You have a dataset with: - Numerical column: age (missing values) - Categorical column: gender (values: M, F, Other) - Text column: review (raw text)
age
gender
M
F
Other
review
Build a pipeline that: 1. Imputes missing age with the median.2. One-hot encodes gender (ignore new categories in production).3. Vectorizes review with TfidfVectorizer (limit to 50 features).4. Scales all numerical features.
Solution:
from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.feature_extraction.text import TfidfVectorizer preprocessor = ColumnTransformer([ ("num", Pipeline([ ("imputer", SimpleImputer(strategy="median")), ("scaler", StandardScaler()) ]), ["age"]), ("cat", OneHotEncoder(handle_unknown="ignore"), ["gender"]), ("text", TfidfVectorizer(max_features=50), "review") ]) pipeline = Pipeline([("preprocessor", preprocessor)])
Why it works: - ColumnTransformer applies different steps to different columns.- handle_unknown="ignore" prevents crashes on new gender values.- max_features=50 limits text feature dimensionality.
max_features=50
Pipeline([("step1", Transformer()), ("step2", Model())])
ColumnTransformer([("name", transformer, columns)])
SimpleImputer(strategy="median")
strategy="most_frequent"
MinMaxScaler()
OneHotEncoder(handle_unknown="ignore")
handle_unknown
TfidfVectorizer(max_features=100)
FeatureUnion([("step1", transformer1), ("step2", transformer2)])
joblib.dump(pipeline, "file.joblib")
pipeline.named_steps["step_name"]
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.