ml-finance-python
python scripts for finance machine learning
git clone https://9o.is/git/ml-finance-python.git
generative_adversarial_network.py
(5842B)
1 from __future__ import print_function, division
2 from sklearn import datasets
3 import math
4 import matplotlib.pyplot as plt
5 import numpy as np
6 import progressbar
7
8 from sklearn.datasets import fetch_mldata
9
10 from mlfromscratch.deep_learning.optimizers import Adam
11 from mlfromscratch.deep_learning.loss_functions import CrossEntropy
12 from mlfromscratch.deep_learning.layers import Dense, Dropout, Flatten, Activation, Reshape, BatchNormalization
13 from mlfromscratch.deep_learning import NeuralNetwork
14
15
16 class GAN():
17 """A Generative Adversarial Network with deep fully-connected neural nets as
18 Generator and Discriminator.
19
20 Training Data: MNIST Handwritten Digits (28x28 images)
21 """
22 def __init__(self):
23 self.img_rows = 28
24 self.img_cols = 28
25 self.img_dim = self.img_rows * self.img_cols
26 self.latent_dim = 100
27
28 optimizer = Adam(learning_rate=0.0002, b1=0.5)
29 loss_function = CrossEntropy
30
31 # Build the discriminator
32 self.discriminator = self.build_discriminator(optimizer, loss_function)
33
34 # Build the generator
35 self.generator = self.build_generator(optimizer, loss_function)
36
37 # Build the combined model
38 self.combined = NeuralNetwork(optimizer=optimizer, loss=loss_function)
39 self.combined.layers.extend(self.generator.layers)
40 self.combined.layers.extend(self.discriminator.layers)
41
42 print ()
43 self.generator.summary(name="Generator")
44 self.discriminator.summary(name="Discriminator")
45
46 def build_generator(self, optimizer, loss_function):
47
48 model = NeuralNetwork(optimizer=optimizer, loss=loss_function)
49
50 model.add(Dense(256, input_shape=(self.latent_dim,)))
51 model.add(Activation('leaky_relu'))
52 model.add(BatchNormalization(momentum=0.8))
53 model.add(Dense(512))
54 model.add(Activation('leaky_relu'))
55 model.add(BatchNormalization(momentum=0.8))
56 model.add(Dense(1024))
57 model.add(Activation('leaky_relu'))
58 model.add(BatchNormalization(momentum=0.8))
59 model.add(Dense(self.img_dim))
60 model.add(Activation('tanh'))
61
62 return model
63
64 def build_discriminator(self, optimizer, loss_function):
65
66 model = NeuralNetwork(optimizer=optimizer, loss=loss_function)
67
68 model.add(Dense(512, input_shape=(self.img_dim,)))
69 model.add(Activation('leaky_relu'))
70 model.add(Dropout(0.5))
71 model.add(Dense(256))
72 model.add(Activation('leaky_relu'))
73 model.add(Dropout(0.5))
74 model.add(Dense(2))
75 model.add(Activation('softmax'))
76
77 return model
78
79 def train(self, n_epochs, batch_size=128, save_interval=50):
80
81 mnist = fetch_mldata('MNIST original')
82
83 X = mnist.data
84 y = mnist.target
85
86 # Rescale [-1, 1]
87 X = (X.astype(np.float32) - 127.5) / 127.5
88
89 half_batch = int(batch_size / 2)
90
91 for epoch in range(n_epochs):
92
93 # ---------------------
94 # Train Discriminator
95 # ---------------------
96
97 self.discriminator.set_trainable(True)
98
99 # Select a random half batch of images
100 idx = np.random.randint(0, X.shape[0], half_batch)
101 imgs = X[idx]
102
103 # Sample noise to use as generator input
104 noise = np.random.normal(0, 1, (half_batch, self.latent_dim))
105
106 # Generate a half batch of images
107 gen_imgs = self.generator.predict(noise)
108
109 # Valid = [1, 0], Fake = [0, 1]
110 valid = np.concatenate((np.ones((half_batch, 1)), np.zeros((half_batch, 1))), axis=1)
111 fake = np.concatenate((np.zeros((half_batch, 1)), np.ones((half_batch, 1))), axis=1)
112
113 # Train the discriminator
114 d_loss_real, d_acc_real = self.discriminator.train_on_batch(imgs, valid)
115 d_loss_fake, d_acc_fake = self.discriminator.train_on_batch(gen_imgs, fake)
116 d_loss = 0.5 * (d_loss_real + d_loss_fake)
117 d_acc = 0.5 * (d_acc_real + d_acc_fake)
118
119
120 # ---------------------
121 # Train Generator
122 # ---------------------
123
124 # We only want to train the generator for the combined model
125 self.discriminator.set_trainable(False)
126
127 # Sample noise and use as generator input
128 noise = np.random.normal(0, 1, (batch_size, self.latent_dim))
129
130 # The generator wants the discriminator to label the generated samples as valid
131 valid = np.concatenate((np.ones((batch_size, 1)), np.zeros((batch_size, 1))), axis=1)
132
133 # Train the generator
134 g_loss, g_acc = self.combined.train_on_batch(noise, valid)
135
136 # Display the progress
137 print ("%d [D loss: %f, acc: %.2f%%] [G loss: %f, acc: %.2f%%]" % (epoch, d_loss, 100*d_acc, g_loss, 100*g_acc))
138
139 # If at save interval => save generated image samples
140 if epoch % save_interval == 0:
141 self.save_imgs(epoch)
142
143 def save_imgs(self, epoch):
144 r, c = 5, 5 # Grid size
145 noise = np.random.normal(0, 1, (r * c, self.latent_dim))
146 # Generate images and reshape to image shape
147 gen_imgs = self.generator.predict(noise).reshape((-1, self.img_rows, self.img_cols))
148
149 # Rescale images 0 - 1
150 gen_imgs = 0.5 * gen_imgs + 0.5
151
152 fig, axs = plt.subplots(r, c)
153 plt.suptitle("Generative Adversarial Network")
154 cnt = 0
155 for i in range(r):
156 for j in range(c):
157 axs[i,j].imshow(gen_imgs[cnt,:,:], cmap='gray')
158 axs[i,j].axis('off')
159 cnt += 1
160 fig.savefig("mnist_%d.png" % epoch)
161 plt.close()
162
163
164 if __name__ == '__main__':
165 gan = GAN()
166 gan.train(n_epochs=200000, batch_size=64, save_interval=400)
167
168