# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import errno import math import os import matplotlib import numpy import paddle import paddle.fluid as fluid matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec NOISE_SIZE = 100 NUM_PASS = 1000 NUM_REAL_IMGS_IN_BATCH = 121 NUM_TRAIN_TIMES_OF_DG = 3 LEARNING_RATE = 2e-5 def D(x): hidden = fluid.layers.fc(input=x, size=200, act='relu', param_attr='D.w1', bias_attr='D.b1') logits = fluid.layers.fc(input=hidden, size=1, act=None, param_attr='D.w2', bias_attr='D.b2') return logits def G(x): hidden = fluid.layers.fc(input=x, size=200, act='relu', param_attr='G.w1', bias_attr='G.b1') img = fluid.layers.fc(input=hidden, size=28 * 28, act='tanh', param_attr='G.w2', bias_attr='G.b2') return img def plot(gen_data): gen_data.resize(gen_data.shape[0], 28, 28) n = int(math.ceil(math.sqrt(gen_data.shape[0]))) fig = plt.figure(figsize=(n, n)) gs = gridspec.GridSpec(n, n) gs.update(wspace=0.05, hspace=0.05) for i, sample in enumerate(gen_data): 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 def main(): try: os.makedirs("./out") except OSError as e: if e.errno != errno.EEXIST: raise startup_program = fluid.Program() d_program = fluid.Program() dg_program = fluid.Program() with fluid.program_guard(d_program, startup_program): img = fluid.layers.data(name='img', shape=[784], dtype='float32') d_loss = fluid.layers.sigmoid_cross_entropy_with_logits( x=D(img), label=fluid.layers.data( name='label', shape=[1], dtype='float32')) d_loss = fluid.layers.mean(d_loss) with fluid.program_guard(dg_program, startup_program): noise = fluid.layers.data( name='noise', shape=[NOISE_SIZE], dtype='float32') g_img = G(x=noise) g_program = dg_program.clone() dg_loss = fluid.layers.sigmoid_cross_entropy_with_logits( x=D(g_img), label=fluid.layers.fill_constant_batch_size_like( input=noise, dtype='float32', shape=[-1, 1], value=1.0)) dg_loss = fluid.layers.mean(dg_loss) opt = fluid.optimizer.Adam(learning_rate=LEARNING_RATE) opt.minimize(loss=d_loss, startup_program=startup_program) opt.minimize( loss=dg_loss, startup_program=startup_program, parameter_list=[ p.name for p in g_program.global_block().all_parameters() ]) exe = fluid.Executor(fluid.CPUPlace()) exe.run(startup_program) num_true = NUM_REAL_IMGS_IN_BATCH train_reader = paddle.batch( paddle.reader.shuffle( paddle.dataset.mnist.train(), buf_size=60000), batch_size=num_true) for pass_id in range(NUM_PASS): for batch_id, data in enumerate(train_reader()): num_true = len(data) n = numpy.random.uniform( low=-1.0, high=1.0, size=[num_true * NOISE_SIZE]).astype('float32').reshape( [num_true, NOISE_SIZE]) generated_img = exe.run(g_program, feed={'noise': n}, fetch_list={g_img})[0] real_data = numpy.array(map(lambda x: x[0], data)).astype('float32') real_data = real_data.reshape(num_true, 784) total_data = numpy.concatenate([real_data, generated_img]) total_label = numpy.concatenate([ numpy.ones( shape=[real_data.shape[0], 1], dtype='float32'), numpy.zeros( shape=[real_data.shape[0], 1], dtype='float32') ]) d_loss_np = exe.run(d_program, feed={'img': total_data, 'label': total_label}, fetch_list={d_loss})[0] for _ in xrange(NUM_TRAIN_TIMES_OF_DG): n = numpy.random.uniform( low=-1.0, high=1.0, size=[2 * num_true * NOISE_SIZE]).astype('float32').reshape( [2 * num_true, NOISE_SIZE, 1, 1]) dg_loss_np = exe.run(dg_program, feed={'noise': n}, fetch_list={dg_loss})[0] print("Pass ID={0}, Batch ID={1}, D-Loss={2}, DG-Loss={3}".format( pass_id, batch_id, d_loss_np, dg_loss_np)) # generate image each batch fig = plot(generated_img) plt.savefig( 'out/{0}.png'.format(str(pass_id).zfill(3)), bbox_inches='tight') plt.close(fig) if __name__ == '__main__': main()