0. introduction
GAN模型最早由Ian Goodfellow et al於2014年提出,之后主要用於signal processing和natural document processing兩方面,包含圖片、視頻、詩歌、一些簡單對話的生成等。由於文字在高維空間上不連續的問題(即任取一個word embedding向量不一定能找到其所對應的文字),GAN對於NLP的處理不如圖像的處理得心應手,並且從本質上講,圖片處理相較於NLP更為簡單(因為任何動物都可以處理圖像,但只有人類可以處理語言)。因而將GAN與NLP結合,具有很深遠的影響。Bengio也說,這將是讓計算機獲得更高智能的關鍵一步。
在開始之前,有一些先驗知識,已經懂的可以跳過。
信息量:“中國隊進入了2018世界杯決賽圈”顯然比“巴西隊進入了2018世界杯決賽圈”發生概率p(x)要低,信息量 I(x)=−log(p(x))要大。
熵(Entropy):為事件發生所有概率p(xi)的信息量,即
KL(Kullback-Leibler)散度,也叫相對熵,用來衡量真實分布P與預測分布Q之間的差異,即,KL散度越小,預測分布越接近於真實分布。需要注意這里DKL(P||Q)!=DKL(Q||P)。
交叉熵(cross entropy),為KL散度拆解后的一部分內容,公式是。可以看出,相對熵DKL(p||q) = -H(p) + H(p,q),可以看做負的真實分布p的熵,加p與q交叉熵的結果。
由於p的熵不變,故在機器學習中只需要優化交叉熵作為損失函數即可,以下m為當前batch中樣本數,n為標簽數。
在單分類問題中(一個節點屬於一個類別,使用softmax計算預測數據,每個label累積和為1),損失函數為;
在多分類問題中(一個節點可以屬於多個類別,使用sigmoid計算預測數據,每個label獨立分布),交叉熵寫法可以簡化為,損失函數為
。
JSD(Jensen-Shannon)散度,優化了KL散度中p與q不能換方向的限制,,其中M為P和Q的算數平均數M=1/2*(P+Q),可以看出,這里P與Q是對稱的,JSD(P||Q) = JSD(Q||P)。
1. 與VAE對比
Autoencoder的主要思想是,生成內容盡可能和原內容一致。如下圖所示,一開始隨機生成一個向量作為code,之后通過NN Decoder解碼看是否生成對應圖片。即原圖片input為x,code為z,經過Decoder后output為生成圖片x',其中z要相較於x更小,壓縮更多內容。其損失函數由下面所示。VAE是加入高斯噪聲的Autoencoder更進一步,進而可以生成更多樣的結果。關於Autoencoder和VAE具體可以參見之前文章https://www.cnblogs.com/rucwxb/p/8056144.html (不參見也可以。。)
但是能夠生成多樣化結果的VAE有一個問題是,它並不是真正的模擬生成真實圖片,比如對於同樣的7來說,下圖的左右和原圖都是1個像素點的不同,但右邊就是非真實圖片,而VAE對於這兩個生成圖片的處理方法是相同的。
因而與VAE一步到位、非黑即白的使用重構損失函數的判別方法不同,GAN的判別器對生成器的指導是一步一步地,逐步優化生成器。
2. GAN的原理
一般來說,GAN分為Generator和Discriminator,它們有不同的目標,Generator的目標是盡可能train,Discriminator是not train。起初Generator和VAE類似,隨機生成一個向量,再由Discriminator判斷真假(0/1),之后固定Discriminator,使用gradient descent來更新Generator的參數,使得Discriminator的輸出盡可能接近1。
原始GAN的原理是最大似然估計,總體損失函數為,即優化Discriminator使得損失盡可能明顯,優化Generator使得損失盡可能縮小。這里G是個函數,輸入的是z(一個預先隨機設定的標准正態分布,每一輪迭代都會改變),輸出的是生成數據x,即G(z)=x,如下圖所示。其中,要注意的是優化時改變的不僅是G的參數,還有G。D也是個函數,輸入的是x,輸出一個x和真實數據的差異(標量)。
損失函數V可以看做真實數據分布P_data與生成數據分布P_G的交叉熵(文章開頭有詳細介紹),即
在訓練時,先固定G不動,經過k次迭代后找到最優的D。由於對於式子f(D) = alogD + blog(1-D)來說,當D*=a/(a+b)時f(D)有最大值,所以對於上面的函數V來說,D*(x) = Pdata(x) / (Pdata(x)+PG(x)) 時,V(G,D)有最大值,此時可以轉換成
的形式,損失函數V(G,D)變成P_data和P_G的JSD距離。
同時,對於Discriminator來說,應該做到輸入為真實數據xi時接受,為生成數據x*i時拒絕,V還可以寫成這樣的形式,同時,D的目標是maximize這個V,即minimize
,這也是Discriminator的損失函數。
對於Generator來說,只需考慮生成數據x*i的情況,因此Generator的損失函數為,但是由於log(1-D(x))在一開始訓練很慢(如下圖所示),於是進一步優化Generator的損失函數改為
最終總結下GAN每輪迭代的步驟:
a. 從P_data(x)中采樣m個 {x1,x2, … xm}
b. 通過高斯分布P_prior(z)生成m個{z1, … , zm}
c. 通過x*i=G(zi)獲得生成數據 {x*1, … , x*m}
d. 更新Discriminator的參數,以最大化,
更新方法為梯度下降法θd = θd + ηΔV’(θd)
a-d重復k次學得Discriminator
e. 通過高斯分布P_prior(z)重新生成m個{z1, … , zm},並由此生成x*i=G(zi)
f. 更新generator的參數,以最小化,
更新方法為梯度下降法θg = θg − ηΔV’(θg)
e-f只需重復1次學得Generator
3. 訓練GAN中遇到的問題
問題1 —— JS散度=0
Discriminator很快就准確度很接近1,too strong,由於此時還沒有訓練出很好的Generator(即P_data(x)與P_G(x)在高維空間上幾乎沒有交疊),生成數據與真實數據完全不同,JSD(P_data||P_G)=0。這樣 Discriminator估計的JS散度幾乎不會給Generator提供任何信息,使其停止優化。
某種程度上可以通過添加噪聲來解決,這樣增大P_data(x)與P_G(x)重合面積,使得Discriminator不能完美將P_data(x)與P_G(x)區分開。並且噪聲隨着時間逐漸減少。
問題2 —— Mode Collapse
這個即為只生成一種類型生成數據的情形。如下圖所示,紅色是生成數據,藍色是真實數據,由於Discriminator只能提供判斷是否生成了正確數據,而對遺失了什么數據不得而知,最終模型會擬合到單一情形中。
而對於以上兩個問題,WGAN都可以解決。
關於WGAN的介紹,知乎上的這篇文章https://zhuanlan.zhihu.com/p/25071913寫的很好。
簡言之,其修改損失函數,不使用不穩定的JS散度,而是使用Wasserstein距離,即EM(earth-mover)距離,代替了JS散度,解決即使兩個分布沒有任何重疊情況下對於距離的計算方法,為Generator提供有意義的梯度。
主要在模型上做了四點變化,由於不再使用交叉熵,因而Discriminator最后一層無需sigmoid函數,G與D的損失函數也不取log,另外加入損失函數務必Lipschitz連續的要求,即每次更新判別器的參數之后把它們的絕對值截斷到不超過一個固定常數c,使用適合梯度不穩定情況的RMSProp優化器。
——————— END ———————
之后會繼續寫出seqGAN等引入強化學習方法將GAN用於NLP領域的文章,敬請期待。