From 76756103ef6883e70a0379035cd539456b717aa9 Mon Sep 17 00:00:00 2001 From: JGlombitza <jonas.glombitza@rwth-aachen.de> Date: Thu, 15 Feb 2018 16:40:14 +0100 Subject: [PATCH] remove unused functiony from utils add build_critic_training add build_generator_training --- AirShower_WGAN/ShowerGAN.py | 27 ++---- AirShower_WGAN/utils.py | 171 ++++++------------------------------ 2 files changed, 34 insertions(+), 164 deletions(-) diff --git a/AirShower_WGAN/ShowerGAN.py b/AirShower_WGAN/ShowerGAN.py index 7daf6ee..f879d90 100644 --- a/AirShower_WGAN/ShowerGAN.py +++ b/AirShower_WGAN/ShowerGAN.py @@ -16,7 +16,7 @@ import tensorflow as tf KTF.set_session(utils.get_session()) # Allows 2 jobs per GPU, Please do not change this during the tutorial log_dir="." -EPOCHS = 10 +EPOCHS = 3 GRADIENT_PENALTY_WEIGHT = 10 BATCH_SIZE = 256 NCR = 5 @@ -62,7 +62,7 @@ def build_generator(latent_size): outputs = Conv2D(1, (3, 3), padding='same', kernel_initializer='he_normal', activation='relu')(x) return Model(inputs=inputs, outputs=outputs, name='generator') - +# build critic def build_critic(): critic = Sequential(name='critic') critic.add(Conv2D(64, (3, 3), padding='same', kernel_initializer='he_normal', input_shape=(9,9,1))) @@ -79,6 +79,7 @@ def build_critic(): critic.add(Dense(1)) return critic + generator = build_generator(latent_size) #plot_model(generator, to_file=log_dir + '/generator.png', show_shapes=True) critic = build_critic() @@ -88,10 +89,7 @@ critic = build_critic() utils.make_trainable(critic, False) utils.make_trainable(generator, True) -generator_in = Input(shape=(latent_size,)) -generator_out = generator(generator_in) -critic_out = critic(generator_out) -generator_training = Model(inputs=generator_in, outputs=critic_out) +generator_training = utils.build_generator_graph(generator, critic, latent_size) generator_training.compile(optimizer=Adam(0.0001, beta_1=0.5, beta_2=0.9, decay=0.0), loss=[utils.wasserstein_loss]) #plot_model(generator_training, to_file=log_dir + '/generator_training.png', show_shapes=True) @@ -99,14 +97,8 @@ generator_training.compile(optimizer=Adam(0.0001, beta_1=0.5, beta_2=0.9, decay= utils.make_trainable(critic, True) utils.make_trainable(generator, False) -generator_in_critic_training = Input(shape=(latent_size,), name="noise") -shower_in_critic_training = Input(shape=(9,9,1), name='shower_maps') -generator_out_critic_training = generator(generator_in_critic_training) -out_critic_training_gen = critic(generator_out_critic_training) -out_critic_training_shower = critic(shower_in_critic_training) -averaged_batch = RandomWeightedAverage(name='Average')([generator_out_critic_training, shower_in_critic_training]) -averaged_batch_out = critic(averaged_batch) -critic_training = Model(inputs=[generator_in_critic_training, shower_in_critic_training], outputs=[out_critic_training_gen, out_critic_training_shower, averaged_batch_out]) + +critic_training, averaged_batch = utils.build_critic_graph(generator, critic, latent_size, batch_size=BATCH_SIZE) gradient_penalty = partial(utils.gradient_penalty_loss, averaged_batch=averaged_batch, penalty_weight=GRADIENT_PENALTY_WEIGHT) gradient_penalty.__name__ = 'gradient_penalty' critic_training.compile(optimizer=Adam(0.0001, beta_1=0.5, beta_2=0.9, decay=0.0), loss=[utils.wasserstein_loss, utils.wasserstein_loss, gradient_penalty]) @@ -115,7 +107,7 @@ critic_training.compile(optimizer=Adam(0.0001, beta_1=0.5, beta_2=0.9, decay=0.0 # For Wassersteinloss positive_y = np.ones(BATCH_SIZE) negative_y = -positive_y -dummy = np.zeros(BATCH_SIZE) # keras throws an error when calculating a loss withuot having a label -> needed for using the gradient penalty loss +dummy = np.zeros(BATCH_SIZE) # keras throws an error when calculating a loss without having a label -> needed for using the gradient penalty loss generator_loss = [] critic_loss = [] @@ -136,9 +128,8 @@ for epoch in range(EPOCHS): generator_loss.append(generator_training.train_on_batch([noise_batch], [positive_y])) print "generator loss:", generator_loss[-1] -utils.plot_loss(critic_loss, name="critic", iterations_per_epoch=iterations_per_epoch, NCR=NCR, log_dir=log_dir, bins_per_epoch=3) -utils.plot_loss(generator_loss, name="generator", iterations_per_epoch=iterations_per_epoch, log_dir=log_dir, bins_per_epoch=3) - +utils.plot_loss(critic_loss, name="critic", log_dir=log_dir) +utils.plot_loss(generator_loss, name="generator",log_dir=log_dir) # plot some generated figures generated_map = generator.predict(np.random.randn(BATCH_SIZE, latent_size)) diff --git a/AirShower_WGAN/utils.py b/AirShower_WGAN/utils.py index 4702374..ef1772c 100644 --- a/AirShower_WGAN/utils.py +++ b/AirShower_WGAN/utils.py @@ -8,13 +8,15 @@ import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt + def get_session(gpu_fraction=0.40): - ''' Allocate only a fraction of the GPU RAM - (1080 GTX 8Gb)''' + ''' Allocate only a fraction of the GPU RAM - (1080 GTX 8Gb). Please do not change the fraction during the tutorial!''' gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_fraction) return tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) def ReadInData(filenames): + '''Reads in the trainings data''' N = 100000 *len(filenames) a = 100000 shower_maps = np.zeros(N*9*9*1).reshape(N,9,9,1) @@ -26,36 +28,8 @@ def ReadInData(filenames): return shower_maps, Energy -def ang2vec(phi, zenith): - """ Get 3-vector from spherical angles. - Args: - phi (array): azimuth (pi, -pi), 0 points in x-direction, pi/2 in y-direction - zenith (array): zenith (0, pi), 0 points in z-direction - Returns: - array of 3-vectors - """ - x = np.sin(zenith) * np.cos(phi) - y = np.sin(zenith) * np.sin(phi) - z = np.cos(zenith) - return np.array([x, y, z]).T - - -def vec2ang(v): - '''Calculates phi and theta for given shower axis''' - x, y, z = np.asarray(v).T - phi = np.arctan2(y, x) - theta = np.pi/2 - np.arctan2(z, (x**2 + y**2)**.5) - return np.rad2deg(phi), np.rad2deg(theta) - - -def DenselyConnectedConv(z, nfilter): - ''' Densely Connected SeparableConvolution2D Layer''' - c = Conv2D(nfilter, (3, 3), padding = 'same', activation='relu', kernel_initializer='he_normal')(z) - return concatenate([z, c], axis=-1) - - def make_trainable(model, trainable): - ''' Freezes/unfreezes the weights in the given model ''' + ''' Freezes/unfreezes the weights in the given model for each layer''' for layer in model.layers: model.trainable=trainable model.trainable=trainable @@ -69,14 +43,13 @@ def rectangular_array(n=9): def wasserstein_loss(y_true, y_pred): """Calculates the Wasserstein loss - critic maximises the distance between its output for real and generated samples. - To achieve this generated samples have the label -1 and real samples the label 1. Multiplying the outputs by the labels results to the wasserstein loss""" + To achieve this generated samples have the label -1 and real samples the label 1. Multiplying the outputs by the labels results to the wasserstein loss via the Kantorovich-Rubinstein duality""" return K.mean(y_true * y_pred) def gradient_penalty_loss(y_true, y_pred, averaged_batch, penalty_weight): """Calculates the gradient penalty (for details see arXiv:1704.00028v3). - The 1-Lipschitz constraint for improved WGANs is enforced by adding a term which penalizes if the gradient norm in the critic unequal to 1. - (With this loss we penalize gradients with respect to the input of the averaged samples.)""" + The 1-Lipschitz constraint for improved WGANs is enforced by adding a term to the loss which penalizes if the gradient norm in the critic unequal to 1""" gradients = K.gradients(K.sum(y_pred), averaged_batch) gradient_l2_norm = K.sqrt(K.sum(K.square(gradients))) gradient_penalty = penalty_weight * K.square(1 - gradient_l2_norm) @@ -94,103 +67,43 @@ class RandomWeightedAverage(_Merge): return (weights * inputs[0]) + ((1 - weights) * inputs[1]) -def build_generator_graph(generator, critic, conditioner, latent_size, energy_in=1): +def build_generator_graph(generator, critic, latent_size): + '''Builds the graph for training the generator part of the improved WGAN''' generator_in = Input(shape=(latent_size,)) - generator_in_energy_label = Input(shape=(energy_in,)) - generator_out = generator([generator_in, generator_in_energy_label]) + generator_out = generator([generator_in]) critic_out = critic(generator_out) - energy_rec_out = conditioner(generator_out) - return Model(inputs=[generator_in, generator_in_energy_label], outputs=[critic_out, energy_rec_out]) + return Model(inputs=[generator_in], outputs=[critic_out]) -def build_critic_graph(generator, critic, conditioner, latent_size, energy_in, batch_size=1): +def build_critic_graph(generator, critic, latent_size, batch_size=1): + '''Builds the graph for training the critic part of the improved WGAN''' generator_in_critic_training = Input(shape=(latent_size,), name="noise") - generator_in_critic_training_energy_label = Input(shape=(energy_in,), name="energy_label") shower_in_critic_training = Input(shape=(9,9,1), name='shower_maps') - generator_out_critic_training = generator([generator_in_critic_training, generator_in_critic_training_energy_label]) + generator_out_critic_training = generator([generator_in_critic_training]) out_critic_training_gen = critic(generator_out_critic_training) out_critic_training_shower = critic(shower_in_critic_training) averaged_batch = RandomWeightedAverage(batch_size, name='Average')([generator_out_critic_training, shower_in_critic_training]) averaged_batch_out = critic(averaged_batch) - rec_out = conditioner(shower_in_critic_training) - return Model(inputs=[generator_in_critic_training, shower_in_critic_training, generator_in_critic_training_energy_label], outputs=[out_critic_training_gen, out_critic_training_shower, averaged_batch_out, rec_out]), averaged_batch - - -def plot_loss_wasserstein(loss, log_dir = ".", name="", iterations_per_epoch=10, NCR=1, Rec_scaling=1): - fig, ax1 = plt.subplots(1, figsize=(10,5)) - epoch = np.arange(len(loss)) - loss = np.array(loss) - plt.plot(epoch, loss[:,1] + loss[:,2] + loss[:,3], color='red', markersize=12, label=r'$Wasserstein$') - plt.legend(loc='upper right',prop={'size':10}) - ax1.set_xlabel(r'$Iterations$') - ax1.set_ylabel(r'$Loss$') - ax1.set_ylim(-2, 2) - fig.savefig(log_dir + '/%s_Loss_wasserstein.png' %name, dpi=480) - plt.plot(epoch, loss[:,4]*Rec_scaling, color='orange', markersize=12, label=r'$Reconstruction$') - plt.close('all') - - -def plot_loss_reco(loss, log_dir = ".", name="", iterations_per_epoch=10, NCR=1, Rec_scaling=1): - fig, ax1 = plt.subplots(1, figsize=(10,4)) - epoch = np.arange(len(loss)) - loss = np.array(loss) - plt.plot(epoch, loss[:,2], color='orange', markersize=12, label=r'$Reconstruction$') - plt.legend(loc='upper right',prop={'size':10}) - ax1.set_xlabel(r'$Iterations$') - ax1.set_ylabel(r'$Loss$') - ax1.set_yscale("log", nonposy='clip') - fig.savefig(log_dir + '/%s_Loss_reco.png' %name, dpi=480) - plt.close('all') + return Model(inputs=[generator_in_critic_training, shower_in_critic_training], outputs=[out_critic_training_gen, out_critic_training_shower, averaged_batch_out]), averaged_batch -def plot_loss(loss, log_dir = ".", name="", iterations_per_epoch=10, NCR=1, Rec_scaling=1): +def plot_loss(loss, log_dir = ".", name=""): + """Plot the traings curve""" fig, ax1 = plt.subplots(1, figsize=(10,4)) epoch = np.arange(len(loss)) loss = np.array(loss) try: - plt.plot(epoch, loss[:,0], color='red', markersize=12, label=r'$Total$') - plt.plot(epoch, loss[:,1] + loss[:,2], color='green', label=r'$Wasserstein$', linestyle='dashed') - plt.plot(epoch, loss[:,3], color='royalblue', markersize=12, label=r'$Gradient$', linestyle='dashed') - plt.plot(epoch, Rec_scaling*loss[:,4], color='orange', markersize=12, label=r'$Reconstrucion$', linestyle='dashed') + plt.plot(epoch, loss[:,0], color='red', markersize=12, label=r'Total') + plt.plot(epoch, loss[:,1] + loss[:,2], color='green', label=r'Wasserstein', linestyle='dashed') + plt.plot(epoch, loss[:,3], color='royalblue', markersize=12, label=r'GradientPenalty', linestyle='dashed') except: - plt.plot(epoch, loss[:,0], color='red', markersize=12, label=r'$Total$') + plt.plot(epoch, loss[:], color='red', markersize=12, label=r'Total') plt.legend(loc='upper right',prop={'size':10}) - ax1.set_xlabel(r'$Iterations$') - ax1.set_ylabel(r'$Cost \Theta (MSE)$') - ax1.set_ylim(-2, 2) - fig.savefig(log_dir + '/%s_Loss.png' %name, dpi=480) - plt.close('all') - - -def plot_array_scatter(values, label, axis, vmin=0): - """Plot a map *values* for an detector array specified by *v_stations*. """ - xd, yd = rectangular_array() - filter = values!=0 - filter[5,5] = True - axis.scatter(xd[~filter], yd[~filter], c = 'grey', s = 220, alpha=0.1, label="silent") - circles = axis.scatter(xd[filter], yd[filter], c = values[filter], s = 200, alpha=1, label="loud", vmin=vmin) - cbar = plt.colorbar(circles, ax=axis) - cbar.set_label(label + ' [a.u.]') - axis.grid(True) - axis.set_title(label + ' footprint', fontsize=10) - axis.set_aspect('equal') - axis.set_xlim(-5, 5) - axis.set_ylim(-5, 5) - axis.set_xlabel('x [km]') - axis.set_ylabel('y [km]') - - -def plot_showermaps(footprint, log_dir='.', title='', epoch=''): - """ Plots the time and signal footprint in one figure """ - fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10,4)) - fig.subplots_adjust(left=0, bottom=0.13) - plot_array_scatter(footprint[:,:,0], label = 'time', axis=ax1, vmin=1) - plot_array_scatter(footprint[:,:,1], label = 'signal', axis=ax2) - plt.suptitle(title + ' ' + str(epoch), fontsize=16) - plt.tight_layout() - plt.legend(bbox_to_anchor=(0.59, 0.12, 0, 0.0), bbox_transform=plt.gcf().transFigure, ncol=2) - fig.savefig(log_dir + '/%s_shower_map.png' %epoch, dpi=140) + ax1.set_xlabel(r'Iterations') + ax1.set_ylabel(r'Loss') + ax1.set_ylim(-1, 3) + fig.savefig(log_dir + '/%s_Loss.png' %name, dpi=120) plt.close('all') @@ -229,39 +142,5 @@ def plot_multiple_signalmaps(footprint, log_dir='.', title='', epoch='', nrows=2 plt.tight_layout() fig.subplots_adjust(left=0.02, top=0.95) plt.suptitle(title + ' ' + str(epoch), fontsize=12) - fig.savefig(log_dir + '/%s_signal_maps.png' %epoch, dpi=140) + fig.savefig(log_dir + '/%s_signal_maps.png' %epoch, dpi=120) plt.close('all') - - -def plot_energy_histos(y_true, y_pred, log_dir, name): - ''' Plottingfunction to evaluate the reconstruction of the cosmic ray energy - plots: predicted Energy against MC Energy and the energy dependence of the relative energy resolution (embedded)''' - y_true = y_true.reshape(y_true.shape[0],1) - reco = y_true-y_pred - # Embedding plot - fig, ax1 = plt.subplots(1) - ax1.scatter(y_true, y_pred, s = 2, color='royalblue', alpha=.90) - ax1.set_xlabel(r'$Energy_{Input}\;[EeV]$') - ax1.set_ylabel(r'$Energy_{DNN}\;[EeV]$') - left, bottom, width, height = [0.23, 0.6, 0.3, 0.26] # Links Oben - ax1.text(0.95,0.2, r"$\mu = $ %.3f" % np.mean(reco) + " [EeV]" + "\n" + "$\sigma = $ %.3f" % np.std(reco) + " [EeV]", verticalalignment = 'top', horizontalalignment = 'right', transform=ax1.transAxes, backgroundcolor='w') - ax1.plot([np.min(y_true), np.max(y_true)], [np.min(y_true), np.max(y_true)], color='red') - fig.savefig(log_dir + '/%s_Energy_reconstruction.png' %name, dpi=140) - return reco - -def plot_energy_histos_real(y_true, y_pred, log_dir, name): - ''' Plottingfunction to evaluate the reconstruction of the cosmic ray energy - plots: predicted Energy against MC Energy and the energy dependence of the relative energy resolution (embedded)''' - y_true = y_true.reshape(y_true.shape[0],1) - reco = y_true-y_pred - # Embedding plot - fig, ax1 = plt.subplots(1) - ax1.scatter(y_true, y_pred, s = 2, color='royalblue', alpha=.90) - ax1.set_xlabel(r'$Energy_{MC}\;[EeV]$') - ax1.set_ylabel(r'$Energy_{DNN}\;[EeV]$') - left, bottom, width, height = [0.23, 0.6, 0.3, 0.26] # Links Oben - ax1.text(0.95,0.2, r"$\mu = $ %.3f" % np.mean(reco) + " [EeV]" + "\n" + "$\sigma = $ %.3f" % np.std(reco) + " [EeV]", verticalalignment = 'top', horizontalalignment = 'right', transform=ax1.transAxes, backgroundcolor='w') - ax1.plot([np.min(y_true), np.max(y_true)], [np.min(y_true), np.max(y_true)], color='red') - fig.savefig(log_dir + '/%s_Energy_reconstruction.png' %name, dpi=140) - return reco - -- GitLab