不要慫,就是GAN (生成式對抗網路) (三):判別器和生成器 TensorFlow Model

在 /home/your_name/TensorFlow/DCGAN/ 下新建文件 utils.py,輸入如下代碼:

import scipy.miscnimport numpy as npnn# 保存圖片函數ndef save_images(images, size, path):n n """n Save the samples imagesn The best size number isn int(max(sqrt(image.shape[0]),sqrt(image.shape[1]))) + 1n example:n The batch_size is 64, then the size is recommended [8, 8]n The batch_size is 32, then the size is recommended [6, 6]n """nn # 圖片歸一化,主要用於生成器輸出是 tanh 形式的歸一化n img = (images + 1.0) / 2.0n h, w = img.shape[1], img.shape[2]nn # 產生一個大畫布,用來保存生成的 batch_size 個圖像n merge_img = np.zeros((h * size[0], w * size[1], 3))nn # 循環使得畫布特定地方值為某一幅圖像的值n for idx, image in enumerate(images):n i = idx % size[1]n j = idx // size[1]n merge_img[j*h:j*h+h, i*w:i*w+w, :] = imagen n # 保存畫布n return scipy.misc.imsave(path, merge_img)n

這個函數的作用是在訓練的過程中保存採樣生成的圖片。

在 /home/your_name/TensorFlow/DCGAN/ 下新建文件 model.py,定義生成器,判別器和訓練過程中的採樣網路,在 model.py 輸入如下代碼:

import tensorflow as tfnfrom ops import *nnBATCH_SIZE = 64nn# 定義生成器ndef generator(z, y, train = True):n # y 是一個 [BATCH_SIZE, 10] 維的向量,把 y 轉成四維張量n yb = tf.reshape(y, [BATCH_SIZE, 1, 1, 10], name = yb)n # 把 y 作為約束條件和 z 拼接起來n z = tf.concat(1, [z, y], name = z_concat_y)n # 經過一個全連接,BN 和激活層 ReLun h1 = tf.nn.relu(batch_norm_layer(fully_connected(z, 1024, g_fully_connected1), n is_train = train, name = g_bn1))n # 把約束條件和上一層拼接起來n h1 = tf.concat(1, [h1, y], name = active1_concat_y)n n h2 = tf.nn.relu(batch_norm_layer(fully_connected(h1, 128 * 49, g_fully_connected2), n is_train = train, name = g_bn2))n h2 = tf.reshape(h2, [64, 7, 7, 128], name = h2_reshape)n # 把約束條件和上一層拼接起來n h2 = conv_cond_concat(h2, yb, name = active2_concat_y)nn h3 = tf.nn.relu(batch_norm_layer(deconv2d(h2, [64,14,14,128], n name = g_deconv2d3), n is_train = train, name = g_bn3))n h3 = conv_cond_concat(h3, yb, name = active3_concat_y)n n # 經過一個 sigmoid 函數把值歸一化為 0~1 之間,n h4 = tf.nn.sigmoid(deconv2d(h3, [64, 28, 28, 1], n name = g_deconv2d4), name = generate_image)n n return h4nn# 定義判別器 ndef discriminator(image, y, reuse = False):n n # 因為真實數據和生成數據都要經過判別器,所以需要指定 reuse 是否可用n if reuse:n tf.get_variable_scope().reuse_variables()nn # 同生成器一樣,判別器也需要把約束條件串聯進來n yb = tf.reshape(y, [BATCH_SIZE, 1, 1, 10], name = yb)n x = conv_cond_concat(image, yb, name = image_concat_y)n n # 卷積,激活,串聯條件。n h1 = lrelu(conv2d(x, 11, name = d_conv2d1), name = lrelu1)n h1 = conv_cond_concat(h1, yb, name = h1_concat_yb)n n h2 = lrelu(batch_norm_layer(conv2d(h1, 74, name = d_conv2d2), n name = d_bn2), name = lrelu2)n h2 = tf.reshape(h2, [BATCH_SIZE, -1], name = reshape_lrelu2_to_2d)n h2 = tf.concat(1, [h2, y], name = lrelu2_concat_y)nn h3 = lrelu(batch_norm_layer(fully_connected(h2, 1024, name = d_fully_connected3), n name = d_bn3), name = lrelu3)n h3 = tf.concat(1,[h3, y], name = lrelu3_concat_y)n n # 全連接層,輸出以為 loss 值n h4 = fully_connected(h3, 1, name = d_result_withouts_sigmoid)n n return tf.nn.sigmoid(h4, name = discriminator_result_with_sigmoid), h4n n# 定義訓練過程中的採樣函數 ndef sampler(z, y, train = True):n tf.get_variable_scope().reuse_variables()n return generator(z, y, train = train)n

可以看到,生成器由 7 × 7 變為 14 × 14 再變為 28 × 28大小,每一層都加入了約束條件 y,完美的詮釋了論文所給出的網路,之所以要加入 is_train 參數,是由於 Batch_norm 層中訓練和測試的時候的過程是不同的,用這個參數區分訓練和測試,生成器的最後一層,用了一個 sigmoid 函數把值歸一化到 0~1 之間,如果是不加約束的網路,則用 tanh 函數,所以在 save_images 函數中要用到語句:img = (images + 1.0) / 2.0。

sampler 函數的作用是在訓練過程中對生成器生成的圖片進行採樣,所以這個函數必須指定 reuse 可用,關於 reuse 說明,請看:知乎專欄。

參考資料:

1. carpedm20/DCGAN-tensorflow

推薦閱讀:

機器學習:通過深度神經網路再識評估器
IOS平台TensorFlow實踐
TensorFlow會話的配置項

TAG:TensorFlow | 深度学习DeepLearning | 生成对抗网络GAN |