【翻译】使用TensorFlow实现GAN

本文翻译自这个博客,已获得作者授权,翻译的不好还请指教。

生成对抗网络(Generative Adversarial Nets)是一种非常流行的神经网络。它首先由Ian Goodfellow在2014年NIPS大会上发表。它点燃了神经网络中对抗学习的兴趣,这可以从论文被引用的次数中证明。一时之间,冒出来许多不同的GAN:DCGAN,Sequence-GAN,LSTM-GAN等。在NIPS 2016,甚至将会有一整场的对抗学习讨论会。

现在代码可以从https://github.com/wiseodd/generative-models得到。

首先让我们回顾一下论文的要点。之后我们会用TensorFlow来实现GAN,数据集是MNIST。

Generative Adversarial Net

让我们举一个假币制造商和警察的例子。假币制造商和警察各自的目标是什么呢?

  • 一个成功的假币制造商会想尽方法骗过警察,使警察分不清假币与真币。
  • 一个合格的警察会尽力分辨出假币和真币。

现在就产生了冲突。这种情况可以认为是博弈论中的最大最小游戏。这个过程称为对抗过程。

GAN是对抗过程的一个特例,它的组成(警察和假币制造商)是神经网络。第一个网络试图生成数据,第二个网络试图分辨出真实数据和第一个网络生成的伪造数据。第二个网络会输出表示真实数据概率的张量[0,1]。

在GAN中,第一个网络称为生成器G(Z),第二个网络称为判别器D(X)。


在平衡点,也就是最大最小游戏中的最优点,第一个网络会生成真实数据,第二个网络输出的概率会是0.5,因为第一个网络生成了真实数据。

我们不禁会想“为什么要训练GAN呢?”,这是因为数据分布P_{data}可能非常复杂,很难推断。所以使用对抗网络可以从布P_{data}中生成样本而不用处理讨厌的概率分布问题。

GAN实现

根据GAN的定义我们需要两个网络。可以是任意的网络,比如卷积网络或仅仅是两层的感知器网络。首先我们使用简单的两层感知器网络。

# 判别器
X = tf.placeholder(tf.float32, shape=[None, 784], name='X')

D_W1 = tf.Variable(xavier_init([784, 128]), name='D_W1')
D_b1 = tf.Variable(tf.zeros(shape=[128]), name='D_b1')

D_W2 = tf.Variable(xavier_init([128, 1]), name='D_W2')
D_b2 = tf.Variable(tf.zeros(shape=[1]), name='D_b2')

theta_D = [D_W1, D_W2, D_b1, D_b2]

# 生成器
Z = tf.placeholder(tf.float32, shape=[None, 100], name='Z')

G_W1 = tf.Variable(xavier_init([100, 128]), name='G_W1')
G_b1 = tf.Variable(tf.zeros(shape=[128]), name='G_b1')

G_W2 = tf.Variable(xavier_init([128, 784]), name='G_W2')
G_b2 = tf.Variable(tf.zeros(shape=[784]), name='G_b2')

theta_G = [G_W1, G_W2, G_b1, G_b2]


def generator(z):
    G_h1 = tf.nn.relu(tf.matmul(z, G_W1) + G_b1)
    G_log_prob = tf.matmul(G_h1, G_W2) + G_b2
    G_prob = tf.nn.sigmoid(G_log_prob)

    return G_prob


def discriminator(x):
    D_h1 = tf.nn.relu(tf.matmul(x, D_W1) + D_b1)
    D_logit = tf.matmul(D_h1, D_W2) + D_b2
    D_prob = tf.nn.sigmoid(D_logit)

    return D_prob, D_logit

上面,generator(z)接受一个100维的矢量,输出一个784维的矢量(MNIST图片大小(28x28))。

discriminator(x)接受MNIST图片作为输入,返回一个代表真实图片概率的张量。

现在让我们解释一下GAN的对抗过程。下面是论文中的训练算法:

G_sample = generator(Z)
D_real, D_logit_real = discriminator(X)
D_fake, D_logit_fake = discriminator(G_sample)

D_loss = -tf.reduce_mean(tf.log(D_real) + tf.log(1. - D_fake))
G_loss = -tf.reduce_mean(tf.log(D_fake))

上面我们对损失函数取负是因为它们需要最大化,而TensorFlow的优化器只能进行最小化。

另外根据论文的建议,最好最大化tf.reduce_mean(tf.log(D_fake)),而不是最小化tf.reduce_mean(1-tf.log(D_fake))。

接下来我们来训练网络。

# 只更新 D(X)的参数, 所以 var_list = theta_D
D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=theta_D)
# 只更新 G(X)的参数, 所以 var_list = theta_G
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=theta_G)

def sample_Z(m, n):
    '''Uniform prior for G(Z)'''
    return np.random.uniform(-1., 1., size=[m, n])

for it in range(1000000):
    X_mb, _ = mnist.train.next_batch(mb_size)

    _, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: sample_Z(mb_size, Z_dim)})
    _, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: sample_Z(mb_size, Z_dim)})

这样我们就完成了!我们可以看一看训练过程


刚开始我们使用随机噪声作为输入,随着训练的进行,G(Z)开始越来越趋近P_{data}。

替代的损失函数

我们可以使用不同的方法来表示D_loss和G_loss。
让我们跟随自己的直觉。这个方法根据Brandon Amos’ blog.

让我们想一想,discriminator(x)试图将所有的输出变为1,也就是我们想最大化真实数据的概率。而discriminator(G_sample)试图将所有的输出变为0,即D(G(Z))希望最小化伪造数据的概率。

那么generator(z)呢?它当然想最大化伪造数据的概率!它与D(G(Z))正相反!

因此,代码可以写成:

# 另外的损失:
# -------------------
D_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(D_logit_real, tf.ones_like(D_logit_real)))
D_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(D_logit_fake, tf.zeros_like(D_logit_fake)))
D_loss = D_loss_real + D_loss_fake
G_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(D_logit_fake, tf.ones_like(D_logit_fake)))

这里我们使用的是Logistic Loss。改变损失函数不会影响到GAN的训练。

参考

Goodfellow, Ian, et al. “Generative adversarial nets.” Advances in Neural Information Processing Systems. 2014.

Image Completion with Deep Learning in TensorFlow

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容