2014 - Goodfellow 生成對抗網路(GAN,造假者的博弈)#
案件摘要#
2014 年,Ian Goodfellow(1981–) 在蒙特婁(Yoshua Bengio 實驗室)發表 Generative Adversarial Nets,提出生成對抗網路(GAN):
核心目標函數是一個極小極大博弈(minimax game):
- \(G\) :從**雜訊 \(z\) ** 生成「假資料」,極小化 \(V\) (騙過 \(D\) );
- \(D\) :判斷「真資料還是假資料」,極大化 \(V\) (抓出 \(G\) );
- 理論保證:博弈的唯一平衡點是 \(D(x) = 1/2\) (判別器分不出真假), 且此時 \(G\) 生成的分佈恰好等於資料分佈:
這是「機器學會造假」的創世紀——2014 年的模糊人臉, 十年後變成了以假亂真的影音(見 2022-擴散模型影音生成.md)。
前因 -- 為什麼會有這個案子#
- AlexNet 之後的「視覺不對稱」(2012): 2012 年 AlexNet(見
2012-亞歷克斯AlexNet.md)讓電腦認得圖片(判別任務)大獲成功—— 但電腦畫不出圖片(生成任務)仍然一籌莫展。
深度學習的判別器(CNN)已經是完美的「驗鈔機」—— 缺的只是一個懂得造假的「偽鈔集團」。 - 變分自編碼器 VAE 的先聲(2013): Kingma 與 Welling 的 VAE(2013) 用變分推斷學生成模型: 編碼器把資料壓進潛空間,解碼器從潛空間重建資料。 但 VAE 的生成結果過度模糊(因為逐像素的均方誤差懲罰)。
GAN 與 VAE 的對照線索:VAE 最大化證據下界(ELBO,單人優化), GAN 最大化博弈價值(兩人對抗)——對抗帶來銳利,也帶來不穩定。 - 深度生成模型的難題: 2014 年之前,深度生成模型的最大似然估計需要算配分函數 \(Z\) :
Goodfellow 的洞察:乾脆不要算 \(Z\) —— 讓一個判別器來告訴你「你的生成有多像真的」。 - 傳奇的誕生之夜(2014): Goodfellow 在與朋友 bars 閒聊生成模型時靈光一閃: 「讓兩個網路互相對抗!」他當晚回家寫出原型代碼,第一次跑就成功了—— 女友(後來的太太)看了生成的數字說「這是 7」——機器第一次騙過了人眼。
線索與推理 -- 數學式、程式、理論#
第一條線索:極小極大博弈#
GAN 的目標函數:
兩步循環訓練: 1. **固定 \(G\) ,訓練 \(D\) **:對任意 \(G\) ,最優判別器是
- **固定 \(D^*\) ,訓練 \(G\) **:此時 \(V(D^*, G) = -\log 4 + 2 \cdot JS(p_{data} \| p_g)\) , 其中 \(JS\) 是 Jensen–Shannon 散度(兩分佈的「距離」)。
納許均衡:博弈在 \(D(x) = 1/2\) 、 \(p_g = p_{data}\) 時達到平衡—— 判別器擲硬幣,生成器以假亂真。
第二條線索:為什麼「對抗」比「逐像素」銳利#
VAE 的困境:逐像素損失 \(\|x - \hat{x}\|^2\) 對「偏移一點點」與「整體錯位」一視同仁—— 生成結果傾向所有可能性的平均,因此模糊。 GAN 的解法:判別器學的是「像不像真資料的分佈」這個抽象判斷—— 它可以發現「這張臉多了一隻眼睛」而拒絕平均解。
代價:博弈不穩定——模式崩潰(mode collapse, \(G\) 只生成少數幾種樣本)、 訓練震盪——這是 GAN 的未結懸案(後由 2015 DCGAN、2017 WGAN 等偵辦)。
第三條線索:玩具 1D 高斯的糾纏過程#
用一個一維高斯分佈 \(p_{data} = \mathcal{N}(0, 1)\) 當「真鈔」, 切成 32 個 bins;生成器是一個 softmax 機率向量 \(p_g\) (學「假樣本該落在哪個 bin」), 判別器是每個 bin 一個 sigmoid 分數 \(d_j\) (原論文的玩具實驗正是這種 table 式網路)。 觀察重點:判別器的準確度從 75%(一眼識破)被 \(G\) 一步步拉回 50%—— 博弈糾纏的縮影。
Python:玩具 1D 高斯 GAN(純 Python 手寫梯度)#
# 純 Python 實作:玩具 1D 高斯分佈的簡化 GAN 訓練(離散化 32 bins)
import math, random
random.seed(42)
K, LO, HI = 32, -4.0, 4.0
w = (HI - LO) / K # bin 寬度
def bin_of(x): # 樣本落在哪個 bin
return max(0, min(K-1, int((x-LO)/w)))
def sample_gauss(): # 真資料:N(0,1)
u1, u2 = random.random(), random.random()
return math.sqrt(-2*math.log(u1))*math.cos(2*math.pi*u2)
def Phi(t): # 常態 CDF
return 0.5*(1+math.erf(t/math.sqrt(2)))
p_data = [Phi((j+1)*w+LO) - Phi(j*w+LO) for j in range(K)] # 每個 bin 的真實機率
s = sum(p_data)
p_data = [p/s for p in p_data]
logits = [0.0]*K # 生成器:softmax 機率向量的 logits
d_logits = [0.0]*K # 判別器:每個 bin 一個 sigmoid 分數
def softmax(l):
m = max(l)
e = [math.exp(v-m) for v in l]
s = sum(e)
return [v/s for v in e]
def dsig(j):
a = max(-30.0, min(30.0, d_logits[j]))
return 1/(1+math.exp(-a))
def sample_from(p): # 從 p_g 抽一個 bin
r, c = random.random(), 0.0
for i, v in enumerate(p):
c += v
if r < c:
return i
return K-1
def acc(n=2000):
c = 0
for _ in range(n):
p = softmax(logits)
if dsig(bin_of(sample_gauss())) > 0.5: c += 1 # 真:應判 1
if dsig(sample_from(p)) < 0.5: c += 1 # 假:應判 0
return 100.0*c/(2*n)
print("玩具 GAN:離散化 1D 高斯(32 bins)的博弈糾纏")
lrd, lrg = 1.0, 2.0
for ep in range(1, 601):
p = softmax(logits)
for j in range(K): # D 學習:逐 bin BCE 的期望梯度
d_logits[j] += lrd * ((1-dsig(j))*p_data[j] - dsig(j)*p[j])
p = softmax(logits)
Elog = sum(p[j]*math.log(dsig(j)+1e-9) for j in range(K))
for i in range(K): # G 學習:dL/dlogit_i = p_i*(E[log d] - log d_i)
logits[i] -= lrg * p[i] * (Elog - math.log(dsig(i)+1e-9))
if ep in (1, 50, 150, 300, 600):
print(f" epoch {ep:>3}: 判別器準確度 = {acc():5.1f}%")
p = softmax(logits)
js = 0.5*sum(p[j]*math.log(p[j]/p_data[j]+1e-9) for j in range(K)) + 0.5*sum(p_data[j]*math.log(p_data[j]/p[j]+1e-9) for j in range(K))
print(f"\n收斂後:判別器準確度 = {acc(3000):5.1f}%(接近 50% = 分不出真假)")
print(f"Jensen–Shannon 散度 ≈ {js:.4f}(0 = 分佈完全相同)")
for j in range(6):
print(f" bin {j} [{LO+j*w:+.1f},{LO+(j+1)*w:+.1f}): p_g={p[j]:.4f} p_data={p_data[j]:.4f}")
玩具 GAN:離散化 1D 高斯(32 bins)的博弈糾纏
epoch 1: 判別器準確度 = 75.4%
epoch 50: 判別器準確度 = 64.0%
epoch 150: 判別器準確度 = 52.1%
epoch 300: 判別器準確度 = 50.8%
epoch 600: 判別器準確度 = 51.2%
收斂後:判別器準確度 = 51.0%(接近 50% = 分不出真假)
Jensen–Shannon 散度 ≈ 0.0092(0 = 分佈完全相同)
bin 0 [-4.0,-3.8): p_g=0.0010 p_data=0.0001
bin 1 [-3.8,-3.5): p_g=0.0010 p_data=0.0001
bin 2 [-3.5,-3.2): p_g=0.0011 p_data=0.0003
bin 3 [-3.2,-3.0): p_g=0.0011 p_data=0.0008
bin 4 [-3.0,-2.8): p_g=0.0013 p_data=0.0016
bin 5 [-2.8,-2.5): p_g=0.0018 p_data=0.0032
結案 -- 後果與影響#
- GAN 的分水嶺(2014):
納許均衡的理論保證:博弈收斂時 \(p_g = p_{data}\) —— 生成器的終點是「與真相無法區分」。 - DCGAN 的工程化(2015): Radford 等的 DCGAN(2015) 把 CNN 架構引入 GAN: 轉置卷積(反卷積)生成影像、BatchNorm 穩定訓練——
之後2017 WGAN(把 JS 散度換成 Wasserstein 距離,穩定訓練)、 2018 StyleGAN(NVIDIA 的 style 控制,生成以假亂真人臉)—— GAN 統治影像生成七年。 - 擴散模型的伏筆(2022): 2022 年,擴散模型(diffusion models) 以更穩定的訓練取代 GAN 成為影像生成的主流(見 2022-擴散模型影音生成.md):
GAN 的遺產:「判別式訓練生成模型」的思想仍在—— GAN 判別器化身為擴散模型的「品質濾網」。 - 深偽的陰影(2017–): GAN 的生成能力帶來 deepfake(深偽) 的社會案件—— 假臉、假影音以假亂真——偵測深偽成為新戰場:
- 歷史定位:Goodfellow 是「機器造假」的福爾摩斯—— 他證明了對抗是學習分佈的捷徑;
電腦不只能認出世界,還能畫出世界。
關鍵人物與文獻#
- I. Goodfellow:Generative Adversarial Nets(2014);Deep Learning 教科書(2016)。
- Y. Bengio:Goodfellow 的指導教授(2018 圖靈獎,見
2013-米科洛夫詞向量.md)。 - D. Kingma:VAE(2013)——GAN 的對照路線。
- A. Radford:DCGAN(2015)——GAN 的工程化。
- I. Goodfellow 等:Deep Learning(MIT Press, 2016)。
- 相關案件:
2012-亞歷克斯AlexNet.md、2013-米科洛夫詞向量.md、2022-擴散模型影音生成.md、../資訊科學/1936-圖靈機.md。