Many models combined. Where tabular accuracy lives.
sklearn.ensemble
ensemble
Many models combined. Where tabular accuracy lives.
1Get dataSomething to practise on
2Split & tuneAn honest test set
3PrepareInto numbers a model accepts
4ComposeOne object, no leakage
5ModelThe algorithm itself
6UnsupervisedNo labels available
7MeasureIs it any good, and why
8UtilitiesGlue and extension
What it is for
Combining many weak learners into a strong one. On tabular data with a few hundred features these still beat neural networks, train in minutes, and come with mature explainability tooling.
Boosting
HistGradientBoosting is sklearn's answer to LightGBM and is usually the best in-library tabular model. It needs no scaling, no one-hot encoding and no imputation.
HistGradientBoostingClassifier / Regressorcommon
Fast, handles missing values and categoricals natively
GradientBoostingClassifier / Regressor
The older, slower implementation. Prefer Hist
AdaBoostClassifier
Mostly historical interest now
Bagging
RandomForestClassifier / Regressorcommon
Strong default, little tuning needed
ExtraTreesClassifier / Regressor
More randomised, faster to fit, sometimes better
BaggingClassifier
Wrap any estimator in bootstrap aggregation
Combining models
VotingClassifier / Regressor
Combine by vote or averaged probability
StackingClassifier / Regressor
Train a meta-model on the base models' outputs
Anomaly detection
IsolationForestbank
Unsupervised outlier scoring. Useful in AML where labels are scarce
Worked examples 4
Runnable, with the arguments that change the outcome
called out. Output shapes are shown as comments where they help.
sklearn.ensemble
from sklearn.ensemble import HistGradientBoostingClassifier
# No scaling, no one-hot, no imputation needed.
clf = HistGradientBoostingClassifier(
max_iter=500,
learning_rate=0.05,
max_leaf_nodes=31,
early_stopping=True,
validation_fraction=0.15,
categorical_features="from_dtype", # pandas 'category' columns (1.4+)
class_weight="balanced", # 1.5+
random_state=42,
)
clf.fit(X_train, y_train)
The strongest tabular model in the library
No scaling, no one-hot encoding, no imputation. Usually within a hair of LightGBM without the extra dependency.
from sklearn.ensemble import HistGradientBoostingClassifier
clf = HistGradientBoostingClassifier(
max_iter=1000, # boosting rounds; early stopping cuts it
learning_rate=0.05, # lower needs more rounds, generalises better
max_leaf_nodes=31, # complexity per tree
min_samples_leaf=50, # raise on noisy data
l2_regularization=1.0,
early_stopping=True,
validation_fraction=0.15,
n_iter_no_change=30,
categorical_features="from_dtype", # pandas 'category' dtype (1.4+)
class_weight="balanced", # 1.5+
random_state=42,
)
clf.fit(X_train, y_train)
print("stopped at iteration", clf.n_iter_)
# Feed it a DataFrame with proper dtypes and it does the rest:
# df["product"] = df["product"].astype("category")
# df["income"] stays float, NaNs and all
Random forest, and why its importances mislead
feature_importances_ is biased toward high-cardinality features. Model validation teams know this and will ask.
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
import numpy as np
rf = RandomForestClassifier(
n_estimators=500,
max_depth=None,
min_samples_leaf=5,
class_weight="balanced_subsample",
n_jobs=-1, random_state=42,
)
rf.fit(X_train, y_train)
# Built in - fast, but biased toward features with many distinct values
built_in = rf.feature_importances_
# Permutation - slower, model-agnostic, computed on HELD-OUT data
perm = permutation_importance(rf, X_test, y_test, n_repeats=10,
scoring="average_precision",
n_jobs=-1, random_state=42)
print(f"{'feature':26} {'built-in':>10} {'permutation':>12}")
for i in np.argsort(perm.importances_mean)[::-1][:10]:
print(f"{feature_names[i]:26} {built_in[i]:10.4f} "
f"{perm.importances_mean[i]:12.4f}")
# Where the two disagree sharply, the built-in number is usually the
# one that is wrong - typically on an ID-like column.
Unsupervised anomaly detection when you have no labels
Useful in AML and fraud where confirmed positives are scarce. Scores how easily each row is isolated from the rest.
from sklearn.ensemble import IsolationForest
iso = IsolationForest(
n_estimators=200,
contamination=0.01, # expected proportion of anomalies - this is
# a business decision, not a fitted parameter
max_samples="auto",
random_state=42, n_jobs=-1,
)
iso.fit(X_train) # no y at all
pred = iso.predict(X_test) # -1 anomalous, 1 normal
score = iso.score_samples(X_test) # lower = more anomalous
import numpy as np
order = np.argsort(score)
print("most anomalous rows:", order[:10])
print("their scores:", score[order[:10]].round(3))
# Rank by score rather than trusting the -1/1 label. contamination
# only sets where the cut falls, and you usually want to hand
# investigators a ranked queue rather than a binary flag.