2017-10-10 40 views
0

我用來在Keras中設計我的GAN。但是,對於特定需求,我想將我的代碼調整爲Tensorflow。大多數甘斯實現與Tensorflow的使用類的GAN然後爲鑑別功能和發電機用Python類在Tensorflow中構建GAN

其中給出的東西,看起來像這樣:

class MyGAN(): 
    def __init__(self): 
     # various initialisation 

    def generator(self, n_examples): 
     ### do some business and return n_examples generated. 

     return G_output 

    def discrimintator(self, images): 
     ### do some business with the images 

     return D_Prob, D_logits 

哪個,事實上完全沒問題。不過,我更喜歡每個部分[MyGAN,Generator,Discriminator]都是完全獨立的類的設計。您只初始化了主文件:MyGAN,它由其自己處理。它允許我更簡單的代碼組織和相對簡單的代碼閱讀。

但是,我在一些設計模式上掙扎,我可以使用「輸入」圖層,它允許我從給定數據集的Discriminator真實數據和發生器生成的假數據切換。短短几行與Keras 僞代碼暴露的想法:

class Generator(object): 

    def __init__(self, latent_shape): 

     gen_input = Input(shape=latent_shape, name='generator_input') 

     #### ====== do some business ====== #### 

     gen_output = Activation('tanh', name='generator_output')(previous_layer) 

     self.model = Model(gen_input, gen_output) 

class Discriminator(object): 

    def __init__(self): 

     disc_input = Input(shape=self.input_shape, name='discriminator_input') 

     #### ====== do some business ====== #### 

     disc_output = Activation('sigmoid', name='discriminator_output')(previous_layer) 

     # Model definition with Functional API 
     self.model = Model(disc_input, disc_output) 

class MyGAN(object): 

    def __init__(self): 

     ########## GENERATOR ########## 

     # We create the optimizer for G 
     g_optim = Adam(lr=2e-4, beta_1=0.5) 

     self.generator = Generator(latent_shape=(100,))   
     self.generator.model.compile(loss='binary_crossentropy', optimizer=g_optim) 

     ########## DISCRIMINATOR ########## 

     We create the optimizer for D 
     d_optim = Adam(lr=2e-4, beta_1=0.5) 

     self.discriminator = Discriminator() 
     self.discriminator.model.compile(loss='binary_crossentropy', optimizer=d_optim, metrics=['accuracy']) 

     ########## FULL GAN ########## 

     # create an Input Layer for the complete GAN 
     gan_input = Input(shape=self.latent_shape) 

     # link the input of the GAN to the Generator 
     G_output = self.generator.model(gan_input) 

     For the combined model we will only train the generator => We do not want to backpropagate D while training G 
     self.discriminator.model.trainable = False 

     # we retrieve the output of the GAN 
     gan_output = self.discriminator.model(G_output) 

     # we construct a model out of it. 
     self.fullgan_model = Model(gan_input, gan_output) 
     self.fullgan_model.compile(loss='binary_crossentropy', optimizer=g_optim, metrics=['accuracy']) 

    def train_step(self, batch): 

     ## Train Generator First ## 

     noise = #### Generate some noise with the size: 2*batch (D is trained twice)   
     loss, acc = self.fullgan_model.train_on_batch(noise, np.ones(noise.shape[0])) 

     ## Train Discriminator Then ## 

     self.discriminator.model.trainable = True 

     generated_images = ### Generate samples with G with same size as batch 

     d_loss_fake, d_acc_fake = self.discriminator.model.train_on_batch(
       generated_images, 
       np.zeros(generated_images.shape[0]) 
      ) 
     d_loss_real, d_acc_real = self.discriminator.model.train_on_batch(
      X, 
      np.ones(X.shape[0]) 
     ) 

     d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) 
     d_acc = 0.5 * np.add(d_acc_real, d_acc_fake) 

     self.discriminator.model.trainable = False 

我的問題很簡單,我怎麼能再現這樣的代碼結構Tensorflow?我有一些想法,但我不說服了與任何這些:

我可以用一個tf.Variable然後用負載函數執行過程中進行分配。問題是:對於每個培訓步驟,似乎需要爲每個網絡(D和G)執行兩個sess.run()。這顯然是低效的...

  • 對於發電機:

    • 1:其中G生成數據與sess.run()呼叫
    • 2:用sess.run()呼叫
    • 3裝載在d中的數據:計算與所述損失另一個sess.run()致電
    • 4:最後反向傳播G與最後一個sess.run()
  • 對於鑑別:

    • 1:其中G生成數據與sess.run()呼叫
    • 2:計算用於假數據損失:用sess.run()呼叫
    • 3裝載在d中的數據用sess.run()呼叫
    • 4:計算用於真實數據的丟失與sess.run()呼叫
    • 5:最後backpropagate d與最後sess.run()

對我來說這只是看起來顯然效率不高,我也沒有更好的主意。我當然可以使用佔位符,它可以用feed_dict「隱藏」加載操作,但不會真正影響性能(我試過)。

我的目標是以下內容:

  • 直接連接g至d,並能避免調用G,只是具有G和d直接相連。

  • 在從G或數據批處理中獲取數據時,能夠「切換D」。這將允許我以避免從GPU/CPU的數據傳輸=>節省時間

+0

不能將G的輸出連接到D的第一個「圖層」嗎?看起來你可以把東西自由地連接起來,就好像它們是樹枝一樣(這看起來正是keras所做的),你可以運行最後一個輸出,它會考慮整個網絡,或者你可以運行一箇中間輸出,它只考慮網絡 –

+0

這是正確的,但是如何設計D從G和真實數據中隨時切換?問題不在於連接G和D.這是關於切換入口點的問題 –

回答

0

你可以達到你想要使用純功能的方法,並重新申請使用變量的作用域網絡的設計結構。例如,這個代碼片段設置網絡的真正/假冒的部分:

with variable_scope.variable_scope(generator_scope) as gen_scope: 
    generated_data = generator_fn(generator_inputs) 
with variable_scope.variable_scope(discriminator_scope) as dis_scope: 
    discriminator_gen_outputs = discriminator_fn(generated_data, 
               generator_inputs) 
with variable_scope.variable_scope(dis_scope, reuse=True): 
    discriminator_real_outputs = discriminator_fn(real_data, generator_inputs) 

考慮使用TensorFlow's TFGAN以避免重現GAN基礎設施。 These examples演示如何使用TFGAN創建各種GAN(使用,以及使用內置功能)。

+1

雖然此鏈接可能回答問題,最好在這裏包括答案的重要部分,並提供參考鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/ review/low-quality-posts/18093589) – aaron