0. introductionhtml
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)。spa
交叉熵(cross entropy),爲KL散度拆解後的一部份內容,公式是。能夠看出,相對熵DKL(p||q) = -H(p) + H(p,q),能夠看作負的真實分佈p的熵,加p與q交叉熵的結果。3d
因爲p的熵不變,故在機器學習中只須要優化交叉熵做爲損失函數便可,如下m爲當前batch中樣本數,n爲標籤數。code
在單分類問題中(一個節點屬於一個類別,使用softmax計算預測數據,每一個label累積和爲1),損失函數爲;視頻
在多分類問題中(一個節點能夠屬於多個類別,使用sigmoid計算預測數據,每一個label獨立分佈),交叉熵寫法能夠簡化爲,損失函數爲
。htm
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具體能夠參見以前文章http://www.javashuo.com/article/p-kpuvmtgw-ez.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領域的文章,敬請期待。