> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# scikit-learn 完全指南
- URL: https://blog.vercanti.com/scikit-learn-wan-quan-zhi-nan/
- Published: 2026-08-28T14:35:41.000Z
- Updated: 2026-08-28T14:59:21.000Z
- Description: scikit-learn 是 Python 最成熟的机器学习库，提供监督学习、无监督学习、模型选择与评估的完整工具链，所有算法遵循统一的 fit/predict/transform 接口。 与其他框架的对比： 适合场景：结构化（表格）数据的分类、回归、聚类；需要快速建立 baseline；特征工程 Pipeline 构建；模型选择与超参调优。 不适合场景：图像/音频/文本深度学习（用 PyTorch完全指南(/pytorchwan-quan-zhi-nan/) 或 HuggingFace Transformers完全指南(/huggingface-tra
- Author: yellowdog
- Tags: 机器学习

> 官方文档：<https://scikit-learn.org/stable/>  
> 适用版本：scikit-learn 1.8.0（2026-05-07 核实）

---

## 概述

scikit-learn 是 Python 最成熟的机器学习库，提供监督学习、无监督学习、模型选择与评估的完整工具链，所有算法遵循统一的 `fit/predict/transform` 接口。

与其他框架的对比：

|        | scikit-learn | PyTorch    | XGBoost |
| ------ | ------------ | ---------- | ------- |
| 定位     | 经典 ML 算法大全   | 深度学习框架     | 梯度提升专用  |
| 上手成本   | 低（统一接口）      | 高（需手写训练循环） | 中       |
| 适合数据量  | 中小型（内存能加载）   | 无上限（批量训练）  | 中大型     |
| GPU 支持 | 有限（部分算法）     | 原生         | 支持      |
| 可解释性   | 高（线性模型、决策树）  | 低（黑盒）      | 中       |

适合场景：结构化（表格）数据的分类、回归、聚类；需要快速建立 baseline；特征工程 Pipeline 构建；模型选择与超参调优。

不适合场景：图像/音频/文本深度学习（用 [PyTorch完全指南](https://blog.vercanti.com/pytorchwan-quan-zhi-nan/) 或 [HuggingFace Transformers完全指南](https://blog.vercanti.com/huggingface-transformers-wan-quan-zhi-nan/)）；超大规模分布式训练。

---

## 安装

```bash
pip install scikit-learn

```

---

## 核心设计：Estimator 接口

所有 scikit-learn 对象实现统一接口：

| 方法                      | 适用对象                     | 说明                               |
| ----------------------- | ------------------------ | -------------------------------- |
| fit(X, y)               | Estimator（含 Transformer） | 用训练数据拟合模型；无监督只需 X                |
| predict(X)              | Classifier / Regressor   | 返回预测标签或数值                        |
| predict\_proba(X)       | 支持概率输出的 Classifier       | 返回每类的概率，形状 (n, n\_classes)       |
| transform(X)            | Transformer              | 对数据做变换（如归一化、降维）                  |
| fit\_transform(X)       | Transformer              | 等价于 fit(X).transform(X)，避免两次调用   |
| score(X, y)             | Estimator                | 返回默认评估指标（分类器返回 accuracy，回归返回 R²） |
| set\_params(\*\*params) | 所有 Estimator             | 修改超参数，用于 GridSearch              |
| get\_params()           | 所有 Estimator             | 获取当前超参数字典                        |

---

## 数据预处理（sklearn.preprocessing）

### `StandardScaler`

零均值、单位方差标准化（Z-score）。

```python
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler(copy=True, with_mean=True, with_std=True)

```

| 参数         | 类型   | 默认值  | 说明                            |
| ---------- | ---- | ---- | ----------------------------- |
| copy       | bool | True | 是否拷贝数据；False 原地修改节省内存，但会修改原数组 |
| with\_mean | bool | True | 是否减去均值（中心化）；稀疏矩阵设 False 否则报错  |
| with\_std  | bool | True | 是否除以标准差；False 只中心化不缩放         |

```python
from sklearn.preprocessing import StandardScaler

X_train = [[0, 0], [0, 0], [1, 1], [1, 1]]
scaler = StandardScaler()
scaler.fit(X_train)
# 务必只在训练集上 fit，测试集只做 transform
X_test = scaler.transform([[2, 2], [-1, -1]])
print(scaler.mean_)    # [0.5 0.5]
print(scaler.scale_)   # [0.5 0.5]

```

### `MinMaxScaler`

将特征缩放到指定范围 `[feature_range[0], feature_range[1]]`。

```python
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler(feature_range=(0, 1), copy=True, clip=False)

```

| 参数             | 类型                    | 默认值    | 说明                                    |
| -------------- | --------------------- | ------ | ------------------------------------- |
| feature\_range | tuple\[float, float\] | (0, 1) | 目标范围；两端点必须满足 min < max                |
| copy           | bool                  | True   | 是否拷贝数据                                |
| clip           | bool                  | False  | True 时超出训练范围的测试值被裁剪到 feature\_range 内 |

### `OneHotEncoder`

将类别特征编码为 one-hot 矩阵。

```python
from sklearn.preprocessing import OneHotEncoder

enc = OneHotEncoder(
    categories='auto',
    drop=None,
    sparse_output=True,
    dtype=float,
    handle_unknown='error',
    min_frequency=None,
    max_categories=None,
)

```

| 参数              | 类型                    | 默认值                     | 说明                                 |                                                   |
| --------------- | --------------------- | ----------------------- | ---------------------------------- | ------------------------------------------------- |
| categories      | "auto" 或 list\[list\] | "auto"                  | "auto" 从数据中推断；或手动指定每列的类别列表         |                                                   |
| drop            | None \| "first"       | "if\_binary"            | None                               | 删除冗余列；"first" 删第一列（避免多重共线性）；"if\_binary" 仅对二值特征删除 |
| sparse\_output  | bool                  | True                    | True 返回稀疏矩阵（节省内存）；False 返回 ndarray |                                                   |
| dtype           | numeric type          | float                   | 输出数组的数值类型                          |                                                   |
| handle\_unknown | "error" \| "ignore"   | "infrequent\_if\_exist" | "error"                            | 遇到训练时未见过的类别的处理方式；"ignore" 输出全零列                   |
| min\_frequency  | int \| float          | None                    | None                               | 低于此频率的类别归入 infrequent 类                           |
| max\_categories | int \| None           | None                    | 每列最多保留的类别数，超出部分合并为 infrequent      |                                                   |

```python
from sklearn.preprocessing import OneHotEncoder
import numpy as np

enc = OneHotEncoder(sparse_output=False, handle_unknown='ignore')
X = [['cat'], ['dog'], ['fish']]
enc.fit(X)

# 测试集有未见类别 'bird'，handle_unknown='ignore' 输出全零
print(enc.transform([['dog'], ['bird']]))
# [[0. 1. 0.]
#  [0. 0. 0.]]

```

### `LabelEncoder`

对目标变量（y）的类别进行整数编码。

```python
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
le.fit(['cat', 'dog', 'fish'])
print(le.transform(['dog', 'cat']))  # [1 0]
print(le.inverse_transform([2]))     # ['fish']

```

`LabelEncoder` 无超参数，不应用于输入特征（用 `OrdinalEncoder` 代替）。

### `PolynomialFeatures`

生成多项式特征，用于线性模型捕捉非线性关系。

```python
from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(degree=2, interaction_only=False, include_bias=True, order='C')

```

| 参数                | 类型                      | 默认值   | 说明                                            |
| ----------------- | ----------------------- | ----- | --------------------------------------------- |
| degree            | int \| tuple\[int,int\] | 2     | 多项式最高次数；tuple 指定范围 (min\_degree, max\_degree) |
| interaction\_only | bool                    | False | True 只生成交叉项（不含 x² 类纯次方项）                      |
| include\_bias     | bool                    | True  | 是否包含偏置列（全为 1 的列）                              |
| order             | "C" \| "F"              | "C"   | 输出数组的内存布局；"C" 行优先，"F" 列优先                     |

---

## 线性模型（sklearn.linear\_model）

### `LogisticRegression`

逻辑回归分类器，适合线性可分的二分类和多分类问题。

```python
from sklearn.linear_model import LogisticRegression

clf = LogisticRegression(
    penalty='l2',
    dual=False,
    tol=1e-4,
    C=1.0,
    fit_intercept=True,
    intercept_scaling=1,
    class_weight=None,
    random_state=None,
    solver='lbfgs',
    max_iter=100,
    multi_class='deprecated',
    verbose=0,
    warm_start=False,
    n_jobs=None,
    l1_ratio=None,
)

```

| 参数            | 类型                 | 默认值          | 说明                                                                           |                                     |                                                 |
| ------------- | ------------------ | ------------ | ---------------------------------------------------------------------------- | ----------------------------------- | ----------------------------------------------- |
| penalty       | "l1" \| "l2"       | "elasticnet" | None                                                                         | "l2"                                | 正则化类型；None 无正则；l1 需 solver='liblinear' 或 'saga' |
| C             | float              | 1.0          | 正则化强度的倒数；越小正则越强；必须 > 0                                                       |                                     |                                                 |
| solver        | str                | "lbfgs"      | 优化算法：lbfgs（小数据集）、liblinear（小/稀疏）、saga（大数据集/L1）、newton-cg、newton-cholesky、sag |                                     |                                                 |
| max\_iter     | int                | 100          | 求解器最大迭代次数；若不收敛会抛出 ConvergenceWarning                                         |                                     |                                                 |
| class\_weight | dict \| "balanced" | None         | None                                                                         | 类别权重；"balanced" 自动按类频率倒数加权（处理不平衡数据） |                                                 |
| random\_state | int \| None        | None         | 随机种子（solver='sag'/'saga'/'liblinear' 时使用）                                    |                                     |                                                 |
| n\_jobs       | int \| None        | None         | 多分类时并行数；\-1 使用全部 CPU                                                         |                                     |                                                 |
| l1\_ratio     | float \| None      | None         | ElasticNet 混合比例；0=纯L2，1=纯L1；仅 penalty='elasticnet' 时有效                       |                                     |                                                 |
| warm\_start   | bool               | False        | True 用上次 fit 的结果初始化，用于增量训练                                                   |                                     |                                                 |

```python
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

clf = LogisticRegression(max_iter=1000, C=0.1)
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))        # accuracy
print(clf.predict_proba(X_test[:2]))   # 概率矩阵

```

### `LinearRegression`

最小二乘线性回归。

```python
from sklearn.linear_model import LinearRegression

reg = LinearRegression(fit_intercept=True, copy_X=True, n_jobs=None, positive=False)

```

| 参数             | 类型          | 默认值   | 说明                          |
| -------------- | ----------- | ----- | --------------------------- |
| fit\_intercept | bool        | True  | 是否拟合截距；False 假设数据已中心化       |
| copy\_X        | bool        | True  | False 原地修改 X（节省内存，但会修改原始数据） |
| n\_jobs        | int \| None | None  | 计算并行数；仅多目标回归时有效             |
| positive       | bool        | False | True 强制系数非负（非负约束最小二乘）       |

### `Ridge`

L2 正则化线性回归（岭回归）。

```python
from sklearn.linear_model import Ridge

reg = Ridge(alpha=1.0, fit_intercept=True, copy_X=True, max_iter=None,
            tol=1e-4, solver='auto', positive=False, random_state=None)

```

| 参数        | 类型                  | 默认值    | 说明                                                         |
| --------- | ------------------- | ------ | ---------------------------------------------------------- |
| alpha     | float \| array-like | 1.0    | 正则化系数；越大正则越强；为 0 等价于 LinearRegression；array 时对每个目标单独设置     |
| solver    | str                 | "auto" | 求解器：auto（自动选择）、svd、cholesky、lsqr、sparse\_cg、sag、saga、lbfgs |
| max\_iter | int \| None         | None   | 迭代求解器最大迭代次数                                                |

### `Lasso`

L1 正则化线性回归（Lasso），产生稀疏解（特征选择）。

```python
from sklearn.linear_model import Lasso

reg = Lasso(alpha=1.0, fit_intercept=True, precompute=False, copy_X=True,
            max_iter=1000, tol=1e-4, warm_start=False, positive=False,
            random_state=None, selection='cyclic')

```

| 参数        | 类型                   | 默认值      | 说明                       |
| --------- | -------------------- | -------- | ------------------------ |
| alpha     | float                | 1.0      | L1 正则化系数；越大稀疏度越高（更多系数为零） |
| max\_iter | int                  | 1000     | 坐标下降最大迭代次数               |
| selection | "cyclic" \| "random" | "cyclic" | 坐标更新策略；"random" 有时收敛更快   |

---

## 集成方法（sklearn.ensemble）

### `RandomForestClassifier`

随机森林：并行训练多棵决策树，以投票方式聚合结果。

```python
from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(
    n_estimators=100,
    criterion='gini',
    max_depth=None,
    min_samples_split=2,
    min_samples_leaf=1,
    min_weight_fraction_leaf=0.0,
    max_features='sqrt',
    max_leaf_nodes=None,
    min_impurity_decrease=0.0,
    bootstrap=True,
    oob_score=False,
    n_jobs=None,
    random_state=None,
    verbose=0,
    warm_start=False,
    class_weight=None,
    ccp_alpha=0.0,
    max_samples=None,
    monotonic_cst=None,
)

```

| 参数                  | 类型                  | 默认值                   | 说明                                    |                                   |        |                                     |
| ------------------- | ------------------- | --------------------- | ------------------------------------- | --------------------------------- | ------ | ----------------------------------- |
| n\_estimators       | int                 | 100                   | 决策树数量；越多越稳定，但计算越慢                     |                                   |        |                                     |
| criterion           | "gini" \| "entropy" | "log\_loss"           | "gini"                                | 节点分裂的衡量标准                         |        |                                     |
| max\_depth          | int \| None         | None                  | 树最大深度；None 展开到所有叶子纯净为止（可能过拟合）         |                                   |        |                                     |
| min\_samples\_split | int \| float        | 2                     | 内部节点最少样本数才允许分裂；float 表示比例             |                                   |        |                                     |
| min\_samples\_leaf  | int \| float        | 1                     | 叶子节点最少样本数；增大可减少过拟合                    |                                   |        |                                     |
| max\_features       | "sqrt" \| "log2"    | int                   | float                                 | None                              | "sqrt" | 每次分裂考虑的最大特征数；"sqrt" 适合分类，"auto" 已废弃 |
| bootstrap           | bool                | True                  | True 使用有放回抽样；False 使用全部训练数据           |                                   |        |                                     |
| oob\_score          | bool                | False                 | True 使用袋外样本估计泛化误差（bootstrap=True 时可用） |                                   |        |                                     |
| n\_jobs             | int \| None         | None                  | 并行树的训练数；\-1 使用全部 CPU                  |                                   |        |                                     |
| class\_weight       | dict \| "balanced"  | "balanced\_subsample" | None                                  | None                              | 类别权重   |                                     |
| ccp\_alpha          | float               | 0.0                   | 代价复杂度剪枝参数；0 不剪枝                       |                                   |        |                                     |
| max\_samples        | int \| float        | None                  | None                                  | bootstrap 时每棵树抽取的样本数；None 等于训练集大小 |        |                                     |

### `GradientBoostingClassifier`

梯度提升：顺序训练，每棵树拟合前一棵的残差。准确率通常高于随机森林，但训练慢。

```python
from sklearn.ensemble import GradientBoostingClassifier

clf = GradientBoostingClassifier(
    loss='log_loss',
    learning_rate=0.1,
    n_estimators=100,
    subsample=1.0,
    criterion='friedman_mse',
    min_samples_split=2,
    min_samples_leaf=1,
    min_weight_fraction_leaf=0.0,
    max_depth=3,
    min_impurity_decrease=0.0,
    init=None,
    random_state=None,
    max_features=None,
    verbose=0,
    max_leaf_nodes=None,
    warm_start=False,
    validation_fraction=0.1,
    n_iter_no_change=None,
    tol=1e-4,
    ccp_alpha=0.0,
)

```

| 参数                   | 类型          | 默认值  | 说明                                   |
| -------------------- | ----------- | ---- | ------------------------------------ |
| learning\_rate       | float       | 0.1  | 每棵树的贡献缩减系数（步长）；越小需要越多树               |
| n\_estimators        | int         | 100  | 树的数量；与 learning\_rate 反向调整（小步长 + 多树） |
| subsample            | float       | 1.0  | 每棵树训练时的样本比例；< 1 实现随机梯度提升，减少过拟合       |
| max\_depth           | int         | 3    | 每棵树的最大深度；梯度提升通常用浅树（3–5）              |
| n\_iter\_no\_change  | int \| None | None | 早停：连续 N 轮验证集分数无改善则停止                 |
| validation\_fraction | float       | 0.1  | 早停时从训练集划分的验证比例                       |

---

## 支持向量机（sklearn.svm）

### `SVC`

支持向量机分类，适合高维、小数据集的分类问题。

```python
from sklearn.svm import SVC

clf = SVC(
    C=1.0,
    kernel='rbf',
    degree=3,
    gamma='scale',
    coef0=0.0,
    shrinking=True,
    probability=False,
    tol=1e-3,
    cache_size=200,
    class_weight=None,
    verbose=False,
    max_iter=-1,
    decision_function_shape='ovr',
    break_ties=False,
    random_state=None,
)

```

| 参数                        | 类型                 | 默认值   | 说明                             |                                                                   |       |                                     |
| ------------------------- | ------------------ | ----- | ------------------------------ | ----------------------------------------------------------------- | ----- | ----------------------------------- |
| C                         | float              | 1.0   | 正则化参数；越小间隔越宽（欠拟合），越大越严格分类（过拟合） |                                                                   |       |                                     |
| kernel                    | "linear" \| "poly" | "rbf" | "sigmoid"                      | "precomputed"                                                     | "rbf" | 核函数类型；"rbf" 适合大多数场景；"linear" 适合线性可分 |
| degree                    | int                | 3     | 多项式核的次数；仅 kernel='poly' 时有效    |                                                                   |       |                                     |
| gamma                     | "scale" \| "auto"  | float | "scale"                        | 核系数；"scale" 使用 1/(n\_features \* X.var())；"auto" 使用 1/n\_features |       |                                     |
| probability               | bool               | False | True 启用概率估计（启用后会有额外开销，影响训练速度）  |                                                                   |       |                                     |
| cache\_size               | float              | 200   | 核矩阵缓存大小（MB）；大数据集增大可加速          |                                                                   |       |                                     |
| decision\_function\_shape | "ovr" \| "ovo"     | "ovr" | 多分类策略："ovr" 一对多，"ovo" 一对一      |                                                                   |       |                                     |

---

## 聚类（sklearn.cluster）

### `KMeans`

K-均值聚类，将数据分为 K 个簇。

```python
from sklearn.cluster import KMeans

km = KMeans(
    n_clusters=8,
    init='k-means++',
    n_init='auto',
    max_iter=300,
    tol=1e-4,
    verbose=0,
    random_state=None,
    copy_x=True,
    algorithm='lloyd',
)

```

| 参数          | 类型                      | 默认值      | 说明                                                  |                              |
| ----------- | ----------------------- | -------- | --------------------------------------------------- | ---------------------------- |
| n\_clusters | int                     | 8        | 簇的数量 K；需通过肘部法或轮廓系数确定                                |                              |
| init        | "k-means++" \| "random" | callable | "k-means++"                                         | 初始化方法；"k-means++" 加速收敛并提升稳定性 |
| n\_init     | int \| "auto"           | "auto"   | 不同初始化的运行次数，取最优；"auto" 对 k-means++ 使用 10，random 使用 1 |                              |
| max\_iter   | int                     | 300      | 单次运行最大迭代次数                                          |                              |
| algorithm   | "lloyd" \| "elkan"      | "lloyd"  | 算法实现；"elkan" 用三角不等式加速，但内存更多                         |                              |

```python
from sklearn.cluster import KMeans
import numpy as np

X = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])
km = KMeans(n_clusters=2, random_state=42, n_init=10)
km.fit(X)
print(km.labels_)         # 每个样本的簇标签
print(km.cluster_centers_) # 簇中心坐标
print(km.inertia_)         # 误差平方和（越小越好）

```

### `DBSCAN`

基于密度的聚类，不需要预先指定 K，能发现任意形状的簇并识别噪声点。

```python
from sklearn.cluster import DBSCAN

db = DBSCAN(
    eps=0.5,
    min_samples=5,
    metric='euclidean',
    metric_params=None,
    algorithm='auto',
    leaf_size=30,
    p=None,
    n_jobs=None,
)

```

| 参数           | 类型                     | 默认值         | 说明                                    |        |          |
| ------------ | ---------------------- | ----------- | ------------------------------------- | ------ | -------- |
| eps          | float                  | 0.5         | 两个样本被视为邻居的最大距离；核心超参数，需根据数据尺度调整        |        |          |
| min\_samples | int                    | 5           | 核心点的最少邻居数（含自身）；增大可减少噪声标签              |        |          |
| metric       | str \| callable        | "euclidean" | 距离度量；支持所有 scipy.spatial.distance 中的距离 |        |          |
| algorithm    | "auto" \| "ball\_tree" | "kd\_tree"  | "brute"                               | "auto" | 查找最近邻的算法 |

DBSCAN 的标签中 `-1` 表示噪声点（不属于任何簇）。

---

## 模型选择（sklearn.model\_selection）

### `train_test_split`

将数组或矩阵按比例随机分为训练集和测试集。

```python
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    *arrays,
    test_size=None,
    train_size=None,
    random_state=None,
    shuffle=True,
    stratify=None,
)

```

| 参数            | 类型                 | 默认值  | 说明                               |                                          |
| ------------- | ------------------ | ---- | -------------------------------- | ---------------------------------------- |
| \*arrays      | indexable          | 必填   | 要分割的数组（X, y, weights 等），所有数组必须等长 |                                          |
| test\_size    | float \| int       | None | None                             | float 表示比例（0–1），int 表示绝对数量；None 时默认 0.25 |
| train\_size   | float \| int       | None | None                             | 同上；None 时取 1 - test\_size                |
| random\_state | int \| None        | None | 随机种子；固定种子保证结果可复现                 |                                          |
| shuffle       | bool               | True | 分割前是否打乱；时序数据应设 False             |                                          |
| stratify      | array-like \| None | None | 按此数组的类分布进行分层抽样；保证训练/测试集类别比例相同    |                                          |

### `cross_val_score`

K 折交叉验证，返回每折的评分数组。

```python
from sklearn.model_selection import cross_val_score

scores = cross_val_score(
    estimator,
    X,
    y=None,
    groups=None,
    scoring=None,
    cv=5,
    n_jobs=None,
    verbose=0,
    fit_params=None,
    params=None,
    pre_dispatch='2*n_jobs',
    error_score=nan,
)

```

| 参数        | 类型                 | 默认值  | 说明                               |                                                          |
| --------- | ------------------ | ---- | -------------------------------- | -------------------------------------------------------- |
| estimator | estimator          | 必填   | 实现了 fit 的 sklearn 兼容对象           |                                                          |
| X         | array-like         | 必填   | 特征矩阵                             |                                                          |
| y         | array-like \| None | None | 目标变量；无监督学习传 None                 |                                                          |
| scoring   | str \| callable    | None | None                             | 评估指标；None 使用 estimator 的默认分数；字符串如 "f1\_macro"、"roc\_auc" |
| cv        | int \| CV splitter | 5    | 折数；或自定义 KFold/StratifiedKFold 对象 |                                                          |
| n\_jobs   | int \| None        | None | 并行折数；\-1 使用全部 CPU                |                                                          |

```python
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)
clf = LogisticRegression(max_iter=1000)
scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
print(f"Accuracy: {scores.mean():.3f} ± {scores.std():.3f}")

```

### `GridSearchCV`

穷举超参数网格，用交叉验证选最优参数组合。

```python
from sklearn.model_selection import GridSearchCV

search = GridSearchCV(
    estimator,
    param_grid,
    scoring=None,
    n_jobs=None,
    refit=True,
    cv=5,
    verbose=0,
    pre_dispatch='2*n_jobs',
    error_score=nan,
    return_train_score=False,
)

```

| 参数                   | 类型                   | 默认值   | 说明                                    |      |      |                            |
| -------------------- | -------------------- | ----- | ------------------------------------- | ---- | ---- | -------------------------- |
| estimator            | estimator            | 必填    | 待搜索的模型，需实现 fit/score                  |      |      |                            |
| param\_grid          | dict \| list\[dict\] | 必填    | 参数名（含 \_\_ 分隔的 Pipeline 参数）到候选值列表的映射  |      |      |                            |
| scoring              | str \| callable      | list  | dict                                  | None | None | 评估指标；多指标时用 dict 并需指定 refit |
| cv                   | int \| CV splitter   | 5     | 交叉验证折数                                |      |      |                            |
| refit                | bool \| str          | True  | 找到最优参数后用全量数据重新训练；多指标时需指定用哪个指标         |      |      |                            |
| n\_jobs              | int \| None          | None  | 并行候选数；\-1 全部 CPU                      |      |      |                            |
| return\_train\_score | bool                 | False | True 在 cv\_results\_ 中包含训练集分数（诊断过拟合用） |      |      |                            |

```python
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 3, 5],
}
search = GridSearchCV(
    RandomForestClassifier(random_state=42),
    param_grid,
    cv=5,
    scoring='accuracy',
    n_jobs=-1,
)
search.fit(X, y)
print(search.best_params_)   # {'max_depth': None, 'n_estimators': 100}
print(search.best_score_)    # 0.973...
# search.best_estimator_ 是已用全量数据重训的最优模型

```

### `RandomizedSearchCV`

随机采样超参数空间，比 `GridSearchCV` 更高效（适合大参数空间）。

```python
from sklearn.model_selection import RandomizedSearchCV

search = RandomizedSearchCV(
    estimator,
    param_distributions,
    n_iter=10,
    scoring=None,
    n_jobs=None,
    refit=True,
    cv=5,
    verbose=0,
    pre_dispatch='2*n_jobs',
    random_state=None,
    error_score=nan,
    return_train_score=False,
)

```

| 参数                   | 类型                   | 默认值  | 说明                                 |
| -------------------- | -------------------- | ---- | ---------------------------------- |
| param\_distributions | dict \| list\[dict\] | 必填   | 参数到候选值列表或 scipy 分布对象的映射；连续超参用分布更高效 |
| n\_iter              | int                  | 10   | 随机采样次数；越大越接近 Grid Search 但耗时越多     |
| random\_state        | int \| None          | None | 随机种子                               |

---

## Pipeline（sklearn.pipeline）

### `Pipeline`

将多个预处理步骤和最终估计器串联，避免数据泄漏（`fit_transform` 仅在训练集执行）。

```python
from sklearn.pipeline import Pipeline

pipe = Pipeline(steps, memory=None, verbose=False)

```

| 参数      | 类型                              | 默认值    | 说明                                                              |                                              |
| ------- | ------------------------------- | ------ | --------------------------------------------------------------- | -------------------------------------------- |
| steps   | list\[tuple\[str, estimator\]\] | 必填     | 每个元素为 (name, transformer) 或 (name, estimator)；最后一步可以是 Estimator |                                              |
| memory  | None \| str                     | Memory | None                                                            | 缓存已拟合的 Transformer（加速 GridSearch 时相同参数不重新拟合） |
| verbose | bool                            | False  | True 打印每步执行时间                                                   |                                              |

访问步骤：`pipe['scaler']` 或 `pipe.named_steps['scaler']`。

超参数路径：`pipe.set_params(classifier__C=0.1)`（`stepname__param` 格式）。

```python
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True)

# Pipeline 防止数据泄漏：Scaler 只在训练折 fit
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(max_iter=1000)),
])

# 通过 __ 分隔符访问 Pipeline 内的超参数
param_grid = {
    'clf__C': [0.01, 0.1, 1, 10],
    'clf__penalty': ['l2'],
}
grid = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1)
grid.fit(X, y)
print(grid.best_params_)

```

---

## 评估指标（sklearn.metrics）

### 分类指标

```python
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score, f1_score,
    confusion_matrix, classification_report, roc_auc_score
)

# 二分类
y_true = [0, 1, 1, 0, 1]
y_pred = [0, 1, 0, 0, 1]

print(accuracy_score(y_true, y_pred))                    # 0.8
print(precision_score(y_true, y_pred))                   # 1.0
print(recall_score(y_true, y_pred))                      # 0.667
print(f1_score(y_true, y_pred))                          # 0.8
print(confusion_matrix(y_true, y_pred))
# [[2 0]
#  [1 2]]
print(classification_report(y_true, y_pred))             # 多指标汇总

```

`average` 参数说明（多分类时必须指定）：

| 值          | 说明                      |
| ---------- | ----------------------- |
| "binary"   | 二分类，默认 positive label=1 |
| "micro"    | 全局统计 TP/FP/FN，适合样本不平衡   |
| "macro"    | 各类均值（等权），适合类别均衡         |
| "weighted" | 按类别样本数加权均值，适合不平衡        |

### 回归指标

```python
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

y_true = [3, -0.5, 2, 7]
y_pred = [2.5, 0.0, 2, 8]

print(mean_squared_error(y_true, y_pred))        # MSE = 0.375
print(mean_absolute_error(y_true, y_pred))       # MAE = 0.5
print(r2_score(y_true, y_pred))                  # R² = 0.948

```

---

## 完整示例：端到端 ML 工作流

```python
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, roc_auc_score

# 加载数据
X, y = load_breast_cancer(return_X_y=True)
print(f"Samples: {X.shape[0]}, Features: {X.shape[1]}, Classes: {np.unique(y)}")

# 分层划分训练/测试集（保证类别比例相同）
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 构建 Pipeline（Scaler 只在训练折 fit，防止数据泄漏）
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', RandomForestClassifier(random_state=42)),
])

# 超参数搜索
param_grid = {
    'clf__n_estimators': [100, 200],
    'clf__max_depth': [None, 5, 10],
    'clf__min_samples_leaf': [1, 2],
}
grid = GridSearchCV(pipe, param_grid, cv=5, scoring='roc_auc', n_jobs=-1, verbose=1)
grid.fit(X_train, y_train)

print(f"Best params: {grid.best_params_}")
print(f"CV ROC AUC: {grid.best_score_:.4f}")

# 测试集评估
y_pred = grid.predict(X_test)
y_prob = grid.predict_proba(X_test)[:, 1]

print(classification_report(y_test, y_pred, target_names=['malignant', 'benign']))
print(f"Test ROC AUC: {roc_auc_score(y_test, y_prob):.4f}")

# 特征重要性（从 Pipeline 中取出 clf）
importances = grid.best_estimator_['clf'].feature_importances_
top_features = np.argsort(importances)[-5:][::-1]
print("Top 5 features:", top_features)

```

---

## 最佳实践

**始终在 Pipeline 内做预处理，而非手动拆分：** 在 Pipeline 外对整个数据集做 `fit_transform`，再分训练测试集，会导致测试集信息泄漏到 Scaler 中，使评估结果过于乐观。

```python
# 错误：先 fit scaler 再分割，测试集信息泄漏
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)  # 使用了测试集的均值/方差
X_train, X_test = train_test_split(X_scaled)

# 正确：先分割，再在 Pipeline 内 fit
X_train, X_test = train_test_split(X)
pipe = Pipeline([('scaler', StandardScaler()), ('clf', clf)])
pipe.fit(X_train, y_train)
pipe.predict(X_test)

```

**固定 `random_state` 保证可复现性：** 所有带随机性的操作（分割、模型初始化）都传入 `random_state=42`，确保实验结果可复现和对比。

**类别不平衡时用分层抽样和合适指标：** 不平衡数据集上 accuracy 是误导性指标，应用 ROC AUC、F1-macro 或 PR AUC；`train_test_split(stratify=y)` 保证训练/测试集类别比例一致。

**用 `cross_val_score` 代替单次 train/test 分割评估：** 单次分割结果受随机种子影响大，K 折交叉验证的均值 ± 标准差更可靠。

**超参数调优优先用 `RandomizedSearchCV` 再细化：** 参数空间大时（>30 个组合），先用 `RandomizedSearchCV` 找到大致区间，再用 `GridSearchCV` 在小范围精调，比直接全网格搜索节省 90% 时间。

**使用 `joblib.dump/load` 持久化 Pipeline：** 保存的 Pipeline 含 Scaler 参数，部署时直接 `load` 即可预测，无需重新 fit。

```python
import joblib

joblib.dump(grid.best_estimator_, 'model.pkl')
model = joblib.load('model.pkl')
model.predict(X_test)

```

---

## 常见陷阱

### 陷阱：测试集泄漏到预处理步骤

**现象：** 交叉验证或测试集分数比实际部署效果好得多。

**原因：** 在 Pipeline 外对全量数据做了 `fit_transform`，导致 Scaler 的统计量包含了测试集的信息，测试集相当于被"见过"了。

**解决：** 所有预处理必须放进 Pipeline，只调用 `Pipeline.fit(X_train)` 和 `Pipeline.transform(X_test)`。

### 陷阱：`GridSearchCV` 内外套了不必要的 Scaler

**现象：** Pipeline 内已有 Scaler，外部又手动对全量数据做了归一化，导致双重标准化（零均值数据再次标准化后变形）。

**原因：** 不清楚 Pipeline 内部已经做了预处理。

**解决：** 检查 Pipeline 内已有的步骤，外部不要再做重复预处理。

### 陷阱：类别特征使用了 `LabelEncoder`

**现象：** 模型对类别特征赋予了大小关系（如 `cat=0 < dog=1 < fish=2`），线性模型或神经网络效果差。

**原因：** `LabelEncoder` 产生有序整数，暗示了不存在的大小关系；它只应用于目标变量 y，不应用于输入特征 X。

**解决：** 输入特征的类别编码使用 `OneHotEncoder` 或 `OrdinalEncoder`（仅当类别本身有序时）。

```python
from sklearn.preprocessing import OrdinalEncoder, OneHotEncoder

# 错误：对类别特征用 LabelEncoder（产生错误的有序关系）
le = LabelEncoder()
X[:, 0] = le.fit_transform(X[:, 0])

# 正确：用 OneHotEncoder 在 Pipeline 内处理
pipe = Pipeline([
    ('enc', OneHotEncoder(handle_unknown='ignore')),
    ('clf', LogisticRegression()),
])

```

### 陷阱：`max_iter` 不足导致 `ConvergenceWarning`

**现象：** 输出 `ConvergenceWarning: Lbfgs failed to converge`，但模型看起来还能用。

**原因：** 求解器在 `max_iter` 次迭代内没有达到收敛条件，参数优化未完成，模型是次优解。

**解决：** 增大 `max_iter`（从 100 → 1000 → 10000），或先对数据做 `StandardScaler` 加速收敛，或换 `solver`。

---

## 参见

- [PyTorch完全指南](https://blog.vercanti.com/pytorchwan-quan-zhi-nan/) — 深度学习，处理图像/文本/序列数据
- [HuggingFace Transformers完全指南](https://blog.vercanti.com/huggingface-transformers-wan-quan-zhi-nan/) — 预训练模型微调与推理
- [Pandas完全指南](https://blog.vercanti.com/pandas-wan-quan-zhi-nan/) — 特征工程的数据处理基础
- [数据库设计规范](https://blog.vercanti.com/shu-ju-ku-she-ji-gui-fan/) — 训练数据的存储与查询