00. 概念
GAN咙俩,全稱為 Generative Adversarial Nets耿戚,直譯為生成式對抗網(wǎng)絡(luò),是一種非監(jiān)督式模型阿趁。
2014年由Ian Goodfellow提出膜蛔,業(yè)內(nèi)另一位大牛 Yan Lecun 也對它交口稱贊,稱其為“20 年來機(jī)器學(xué)習(xí)領(lǐng)域最酷的想法” 脖阵,至今為止GAN依然是炙手可熱的研究方向皂股。
“生成對抗網(wǎng)絡(luò)是一種生成模型(Generative Model),其背后基本思想是從訓(xùn)練庫里獲取很多訓(xùn)練樣本命黔,從而學(xué)習(xí)這些訓(xùn)練案例生成的概率分布呜呐。
而實(shí)現(xiàn)的方法,是讓兩個網(wǎng)絡(luò)相互競爭悍募,‘玩一個游戲’蘑辑。其中一個叫做生成器網(wǎng)絡(luò)( Generator Network),它不斷捕捉訓(xùn)練庫里真實(shí)圖片的概率分布坠宴,將輸入的隨機(jī)噪聲(Random Noise)轉(zhuǎn)變成新的樣本(也就是假數(shù)據(jù))洋魂。另一個叫做判別器網(wǎng)絡(luò)(Discriminator Network),它可以同時觀察真實(shí)和假造的數(shù)據(jù)喜鼓,判斷這個數(shù)據(jù)到底是不是真的副砍。”
--- Ian Goodfellow
01. 例子
生成sin 正玄曲線(使用keras)
import os
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from tqdm import tqdm_notebook as tqdm
from keras.models import Model
from keras.layers import Input, Reshape
from keras.layers.core import Dense, Activation, Dropout, Flatten
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import UpSampling1D, Conv1D
from keras.layers.advanced_activations import LeakyReLU
from keras.optimizers import Adam, SGD
from keras.callbacks import TensorBoard
- Generative model:
輸入:noise data
輸出:嘗試生成真實(shí)的 sin 數(shù)據(jù)
def get_generative(G_in, dense_dim=200, out_dim=50, lr=1e-3):
x = Dense(dense_dim)(G_in)
x = Activation('tanh')(x)
G_out = Dense(out_dim, activation='tanh')(x)
G = Model(G_in, G_out)
opt = SGD(lr=lr)
G.compile(loss='binary_crossentropy', optimizer=opt)
return G, G_out
- Discriminative model:
輸出:識別此數(shù)據(jù)是真實(shí)的庄岖,還是由 Generative model 生成的
def get_discriminative(D_in, lr=1e-3, drate=.25, n_channels=50, conv_sz=5, leak=.2):
x = Reshape((-1, 1))(D_in)
x = Conv1D(n_channels, conv_sz, activation='relu')(x)
x = Dropout(drate)(x)
x = Flatten()(x)
x = Dense(n_channels)(x)
D_out = Dense(2, activation='sigmoid')(x)
D = Model(D_in, D_out)
dopt = Adam(lr=lr)
D.compile(loss='binary_crossentropy', optimizer=dopt)
return D, D_out
- chain the two models into a GAN:
set_trainability 的作用是每次訓(xùn)練 generator 時要凍住 discriminator豁翎。
def set_trainability(model, trainable=False):
model.trainable = trainable
for layer in model.layers:
layer.trainable = trainable
def make_gan(GAN_in, G, D):
set_trainability(D, False)
x = G(GAN_in)
GAN_out = D(x)
GAN = Model(GAN_in, GAN_out)
GAN.compile(loss='binary_crossentropy', optimizer=G.optimizer)
return GAN, GAN_out
- Training:
交替訓(xùn)練 discriminator 和 chained GAN,在訓(xùn)練 chained GAN 時要凍住 discriminator 的參數(shù):
def sample_noise(G, noise_dim=10, n_samples=10000):
X = np.random.uniform(0, 1, size=[n_samples, noise_dim])
y = np.zeros((n_samples, 2))
y[:, 1] = 1
return X, y
def train(GAN, G, D, epochs=500, n_samples=10000, noise_dim=10, batch_size=32, verbose=False, v_freq=50):
d_loss = []
g_loss = []
e_range = range(epochs)
if verbose:
e_range = tqdm(e_range)
for epoch in e_range:
X, y = sample_data_and_gen(G, n_samples=n_samples, noise_dim=noise_dim)
set_trainability(D, True)
d_loss.append(D.train_on_batch(X, y))
X, y = sample_noise(G, n_samples=n_samples, noise_dim=noise_dim)
set_trainability(D, False)
g_loss.append(GAN.train_on_batch(X, y))
if verbose and (epoch + 1) % v_freq == 0:
print("Epoch #{}: Generative Loss: {}, Discriminative Loss: {}".format(epoch + 1, g_loss[-1], d_loss[-1]))
return d_loss, g_loss
d_loss, g_loss = train(GAN, G, D, verbose=True)
- Results:
N_VIEWED_SAMPLES = 2
data_and_gen, _ = sample_data_and_gen(G, n_samples=N_VIEWED_SAMPLES)
pd.DataFrame(np.transpose(data_and_gen[N_VIEWED_SAMPLES:])).rolling(5).mean()[5:].plot()
- 后記
這篇文章是在微信公號里看到的隅忿,原鏈接如下:https://mp.weixin.qq.com/s/8vw5LpOPAnNKQmQ_ck-oWg
但是原文中的代碼和描述并不完整心剥,原作者是Robin Ricard的blog中翻譯的,詳細(xì)內(nèi)容參見這篇文章:http://www.rricard.me/machine/learning/generative/adversarial/networks/keras/tensorflow/2017/04/05/gans-part2.html
我把代碼重新整理了一下背桐,做在 jupyter筆記中刘陶,這個是可以運(yùn)行的代碼(python3,tensorflow>=1.0,keras>=2.0),如果需要發(fā)郵件索取(我的郵箱582711548@qq.com)牢撼。