同一个任务——识别手写数字——用规则方法几乎不可能,用传统 ML 勉强能打,用 DL 像开挂。这个进化过程比任何理论都更能说明"为什么深度学习是革命"。
MNIST:60000 张 28×28 的手写数字灰度图,判断每张是 0-9 中的哪个数字。AI 界的 "Hello World"。
def recognize_digit(image):
if has_horizontal_top_line(image) and has_diagonal_line(image):
return 7
if has_two_loops(image):
return 8
if has_vertical_line_only(image):
return 1
# ... 需要写几百条规则,且每个人写法不同
return "?"
# ❌ 准确率:<20%
手写变体无穷、旋转倾斜、每个人字迹不同——规则方法完全不可行。
思路:人工提取 HOG(方向梯度直方图)特征 → SVM 学习分类边界。
import numpy as np
from sklearn import svm, metrics
from sklearn.preprocessing import StandardScaler
from skimage.feature import hog
from tensorflow.keras.datasets import mnist
# 1. 加载数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 2. 特征工程:提取 HOG 特征
def extract_hog_features(images):
features = []
for img in images:
hog_feat = hog(img, orientations=9,
pixels_per_cell=(4, 4),
cells_per_block=(2, 2))
features.append(hog_feat)
return np.array(features)
X_train_hog = extract_hog_features(x_train) # (60000, 324)
X_test_hog = extract_hog_features(x_test)
# 3. 标准化
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train_hog)
X_test_s = scaler.transform(X_test_hog)
# 4. 训练 SVM
clf = svm.SVC(kernel='rbf', C=5, gamma=0.05)
clf.fit(X_train_s, y_train)
# 5. 评估
y_pred = clf.predict(X_test_s)
print(f"准确率: {metrics.accuracy_score(y_test, y_pred):.2%}")
# 典型结果:~98.5%
✅ 准确率不错 · ❌ 特征工程依赖人 · ❌ HOG 丢掉笔顺等信息 · ❌ 换任务要重设计特征
思路:原始像素直接丢 CNN,网络自己学会边缘→纹理→形状→数字。零手工特征。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from tensorflow.keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train_t = torch.tensor(x_train, dtype=torch.float32).unsqueeze(1) / 255.0
y_train_t = torch.tensor(y_train, dtype=torch.long)
x_test_t = torch.tensor(x_test, dtype=torch.float32).unsqueeze(1) / 255.0
y_test_t = torch.tensor(y_test, dtype=torch.long)
train_loader = DataLoader(
TensorDataset(x_train_t, y_train_t),
batch_size=64, shuffle=True)
# 经典 LeNet 风格 CNN
class SimpleCNN(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3) # 1→32 通道
self.conv2 = nn.Conv2d(32, 64, 3) # 32→64
self.pool = nn.MaxPool2d(2)
self.dropout = nn.Dropout(0.25)
self.fc1 = nn.Linear(64 * 5 * 5, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 5 * 5)
x = torch.relu(self.fc1(x))
x = self.dropout(x)
return self.fc2(x)
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练 5 epochs
for epoch in range(5):
for batch_x, batch_y in train_loader:
optimizer.zero_grad()
loss = criterion(model(batch_x), batch_y)
loss.backward()
optimizer.step()
# 评估
model.eval()
with torch.no_grad():
pred = model(x_test_t).argmax(dim=1)
acc = (pred == y_test_t).float().mean()
print(f"准确率: {acc:.2%}")
# 典型结果:~99.2%
✅ 准确率最高 · ✅ 零手工特征 · ✅ 换任务只改数据 · ❌ 模型是黑箱
| 维度 | 规则方法 | HOG + SVM | CNN |
|---|---|---|---|
| 准确率 | <20% | ~98.5% | ~99.2% |
| 代码量 | 巨量规则 | ~30 行 | ~50 行 |
| 人工设计量 | 极重 | 中等(HOG) | 几乎零 |
| 需要的知识 | 手写规则逻辑 | CV 特征工程 | 神经网络基础 |
| 可扩展性 | 换任务重写 | 换任务重设计特征 | 换数据就行 |
| 可解释性 | 清晰 | HOG 可视化 | 黑箱 |
规则方法:人把知识写成规则 → 机器执行
↓
传统 ML:人设计特征模板 → 机器学分类边界
↓
深度学习:机器自己学特征 + 分类边界
↓
未来?:机器自己提问、设计实验、自己学
💡 98.5% vs 99.2% 没差多少?
对 MNIST 如此,但换成 ImageNet(1000 类物体):
传统 ML(SIFT + SVM):~60%
CNN:~90%+
任务越难,DL 的优势越碾压。
跑完这三套代码的最大感受:DL 真正把 AI 开发从"设计智能"变成了"设计学习机制"。
写规则 = 假设我知道答案
设计特征 = 假设我知道什么信息重要
训练网络 = 我不知道,让数据来告诉我
这个谦逊的转变,反而带来了更强大的结果。