我用來在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生成數據與
對於鑑別:
- 1:其中G生成數據與
sess.run()
呼叫 - 2:計算用於假數據損失:用
sess.run()
呼叫 - 3裝載在d中的數據用
sess.run()
呼叫 - 4:計算用於真實數據的丟失與
sess.run()
呼叫 - 5:最後backpropagate d與最後
sess.run()
- 1:其中G生成數據與
對我來說這只是看起來顯然效率不高,我也沒有更好的主意。我當然可以使用佔位符,它可以用feed_dict「隱藏」加載操作,但不會真正影響性能(我試過)。
我的目標是以下內容:
直接連接g至d,並能避免調用G,只是具有G和d直接相連。
在從G或數據批處理中獲取數據時,能夠「切換D」。這將允許我以避免從GPU/CPU的數據傳輸=>節省時間
不能將G的輸出連接到D的第一個「圖層」嗎?看起來你可以把東西自由地連接起來,就好像它們是樹枝一樣(這看起來正是keras所做的),你可以運行最後一個輸出,它會考慮整個網絡,或者你可以運行一箇中間輸出,它只考慮網絡 –
這是正確的,但是如何設計D從G和真實數據中隨時切換?問題不在於連接G和D.這是關於切換入口點的問題 –