3
votes

I'm new to generative networks and I decided to first try it on my own before seeing up a code. These are the steps I used to train my GAN.

[lib: tensorflow]

1) Train a discriminator on the dataset. (I used a dataset of 2 features with labels of either 'mediatating' or 'not meditating', dataset: https://drive.google.com/open?id=0B5DaSp-aTU-KSmZtVmFoc0hRa3c )

2) Once the the discriminator is trained, save it.

3) Make another file with for another feed forward network (or any other depending on your dataset). This feed forward network is the generator.

4) Once the generator is constructed, restore the discriminator and define a loss function for generator such that it learns to fool the discriminator. (this didn't work in tensorflow because sess.run() doesn't return a tf tensor and the path between G and D breaks but should work when done from scratch)

d_output = sess.run(graph.get_tensor_by_name('ol:0'), feed_dict={graph.get_tensor_by_name('features_placeholder:0'): g_output})
print(d_output)

optimize_for = tf.constant([[0.0]*10]) #not meditating

g_loss = -tf.reduce_mean((d_output - optimize_for)**2)

train = tf.train.GradientDescentOptimizer(learning_rate).minimize(g_loss)

Why don't we train a generator like this? This seems so much simpler. It's true I couldn't manage to run this on tensorflow but this should be possible if I do from scratch.

Full code:

Discriminator:

import pandas as pd
import tensorflow as tf
from sklearn.utils import shuffle

data = pd.read_csv("E:/workspace_py/datasets/simdata/linear_data_train.csv")

learning_rate = 0.001
batch_size = 1
n_epochs = 1000
n_examples = 999 # This is highly unsatisfying >:3
n_iteration = int(n_examples/batch_size)


features = tf.placeholder('float', [None, 2], name='features_placeholder')
labels = tf.placeholder('float', [None, 1], name = 'labels_placeholder')

weights = {
            'ol': tf.Variable(tf.random_normal([2, 1]), name = 'w_ol')
}

biases = {
            'ol': tf.Variable(tf.random_normal([1]), name = 'b_ol')
}

ol = tf.nn.sigmoid(tf.add(tf.matmul(features, weights['ol']), biases['ol']), name = 'ol')

loss = tf.reduce_mean((labels - ol)**2, name = 'loss')

train = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for epoch in range(n_epochs):
    ptr = 0
    data = shuffle(data)
    data_f = data.drop("lbl", axis = 1)
    data_l = data.drop(["f1", "f2"], axis = 1)

    for iteration in range(n_iteration):
        epoch_x = data_f[ptr: ptr + batch_size]
        epoch_y = data_l[ptr: ptr + batch_size]
        ptr = ptr + batch_size

        _, lss = sess.run([train, loss], feed_dict={features: epoch_x, labels:epoch_y})
    print("Loss @ epoch ", epoch, " = ", lss)

print("\nTesting...\n")

data = pd.read_csv("E:/workspace_py/datasets/simdata/linear_data_eval.csv")
test_data_l = data.drop(["f1", "f2"], axis = 1)
test_data_f = data.drop("lbl", axis = 1)
print(sess.run(ol, feed_dict={features: test_data_f}))
print(test_data_l)

print("Saving model...")
saver = tf.train.Saver()
saver.save(sess, save_path="E:/workspace_py/saved_models/meditation_disciminative_model.ckpt")
sess.close()

Generator:

import tensorflow as tf

# hyper parameters

learning_rate = 0.1
# batch_size = 1
n_epochs = 100

from numpy import random
noise = random.rand(10, 2)
print(noise)

# Model

input_placeholder = tf.placeholder('float', [None, 2])

weights = {
            'hl1': tf.Variable(tf.random_normal([2, 3]), name = 'w_hl1'),
            'ol': tf.Variable(tf.random_normal([3, 2]), name = 'w_ol')
}

biases = {
            'hl1': tf.Variable(tf.zeros([3]), name = 'b_hl1'),
            'ol': tf.Variable(tf.zeros([2]), name = 'b_ol')
}

hl1 = tf.add(tf.matmul(input_placeholder, weights['hl1']), biases['hl1'])
ol = tf.add(tf.matmul(hl1, weights['ol']), biases['ol'])

sess = tf.Session()
sess.run(tf.global_variables_initializer())

g_output = sess.run(ol, feed_dict={input_placeholder: noise})

# restoring discriminator

saver = tf.train.import_meta_graph("E:/workspace_py/saved_models/meditation_disciminative_model.ckpt.meta")
saver.restore(sess, tf.train.latest_checkpoint('E:/workspace_py/saved_models/'))

graph = tf.get_default_graph()

d_output = sess.run(graph.get_tensor_by_name('ol:0'), feed_dict={graph.get_tensor_by_name('features_placeholder:0'): g_output})
print(d_output)

optimize_for = tf.constant([[0.0]*10])

g_loss = -tf.reduce_mean((d_output - optimize_for)**2)

train = tf.train.GradientDescentOptimizer(learning_rate).minimize(g_loss)
1

1 Answers

7
votes

The discriminator's purpose isn't to classify your original data, or really discriminate anything about your original data. Its sole purpose is to discriminate your generator's output from original output.

Think of an example of an art forger. Your dataset is all original paintings. Your generator network G is an art forger, and your discriminator D is a detective whose sole purpose in life is to find forgeries made by G.

D can't learn much just by looking at original paintings. What's really important for him is to figure out what sets G's forgeries apart from everything else. G can't make any money selling forgeries if all his pieces are discovered and marked as such by D, so he must learn how to thwart D.

This creates an environment where G is constantly trying to make his pieces look more "like" original artwork, and D is constantly getting better at finding the nuances to G's forgery style. The better D gets, the better G needs to be in order to make a living. They each get better at their task until they (theoretically) reach some Nash equilibrium defined by the complexity of the networks and the data they're trying to forge.

That's why D needs to be trained back-and-forth with G, because it needs to know and adapt to G's particular nuances (which change over time as G learns and adapts), not just find some average definition of "not forged". By making D hunt G specifically, you force G to become a better forger, and thus end up with a better generator network. If you just train D once, then G can learn some easy, obvious, unimportant way to beat D and never actually produce very good forgeries.