Loading...
Loading...
Loading Curriculum...
Loading Subject...
Loading Topic...
Loading Lesson...
Loading Lab...
scikit-learn is the go-to library for classical machine learning: preprocessing, feature engineering, models, evaluation, and pipelines.
Every estimator follows fit / predict / transform. Switch models by changing one class name — the rest of your code stays the same.
Linear models, decision trees, ensembles, SVMs, KNN, naive Bayes, clustering, dimensionality reduction — all in one library.
Chain preprocessing and models into a single object. Prevents data leakage, simplifies cross-validation, and makes deployment clean.
Cross-validation, GridSearchCV, RandomizedSearchCV, and 30+ metrics out of the box. The standard for reproducible ML evaluation.
ColumnTransformer applies different transformers to different columns in a single step — essential for mixed numeric/categorical data.
Outputs are NumPy arrays; inputs accept Pandas DataFrames. Plays well with XGBoost, LightGBM, and any sklearn-compatible estimator.
A Pipeline chains preprocessing and a model into one object. When you call fit, each step is fitted on training data only — the scaler never sees test data, eliminating the most common source of data leakage. ColumnTransformer lets you apply different transforms to different column types in one step.
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier
numeric_features = ["age", "income", "tenure"]
categorical_features = ["country", "plan"]
numeric_transformer = Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
])
categorical_transformer = Pipeline([
("imputer", SimpleImputer(strategy="most_frequent")),
("encoder", OneHotEncoder(handle_unknown="ignore")),
])
preprocessor = ColumnTransformer([
("num", numeric_transformer, numeric_features),
("cat", categorical_transformer, categorical_features),
])
pipe = Pipeline([
("preprocessor", preprocessor),
("classifier", RandomForestClassifier(n_estimators=200, random_state=0)),
])
pipe.fit(X_train, y_train)
pipe.score(X_test, y_test)PipelineSequential chain of (name, estimator) tuples. Last step must be an estimator; all others must implement transform.
ColumnTransformerApply different transformers to different subsets of columns and concatenate the results.
FunctionTransformerWrap any stateless function (e.g. np.log1p) as a pipeline-compatible transformer.
Start with a simple baseline, then move to ensembles. All follow the same fit / predict interface.
LogisticRegressionClassificationStrong baseline; interpretable coefficients; fast.
Ridge / LassoRegressionRidge = L2 regularisation; Lasso = L1 + feature selection.
SGDClassifierClassificationScales to millions of samples with partial_fit.
DecisionTreeClassifierClassificationInterpretable; prone to overfitting without pruning.
RandomForestClassifierBothRobust ensemble; good out-of-the-box; built-in feature importance.
GradientBoostingClassifierBothHigh accuracy; slower than RF; tune n_estimators + learning_rate.
HistGradientBoosting*Bothsklearn's fast GBDT for large datasets; handles NaNs natively.
SVCClassificationStrong on high-dimensional data; doesn't scale past ~100k rows.
KNeighborsClassifierBothSimple, no training phase; slow at inference on large data.
MLPClassifierBothShallow neural net; use PyTorch instead for anything serious.
* HistGradientBoostingClassifier / Regressor — sklearn s fastest tree method for >10k rows.
Prefer RandomizedSearchCV over GridSearchCV — it samples the parameter space randomly, finding good regions much faster than exhaustive grid search and scaling to large param spaces. Set n_jobs=-1 to use all CPU cores.
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import GradientBoostingClassifier
from scipy.stats import randint, uniform
param_dist = {
"classifier__n_estimators": randint(50, 500),
"classifier__max_depth": randint(2, 8),
"classifier__learning_rate": uniform(0.01, 0.3),
"classifier__subsample": uniform(0.6, 0.4),
}
search = RandomizedSearchCV(
pipe,
param_distributions=param_dist,
n_iter=50,
cv=5,
scoring="roc_auc",
n_jobs=-1,
random_state=0,
verbose=1,
)
search.fit(X_train, y_train)
print(f"Best AUC: {search.best_score_:.4f}")
print(search.best_params_)GridSearchCVExhaustive — tries every combination. Fine for 2–3 params with a few values; explodes otherwise.
RandomizedSearchCVSamples n_iter combinations at random. Scales well; often finds better results in fewer evaluations.
HalvingRandomSearchCVSuccessive halving — eliminates weak candidates early. Faster than RandomizedSearchCV for large budgets.
Nested CVOuter CV evaluates generalisation; inner CV tunes hyperparams. Prevents overfitting the validation set.
Always plot a confusion matrix, ROC curve, and precision-recall curve together. ROC AUC is optimistic on imbalanced data — PR AUC is more informative when the positive class is rare.
from sklearn.metrics import (
classification_report,
ConfusionMatrixDisplay,
RocCurveDisplay,
PrecisionRecallDisplay,
)
import matplotlib.pyplot as plt
y_pred = pipe.predict(X_test)
y_proba = pipe.predict_proba(X_test)[:, 1]
print(classification_report(y_test, y_pred))
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
ConfusionMatrixDisplay.from_predictions(y_test, y_pred, ax=axes[0])
RocCurveDisplay.from_predictions(y_test, y_proba, ax=axes[1])
PrecisionRecallDisplay.from_predictions(y_test, y_proba, ax=axes[2])
plt.tight_layout()AccuracyMisleading when classes are imbalanced. Use as a secondary metric only.
ROC AUCThreshold-free ranking metric. Good general-purpose metric for binary classification.
F1 / PR AUCPrecision-recall trade-off — use when false positives and false negatives have different costs.
R² / MAE / RMSEFor regression. MAE is robust to outliers; RMSE penalises large errors more heavily.
Log lossMeasures calibration of probability estimates — important when you need reliable probabilities.
Cohen's kappaAgreement corrected for chance — useful for multi-class problems with class imbalance.
Tree-based models expose feature_importances_ (impurity-based — can be biased toward high-cardinality features). Use permutation_importance as a model-agnostic, unbiased alternative. For linear models, inspect coef_ after scaling.
import pandas as pd
import numpy as np
# For tree-based models inside a Pipeline
rf = pipe.named_steps["classifier"]
feature_names = (
numeric_features
+ pipe.named_steps["preprocessor"]
.named_transformers_["cat"]
.named_steps["encoder"]
.get_feature_names_out(categorical_features)
.tolist()
)
importance_df = pd.DataFrame({
"feature": feature_names,
"importance": rf.feature_importances_,
}).sort_values("importance", ascending=False)
print(importance_df.head(10))
# Model-agnostic: permutation importance
from sklearn.inspection import permutation_importance
result = permutation_importance(pipe, X_test, y_test, n_repeats=10, random_state=0)Subclass BaseEstimator and TransformerMixin. Implement fit (return self) and transform. Your custom transformer is now a first-class Pipeline citizen — it participates in cross-validation, cloning, and serialisation.
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np
class LogTransformer(BaseEstimator, TransformerMixin):
"""Log1p-transform skewed numeric columns."""
def __init__(self, columns=None):
self.columns = columns
def fit(self, X, y=None):
return self # stateless
def transform(self, X):
X = X.copy()
cols = self.columns or X.columns.tolist()
X[cols] = np.log1p(X[cols].clip(lower=0))
return X
# Drop into any Pipeline
pipe = Pipeline([
("log", LogTransformer(columns=["income", "tenure"])),
("scaler", StandardScaler()),
("clf", LogisticRegression()),
])Key rule: fit must only learn from X (the training data) and must return self. Never store test-time data in fit. If your transformer is stateless (like a log transform), fit can simply return self immediately.
StandardScalerZero mean, unit variance. Sensitive to outliers.
MinMaxScalerScales to [0, 1]. Distorted by outliers.
RobustScalerUses median + IQR — not affected by extreme values.
OneHotEncoderCreates one binary column per category. Use handle_unknown='ignore' for unseen categories.
OrdinalEncoderEncodes as integers. Only use when order is meaningful.
SimpleImputerStrategies: mean, median, most_frequent, constant.
IterativeImputerModels each feature as a function of others — more accurate, more expensive.
PolynomialFeaturesCreates x², x³, x·y interaction terms. Degree=2 is usually sufficient.
PCAUnsupervised. Useful before KNN or SVMs on high-dimensional data.
Fit/predict, pipelines, and train/test split.
| Framework | Best at | Typical tasks | Output |
|---|---|---|---|
| NumPy | Fast array math + linear algebra | Numerics, prototyping, preprocessing | ndarray (CPU) |
| Pandas | Tabular ETL + joins + aggregation | Cleaning, feature engineering, analysis | DataFrame / Series |
| scikit-learn | Classical ML + evaluation + pipelines | Baselines, CV, model selection | Estimator / Pipeline |
| PyTorch | Neural nets + custom training loops | Deep learning, research, fine-tuning | Tensors + nn.Module |
| TensorFlow | Keras training + production deployment | Deep learning, serving, mobile/edge | Tensors + Keras Model |
| Hugging Face | Model hub + transformer tooling | Inference, fine-tuning, sharing | Checkpoints + pipelines |