01
它是什么:经典机器学习的「标准库」
Scikit-learn 建在 NumPy / SciPy 之上,把十几年的经典机器学习算法——线性模型、决策树、随机森林、SVM、聚类、降维——统一成同一套 API:构造 → fit 训练 → predict / transform 使用 → score 打分。它从 2007 年一个 Google Summer of Code 项目起步,由法国国家信息与自动化研究院(Inria)等机构带领社区维护至今,是 Python 机器学习事实上的标准起点。
「统一」是它最大的价值:换模型只换一两行代码;Pipeline 能把预处理和模型串成一个对象;GridSearchCV 能对整条管道统一调参。学的是一套接口,用到的是整个算法库。
- 当前稳定版
- 1.9.1(2026-09 发布,以官网为准)
- 许可证
- BSD-3,商用项目可放心集成
- 语言
- Python(热点代码用 Cython 编译加速)
- 运行依赖
- NumPy、SciPy、joblib、threadpoolctl
- Python 版本
- 较新版本要求 3.11+(以安装页为准)
- GPU
- 不支持,经典 ML 在 CPU 上就够快
- 不做的事
- 深度学习、强化学习请用 PyTorch / TensorFlow
- 名字来历
- SciPy Toolkit(scikit)系列之一,learn 最出名
02
安装:一条 pip,或者一条 conda
官方推荐装进虚拟环境。二进制轮子直接下载安装,不需要 C 编译器,连依赖一起装好。
# 建独立环境(scikit-learn 1.9 要 Python 3.11+) python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate python -m pip install scikit-learn # 已装过,升级到最新: python -m pip install -U scikit-learn
conda create -n sklearn python=3.11
conda activate sklearn
# conda-forge 渠道版本更新最快
conda install -c conda-forge scikit-learn
python -c "import sklearn; print(sklearn.__version__)" # 详细环境报告:排查问题先跑这个 python -c "import sklearn; sklearn.show_versions()"
python -m pip install;Windows 下若 pip 装不上,优先换 conda。03
快速上手:十行以内的第一个分类器
用内置的红酒数据集(178 条样本、13 个化学特征、3 个品种)走一次完整流程。注意每一行的分工:载入、切分、训练、打分,各占一两行。
from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier X, y = load_wine(return_X_y=True) # 数据:直接拿到 numpy 数组 X_tr, X_te, y_tr, y_te = train_test_split( X, y, test_size=0.25, random_state=0, stratify=y) clf = RandomForestClassifier(random_state=0) clf.fit(X_tr, y_tr) # 训练:一行 print(clf.score(X_te, y_te)) # 评分:还是一行,这份数据能到 1.0 print(clf.predict(X_te[:3])) # 预测新样本的类别
-
01
载入数据
load_wine()一行拿到。return_X_y=True直接返回特征矩阵 X 和标签 y,不绕弯。 -
02
切分并分层
train_test_split留出 25% 当测试集;stratify=y让两份数据的类别比例保持一致,小数据集必加。 -
03
fit:所有学习的入口
sklearn 里任何模型都这样用:先构造(超参在括号里),再
fit。换模型就是换这两行。 -
04
score / predict
score给出测试集默认指标(分类是准确率);predict输出具体预测。这一步之后才谈调参。
RandomForestClassifier 换成 SVC 或 LogisticRegression,其余一行不动。这就是统一 API 的甜头,下一节展开。04
核心概念:统一 API、数据集、Pipeline、调参
统一 API:换模型只换一行
sklearn 把每个模型都做成「估计器(estimator)」类,接口完全一致。想比较三个模型?一个 for 循环就够,不用读三份文档:
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
for model in [LogisticRegression(max_iter=1000),
RandomForestClassifier(random_state=0),
SVC()]:
model.fit(X_tr, y_tr) # 同一个 fit
print(model.__class__.__name__,
model.score(X_te, y_te)) # 同一个 score
这也是学习方法论:先跑通最简单的逻辑回归当基线,再逐个换更强的模型比较——成本只剩一行 import。
- fit(X, y)
- 学习:从数据估计参数。监督模型要传标签 y;转换器只吃 X(学均值、方差这类统计量)。
- predict(X)
- 预测:训练好的模型对新样本输出类别或数值。
- transform(X)
- 变换:转换器专用,按 fit 学到的统计量改写数据。fit_transform 是两步合一步。
- score(X, y)
- 打分:模型默认指标——分类给准确率,回归给 R²。想换指标用 metrics 模块。
内置数据集:load_*、fetch_*、make_*
三组前缀记牢:load_ 玩具数据随包自带;fetch_ 真实数据首次运行才下载;make_ 按需合成数据。
from sklearn import datasets iris = datasets.load_iris() # 150x4 鸢尾花三分类 digits = datasets.load_digits() # 1797 个 8x8 手写数字 wine = datasets.load_wine() # 178x13 红酒三分类 # 回归练习用加州房价:20640 条 x 8 特征,首次运行联网下载 housing = datasets.fetch_california_housing() # 旧教程里的 load_boston 已在 1.2 版被移除(伦理问题),别再用 Xs, ys = datasets.make_classification(n_samples=1000, random_state=0)
load_wine() 不带 return_X_y 时返回 Bunch 对象,用 .data、.target、.feature_names 取内容——探索数据时这个形态更好用。
预处理与 Pipeline:transformer 串成一条线
另一类对象叫「转换器(transformer)」:提供 fit(学参数,如均值方差)和 transform(应用变换)。StandardScaler、OneHotEncoder、SimpleImputer 都是。把转换器和模型装进 Pipeline,一次 fit 全部按序执行:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
pipe = Pipeline([
("scaler", StandardScaler()), # 第一步:标准化
("model", LogisticRegression()), # 第二步:模型
])
pipe.fit(X_tr, y_tr) # 一次调用:先 fit 缩放,再训练模型
pipe.score(X_te, y_te) # 评分时同样的顺序自动重放
为什么非要装管道?两个理由:防泄漏——缩放参数只在训练折上 fit,交叉验证时每折自动重做;可部署——管道是一个整体,保存、加载、上线都只搬一个对象,不会漏掉某个预处理步骤。
交叉验证与调参:GridSearchCV 一件套
cross_val_score 五折验证看泛化;GridSearchCV 穷举参数组合并内置交叉验证。对管道调参时,用双下划线定位深处的参数:
from sklearn.model_selection import cross_val_score, GridSearchCV
print(cross_val_score(pipe, X_tr, y_tr, cv=5).mean().round(3))
param_grid = {"model__C": [0.1, 1, 10]}
# model 这一步的 C 参数 —— 双下划线 = 「走进去」
grid = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1)
grid.fit(X_tr, y_tr)
print(grid.best_params_, grid.best_score_.round(3))
n_jobs=-1 让所有 CPU 核一起算。搜完的 grid 本身就是训练好的最佳模型,直接 grid.score(X_te, y_te) 做终评。参数空间一大,网格组合数会指数爆炸——那时换 RandomizedSearchCV:同样参数下随机采样固定次数(n_iter),往往花 1/10 的时间找到差不多好的组合。完整的实战组合见第 06 节。
05
速查表:核心类、预处理、模型选择、数据集
下面这块表格能搜。忘了类名,直接搜 编码、交叉验证、聚类 之类的词。
| 类(sklearn.xxx) | 用途 |
|---|---|
| linear_model.LinearRegression | 线性回归,回归的第一基线 |
| linear_model.LogisticRegression | 线性分类器,输出概率 |
| ensemble.RandomForestClassifier | 随机森林分类,默认强基线 |
| ensemble.RandomForestRegressor | 随机森林回归 |
| ensemble.HistGradientBoostingClassifier | 直方图加速的梯度提升,大数据集首选 |
| svm.SVC | 支持向量机分类,小样本高维强 |
| neighbors.KNeighborsClassifier | K 近邻投票 |
| naive_bayes.MultinomialNB | 多项朴素贝叶斯,文本分类常客 |
| cluster.KMeans | K 均值聚类(无监督) |
| decomposition.PCA | 主成分降维(无监督) |
| pipeline.Pipeline | 把预处理与模型串成一个对象 |
| compose.ColumnTransformer | 按列分派不同 transformer |
| 转换器 | 作用 |
|---|---|
| StandardScaler | 均值 0、方差 1;线性模型 / SVM 前必配 |
| MinMaxScaler | 压到 [0, 1] 区间 |
| RobustScaler | 按中位数和四分位缩放,抗异常值 |
| OneHotEncoder | 类别列展开为 0/1 列;线上记得 handle_unknown="ignore" |
| OrdinalEncoder | 类别转整数编号,适合有序类别 |
| SimpleImputer | 缺失值填充:mean / median / most_frequent |
| KNNImputer | 用近邻样本估算缺失值 |
| PolynomialFeatures | 构造多项式与交互特征 |
| FunctionTransformer | 把任意函数包装成 transformer |
| PowerTransformer | 把偏态分布拉向正态 |
| 函数 / 类 | 作用 |
|---|---|
| train_test_split | 一次性切分;分类任务记得 stratify=y |
| cross_val_score | K 折交叉验证得分,返回每折分数 |
| cross_validate | 一次算多个指标 + 拟合耗时 |
| GridSearchCV | 网格穷举调参,内置交叉验证 |
| RandomizedSearchCV | 参数空间大时随机采样,更快 |
| StratifiedKFold | 分层 K 折,保持每折类别比例 |
| classification_report | 一次输出精确率 / 召回率 / F1 |
| confusion_matrix | 混淆矩阵,看清错在哪 |
| mean_squared_error | 回归 MSE;开平方即 RMSE |
| r2_score | R²,回归解释方差比例 |
| joblib.dump / load | 保存 / 加载训练好的模型 |
| 入口 | 说明 |
|---|---|
| load_iris() | 150 条 x 4 特征,鸢尾花三分类 |
| load_digits() | 1797 个 8x8 手写数字,10 分类 |
| load_wine() | 178 条 x 13 特征,红酒三分类 |
| fetch_california_housing() | 20640 条 x 8 特征回归;首次联网下载 |
| fetch_openml() | 从 OpenML 在线拉取公开数据集 |
| make_classification() | 合成分类数据,练手 / 测试用 |
| make_regression() | 合成回归数据 |
| make_blobs() | 合成团状数据,练聚类 |
| Bunch 对象 | load_* 默认返回:.data / .target / .feature_names |
| sklearn.show_versions() | 打印版本与环境,排障第一步 |
没有匹配的条目。换个词试试,比如「缩放」「编码」「调参」。
06
表格数据实战:数值列 + 类别列的规范全流程
真实业务数据几乎都是「数值列 + 类别列 + 缺失值」。下面用合成数据演示规范写法:ColumnTransformer 分列处理 → Pipeline 整体串联 → 交叉验证 → 网格调参 → 测试集终评。依赖 pandas,一条 pip install pandas 即可,代码可整体复制运行。
第一步:造一张「脏」表
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
rng = np.random.default_rng(42)
n = 600
df = pd.DataFrame({
"age": rng.integers(18, 70, n).astype(float),
"income": rng.normal(6000, 2000, n).round(2),
"city": rng.choice(["北京", "上海", "广州", "深圳"], n),
"device": rng.choice(["ios", "android", "web"], n),
})
df.loc[df.sample(frac=0.10, random_state=0).index, "device"] = np.nan
df.loc[df.sample(frac=0.05, random_state=1).index, "income"] = np.nan
第二步:目标变量与分列预处理器
# 目标:与特征相关的规则 + 噪声,模拟真实标签 filled = df["income"].fillna(df["income"].median()) logit = (filled - 6000) / 1500 + (df["city"] == "上海") * 0.8 y = (logit + rng.normal(0, 1, n) > 0.8).astype(int) num_cols = ["age", "income"] cat_cols = ["city", "device"] preprocess = ColumnTransformer(transformers=[ ("num", Pipeline([ ("impute", SimpleImputer(strategy="median")), ("scale", StandardScaler())]), num_cols), ("cat", Pipeline([ ("impute", SimpleImputer(strategy="most_frequent")), ("onehot", OneHotEncoder(handle_unknown="ignore"))]), cat_cols), ]) clf = Pipeline([("prep", preprocess), ("model", RandomForestClassifier(random_state=0))])
第三步:交叉验证、调参、终评
X_tr, X_te, y_tr, y_te = train_test_split(
df, y, test_size=0.2, random_state=42, stratify=y)
# 交叉验证:整条管道(含填充、缩放、编码)每折重新 fit,无泄漏
cv = cross_val_score(clf, X_tr, y_tr, cv=5)
print(cv.mean().round(3), cv.std().round(3))
# 网格调参:双下划线直达管道深处的模型参数
param_grid = {"model__n_estimators": [200, 500],
"model__max_depth": [None, 8]}
search = GridSearchCV(clf, param_grid, cv=5, n_jobs=-1)
search.fit(X_tr, y_tr)
print(search.best_params_)
# 测试集终评(只做一次);顺手看 onehot 展开后的特征名
print(round(search.score(X_te, y_te), 3))
names = search.best_estimator_.named_steps["prep"].get_feature_names_out()
print(list(names)[:6])
{'model__max_depth': None, 'model__n_estimators': 500};测试集 0.767;展开后的特征名形如 num__age、cat__city_上海——前缀就是管道里的步骤名,一眼能对上来源。num_cols / cat_cols 和模型那两行。07
避坑:四个最常见的翻车点
坑一:预处理泄漏——在全量数据上先 fit
「先 scaler 全量 fit,再切分」是最高频的错误:测试集的均值方差混进了训练。sklearn 的解法就是把预处理装进 Pipeline / ColumnTransformer,让 cross_val_score 每折自己重新 fit 转换器。
# 错:全量数据先标准化,测试集信息已泄漏 X_scaled = StandardScaler().fit_transform(X) # 对:交给管道,分折处理 pipe = Pipeline([("s", StandardScaler()), ("m", SVC())]) cross_val_score(pipe, X, y, cv=5)
坑二:线上遇到没见过的类别
训练集里城市只有四个,上线后用户填了「杭州」——默认配置的 OneHotEncoder 会直接报错。加 handle_unknown="ignore",未知类别编码成全零行,预测照常进行。
坑三:忘了 stratify,小数据集切出偏差
178 条、3 类的红酒数据,若不分层随机切 25%,某一折可能几乎抽不到某一类。分类任务切分时一律带上 stratify=y,交叉验证则默认用 StratifiedKFold(分类器场景下 GridSearchCV 会自动启用)。
# 不分层:小数据集可能切出「某类样本不足」的测试集 X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.25) # 分层:两份数据的类别比例与全量一致,分类任务的默认写法 X_tr, X_te, y_tr, y_te = train_test_split( X, y, test_size=0.25, stratify=y)
坑四:保存的模型跨版本加载失败
joblib.dump(clf, "model.joblib") # 加载端 sklearn 版本不一致时,可能直接报错或行为变化 python -c "import sklearn; print(sklearn.__version__)"
joblib.dump 本质是 pickle,绑定了训练时的 sklearn 版本。上线前固定版本(requirements.txt 里写死 scikit-learn==x.y.z),升级前先用原版本导出预测结果做回归测试。
08
进阶方向与资源
sklearn 的文档质量是开源界的标杆,顺着官方资源走,比到处搜博客靠谱。
- 官方用户指南——按算法分章,每章配示例代码,值得通读一遍。
- 示例画廊——几百个可跑的官方示例,找「某模型怎么画图」先来这里。
- GitHub 仓库——提 issue、看源码实现;Cython 热点代码也在里面。
- scikit-learn MOOC——Inria 出品的免费系统课程,视频 + Notebook 练习。
- imbalanced-learn——官方生态的类别不平衡扩展(过采样 / 欠采样),接口与 sklearn 兼容。
- 书:《Hands-On Machine Learning with Scikit-Learn, Keras & TensorFlow》(Aurélien Géron)——第 1-2 部分正是 sklearn 的最佳配套读物。
09
收尾:照着勾一遍
0 / 5