initializer總結:
#f.constant_initializer(value)
將變量初始化為給定的常量,初始化一切所提供的值。
#tf.random_normal_initializer(mean,stddev)
功能是將變量初始化為滿足正態分布的隨機值,主要參數(正太分布的均值和標准差),用所給的均值和標准差初始化均勻分布。
#tf.truncated_normal_initializer(mean,stddev,seed,dtype)
mean:用於指定均值; stddev用於指定標准差;
seed:用於指定隨機數種子; dtype:用於指定隨機數的數據類型。
功能:將變量初始化為滿足正態分布的隨機值,但如果隨機出來的值偏離平均值超過2個標准差,那么這個數將會被重新隨機,通常只需要設定一個標准差stddev這一個參數就可以。 #tf.random_uniform_initializer(a,b,seed,dtype) #從a到b均勻初始化,將變量初始化為滿足平均分布的隨機值,主要參數(最大值,最小值)
優化器構造:
1).compute_gradients(loss,var_list=None,gate_gradients=GATE_OP,aggregation_method=None,colocate_gradients_with_ops=False,grad_loss=None)
作用:對於在變量列表(var_list)中的變量計算對於損失函數的梯度,這個函數返回一個(梯度,變量)對的列表,其中梯度就是相對應變量的梯度了。這是minimize()函數的第一個部分,
參數:
loss: 待減小的值
var_list: 默認是在GraphKey.TRAINABLE_VARIABLES.
2).apply_gradients(grads_and_vars,global_step=None,name=None)
作用:把梯度“應用”(Apply)到變量上面去。其實就是按照梯度下降的方式加到上面去。這是minimize()函數的第二個步驟。 返回一個應用的操作。
參數:
grads_and_vars: compute_gradients()函數返回的(gradient, variable)對的列表
global_step: Optional Variable to increment by one after the variables have been updated.
3).minimize(loss,global_step=None,var_list=None,gate_gradients=GATE_OP,aggregation_method=None,colocate_gradients_with_ops=False,name=None,grad_loss=None)
變量初始化:
sess.run(tf.global_variables_initializer())
函數中調用了 variable_initializer() 和 global_variables()
global_variables() 返回一個 Variable list ,里面保存的是 gloabal variables。variable_initializer() 將 Variable list 中的所有 Variable 取出來,將其 variable.initializer 屬性做成一個 op group。然后看 Variable 類的源碼可以發現, variable.initializer 就是一個 assign op。
所以: sess.run(tf.global_variables_initializer()) 就是 run了所有global Variable 的 assign op,這就是初始化參數的本來面目。
廢話不多說,上代碼。
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import os from tensorflow.examples.tutorials.mnist import input_data os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' sess = tf.InteractiveSession() mb_size = 128 Z_dim = 100 mnist = input_data.read_data_sets('MNIST_data', one_hot=True)#mnist數據集 one_hot是為了讓標簽二元,即只有0和1. def weight_var(shape, name): #定義權重,傳入權重shape和name return tf.get_variable(name=name, shape=shape, initializer=tf.contrib.layers.xavier_initializer())
def bias_var(shape, name):#定義偏置,傳入偏置shape和name return tf.get_variable(name=name, shape=shape, initializer=tf.constant_initializer(0)) # discriminater net X = tf.placeholder(tf.float32, shape=[None, 784], name='X') #樣本x的shape是【batchsize】【784】 D_W1 = weight_var([784, 128], 'D_W1') #D的中間層的w1 D_b1 = bias_var([128], 'D_b1') D_W2 = weight_var([128, 1], 'D_W2')#D的輸出層的w2 D_b2 = bias_var([1], 'D_b2') theta_D = [D_W1, D_W2, D_b1, D_b2]#D的參數列表 # generator net Z = tf.placeholder(tf.float32, shape=[None, 100], name='Z')#隨機噪聲向量z的shape是【batchsize】【100】 G_W1 = weight_var([100, 128], 'G_W1')#D的中間層的w1 G_b1 = bias_var([128], 'G_B1') G_W2 = weight_var([128, 784], 'G_W2')#D的輸出層的w2 G_b2 = bias_var([784], 'G_B2') theta_G = [G_W1, G_W2, G_b1, G_b2]#G的參數列表 def generator(z): #定義G,傳入隨機噪聲z,返回G的輸出。 G_h1 = tf.nn.relu(tf.matmul(z, G_W1) + G_b1) #G_h1中間層經過激活函數后的輸出。 G_log_prob = tf.matmul(G_h1, G_W2) + G_b2 #G輸出層沒有經過激活函數的輸出。 G_prob = tf.nn.sigmoid(G_log_prob)#G輸出層經過激活函數后的輸出。 return G_prob def discriminator(x):#定義D,傳入樣本x,返回D的輸出和沒有經過激活函數的輸出。 D_h1 = tf.nn.relu(tf.matmul(x, D_W1) + D_b1)#D_h1中間層經過激活函數后的輸出 D_logit = tf.matmul(D_h1, D_W2) + D_b2#D輸出層沒有經過激活函數的輸出 D_prob = tf.nn.sigmoid(D_logit)#D輸出層經過激活函數后的輸出 return D_prob, D_logit G_sample = generator(Z) #調用generator(z)生成G樣本 D_real, D_logit_real = discriminator(X)#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)) D_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=D_logit_real, labels=tf.ones_like(D_logit_real))) #使用交叉熵代價函數,D的目標:對於真實樣本,target=1 tf.summary.scalar("D_loss_real", D_loss_real) D_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=D_logit_fake, labels=tf.zeros_like(D_logit_fake)))#使用交叉熵代價函數,D的目標:對於生成器生成的樣本,target=0 tf.summary.scalar("D_loss_fake", D_loss_fake) D_loss = D_loss_real + D_loss_fake #D最后的損失函數為D(真)+D(假) G_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=D_logit_fake, labels=tf.ones_like(D_logit_fake)))#使用交叉熵代價函數,G的目標:對於生成器生成的樣本,target=1 tf.summary.scalar("G_loss", G_loss) D_optimizer = tf.train.GradientDescentOptimizer(0.002).minimize(D_loss, var_list=theta_D) G_optimizer = tf.train.GradientDescentOptimizer(0.002).minimize(G_loss, var_list=theta_G)
# init variables sess.run(tf.global_variables_initializer()) def sample_Z(m, n):#隨機噪聲向量的生成,維度為m*n return np.random.uniform(-1., 1., size=[m, n]) def plot(samples):#畫圖 fig = plt.figure(figsize=(4, 4)) gs = gridspec.GridSpec(4, 4) gs.update(wspace=0.05, hspace=0.05) for i, sample in enumerate(samples): # [i,samples[i]] imax=16 ax = plt.subplot(gs[i]) plt.axis('off') ax.set_xticklabels([]) ax.set_yticklabels([]) ax.set_aspect('equal') plt.imshow(sample.reshape(28, 28), cmap='Greys_r') return fig if not os.path.exists('out/'): os.makedirs('out/') i = 0 summary_op = tf.summary.merge_all() writer = tf.summary.FileWriter("E:\Program Files\PycharmProjects\mnist_gan",sess.graph) for it in range(1000000): if it % 1000 == 0: samples = sess.run(G_sample, feed_dict={ Z: sample_Z(16, Z_dim)})#生成一個維度為16*100的向量,其值是-1.——1.的隨機值。 fig = plot(samples) plt.savefig('out/{}.png'.format(str(i).zfill(3)), bbox_inches='tight') i += 1 plt.close(fig) X_mb, _ = mnist.train.next_batch(mb_size)#調用了mnist里的方法,返回x和label _, D_loss_curr = sess.run([D_optimizer, D_loss], feed_dict={#run(D_optimizer),開始進行梯度下降。#run(D_loss),獲得d_loss值 X: X_mb, Z: sample_Z(mb_size, Z_dim)}) #D喂入x樣本和Z樣本 _, G_loss_curr = sess.run([G_optimizer, G_loss], feed_dict={ Z: sample_Z(mb_size, Z_dim)})#G喂入x樣本和Z樣本 result = sess.run(summary_op, feed_dict={X: X_mb, Z: sample_Z(mb_size, Z_dim)}) writer.add_summary(result, i) if it % 1000 == 0: print('Iter: {}'.format(it)) #用format()里的數字來替換“{}” print('D_loss: {:.4}'.format(D_loss_curr)) print('G_loss: {:.4}'.format(G_loss_curr)) print()
