Python机器学习:scikit-learn入门

scikit-learn 是 Python 机器学习的基础库,API 设计统一,文档详尽,适合入门和快速原型开发。本文用一个完整的分类任务串起 sklearn 的核心工作流。

加载数据集

sklearn 内置了不少经典数据集,方便学习和实验:

from sklearn.datasets import load_iris, load_wine, load_digits
from sklearn.model_selection import train_test_split

# 加载 Iris 数据集
iris = load_iris()
X, y = iris.data, iris.target
print(f"特征形状: {X.shape}")  # (150, 4)
print(f"类别: {iris.target_names}")  # ['setosa' 'versicolor' 'virginica']
print(f"特征名: {iris.feature_names}")

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"训练集: {X_train.shape[0]}, 测试集: {X_test.shape[0]}")

stratify=y 确保训练集和测试集中各类别比例与原始数据一致。

数据预处理

大多数算法对特征的尺度敏感,标准化是必要步骤:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # 在训练集上 fit
X_test_scaled = scaler.transform(X_test)  # 在测试集上只 transform

重要原则fit 只能在训练集上做。如果在全量数据上 fit 再 split,就会把测试集的信息泄漏到预处理步骤中(data leakage)。

其他常用预处理:

  • MinMaxScaler:缩放到 [0, 1]
  • LabelEncoder:标签编码
  • OneHotEncoder:独热编码

分类模型

sklearn 所有模型都遵循统一的 API:fit() 训练,predict() 预测,score() 评估。

决策树

from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(X_train_scaled, y_train)

y_pred = dt.predict(X_test_scaled)
print(f"决策树准确率: {dt.score(X_test_scaled, y_test):.4f}")

决策树容易过拟合,通过 max_depthmin_samples_split 等参数控制复杂度。

随机森林

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf.fit(X_train_scaled, y_train)
print(f"随机森林准确率: {rf.score(X_test_scaled, y_test):.4f}")

# 特征重要性
import numpy as np
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1]
for i in range(X.shape[1]):
    print(f"  {iris.feature_names[indices[i]]}: {importances[indices[i]]:.4f}")

随机森林是多棵决策树的集成,通过 bagging 和特征随机选择来降低过拟合。实际项目中它是一个很强的 baseline。

模型评估

准确率只是最基本的指标,还需要更细致的分析:

from sklearn.metrics import (
    accuracy_score, classification_report, confusion_matrix
)

y_pred = rf.predict(X_test_scaled)

# 准确率
print(f"Accuracy: {accuracy_score(y_test, y_pred):.4f}")

# 详细报告:每个类别的 precision / recall / f1
print(classification_report(y_test, y_pred, target_names=iris.target_names))

# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
print("Confusion Matrix:")
print(cm)

混淆矩阵的对角线是预测正确的数量,非对角线是错误的。通过它可以看出模型在哪些类别上容易混淆。

可视化混淆矩阵

import matplotlib.pyplot as plt
from sklearn.metrics import ConfusionMatrixDisplay

fig, ax = plt.subplots(figsize=(6, 5))
ConfusionMatrixDisplay.from_predictions(
    y_test, y_pred,
    display_labels=iris.target_names,
    cmap='Blues',
    ax=ax
)
plt.title('Confusion Matrix')
plt.tight_layout()
plt.savefig('confusion_matrix.png', dpi=100)
plt.close()

交叉验证

单次 train/test split 的结果可能有偏差,交叉验证更可靠:

from sklearn.model_selection import cross_val_score

# 5 折交叉验证
scores = cross_val_score(rf, X, y, cv=5, scoring='accuracy')
print(f"5-Fold CV accuracy: {scores.mean():.4f} (+/- {scores.std():.4f})")
print(f"每折结果: {scores}")

交叉验证将数据分成 k 份,每次用 k-1 份训练、1 份验证,循环 k 次。最终结果是 k 次的平均值,比单次划分更稳定。

用 Pipeline 避免数据泄漏

交叉验证中预处理和模型应该打包在一起,确保 scaler 只在训练折上 fit:

from sklearn.pipeline import Pipeline

pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', RandomForestClassifier(n_estimators=100, random_state=42))
])

scores = cross_val_score(pipeline, X, y, cv=5, scoring='accuracy')
print(f"Pipeline CV accuracy: {scores.mean():.4f} (+/- {scores.std():.4f})")

Pipeline 是 sklearn 中非常推荐的用法——它把预处理和模型封装成一个整体,调用 fit / predict 时自动按步骤执行,杜绝了手动处理时可能出现的数据泄漏。

小结

sklearn 的核心工作流就是:加载数据 -> 预处理 -> 选模型 -> fit/predict -> 评估 -> 交叉验证。统一的 API 设计让切换不同算法几乎只需要换一行代码。下一步可以探索 GridSearchCV 做超参数调优,或者尝试更多模型(SVM、KNN、XGBoost 等)。