一、scikit-learn 概述与设计哲学
scikit-learn 是 Python 生态中最成熟、最广泛使用的机器学习库之一,基于 NumPy、SciPy 和 matplotlib 构建。它提供了统一、简洁、一致的 API 接口,覆盖了从数据预处理、特征工程、模型训练、模型评估到模型部署的完整机器学习流水线。无论你是刚接触机器学习的初学者,还是经验丰富的数据科学家,scikit-learn 都能满足从快速原型验证到生产环境部署的全部需求。
1.1 核心设计理念
scikit-learn 的 API 设计遵循三大核心原则:一致性(所有对象共享统一的接口)、内省性(所有参数值作为公共属性暴露)、限制对象层级(算法以 Python 类形式表示,数据集以 NumPy 数组或 SciPy 稀疏矩阵表示)。这种设计使得不同算法之间的切换几乎不费吹灰之力,极大地降低了学习成本。
1.2 三大核心接口
scikit-learn 将机器学习组件划分为三种基本类型:
| 类型 |
接口方法 |
代表类 |
用途 |
| Estimator(估计器) |
fit() |
所有模型 |
基于数据学习参数 |
| Predictor(预测器) |
predict() |
分类器、回归器 |
对新样本做预测 |
| Transformer(转换器) |
transform() |
Scaler、Encoder |
数据转换与预处理 |
这三类接口遵循着统一的调用模式:先用 fit() 学习数据中的参数(如均值、方差、模型权重),再用 predict() 或 transform() 应用到新数据上。这种 fit / predict(或 transform) 的两阶段模式是整个 scikit-learn 设计的基石。
+------------------+ +---------------------+
| 原始数据 (X, y) | -----> | Estimator.fit(X, y) | -----> 学习得到模型参数
+------------------+ +---------------------+
|
v
+------------------+ +---------------------+
| 新样本 (X_new) | -----> | Estimator.predict | -----> 预测结果 y_pred
+------------------+ +---------------------+
设计哲学要点:
- 统一接口: 无论模型多么复杂,都通过
.fit() 训练和 .predict()(或 .transform())预测
- 参数可访问: 所有超参数通过构造函数参数设置,学习到的参数以下划线后缀属性访问(如
coef_、feature_importances_)
- 组合性: 通过 Pipeline 机制将多个转换器和估计器无缝串联
- 可复现性: 通过
random_state 参数确保结果可复现
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_train)
代码 1:scikit-learn 统一接口调用模式
二、数据预处理与特征工程
真实世界的数据极少是干净整齐的。数据预处理是机器学习流程中最关键、最耗时的环节,直接决定了模型质量的上限。scikit-learn 提供了一套完整的预处理工具链,涵盖数值型数据的标准化与归一化、类别型数据的编码、缺失值处理以及自定义转换。
2.1 数值型数据标准化
大多数机器学习算法(尤其是基于距离和梯度的模型如 SVM、逻辑回归、神经网络)假设所有特征在相似的尺度上。如果某个特征的数值范围远大于其他特征,它可能会主导目标函数,导致模型性能下降。常用的数值缩放方法有以下几种:
| 转换器 |
公式 |
输出范围 |
适用场景 |
StandardScaler |
z = (x - mu) / sigma |
无固定范围(均值为0,标准差为1) |
数据近似正态分布时首选 |
MinMaxScaler |
z = (x - min) / (max - min) |
[0, 1] |
需要有界输出时使用 |
RobustScaler |
z = (x - median) / IQR |
无固定范围 |
数据包含异常值时首选 |
MaxAbsScaler |
z = x / max(|x|) |
[-1, 1] |
稀疏矩阵的推荐选择 |
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import numpy as np
X = np.array([[1., -1., 2.],
[2., 0., 0.],
[0., 1., -1.]])
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print(f"均值: {scaler.mean_}")
print(f"标准差: {scaler.scale_}")
minmax = MinMaxScaler()
X_minmax = minmax.fit_transform(X)
robust = RobustScaler()
X_robust = robust.fit_transform(X)
代码 2:四种常用数值缩放方法
2.2 类别型数据编码
机器学习模型只能处理数值型数据,因此类别型特征需要转换为数值形式。scikit-learn 提供了两种主要编码方式:OneHotEncoder(独热编码)适用于无序类别,OrdinalEncoder(顺序编码)适用于有序类别。对于目标变量(标签),使用 LabelEncoder。
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder, LabelEncoder
X_categorical = [['红色'], ['蓝色'], ['绿色'], ['蓝色']]
ohe = OneHotEncoder(sparse_output=False)
X_ohe = ohe.fit_transform(X_categorical)
print(f"类别列表: {ohe.categories_}")
y_labels = ['猫', '狗', '猫', '鸟']
le = LabelEncoder()
y_encoded = le.fit_transform(y_labels)
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), [0, 1, 2]),
('cat', OneHotEncoder(), [3, 4])
])
代码 3:类别编码与 ColumnTransformer 示例
2.3 自定义转换器与 FunctionTransformer
当内置的转换器无法满足需求时,可以使用 FunctionTransformer 将任意 Python 函数包装为 scikit-learn 兼容的转换器,或者继承 BaseEstimator 和 TransformerMixin 创建完全自定义的转换器。
import numpy as np
from sklearn.preprocessing import FunctionTransformer
from sklearn.base import BaseEstimator, TransformerMixin
def log_transform(X):
"""对数转换:适用于右偏分布的数据"""
return np.log1p(X)
log_transformer = FunctionTransformer(log_transform, validate=True)
X_log = log_transformer.fit_transform(X)
class OutlierClipper(BaseEstimator, TransformerMixin):
"""剪除异常值的自定义转换器"""
def __init__(self, lower_percentile=1, upper_percentile=99):
self.lower_percentile = lower_percentile
self.upper_percentile = upper_percentile
def fit(self, X, y=None):
self.lower_bound_ = np.percentile(X, self.lower_percentile, axis=0)
self.upper_bound_ = np.percentile(X, self.upper_percentile, axis=0)
return self
def transform(self, X):
return np.clip(X, self.lower_bound_, self.upper_bound_)
clipper = OutlierClipper(lower_percentile=5, upper_percentile=95)
X_clean = clipper.fit_transform(X)
代码 4:FunctionTransformer 与自定义转换器
三、数据集划分与验证策略
在训练机器学习模型之前,必须将数据集划分为训练集和测试集。训练集用于拟合模型参数,测试集用于评估模型在未见数据上的泛化性能。scikit-learn 的 train_test_split 是最基础、最常用的划分工具,但它远不止简单的随机切分。
3.1 train_test_split 核心参数
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
stratify=y,
random_state=42
)
from collections import Counter
print(f"原始分布: {Counter(y)}")
print(f"训练分布: {Counter(y_train)}")
print(f"测试分布: {Counter(y_test)}")
X_train, X_test = X[:split_idx], X[split_idx:]
y_train, y_test = y[:split_idx], y[split_idx:]
代码 5:train_test_split 的多种用法
划分策略选择指南
- 分类问题:始终使用
stratify=y 确保训练/测试集中各类别比例与原始数据一致
- 回归问题:无需分层,但可以按目标变量的分位数分层
- 时间序列:永远不要随机打乱!使用时间顺序划分
- 数据量极大(>100万条):可考虑更小的测试比例(如 0.1 或 0.05)
- 数据量极小(<1000条):使用交叉验证替代单次划分
3.2 交叉验证
当数据量有限时,单次划分的评估结果可能不够稳定。交叉验证通过多次划分和评估来获得更可靠的性能估计。
from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kfold, scoring='r2')
print(f"每折 R² 分数: {scores}")
print(f"平均 R²: {scores.mean():.4f} (+/- {scores.std() * 2:.4f})")
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=skf, scoring='accuracy')
scores_f1 = cross_val_score(model, X, y, cv=5, scoring='f1_macro')
scores_auc = cross_val_score(model, X, y, cv=5, scoring='roc_auc_ovr')
代码 6:交叉验证评估模型
四、监督学习模型详解
scikit-learn 实现了几乎所有主流的监督学习算法,从经典的线性模型到强大的集成学习方法。以下精选六个最常用、最有代表性的模型,覆盖回归与分类两大任务。
4.1 线性回归(LinearRegression)
线性回归是最简单的回归模型,假设目标变量与特征之间存在线性关系。它通过最小化残差平方和(OLS,普通最小二乘法)来求解最优的权重系数。线性回归计算效率极高,且具有良好的可解释性——每个特征的系数直接反映了该特征对目标变量的边际影响。
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
print(f"R² 分数: {r2_score(y_test, y_pred):.4f}")
print(f"RMSE: {np.sqrt(mean_squared_error(y_test, y_pred)):.4f}")
print(f"截距: {lr.intercept_:.4f}")
for i, coef in enumerate(lr.coef_):
print(f" 特征 {i} 的系数: {coef:.4f}")
代码 7:线性回归模型训练与评估
4.2 逻辑回归(LogisticRegression)
尽管名称中带有"回归",逻辑回归实际上是最常用的二分类算法之一。它通过 Sigmoid 函数将线性回归的输出映射到 [0,1] 区间的概率值,再根据概率阈值(通常为 0.5)进行分类决策。逻辑回归同样具有出色的可解释性,且通过正则化参数(C 值)可以有效防止过拟合。
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
logreg = LogisticRegression(
C=1.0,
penalty='l2',
solver='lbfgs',
max_iter=1000,
random_state=42
)
logreg.fit(X_train, y_train)
y_pred = logreg.predict(X_test)
y_prob = logreg.predict_proba(X_test)[:, 1]
print("分类报告:")
print(classification_report(y_test, y_pred))
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
from sklearn.metrics import roc_auc_score, roc_curve
auc = roc_auc_score(y_test, y_prob)
print(f"ROC-AUC: {auc:.4f}")
代码 8:逻辑回归分类与评估
4.3 决策树与随机森林
决策树通过树形结构对数据进行递归划分,每个内部节点代表一个特征的判断条件,每个叶节点代表一个预测值或类别。决策树的优势在于:无需特征缩放、天然支持非线性关系、结果可直接可视化和解释。但单棵决策树容易过拟合,对数据中的微小变化非常敏感。
随机森林(RandomForestClassifier / RandomForestRegressor) 通过集成学习(Bagging)的思想,构建多棵决策树并对其预测结果进行投票(分类)或平均(回归),从而显著降低方差、提高泛化能力。随机森林在绝大多数表格数据任务中表现优异,是实战中的"万金油"模型。
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier, plot_tree
import matplotlib.pyplot as plt
dt = DecisionTreeClassifier(max_depth=5, random_state=42)
dt.fit(X_train, y_train)
rf = RandomForestClassifier(
n_estimators=100,
max_depth=10,
min_samples_split=5,
min_samples_leaf=2,
n_jobs=-1,
random_state=42
)
rf.fit(X_train, y_train)
feature_importances = rf.feature_importances_
indices = np.argsort(feature_importances)[::-1]
print("特征重要性排名:")
for i in range(len(indices)):
print(f" {i+1}. 特征 {indices[i]}: {feature_importances[indices[i]]:.4f}")
代码 9:决策树与随机森林
4.4 支持向量机(SVC)
支持向量机的核心思想是在特征空间中找到一个超平面,使不同类别的样本之间的间隔(margin)最大化。SVM 通过核技巧(kernel trick)可以高效地处理非线性分类问题:它将原始数据隐式映射到高维特征空间,在高维空间中寻找线性可分的超平面。常用的核函数包括线性核(linear)、多项式核(poly)和径向基核(rbf)。
from sklearn.svm import SVC
svm = SVC(
kernel='rbf',
C=1.0,
gamma='scale',
probability=True,
random_state=42
)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
svm.fit(X_train_scaled, y_train)
y_pred = svm.predict(X_test_scaled)
print(f"SVM 准确率: {svm.score(X_test_scaled, y_test):.4f}")
代码 10:支持向量机分类
4.5 K近邻(KNeighborsClassifier)
K近邻(KNN)是最"懒惰"的学习算法:它不做任何模型训练,只是简单存储所有训练样本。当需要对新样本进行预测时,KNN 在训练集中查找与该样本最近的 K 个邻居,然后通过邻居的多数投票(分类)或均值(回归)来做出预测。KNN 对特征尺度极为敏感,必须进行标准化处理。
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(
n_neighbors=5,
weights='distance',
metric='minkowski',
p=2
)
knn.fit(X_train_scaled, y_train)
y_pred = knn.predict(X_test_scaled)
best_k, best_score = 1, 0
for k in range(1, 31):
knn = KNeighborsClassifier(n_neighbors=k)
scores = cross_val_score(knn, X_train_scaled, y_train, cv=5, scoring='accuracy')
avg_score = scores.mean()
if avg_score > best_score:
best_score = avg_score
best_k = k
print(f"最优 K 值: {best_k}, 交叉验证准确率: {best_score:.4f}")
代码 11:K近邻分类器与 K 值调优
回归任务模型速查
- LinearRegression — 线性关系,高可解释性
- Ridge / Lasso — 带正则化的线性回归
- RandomForestRegressor — 非线性、高准确率
- SVR — 小数据集、高维特征
- GradientBoostingRegressor — 梯度提升回归
分类任务模型速查
- LogisticRegression — 二分类首选基线
- RandomForestClassifier — 表格数据"万金油"
- SVC — 中小数据集、高维空间
- KNeighborsClassifier — 决策边界复杂时
- GradientBoostingClassifier — 竞赛常用
五、模型评估指标体系
"你怎么衡量模型,你就会得到什么样的模型。"模型评估是机器学习中决定性的一环。scikit-learn 提供了丰富的评估指标,覆盖分类、回归和聚类三大任务。
5.1 分类评估指标
| 指标 |
函数 |
适用场景 |
说明 |
| 准确率 |
accuracy_score |
均衡数据集 |
预测正确的比例,在类别不平衡时失效 |
| 精确率 |
precision_score |
假阳性代价高 |
预测为阳性的样本中实际为阳性的比例 |
| 召回率 |
recall_score |
假阴性代价高 |
实际为阳性的样本中被正确预测的比例 |
| F1分数 |
f1_score |
精确率与召回率的平衡 |
精确率和召回率的调和平均数 |
| ROC-AUC |
roc_auc_score |
排序质量评估 |
模型区分正负类的能力,取值[0.5, 1] |
from sklearn.metrics import (
accuracy_score, precision_score, recall_score, f1_score,
confusion_matrix, classification_report, roc_auc_score, roc_curve
)
print(classification_report(y_test, y_pred, target_names=['负类', '正类']))
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred, average='macro')
recall = recall_score(y_test, y_pred, average='macro')
f1 = f1_score(y_test, y_pred, average='macro')
print(f"准确率: {accuracy:.4f}")
print(f"精确率: {precision:.4f}")
print(f"召回率: {recall:.4f}")
print(f"F1分数: {f1:.4f}")
cm = confusion_matrix(y_test, y_pred)
print("混淆矩阵:")
print(cm)
代码 12:分类模型综合评估
5.2 回归评估指标
from sklearn.metrics import (
r2_score, mean_squared_error, mean_absolute_error,
mean_absolute_percentage_error
)
y_pred = lr.predict(X_test)
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred)
mape = mean_absolute_percentage_error(y_test, y_pred)
print(f"R²: {r2:.4f}")
print(f"RMSE: {rmse:.4f}")
print(f"MAE: {mae:.4f}")
print(f"MAPE: {mape:.4%}")
代码 13:回归模型评估
选择评估指标的核心原则
- 分类任务:不平衡数据集优先看精确率、召回率和 F1(而非准确率),排序任务看 ROC-AUC
- 回归任务:RMSE 对异常值敏感(惩罚大误差),MAE 无偏向性,R² 衡量模型解释了多少方差
- 业务结合:始终从业务视角选择指标——假阳性(FP)和假阴性(FN)哪个成本更高?
- 泛化验证:永远不要用测试集调参!使用验证集或交叉验证,测试集仅供最终评估
六、Pipeline 流水线:从数据到模型的完整封装
在实际项目中,数据预处理通常包含多个步骤(缺失值填充、标准化、编码、特征选择等),然后将处理后的数据传给模型。如果手动串接这些步骤,代码会变得冗余且容易出错——尤其在交叉验证时,很容易不慎将测试集信息泄漏到训练过程中。
Pipeline 是解决这一问题的标准方案。它将多个转换器和最终的估计器打包成一个整体,具有以下关键优势:
- 避免数据泄漏:在交叉验证中,每个 fold 的预处理参数独立学习,不会用全局统计数据污染验证集
- 代码简洁:将整个机器学习流程封装为一个对象,一次
.fit() 和 .predict() 调用即可完成全部流程
- 与 GridSearchCV 完美配合:可以同时对预处理参数和模型超参数进行联合搜索
- 易于部署:训练好的 Pipeline 包含了整个预处理流程,部署时无需额外处理
from sklearn.pipeline import Pipeline, make_pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier
pipeline = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler()),
('classifier', RandomForestClassifier())
])
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
from sklearn.pipeline import make_pipeline
pipeline2 = make_pipeline(StandardScaler(), RandomForestClassifier())
numeric_features = ['age', 'income', 'amount']
categorical_features = ['gender', 'city', 'education']
numeric_transformer = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
categorical_transformer = Pipeline([
('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
('encoder', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer([
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
full_pipeline = Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier(random_state=42))
])
full_pipeline.fit(X_train, y_train)
y_pred = full_pipeline.predict(X_test)
代码 14:Pipeline 与 ColumnTransformer 完整示例
6.2 GridSearchCV 与 Pipeline 联合调参
Pipeline 与 GridSearchCV 结合后,可以同时对预处理参数和模型超参数进行系统化的网格搜索。参数名称使用双下划线 __ 分隔步骤名和参数名(如 classifier__n_estimators)。
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
param_grid = {
'preprocessor__num__scaler': [StandardScaler(), MinMaxScaler(), None],
'classifier__n_estimators': [50, 100, 200],
'classifier__max_depth': [None, 10, 20],
'classifier__min_samples_split': [2, 5, 10],
'classifier__min_samples_leaf': [1, 2, 4]
}
grid_search = GridSearchCV(
estimator=full_pipeline,
param_grid=param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1,
verbose=1,
return_train_score=True
)
grid_search.fit(X_train, y_train)
print(f"最优参数组合: {grid_search.best_params_}")
print(f"最优交叉验证分数: {grid_search.best_score_:.4f}")
test_score = grid_search.score(X_test, y_test)
print(f"测试集分数: {test_score:.4f}")
from scipy.stats import randint, uniform
random_search = RandomizedSearchCV(
estimator=full_pipeline,
param_distributions={
'classifier__n_estimators': randint(50, 500),
'classifier__max_depth': randint(3, 30),
'classifier__min_samples_split': randint(2, 20)
},
n_iter=50,
cv=5,
random_state=42
)
代码 15:GridSearchCV 与 Pipeline 联合调参
七、模型保存与部署
训练好的模型需要进行序列化保存,以便在生产环境中加载和使用。scikit-learn 官方推荐的模型持久化方案是 joblib 库(而非 Python 内置的 pickle),因为 joblib 对大型 NumPy 数组进行了优化,序列化和反序列化速度更快。
import joblib
import pickle
joblib.dump(full_pipeline, 'model_pipeline.joblib')
loaded_pipeline = joblib.load('model_pipeline.joblib')
predictions = loaded_pipeline.predict(X_new)
with open('model_pipeline.pkl', 'wb') as f:
pickle.dump(full_pipeline, f)
with open('model_pipeline.pkl', 'rb') as f:
loaded_pipeline = pickle.load(f)
model_info = {
'model': full_pipeline,
'features': feature_names,
'target': target_name,
'metrics': {'test_accuracy': test_score},
'training_date': '2026-05-05',
'sklearn_version': '1.5.0'
}
joblib.dump(model_info, 'model_with_metadata.joblib')
import datetime
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
joblib.dump(full_pipeline, f'model_{timestamp}.joblib')
代码 16:模型保存与加载
模型序列化注意事项
- Python 版本兼容性:在不同 Python 版本之间序列化和反序列化可能会失败,尽量保持环境一致
- scikit-learn 版本兼容性:不同版本之间的模型文件可能不兼容,记录版本号
- 安全风险:不要加载不可信的 pickle/joblib 文件,可能执行任意代码
- 大模型:随机森林等模型可能体积较大(几百 MB),考虑使用压缩或模型蒸馏
- 生产部署:推荐使用 ONNX 格式或 MLflow 等模型管理平台
八、完整实战案例:Iris 鸢尾花分类
以下是一个端到端的完整案例,从数据加载到模型部署,涵盖本笔记中介绍的所有核心概念。使用经典的 Iris 数据集进行演示:
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
data = load_iris()
X, y = data.data, data.target
feature_names = data.feature_names
target_names = data.target_names
print(f"数据形状: {X.shape}")
print(f"特征: {feature_names}")
print(f"类别: {target_names}")
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
print(f"训练集: {X_train.shape}, 测试集: {X_test.shape}")
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
pipeline = Pipeline([
('scaler', StandardScaler()),
('rf', RandomForestClassifier(random_state=42))
])
from sklearn.model_selection import GridSearchCV
param_grid = {
'rf__n_estimators': [50, 100, 200],
'rf__max_depth': [None, 5, 10],
'rf__min_samples_split': [2, 5]
}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid.fit(X_train, y_train)
print(f"最优参数: {grid.best_params_}")
print(f"最优CV分数: {grid.best_score_:.4f}")
from sklearn.metrics import classification_report, confusion_matrix
y_pred = grid.predict(X_test)
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=target_names))
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
test_acc = grid.score(X_test, y_test)
print(f"测试集准确率: {test_acc:.4f}")
import joblib
joblib.dump(grid.best_estimator_, 'iris_rf_pipeline.joblib')
print("模型已保存为 iris_rf_pipeline.joblib")
代码 17:完整端到端实战案例
实战关键要点回顾
- 始终使用 Pipeline:将预处理和模型训练封装在一起,避免数据泄漏,简化部署
- 分层抽样不可省略:分类任务必须使用
stratify=y,确保训练和测试集分布一致
- 标准化 SVM 和 KNN 的前置条件:基于距离的模型对特征尺度高度敏感
- GridSearchCV + Pipeline:一起对预处理参数和模型参数进行联合搜索
- 多指标评估:不要只看准确率,综合精确率、召回率、F1 和混淆矩阵一起分析
- 模型版本管理:每次训练保存不同文件名,记录 scikit-learn 版本和训练元数据
九、总结与学习路径建议
scikit-learn 提供了一个优雅、一致且功能强大的机器学习框架。掌握本笔记涵盖的内容,你就能独立完成以下任务:加载并探索数据、进行数据预处理和特征工程、划分训练集和测试集、训练监督学习模型、系统化评估模型性能、通过 Pipeline 构建完整流水线、使用 GridSearchCV 调优超参数、保存和部署模型。
推荐的学习路径
- 入门阶段:深入理解 API 设计哲学(fit/predict/transform),掌握 train_test_split 和 StandardScaler
- 建模阶段:逐个实践 LinearRegression → LogisticRegression → RandomForestClassifier → SVC,理解每种算法的适用场景
- 评估阶段:系统学习分类和回归评估指标,掌握交叉验证和 confusion_matrix 分析
- 工程阶段:掌握 Pipeline + ColumnTransformer 构建生产级流水线,联合 GridSearchCV 进行系统调参
- 进阶方向:特征选择(SelectKBest / RFE)、降维(PCA / t-SNE)、集成方法(GradientBoosting / XGBoost / LightGBM)、无监督学习(KMeans / DBSCAN)
一句话总结
scikit-learn 通过 fit / predict / transform 统一接口 + Pipeline 流水线封装 + GridSearchCV 系统调参 三大支柱,将机器学习从"艺术"变成可工程化的"流程"。学好 scikit-learn 是成为数据科学家的第一步,也是最重要的一步。