CHAPTER 09

机器学习入门(scikit-learn)

掌握机器学习的核心概念和工作流程。scikit-learn 提供了统一的 API,让你用几行代码就能训练和评估模型。

机器学习核心概念

核心概念

什么是机器学习?

机器学习是让计算机从数据中自动学习规律,而不是手动编写规则。传统编程:输入数据 + 规则 → 输出结果;机器学习:输入数据 + 期望结果 → 学出规则(模型)。

类型 特点 典型算法 应用场景
监督学习 有标签数据 线性回归、随机森林 房价预测、垃圾邮件分类
无监督学习 无标签数据 K-Means、PCA 用户聚类、降维
强化学习 通过奖惩学习 PPO、DQN 游戏 AI、机器人控制
关键概念

过拟合(Overfitting)与欠拟合(Underfitting)

过拟合:模型在训练集上准确率极高,但在新数据上表现差——死记硬背,不会举一反三。欠拟合:模型太简单,连训练集都学不好。理想状态是训练集和验证集准确率都高且相近。

scikit-learn 的统一 API

scikit-learn 最大的优点是所有算法都有统一的接口fit() 训练,predict() 预测,score() 评分。换算法只需改一行代码。

PYTHON · scikit-learn 基础流程
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

# 1. 加载数据集(鸢尾花,经典入门数据集)
iris = load_iris()
X, y = iris.data, iris.target
print(f"特征形状: {X.shape}, 类别数: {len(set(y))}")

# 2. 切分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 3. 特征标准化(零均值,单位方差)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)   # 在训练集上 fit
X_test  = scaler.transform(X_test)         # 测试集只用 transform!

# 4. 训练模型
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)   # 两行搞定训练

# 5. 评估
y_pred = model.predict(X_test)
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
print(classification_report(y_test, y_pred))
⚠️

数据泄露(Data Leakage)陷阱

StandardScaler 必须在训练集上 fit,然后用同样的参数 transform 测试集。如果用测试集做 fit_transform,测试集的信息就"泄露"给了模型,评估结果会虚高。这是初学者最常犯的错误之一。

常用算法一览

scikit-learn 统一的 API 让换算法变得极其简单。了解各算法的特点,在合适的场景选对工具:

PYTHON · 换算法只需一行
from sklearn.linear_model    import LogisticRegression, LinearRegression
from sklearn.tree             import DecisionTreeClassifier
from sklearn.ensemble         import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm              import SVC
from sklearn.neighbors        import KNeighborsClassifier

# 所有算法接口完全一样!
models = {
    "逻辑回归":   LogisticRegression(),
    "决策树":     DecisionTreeClassifier(max_depth=5),
    "随机森林":   RandomForestClassifier(n_estimators=100),
    "梯度提升":   GradientBoostingClassifier(),
    "SVM":       SVC(kernel="rbf"),
    "KNN":       KNeighborsClassifier(n_neighbors=5),
}

# 快速对比所有算法的效果
for name, clf in models.items():
    clf.fit(X_train, y_train)
    acc = clf.score(X_test, y_test)
    print(f"{name:10s}: {acc:.4f}")
算法 优点 缺点 适用场景
逻辑回归 可解释性强、速度快 只能线性决策边界 二分类基线模型
随机森林 强大、抗过拟合 黑盒、速度慢 结构化数据首选
梯度提升 (XGBoost) Kaggle 竞赛冠军 参数多、训练慢 结构化数据最强
SVM 小数据集效果好 大数据慢、参数敏感 文本分类、小数据集

模型评估与交叉验证

单次划分训练/测试集的结果受随机性影响。交叉验证(Cross-Validation)通过多次不同划分取平均,得到更可靠的评估结果。

PYTHON · 评估指标与交叉验证
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.metrics import (
    accuracy_score, precision_score,
    recall_score, f1_score, roc_auc_score,
    confusion_matrix
)

model = RandomForestClassifier(n_estimators=100, random_state=42)

# 5折交叉验证
cv_scores = cross_val_score(model, X, y, cv=5, scoring="accuracy")
print(f"CV 准确率: {cv_scores.mean():.4f} ± {cv_scores.std():.4f}")

# 评估各指标(在测试集上)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

print(f"准确率 (Accuracy):  {accuracy_score(y_test, y_pred):.4f}")
print(f"精确率 (Precision): {precision_score(y_test, y_pred, average='macro'):.4f}")
print(f"召回率 (Recall):    {recall_score(y_test, y_pred, average='macro'):.4f}")
print(f"F1 Score:          {f1_score(y_test, y_pred, average='macro'):.4f}")

# 混淆矩阵:可视化预测错误的分布
cm = confusion_matrix(y_test, y_pred)
print("混淆矩阵:\n", cm)
🤖

准确率不是万能的

如果正负样本比例严重不均(比如 99% 负样本),模型只要全预测负就有 99% 准确率,但毫无用处。这时应该用 F1 Score 或 AUC-ROC 来评估。在医疗 AI(疾病检测)中,召回率比准确率更重要——漏诊代价更高。

超参数调优

PYTHON · 网格搜索调参
from sklearn.model_selection import GridSearchCV

model = RandomForestClassifier(random_state=42)

# 定义要搜索的参数范围
param_grid = {
    "n_estimators": [50, 100, 200],
    "max_depth":    [None, 5, 10],
    "min_samples_split": [2, 5],
}

# 5折交叉验证 + 网格搜索
grid_search = GridSearchCV(
    model, param_grid,
    cv=5, scoring="f1_macro",
    n_jobs=-1  # 用所有 CPU 核心并行
)
grid_search.fit(X_train, y_train)

print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳得分: {grid_search.best_score_:.4f}")

# 用最佳参数的模型进行预测
best_model = grid_search.best_estimator_
final_score = best_model.score(X_test, y_test)
print(f"测试集得分: {final_score:.4f}")

调参的核心原则

不要在测试集上调参!正确流程:训练集训练 → 验证集(或交叉验证)调参 → 确定模型后最终用测试集评估一次。测试集必须保持"纯洁",代表真实未见数据。