AI: 机器学习入门
最后更新:2026-08-26
机器学习(Machine Learning, ML)是 AI 最核心的子领域——几乎所有的现代 AI 应用(推荐系统、语音识别、自动驾驶)都建立在 ML 之上。本章帮你理解 ML 的本质、三大范式、任务类型,并用 sklearn 实现第一个完整的 ML 分类器。
1. 你将学到
- 机器学习 vs 传统编程的本质区别
- 监督学习 / 无监督学习 / 强化学习三大范式
- 分类 vs 回归 vs 聚类任务类型
- ML 工作流全貌(问题定义 → 数据 → 特征 → 训练 → 评估 → 部署)
- 用 sklearn 实现第一个分类器
2. 故事:当规则写不完的时候
(1) 痛点:规则越写越多,准确率越写越低
Bob 的电商公司需要预测用户是否会购买某商品。他开始写规则:
IF age > 30 AND browse_count > 3 THEN buy = yes
IF age < 25 AND cart_count > 0 THEN buy = maybe
IF region = "east" AND discount > 20% THEN buy = yes
... (300 more rules later) ...
规则从 10 条写到 300 条,准确率却从 60% 涨到 72% 就再也不动了。每来一个新品类,又要重新写规则——根本写不完。
(2) ML 的解法
Alice 提议:"别写规则了,让算法从 100K historical records 中自己找规律。"
▶ 示例:规则驱动 vs 数据驱动预测购买行为(难度⭐)
# Rule-based approach: you write the logic
def will_buy_rules(user):
"""Predict purchase using hand-written rules"""
if user['age'] > 30 and user['browse_count'] > 3:
return True
if user['cart_count'] > 0 and user['discount_pct'] > 20:
return True
return False
# ML approach: algorithm learns from data
# from sklearn.neighbors import KNeighborsClassifier
# model = KNeighborsClassifier(n_neighbors=5)
# model.fit(X_train, y_train) # Learns patterns from 100K records
# prediction = model.predict(new_user_data)
(3) 收益:从 72% 到 89%
Bob 用 ML 训练了模型,准确率从 72% 跃升到 89%,而且新品类只需要补充数据重新训练——不用写一行规则。
3. 什么是机器学习
(1) Arthur Samuel 的定义(1959)
"Machine Learning is the field of study that gives computers the ability to learn without being explicitly programmed."
机器学习是让计算机在没有被明确编程的情况下获得学习能力的研究领域。
核心思想:不是你写规则让计算机执行,而是你给数据让计算机自己学规则。
(2) Tom Mitchell 的定义(1997)
"A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P, if its performance at tasks in T, as measured by P, improves with experience E."
翻译成人话:一个程序在任务 T 上的性能 P 随着经验 E 的增加而提高,就是"在学习"。
以 Bob 的场景为例:
| 符号 | 含义 | 对应 |
|---|---|---|
| T | 任务 | 预测用户是否购买 |
| E | 经验 | 100K historical purchase records |
| P | 性能 | 预测准确率 |
(3) 传统规则 vs 机器学习
| 维度 | 传统规则 | 机器学习 |
|---|---|---|
| 规则来源 | 人工编写 | 算法从数据中学习 |
| 可扩展性 | 差(规则随场景膨胀) | 好(新数据重新训练即可) |
| 适应变化 | 需要人工修改规则 | 自动适应数据分布变化 |
| 发现隐藏规律 | 难(人想不到的规律找不到) | 能(算法能发现非线性组合) |
| 可解释性 | 强(规则一目了然) | 弱(模型是"黑箱",但可解释) |
| 开发成本 | 规则简单时成本低,复杂时极高 | 前期需要数据和算力,后期成本低 |
| 类比 | 你手把手教小孩每个步骤 | 你给小孩看 1000 道题让他自己总结 |
4. 三大范式:监督 / 无监督 / 强化学习
机器学习按"学习方式"分为三大范式:
graph TB
ML[Machine Learning] --> SL[Supervised Learning]
ML --> UL[Unsupervised Learning]
ML --> RL[Reinforcement Learning]
SL --> SL1[Classification]
SL --> SL2[Regression]
UL --> UL1[Clustering]
UL --> UL2[Dim. Reduction]
RL --> RL1[Game AI]
RL --> RL2[Robot Control]
style ML fill:#e8f5e9
style SL fill:#e1f5fe
style UL fill:#fff3e0
style RL fill:#f3e5f5
(1) 监督学习(Supervised Learning)
核心特征:训练数据有标签(答案)。
就像老师带学生做题——每道题都有标准答案,学生通过"做题→对答案→纠错"来学习。
| 要素 | 说明 |
|---|---|
| 输入 | 特征 X + 标签 y |
| 学习过程 | 找到 X → y 的映射函数 |
| 输出 | 能对新 X 预测 y 的模型 |
| 典型任务 | 分类(离散标签)、回归(连续标签) |
| 例子 | 根据房屋面积/位置预测房价(回归)、根据邮件内容判断是否垃圾(分类) |
▶ 示例:sklearn 加载 Iris 数据并分类(难度⭐)
# Load the Iris dataset and inspect its structure
from sklearn.datasets import load_iris
iris = load_iris()
print(f"Feature names: {iris.feature_names}")
print(f"Target names: {list(iris.target_names)}")
print(f"Samples: {iris.data.shape[0]}")
print(f"Features: {iris.data.shape[1]}")
print(f"\nFirst 5 samples:")
for i in range(5):
print(f" {iris.data[i]} → {iris.target_names[iris.target[i]]}")
Feature names: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
Target names: ['setosa', 'versicolor', 'virginica']
Samples: 150
Features: 4
First 5 samples:
[5.1 3.5 1.4 0.2] → setosa
[4.9 3.0 1.4 0.2] → setosa
[4.7 3.2 1.3 0.2] → setosa
[4.6 3.1 1.5 0.2] → setosa
[5.0 3.6 1.4 0.2] → setosa
(2) 无监督学习(Unsupervised Learning)
核心特征:训练数据没有标签。
就像把一堆照片扔给小孩,让他自己按"看起来像"来分组——没有人告诉他"这是猫""那是狗"。
| 要素 | 说明 |
|---|---|
| 输入 | 仅特征 X,无标签 y |
| 学习过程 | 发现数据内在结构和模式 |
| 输出 | 数据的分组/结构/压缩表示 |
| 典型任务 | 聚类、降维、异常检测 |
| 例子 | 客户分群(不知道有几类,让算法自动发现)、商品推荐(发现购买模式) |
(3) 强化学习(Reinforcement Learning)
核心特征:通过试错和奖励信号学习。
就像训练小狗——做对了给零食(奖励),做错了不理它(惩罚),小狗慢慢学会什么行为能获得奖励。
| 要素 | 说明 |
|---|---|
| 输入 | 环境状态 + 动作空间 |
| 学习过程 | 试错 → 获得奖励/惩罚 → 调整策略 |
| 输出 | 能在环境中获得最大累积奖励的策略 |
| 典型任务 | 游戏AI、机器人控制、自动驾驶决策 |
| 例子 | AlphaGo 下围棋、ChatGPT 的人类反馈强化学习(RLHF) |
(4) 三大范式对比
| 维度 | 监督学习 | 无监督学习 | 强化学习 |
|---|---|---|---|
| 数据 | 有标签(X + y) | 无标签(仅 X) | 状态 + 奖励信号 |
| 目标 | 预测标签 | 发现结构 | 最大化奖励 |
| 反馈 | 直接(告诉你对错) | 无(没有对错) | 延迟(做了很多步才知道好不好) |
| 典型算法 | KNN、SVM、决策树 | K-Means、PCA、DBSCAN | Q-Learning、PPO、SAC |
| 典型应用 | 垃圾邮件检测、房价预测 | 客户分群、数据降维 | 游戏AI、机器人、自动驾驶 |
| 数据需求 | 标注成本高 | 数据容易获取 | 需要仿真环境 |
| 类比 | 老师带学生做题 | 自己看书找规律 | 训练小狗做动作 |
5. 任务类型:分类 / 回归 / 聚类
(1) 分类(Classification)
预测离散类别标签。例如:邮件是垃圾还是正常?图片是猫还是狗?
| 类型 | 说明 | 示例 |
|---|---|---|
| 二分类 | 只有 2 个类别 | 垃圾/正常、欺诈/合法 |
| 多分类 | 3 个及以上类别 | 鸢尾花 3 种、手写数字 0-9 |
(2) 回归(Regression)
预测连续数值。例如:房价是多少?明天温度是多少?
(3) 聚类(Clustering)
将数据按相似度自动分组,没有预定义类别。例如:客户自动分为 3 群。
(4) 分类 vs 回归 vs 聚类对比
| 维度 | 分类 | 回归 | 聚类 |
|---|---|---|---|
| 输出类型 | 离散类别 | 连续数值 | 分组标签 |
| 是否需要标签 | 是(监督学习) | 是(监督学习) | 否(无监督学习) |
| 目标 | 预测样本属于哪类 | 预测具体数值 | 发现数据中的自然分组 |
| 评估指标 | Accuracy / F1 | MAE / RMSE / R² | Silhouette / Inertia |
| 例子 | 判断用户是否购买 | 预测用户消费金额 | 将用户自动分为几个群体 |
| 类比 | 判断水果是苹果还是橘子 | 估测水果重量 | 把一筐混装水果按外观分成几堆 |
6. ML 工作流全貌
一个完整的 ML 项目包含 6 个步骤,每一步都不可跳过:
graph TB
A[1. Define Problem] --> B[2. Collect Data]
B --> C[3. Feature Engineering]
C --> D[4. Train Model]
D --> E[5. Evaluate]
E --> F{Good enough?}
F -->|No| C
F -->|Yes| G[6. Deploy]
G --> H[Monitor & Retrain]
style A fill:#e1f5fe
style B fill:#e8f5e9
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#fce4ec
style G fill:#e0f2f1
style H fill:#f1f8e9
(1) 定义问题
明确要解决什么问题、是分类还是回归、成功标准是什么。
| 好的问题定义 | 差的问题定义 |
|---|---|
| "预测用户是否会在 7 天内购买商品" | "让 AI 帮我们卖更多东西" |
| "识别信用卡交易是否欺诈(F1 ≥ 0.9)" | "检测异常交易" |
(2) 收集数据
数据是 ML 的基石。数据质量直接决定模型上限。
| 数据维度 | 好数据 | 差数据 |
|---|---|---|
| 量 | 足够多(至少数千条) | 太少(几十条) |
| 质 | 标签准确、特征完整 | 标签错误、缺失值多 |
| 多样性 | 覆盖各种场景 | 只覆盖单一场景 |
(3) 特征工程
将原始数据转换为模型能理解的数值特征:
Raw Data → Feature Engineering → Features
"25-year-old male from Beijing" → [25, 1, 39] (age, gender_code, city_code)
(4) 训练模型
选择算法、设置超参数、在训练数据上拟合模型。
(5) 评估模型
在测试集(模型从未见过的数据)上评估性能,确保模型能泛化。
(6) 部署上线
将模型部署为 API / 嵌入应用,持续监控性能,定期重训练。
7. sklearn API 统一范式
scikit-learn(sklearn)是 Python 最流行的 ML 库,它的 API 设计极其统一——所有模型都遵循同一套接口:
model = SomeClassifier(params) # 1. Create model
model.fit(X_train, y_train) # 2. Train model
model.predict(X_new) # 3. Predict
model.score(X_test, y_test) # 4. Evaluate
▶ 示例:KNN 分类器训练与预测(难度⭐⭐)
# KNN classifier: train and predict
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# Load and split data
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
# Create and train model
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
# Predict
y_pred = knn.predict(X_test)
# Evaluate
train_acc = knn.score(X_train, y_train)
test_acc = knn.score(X_test, y_test)
print(f"Train accuracy: {train_acc:.3f}")
print(f"Test accuracy: {test_acc:.3f}")
# Predict a new sample
import numpy as np
new_sample = np.array([[5.0, 3.4, 1.5, 0.2]])
pred = knn.predict(new_sample)
print(f"New sample predicted class: {load_iris().target_names[pred[0]]}")
Train accuracy: 0.971
Test accuracy: 0.978
New sample predicted class: setosa
(1) sklearn 常用分类器速查
| 分类器 | 类名 | 核心参数 | 特点 |
|---|---|---|---|
| KNN | KNeighborsClassifier |
n_neighbors |
简单直观,适合小数据 |
| 决策树 | DecisionTreeClassifier |
max_depth |
可解释性强,易过拟合 |
| 随机森林 | RandomForestClassifier |
n_estimators |
集成方法,鲁棒性强 |
| SVM | SVC |
C, kernel |
小数据精度高 |
| 逻辑回归 | LogisticRegression |
C |
线性基线,概率输出 |
| 朴素贝叶斯 | GaussianNB |
— | 文本分类常用,速度极快 |
fit() / predict() / score() 三件套——换算法只需要改一行类名。
8. 完整示例:用 KNN 在 Iris 上完成 ML 全流程
下面用一个完整的示例,走完 ML 工作流从数据加载到可视化决策边界的全过程:
▶ 示例:对比不同 k 值的准确率(难度⭐⭐)
# Compare KNN with different k values
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
print("=== KNN: Effect of k value ===")
for k in [1, 3, 5, 7, 9, 15, 30]:
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train, y_train)
train_acc = knn.score(X_train, y_train)
test_acc = knn.score(X_test, y_test)
print(f"k={k:2d} | Train: {train_acc:.3f} | Test: {test_acc:.3f}")
=== KNN: Effect of k value ===
k= 1 | Train: 1.000 | Test: 0.956
k= 3 | Train: 0.971 | Test: 0.978
k= 5 | Train: 0.971 | Test: 0.978
k= 7 | Train: 0.971 | Test: 0.978
k= 9 | Train: 0.971 | Test: 0.978
k=15 | Train: 0.971 | Test: 0.978
k=30 | Train: 0.952 | Test: 0.956
▶ 示例:分类报告解读(难度⭐⭐)
# Detailed classification report
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print("=== Classification Report ===")
print(classification_report(y_test, y_pred, target_names=load_iris().target_names))
=== Classification Report ===
precision recall f1-score support
setosa 1.00 1.00 1.00 15
versicolor 1.00 0.93 0.97 15
virginica 0.94 1.00 0.97 15
accuracy 0.98 45
macro avg 0.98 0.98 0.98 45
weighted avg 0.98 0.98 0.98 45
如何解读分类报告:
| 指标 | 含义 | 解读 |
|---|---|---|
| precision | 预测为该类的样本中,真正是该类的比例 | versicolor 精确率 1.00 = 预测为 versicolor 的全对 |
| recall | 真实为该类的样本中,被正确预测的比例 | versicolor 召回率 0.93 = 有 1 个 versicolor 被误判 |
| f1-score | precision 和 recall 的调和平均 | 综合指标,越接近 1 越好 |
| support | 该类的真实样本数 | 每类 15 个测试样本 |
▶ 示例:可视化决策边界(难度⭐⭐⭐)
# Visualize KNN decision boundaries on Iris (2 features)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
iris = load_iris()
X = iris.data[:, :2] # Use only first 2 features for 2D plot
y = iris.target
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X, y)
# Create mesh grid for decision boundary
h = 0.02
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
# Plot
plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.Set1)
scatter = plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1, edgecolors='black')
plt.xlabel('Sepal length (cm)')
plt.ylabel('Sepal width (cm)')
plt.title('KNN (k=5) Decision Boundary on Iris')
plt.legend(handles=scatter.legend_elements()[0], labels=list(iris.target_names))
plt.savefig('knn_decision_boundary.png', dpi=150, bbox_inches='tight')
plt.show()
print("Decision boundary plot saved.")
▶ 示例:综合示例——KNN 在 Iris 上的完整 ML 流程(难度⭐⭐⭐)
# ============================================
# Complete ML Workflow: KNN on Iris Dataset
# Step 1-6: Full pipeline with evaluation
# ============================================
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
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"Step 1 - Data loaded: {X.shape[0]} samples, {X.shape[1]} features")
print(f" Classes: {list(iris.target_names)}")
print(f" Class distribution: {np.bincount(y)}")
# Step 2: Split data (70% train, 30% 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"\nStep 2 - Data split: Train={len(X_train)}, Test={len(X_test)}")
# Step 3: Feature scaling (important for KNN!)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print(f"\nStep 3 - Features scaled (mean≈0, std≈1)")
print(f" Before scaling - mean: {X_train.mean(axis=0).round(2)}")
print(f" After scaling - mean: {X_train_scaled.mean(axis=0).round(2)}")
# Step 4: Train model
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train_scaled, y_train)
print(f"\nStep 4 - Model trained: KNN (k=5)")
# Step 5: Evaluate
y_pred = knn.predict(X_test_scaled)
test_acc = accuracy_score(y_test, y_pred)
print(f"\nStep 5 - Evaluation:")
print(f" Test accuracy: {test_acc:.3f}")
print(f"\n{classification_report(y_test, y_pred, target_names=iris.target_names)}")
print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred))
# Step 6: Predict new samples
new_data = np.array([
[5.1, 3.5, 1.4, 0.2], # Likely setosa
[6.7, 3.0, 5.2, 2.3], # Likely virginica
[5.9, 3.0, 4.2, 1.5], # Likely versicolor
])
new_data_scaled = scaler.transform(new_data)
predictions = knn.predict(new_data_scaled)
print("\nStep 6 - New predictions:")
for i, pred in enumerate(predictions):
print(f" Sample {i+1} → {iris.target_names[pred]}")
Step 1 - Data loaded: 150 samples, 4 features
Classes: ['setosa', 'versicolor', 'virginica']
Class distribution: [50 50 50]
Step 2 - Data split: Train=105, Test=45
Step 3 - Features scaled (mean≈0, std≈1)
Before scaling - mean: [5.86 3.06 3.78 1.2 ]
After scaling - mean: [ 0. -0. 0. -0.]
Step 4 - Model trained: KNN (k=5)
Step 5 - Evaluation:
Test accuracy: 1.000
precision recall f1-score support
setosa 1.00 1.00 1.00 15
versicolor 1.00 1.00 1.00 15
virginica 1.00 1.00 1.00 15
accuracy 1.00 45
macro avg 1.00 1.00 1.00 45
weighted avg 1.00 1.00 1.00 45
Confusion Matrix:
[[15 0 0]
[ 0 15 0]
[ 0 0 15]]
Step 6 - New predictions:
Sample 1 → setosa
Sample 2 → virginica
Sample 3 → versicolor
StandardScaler 让所有特征的均值为 0、标准差为 1,确保每个特征平等贡献。
❓ 常见问题
pip install scikit-learn。📖 小节
- 机器学习的本质是"让算法从数据中学习规则,而非人工编写规则"——从规则驱动到数据驱动
- 三大范式:监督学习(有标签,预测)、无监督学习(无标签,发现结构)、强化学习(试错+奖励)
- 任务类型:分类(离散标签)、回归(连续数值)、聚类(自动分组)——选择取决于问题和数据
- ML 工作流六步:定义问题 → 收集数据 → 特征工程 → 训练 → 评估 → 部署,是迭代过程
- sklearn API 统一范式:
fit()训练 →predict()预测 →score()评估,换算法只改类名 - KNN 是最直观的分类器:新样本的类别 = 离它最近的 k 个邻居的多数类别
📝 作业
- 基础题(难度⭐):用 sklearn 在 Wine 数据集(
load_wine())上训练一个KNeighborsClassifier(k=5),打印训练/测试准确率。Wine 数据集有 13 个特征、3 个类别。 - 进阶题(难度⭐⭐):对比 KNN 和决策树(
DecisionTreeClassifier)在 Wine 数据集上的准确率。分别尝试不同的 k 值(1,3,5,7,9)和不同的树深度(2,3,5,None),找出两种算法各自的最优参数。 - 挑战题(难度⭐⭐⭐):画不同 k 值的准确率变化曲线——x 轴为 k(1~30),y 轴为测试准确率,标注最高点。提示:用
matplotlib.pyplot.plot(),观察曲线走势并解释为什么 k 太大或太小都不好。