生成性对抗网络技术实现
生成性對抗網絡技術實現
Generative Adversarial Networks
以某種形式,使用深度神經網絡學習從數據點到標簽的映射。這種學習被稱為區別性學習,因為希望能夠區分貓和狗的照片。量詞和回歸詞都是區別學習的例子。而由反向傳播訓練的神經網絡顛覆了認為在大型復雜數據集上進行區分學習的一切。在僅僅5-6年的時間里,高分辨率圖像的分類精度已經從無用的提高到了人類的水平(有一些警告)。將為提供另一個關于所有其區分性任務的細節,在這些任務中,深層神經網絡做得非常好。
但是機器學習不僅僅是解決有區別的任務。例如,給定一個沒有任何標簽的大型數據集,可能需要學習一個簡潔地捕捉這些數據特征的模型。給定這樣一個模型,就可以抽取與訓練數據分布相似的合成數據點。例如,給定大量的人臉照片,可能希望能夠生成一個新的照片級真實感圖像,看起來似乎似乎來自同一個數據集。這種學習被稱為生成性建模。
直到最近,還沒有一種方法可以合成新的真實感圖像。但是,深度神經網絡在區分學習中的成功開辟了新的可能性。在過去三年中,一個大趨勢是應用有區別的深層網絡來克服通常不認為是有監督學習問題的問題的挑戰。遞歸神經網絡語言模型是一個使用判別網絡(訓練以預測下一個字符)的一個例子,一旦訓練,就可以作為一個生成模型。 2014年,一篇突破性的論文介紹了生成性對抗性網絡(GAN)[Goodfello等人,2014],這是一種巧妙的新方法,可以利用區分模型的能力來獲得良好的生成模型。GANs的核心思想是,如果不能區分假數據和真實數據,那么數據生成器是好的。在統計學中,這被稱為兩個樣本測試-一個用來回答是否有數據集的測試
X={x1,…,xn} and X′={x′1,…,x′n}
來自同一分布。大多數統計論文與GAN的主要區別在于后者以建設性的方式運用了這一觀點。換句話說,不只是訓練一個模型說“嘿,這兩個數據集看起來不像來自同一個分布”,而是使用兩個樣本測試為生成模型提供訓練信號。這允許改進數據生成器,直到生成與實際數據相似的內容。至少,需要愚弄分類器。即使分類器是最先進的深層神經網絡。
Fig. 1 Generative Adversarial Networks
GAN架構如圖1所示。正如所看到的,在GAN架構中有兩個部分-首先,需要一個設備(比如說,一個深度網絡,但實際上可以是任何東西,比如游戲渲染引擎),可能有可能生成看起來像真實的數據。如果要處理圖像,就需要生成圖像。如果在處理語音,需要生成音頻序列,等等。稱之為發啟generator網絡。第二部分是鑒別器網絡。試圖區分假數據和真數據。這兩個網絡互相競爭。生成器網絡試圖欺騙鑒別器discriminator網絡。此時,鑒別器discriminator網絡適應新的假數據。這些信息,反過來又被用來改進generator網絡,等等。
%matplotlib inline
from d2l import mxnet as d2l
from mxnet import autograd, gluon, init, np, npx
from mxnet.gluon import nn
npx.set_np()
- Generate some “real” data
由于這將是世界上最蹩腳的例子,只需從高斯函數中生成數據。
X = np.random.normal(size=(1000, 2))
A = np.array([[1, 2], [-0.1, 0.5]])
b = np.array([1, 2])
data = X.dot(A) + b
讓看看得到了什么。這應該是高斯位移,平均值b,以某種相當任意的方式平均協方差矩陣ATA。
d2l.set_figsize((3.5, 2.5))
d2l.plt.scatter(data[:100, 0].asnumpy(), data[:100, 1].asnumpy());
print(“The covariance matrix is\n%s” % np.dot(A.T, A))
The covariance matrix is
[[1.01 1.95]
[1.95 4.25]]
batch_size = 8
data_iter = d2l.load_array((data,), batch_size)
- Generator
發啟Generator網絡將是最簡單的網絡-單層線性模型。這是因為將用高斯數據Generator驅動線性網絡。因此,實際上只需要學習參數就可以完美地偽造東西。
net_G = nn.Sequential()
net_G.add(nn.Dense(2))
- Discriminator
對于鑒別器Discriminator,將更具鑒別力:將使用一個3層的MLP使事情變得更有趣。
net_D = nn.Sequential()
net_D.add(nn.Dense(5, activation=‘tanh’),
nn.Dense(3, activation='tanh'),nn.Dense(1))
- Training
首先定義了一個函數來更新鑒別器discriminator。
#@save
def update_D(X, Z, net_D, net_G, loss, trainer_D):
"""Update discriminator."""batch_size = X.shape[0]ones = np.ones((batch_size,), ctx=X.ctx)zeros = np.zeros((batch_size,), ctx=X.ctx)with autograd.record():real_Y = net_D(X)fake_X = net_G(Z)# Do not need to compute gradient for net_G, detach it from# computing gradients.fake_Y = net_D(fake_X.detach())loss_D = (loss(real_Y, ones) + loss(fake_Y, zeros)) / 2loss_D.backward()trainer_D.step(batch_size)
return float(loss_D.sum())
生成器也同樣更新。但是從這里的重復使用熵的標簽改變了假數據0到 1。
#@save
def update_G(Z, net_D, net_G, loss, trainer_G): # saved in d2l
"""Update generator."""batch_size = Z.shape[0]ones = np.ones((batch_size,), ctx=Z.ctx)with autograd.record():# We could reuse fake_X from update_D to save computation.fake_X = net_G(Z)# Recomputing fake_Y is needed since net_D is changed.fake_Y = net_D(fake_X)loss_G = loss(fake_Y, ones)loss_G.backward()trainer_G.step(batch_size)
return float(loss_G.sum())
鑒別器Discriminator和產生器Generator都執行帶有交叉熵損失的二元邏輯回歸。用Adam來平滑訓練過程。在每次迭代中,首先更新鑒別器Discriminator,然后更新生成器Generator。將損失和產生的例子都形象化。
def train(net_D, net_G, data_iter, num_epochs, lr_D, lr_G, latent_dim, data):
loss = gluon.loss.SigmoidBCELoss()net_D.initialize(init=init.Normal(0.02), force_reinit=True)net_G.initialize(init=init.Normal(0.02), force_reinit=True)trainer_D = gluon.Trainer(net_D.collect_params(),'adam', {'learning_rate': lr_D})trainer_G = gluon.Trainer(net_G.collect_params(),'adam', {'learning_rate': lr_G})animator = d2l.Animator(xlabel='epoch', ylabel='loss',xlim=[1, num_epochs], nrows=2, figsize=(5, 5),legend=['generator', 'discriminator'])animator.fig.subplots_adjust(hspace=0.3)for epoch in range(1, num_epochs+1):# Train one epochtimer = d2l.Timer()metric = d2l.Accumulator(3) # loss_D, loss_G, num_examplesfor X in data_iter:batch_size = X.shape[0]Z = np.random.normal(0, 1, size=(batch_size, latent_dim))metric.add(update_D(X, Z, net_D, net_G, loss, trainer_D),update_G(Z, net_D, net_G, loss, trainer_G),batch_size)# Visualize generated examplesZ = np.random.normal(0, 1, size=(100, latent_dim))fake_X = net_G(Z).asnumpy()animator.axes[1].cla()animator.axes[1].scatter(data[:, 0], data[:, 1])animator.axes[1].scatter(fake_X[:, 0], fake_X[:, 1])animator.axes[1].legend(['real', 'generated'])# Show the lossesloss_D, loss_G = metric[0]/metric[2], metric[1]/metric[2]animator.add(epoch, (loss_D, loss_G))print('loss_D %.3f, loss_G %.3f, %d examples/sec' % (loss_D, loss_G, metric[2]/timer.stop()))
現在指定超參數來擬合高斯分布。
lr_D, lr_G, latent_dim, num_epochs = 0.05, 0.005, 2, 20
train(net_D, net_G, data_iter, num_epochs, lr_D, lr_G,
latent_dim, data[:100].asnumpy())
loss_D 0.693, loss_G 0.693, 577 examples/sec
5. Summary
Generative adversarial networks (GANs) composes of two deep networks, the generator and the discriminator.
The generator generates the image as much closer to the true image as possible to fool the discriminator, via maximizing the cross-entropy loss, i.e., maxlog(D(x′))maxlog?(D(x′)).
The discriminator tries to distinguish the generated images from the true images, via minimizing the cross-entropy loss, i.e., min?ylogD(x)?(1?y)log(1?D(x))
總結
以上是生活随笔為你收集整理的生成性对抗网络技术实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kaggle上的犬种识别(ImageNe
- 下一篇: 深度卷积生成对抗网络