mrkeyoor.com_
Wed 05 Aug 05:03 UTC
PyPIAI / MLupdated 05 Aug 2026

scikit-learn

scikit-learn is the standard Python library for classical machine learning: classification, regression, clustering, and dimensionality reduction on tabular, in-memory data. Every algorithm, from logistic regression to random forests to k-means, shares the same fit/predict/transform API, so swapping models is a one-line change. Around the estimators sit the pieces that matter in practice: preprocessing transformers, Pipelines that keep preprocessing and models together without leaking test data, cross-validation, and hyperparameter search. Built on NumPy and SciPy under a BSD-3 license, started as a Google Summer of Code project in 2007, and maintained by a large community with institutional backing.

Verdict

For classical ML on in-memory tabular data, this is the library, and its Pipeline/cross-validation design quietly teaches correct methodology. Know its edges: no serious deep learning, no GPU story, and datasets beyond RAM push you to other tools.

API stability5/5The fit/predict/transform contract has held for over a decade; deprecations go through a documented two-release cycle with warnings, and the 1.x line has stayed backward compatible in practice since 2021.
Docs5/5scikit-learn.org pairs a full API reference with a user guide that explains the mathematics, assumptions, and pitfalls of each method, plus hundreds of runnable examples; it is the reference point other ML libraries get compared against.
Maintenance5/5Pushed 2026-08-04 with 66.9k stars, a large contributor community, institutional support acknowledged on the project's about page, nightly wheel builds, and a steady release rhythm on the 1.x series.
Ecosystem5/556M weekly downloads; its estimator API is the interoperability standard that xgboost, lightgbm, and countless companion libraries implement, and pandas/polars input is supported via the narwhals dependency.

Use it if

  • You are doing classical ML on tabular data that fits in memory; for that job its breadth and API consistency are unmatched
  • You want leak-free workflows: Pipeline plus ColumnTransformer plus cross_val_score encode the correct methodology so preprocessing is fit only on training folds
  • You are learning ML; the user guide teaches the statistics behind each method, not just the function signatures, and is one of the best free ML texts anywhere
  • You need a solid baseline before reaching for anything fancy; a Pipeline with LogisticRegression or RandomForest is the honest benchmark every deep model should beat
Skip it if

Setup reality

pip install scikit-learn works painlessly on major platforms because binary wheels ship for everything; it pulls numpy, scipy, joblib, threadpoolctl, and narwhals. Note the interpreter floor: release 1.9.0 requires Python 3.11+. The real-world annoyances: mixing conda and pip in one environment invites BLAS and threading conflicts (threadpoolctl exists for a reason); building from source needs C/C++ toolchains, Cython, and meson and is slow, so avoid platforms without wheels; plotting utilities need an optional matplotlib install; and model persistence via pickle ties you to the exact library version, which the project's own docs warn about, so record versions next to every saved model.

Patterns

Split data, train, and score a first modeltrain-evaluate

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
clf = RandomForestClassifier(n_estimators=300, random_state=42)
clf.fit(X_train, y_train)
print(accuracy_score(y_test, clf.predict(X_test)))

stratify=y keeps class proportions equal across the split; forgetting it skews evaluation on imbalanced data.

Chain preprocessing and a model in a Pipelinepipeline

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
model.fit(X_train, y_train)
model.predict(X_test)

The scaler is fit on training data only and reused at predict time, which is exactly the data leak you cause by scaling before splitting.

Preprocess numeric and categorical columns differentlymixed-columns

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression

pre = ColumnTransformer([
    ('num', StandardScaler(), ['age', 'income']),
    ('cat', OneHotEncoder(handle_unknown='ignore'), ['city', 'plan']),
])
model = make_pipeline(pre, LogisticRegression(max_iter=1000))
model.fit(X_train, y_train)

handle_unknown='ignore' stops predict from crashing when a category unseen in training shows up in production data.

Get an honest score with cross-validationcross-validation

from sklearn.model_selection import cross_val_score

scores = cross_val_score(model, X, y, cv=5, scoring='f1_macro')
print(scores.mean(), scores.std())

Cross-validate the whole pipeline, not just the estimator, or preprocessing leaks information across folds.

Tune hyperparameters with GridSearchCVhyperparameter-search

from sklearn.model_selection import GridSearchCV

param_grid = {
    'randomforestclassifier__n_estimators': [100, 300],
    'randomforestclassifier__max_depth': [None, 10, 30],
}
search = GridSearchCV(model, param_grid, cv=5, n_jobs=-1)
search.fit(X_train, y_train)
print(search.best_params_, search.best_score_)
best = search.best_estimator_

Pipeline parameter names use the step name plus double underscore; RandomizedSearchCV covers big grids at a fraction of the cost.

See per-class performance, not just accuracyclassification-metrics

from sklearn.metrics import classification_report, confusion_matrix

y_pred = model.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))

On imbalanced data accuracy flatters bad models; read the per-class recall rows before believing any headline number.

Persist a trained model with joblibsave-model

import joblib

joblib.dump(model, 'model-v1.joblib')

# later, in the serving process
model = joblib.load('model-v1.joblib')
model.predict(X_new)

Loads are only guaranteed with the same scikit-learn version that saved the file; pin the version and record it alongside the artifact.

Get probabilities and set your own thresholdpredict-probabilities

proba = model.predict_proba(X_test)[:, 1]  # P(class 1)

custom_threshold = 0.3  # favor recall over precision
y_pred = (proba >= custom_threshold).astype(int)

predict() hard-codes a 0.5 threshold; cost-sensitive problems almost always want a different operating point.

Rank features with permutation importancefeature-importance

from sklearn.inspection import permutation_importance

result = permutation_importance(model, X_test, y_test, n_repeats=10, random_state=42)
for idx in result.importances_mean.argsort()[::-1][:10]:
    print(X_test.columns[idx], round(result.importances_mean[idx], 4))

Prefer this over tree feature_importances_, which inflates high-cardinality features; run it on held-out data, not training data.

Cluster unlabeled data with k-meansclustering

from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans

X_scaled = StandardScaler().fit_transform(X)
km = KMeans(n_clusters=4, n_init='auto', random_state=42)
labels = km.fit_predict(X_scaled)

k-means uses Euclidean distance, so unscaled features let the widest-ranged column dominate the clustering.

Reduce dimensions with PCAdimensionality-reduction

from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline

pca = make_pipeline(StandardScaler(), PCA(n_components=0.95))
X_reduced = pca.fit_transform(X_train)
print(pca.named_steps['pca'].n_components_)

n_components=0.95 keeps enough components for 95 percent of variance; transform test data with the fitted pipeline, never refit.

Impute missing values inside the pipelinehandle-missing-values

from sklearn.impute import SimpleImputer
from sklearn.pipeline import make_pipeline
from sklearn.ensemble import HistGradientBoostingClassifier

model = make_pipeline(
    SimpleImputer(strategy='median'),
    HistGradientBoostingClassifier(random_state=42)
)
model.fit(X_train, y_train)

Most estimators raise on NaN, so impute in-pipeline; HistGradientBoosting models are the exception and handle NaN natively.

Alternatives

PackageRegistryPick it when
xgboostPyPIGradient-boosted trees on medium-to-large tabular data where leaderboard accuracy matters
lightgbmPyPIBoosted trees with faster training and lower memory on large datasets
statsmodelsPyPIYou need p-values, confidence intervals, and classical statistical inference, not just predictions
torchPyPIDeep learning on images, text, or audio, or anything that needs GPUs and custom architectures