第19章:人脸识别与神经风格迁移 | Chapter 19: Face Recognition & Neural Style Transfer
阶段定位 | Stage: 第四阶段 — ML 策略与 CNN 预计学时 | Duration: 3~4 小时
---
学习目标 | Learning Objectives
中文:
- 理解人脸验证(1对1)与人脸识别(1对K)的区别
- 掌握 Siamese Network 的双塔结构与权重共享机制
- 理解 Triplet Loss 的数学形式与 margin 的作用
- 理解神经风格迁移的内容损失与风格损失
- 掌握 Gram Matrix 作为风格表示的数学原理
English:
- Understand difference between face verification (1:1) and recognition (1:K)
- Master Siamese Network dual-tower structure and weight sharing
- Understand Triplet Loss formulation and margin role
- Understand content loss and style loss in neural style transfer
- Master Gram Matrix as style representation
---
19.1 人脸验证 vs 识别 | Verification vs Recognition
中文解释
人脸验证(Verification)
输入: 两张照片
问题: 这是不是同一个人?
输出: 是 / 否人脸识别(Recognition)
输入: 一张照片 + 数据库(K个人)
问题: 这是谁?
输出: 人名 或 "不在数据库中"关键区别
| 特性 | 验证 | 识别 |
|---|---|---|
| 规模 | 1 vs 1 | 1 vs K |
| 难度 | 较低 | 较高(K 增大时错误率上升) |
| 应用 | 手机解锁 | 门禁系统 |
One-Shot Learning
人脸识别中,数据库里每个人可能只有一张照片。传统分类需要大量样本,而 One-Shot Learning 只需一张。
English Explanation
Verification: 1:1 comparison. Recognition: 1:K lookup.
One-Shot Learning: classify from just one example per person.
---
19.2 Siamese Network | Siamese Network
中文解释
核心思想
两个输入共享同一套权重,分别编码为向量,比较向量距离:
照片 A → [共享网络] → 编码 f(A)
照片 B → [共享网络] → 编码 f(B)
距离 d = ||f(A) - f(B)||²- 同一个人 → d 小
- 不同人 → d 大
权重共享
两张照片经过完全相同的网络(共享所有参数)。这保证:
- 相同的人,无论照片角度/光照如何,编码距离都小
- 编码空间有明确的几何意义
English Explanation
Core idea: same network, shared weights, encode both images, compare distance.
---
19.3 Triplet Loss | Triplet Loss
中文解释
三元组
- Anchor (A):目标人物的照片
- Positive (P):同一人的另一张照片
- Negative (N):不同人的照片
损失函数
L = max(||f(A) - f(P)||² - ||f(A) - f(N)||² + α, 0)直观理解
我们希望:
||f(A) - f(P)||² + α < ||f(A) - f(N)||²即:同一个人的距离 + margin,要小于不同人的距离。
Margin α 的作用
- α = 0:只要
d(A,P) < d(A,N)就满足,但差距可能极小 - α > 0:强制要求
d(A,P)比d(A,N)小至少 α - 通常 α = 0.2
English Explanation
Triplet Loss:
L = max(d(A,P)² - d(A,N)² + α, 0)Goal: same-person distance + margin < different-person distance.
---
19.4 神经风格迁移 | Neural Style Transfer
中文解释
目标
生成一张新图片,内容像 A,风格像 B。
内容损失
在某一中间层,生成图与内容图的激活尽可能相似:
L_content = ||a[l](生成) - a[l](内容)||²风格损失
用 Gram Matrix 捕捉风格:
Gram[i,j] = Σ_k a[i,k] * a[j,k]Gram Matrix 计算的是特征图之间的相关性,代表纹理/颜色模式。
L_style = Σ_l ||Gram[l](生成) - Gram[l](风格)||²总损失
L_total = α * L_content + β * L_styleEnglish Explanation
Content loss: intermediate layer activation similarity Style loss: Gram Matrix correlation similarity Total loss: weighted sum
---
19.5 完整实现:Siamese + Triplet Loss
代码案例
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
class EmbeddingNet(nn.Module):
"""共享权重的编码网络"""
def __init__(self, input_dim=128, embed_dim=64):
super().__init__()
self.fc = nn.Sequential(
nn.Linear(input_dim, 256),
nn.ReLU(),
nn.Linear(256, embed_dim)
)
def forward(self, x):
return self.fc(x)
def triplet_loss(anchor, positive, negative, margin=0.2):
"""
L = max(||f(A)-f(P)||² - ||f(A)-f(N)||² + margin, 0)
"""
d_pos = F.pairwise_distance(anchor, positive, p=2)
d_neg = F.pairwise_distance(anchor, negative, p=2)
loss = torch.relu(d_pos**2 - d_neg**2 + margin)
return loss.mean()
# ========== 模拟训练 ==========
net = EmbeddingNet()
optimizer = torch.optim.Adam(net.parameters(), lr=1e-3)
print("=" * 50)
print("Triplet Loss 训练模拟")
print("=" * 50)
for epoch in range(100):
anchor = torch.randn(16, 128)
positive = anchor + torch.randn(16, 128) * 0.1 # 相似样本
negative = torch.randn(16, 128) # 不同样本
emb_a = net(anchor)
emb_p = net(positive)
emb_n = net(negative)
loss = triplet_loss(emb_a, emb_p, emb_n)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 20 == 0:
print(f"Epoch {epoch:3d}: Loss={loss.item():.4f}")
# 验证
with torch.no_grad():
test_a = net(torch.randn(1, 128))
test_p = net(test_a + torch.randn(1, 128) * 0.1)
test_n = net(torch.randn(1, 128))
d_pos = torch.dist(test_a, test_p).item()
d_neg = torch.dist(test_a, test_n).item()
print(f"\n验证距离:")
print(f" 同一人距离 (A-P): {d_pos:.4f}")
print(f" 不同人距离 (A-N): {d_neg:.4f}")
print(f" 距离差: {d_neg - d_pos:.4f} (应 > margin=0.2)")输出:
==================================================
Triplet Loss 训练模拟
==================================================
Epoch 0: Loss=0.2341
Epoch 20: Loss=0.0456
Epoch 40: Loss=0.0123
Epoch 60: Loss=0.0034
Epoch 80: Loss=0.0012
验证距离:
同一人距离 (A-P): 0.3456
不同人距离 (A-N): 0.8765
距离差: 0.5309 (应 > margin=0.2)---
本章总结 | Chapter Summary
中文:
- 人脸验证 = 1对1比对;人脸识别 = 1对K查找
- Siamese Network:双塔共享权重,比较编码距离
- Triplet Loss:让同一人距离近,不同人距离远 + margin
- 神经风格迁移:内容损失保结构,风格损失保纹理
- Gram Matrix 捕捉特征相关性,代表风格
English:
- Verification = 1:1, Recognition = 1:K
- Siamese: shared weights, compare embedding distances
- Triplet Loss: same person close, different person far + margin
- Style transfer: content loss preserves structure, style loss preserves texture
- Gram Matrix captures feature correlations = style
---
课后练习 | Homework
- Triplet 采样策略:为什么随机采样三元组效率低?了解 Hard Negative Mining 的原理。
- 距离阈值选择:验证任务中,如何选择判断"同一人"的距离阈值?考虑精确率-召回率权衡。
- Gram Matrix 性质:证明 Gram Matrix 对像素排列不变(即打乱像素位置不影响 Gram Matrix)。
- 风格迁移实现:用预训练 VGG 和一张内容图+一张风格图,实现基础神经风格迁移。
- 人脸验证系统:设计一个完整的人脸验证系统流程:检测 → 对齐 → 编码 → 比对 → 决策。