我用来在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.这是关于切换入口点的问题 –