Machine Learning: Scikit-learn入门 — 统一API与第一个ML模型完全指南

Scikit-learn的统一API让所有算法用同样的方式调用——学会一个,就会全部。

1. 你将学到


2. 一个ML新人的真实故事

(1) 痛点:每个算法的API都不一样

Bob尝试了3个不同的ML库,每个的调用方式都不同——一个用train(),一个用fit_model(),一个用learn()。他花了2天时间读文档才搞清楚怎么调用,换一个算法又要重新学。API不统一是ML入门的最大障碍。

(2) Scikit-learn的解法

Scikit-learn定义了统一的API设计:所有算法都遵循fit → predict → score三步法,换算法只需改一行。

PYTHON
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor

# Same API, different algorithm - just change the model class
models = {
    "LinearRegression": LinearRegression(),
    "RandomForest": RandomForestRegressor(n_estimators=100),
}

for name, model in models.items():
    model.fit(X_train, y_train)
    score = model.score(X_test, y_test)
    print(f"{name}: R² = {score:.3f}")

(3) 收益:学一个API覆盖30+算法

Bob掌握了sklearn的统一API后,30+种算法的调用方式全部统一——从LinearRegression到XGBoost,只需换一个类名。


3. Scikit-learn设计哲学与统一API

(1) 统一API模式

100%
graph LR
    A[Estimator<br/>Base Class] --> B[Transformer<br/>fit + transform]
    A --> C[Predictor<br/>fit + predict]
    A --> D[Model<br/>fit + predict + score]
    B --> E[StandardScaler<br/>PCA<br/>OneHotEncoder]
    C --> F[KMeans<br/>DBSCAN]
    D --> G[LinearRegression<br/>RandomForest<br/>SVM]

(2) 三大接口

接口 核心方法 用途 示例
Estimator fit(X, y) 从数据学习参数 所有模型的基类
Transformer fit() + transform() + fit_transform() 数据预处理 StandardScaler, PCA
Predictor fit() + predict() 预测输出 LinearRegression, SVM

▶ 示例:Estimator/Transformer/Predictor使用模式

PYTHON
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import numpy as np

# Generate sample data
rng = np.random.default_rng(42)
X = rng.uniform(0, 100, (200, 3))
y = 50 + 0.8 * X[:, 0] + 1.2 * X[:, 1] - 0.5 * X[:, 2] + rng.normal(0, 5, 200)

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

# Transformer: StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # fit + transform in one step
X_test_scaled = scaler.transform(X_test)         # only transform (use training stats)

# Predictor: LinearRegression
model = LinearRegression()
model.fit(X_train_scaled, y_train)
predictions = model.predict(X_test_scaled)
score = model.score(X_test_scaled, y_test)

print(f"R² score: {score:.4f}")
print(f"Coefficients: {model.coef_}")
print(f"Intercept: {model.intercept_:.2f}")

输出:

TEXT 📖 仅展示
# 执行成功

4. 第一个ML模型:Iris分类

(1) 完整ML工作流

▶ 示例:Iris决策树分类完整流程

PYTHON
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

# Step 1: Load data
iris = load_iris()
X, y = iris.data, iris.target
print(f"Features: {iris.feature_names}")
print(f"Classes: {iris.target_names}")
print(f"Shape: {X.shape}")

# Step 2: Split train/test
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"Train: {X_train.shape[0]}, Test: {X_test.shape[0]}")

# Step 3: Train model
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)

# Step 4: Predict
y_pred = model.predict(X_test)

# Step 5: Evaluate
acc = accuracy_score(y_test, y_pred)
print(f"\nAccuracy: {acc:.4f}")
print(f"\nClassification Report:\n{classification_report(y_test, y_pred, target_names=iris.target_names)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")

输出:

TEXT 📖 仅展示
Features: ['sepal length (cm)', 'sepal width (cm)', ...]
Classes: ['setosa' 'versicolor' 'virginica']
Shape: (150, 4)
Train: 105, Test: 45

Accuracy: 1.0000

▶ 示例:可视化决策树

PYTHON
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(12, 8))
plot_tree(model, feature_names=iris.feature_names,
          class_names=iris.target_names, filled=True, ax=ax)
plt.title("Iris Decision Tree (max_depth=3)")
plt.tight_layout()
plt.savefig("iris_tree.png", dpi=150)

输出:

TEXT 📖 仅展示
# 执行成功

(2) train_test_split详解

参数 含义 推荐值
test_size 测试集比例 0.2-0.3
random_state 随机种子 42 (可复现)
stratify 分层抽样 分类任务必须设置
shuffle 是否打乱 默认True

5. 数据预处理Pipeline

(1) 为什么需要Pipeline

Pipeline将预处理和模型绑定为一个整体,避免数据泄露(测试集信息泄露到训练过程)。

▶ 示例:StandardScaler + 模型的Pipeline

PYTHON
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris

iris = load_iris()
X, y = iris.data, iris.target

# Build pipeline
pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("classifier", LogisticRegression(max_iter=200)),
])

# Cross-validation with pipeline (no data leakage!)
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print(f"CV Accuracy: {scores.mean():.4f} +/- {scores.std():.4f}")

# Fit on full data and predict
pipe.fit(X, y)
new_sample = [[5.1, 3.5, 1.4, 0.2]]
prediction = pipe.predict(new_sample)
print(f"Prediction: {iris.target_names[prediction[0]]}")

输出:

TEXT 📖 仅展示
# 执行成功

(2) Pipeline vs 手动预处理

维度 手动预处理 Pipeline
数据泄露风险 高(容易用测试集fit scaler) 低(Pipeline自动隔离)
代码可读性 分散 集中
交叉验证 需手动循环 cross_val_score(pipe)
部署便捷性 需分别保存scaler和model 保存一个pipeline对象

▶ 示例:SalesPredict基线Pipeline

PYTHON
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np

# Simulate SalesPredict data
rng = np.random.default_rng(42)
n = 500
df = pd.DataFrame({
    "ad_spend": rng.uniform(10, 100, n),
    "traffic": rng.uniform(100, 1000, n),
    "category": rng.choice(["Elec", "Cloth", "Food"], n),
    "is_weekend": rng.choice([0, 1], n),
})
df["revenue"] = 50 + 0.8 * df["ad_spend"] + 0.1 * df["traffic"] + rng.normal(0, 10, n)

# Define feature groups
num_features = ["ad_spend", "traffic"]
cat_features = ["category", "is_weekend"]

# ColumnTransformer for mixed preprocessing
preprocessor = ColumnTransformer([
    ("num", StandardScaler(), num_features),
    ("cat", OneHotEncoder(drop="first"), cat_features),
])

# Full pipeline
pipe = Pipeline([
    ("preprocessor", preprocessor),
    ("model", LinearRegression()),
])

X = df.drop(columns=["revenue"])
y = df["revenue"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

pipe.fit(X_train, y_train)
score = pipe.score(X_test, y_test)
print(f"SalesPredict Baseline R²: {score:.4f}")

# Predict
sample = pd.DataFrame({"ad_spend": [50], "traffic": [500], "category": ["Elec"], "is_weekend": [1]})
pred = pipe.predict(sample)
print(f"Predicted revenue: {pred[0]:.1f} thousand USD")

输出:

TEXT 📖 仅展示
# 执行成功

6. 模型评估基础

(1) 分类 vs 回归评估指标

任务 指标 含义 sklearn函数
分类 Accuracy 正确率 accuracy_score
分类 Precision 精确率 precision_score
分类 Recall 召回率 recall_score
分类 F1 精确与召回调和 f1_score
回归 MAE 平均绝对误差 mean_absolute_error
回归 MSE 均方误差 mean_squared_error
回归 决定系数 r2_score

▶ 示例:回归模型全面评估

PYTHON
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np

y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([95, 160, 190, 260, 310])

mae = mean_absolute_error(y_true, y_pred)
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_true, y_pred)
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100

print(f"MAE:  {mae:.2f} thousand USD")
print(f"RMSE: {rmse:.2f} thousand USD")
print(f"R²:   {r2:.4f}")
print(f"MAPE: {mape:.1f}%")

输出:

TEXT 📖 仅展示
# 执行成功

❓ 常见问题

Q fit_transform和transform有什么区别?
A fit_transform = fit + transform,用于训练集(学习参数并转换);transform只用已学参数转换,用于测试集。测试集绝不能fit,否则数据泄露。
Q Pipeline的好处是什么?
A 三大好处——1) 防数据泄露(交叉验证时自动隔离fit/transform);2) 代码简洁(一个对象包含全部步骤);3) 部署方便(保存一个pickle文件)。
Q random_state=42是什么意思?
A 设置随机种子确保可复现。42是编程界的"答案"梗(来自《银河系漫游指南》),不影响结果质量。
Q stratify参数什么时候必须设置?
A 分类任务必须设置。stratify=y确保训练集和测试集中各类别比例与原始数据一致,避免小类别全被分到测试集。
Q cross_val_score的cv=5是什么意思?
A 5折交叉验证——数据分成5份,轮流用4份训练1份验证,最终取5次的平均。比单次train_test_split更可靠。
Q ColumnTransformer和Pipeline有什么区别?
A Pipeline是串联(上一步输出=下一步输入),ColumnTransformer是并联(不同列用不同转换器,最后合并)。通常两者组合使用。

📖 小节


📝 作业

  1. 基础题(难度⭐):用sklearn加载Iris数据集,用LogisticRegression训练分类器,输出accuracy。提示:参考第4节的完整流程。
  2. 进阶题(难度⭐⭐):构建Pipeline(StandardScaler + LogisticRegression),用5折交叉验证对比有scaler和无scaler的accuracy差异。提示:Pipeline vs 单独model分别cross_val_score。
  3. 挑战题(难度⭐⭐⭐):用ColumnTransformer构建混合Pipeline处理SalesPredict数据(数值列标准化+类别列独热编码),然后用LinearRegression训练,计算R²和MAE。提示:参考第5节的SalesPredict Pipeline示例。

← 上一课:Matplotlib与Seaborn可视化 | 下一课:综合练习 — 入门项目 →

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏