forked from eriklindernoren/ML-From-Scratch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c82346b
commit 0ab7629
Showing
2 changed files
with
127 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
from __future__ import print_function, division | ||
from sklearn import datasets | ||
import math | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
import progressbar | ||
|
||
from sklearn.datasets import fetch_mldata | ||
|
||
from mlfromscratch.deep_learning.optimizers import Adam | ||
from mlfromscratch.deep_learning.loss_functions import CrossEntropy, SquareLoss | ||
from mlfromscratch.deep_learning.layers import Dense, Dropout, Flatten, Activation, Reshape, BatchNormalization | ||
from mlfromscratch.deep_learning import NeuralNetwork | ||
|
||
|
||
class Autoencoder(): | ||
"""A Autoencoder with deep fully-connected neural nets. | ||
Training Data: MNIST Handwritten Digits (28x28 images) | ||
""" | ||
def __init__(self): | ||
self.img_rows = 28 | ||
self.img_cols = 28 | ||
self.img_dim = self.img_rows * self.img_cols | ||
self.latent_dim = 128 # The dimension of the data embedding | ||
|
||
optimizer = Adam(learning_rate=0.0002, b1=0.5) | ||
loss_function = SquareLoss | ||
|
||
# Build the discriminator | ||
self.encoder = self.build_encoder(optimizer, loss_function) | ||
self.decoder = self.build_decoder(optimizer, loss_function) | ||
|
||
self.autoencoder = NeuralNetwork(optimizer=optimizer, loss=loss_function) | ||
self.autoencoder.layers.extend(self.encoder.layers) | ||
self.autoencoder.layers.extend(self.decoder.layers) | ||
|
||
print () | ||
self.autoencoder.summary(name="Variational Autoencoder") | ||
|
||
def build_encoder(self, optimizer, loss_function): | ||
|
||
encoder = NeuralNetwork(optimizer=optimizer, loss=loss_function) | ||
encoder.add(Dense(512, input_shape=(self.img_dim,))) | ||
encoder.add(Activation('leaky_relu')) | ||
encoder.add(BatchNormalization(momentum=0.8)) | ||
encoder.add(Dense(256)) | ||
encoder.add(Activation('leaky_relu')) | ||
encoder.add(BatchNormalization(momentum=0.8)) | ||
encoder.add(Dense(self.latent_dim)) | ||
|
||
return encoder | ||
|
||
def build_decoder(self, optimizer, loss_function): | ||
|
||
decoder = NeuralNetwork(optimizer=optimizer, loss=loss_function) | ||
decoder.add(Dense(256, input_shape=(self.latent_dim,))) | ||
decoder.add(Activation('leaky_relu')) | ||
decoder.add(BatchNormalization(momentum=0.8)) | ||
decoder.add(Dense(512)) | ||
decoder.add(Activation('leaky_relu')) | ||
decoder.add(BatchNormalization(momentum=0.8)) | ||
decoder.add(Dense(self.img_dim)) | ||
decoder.add(Activation('tanh')) | ||
|
||
return decoder | ||
|
||
def train(self, n_epochs, batch_size=128, save_interval=50): | ||
|
||
mnist = fetch_mldata('MNIST original') | ||
|
||
X = mnist.data | ||
y = mnist.target | ||
|
||
# Rescale [-1, 1] | ||
X = (X.astype(np.float32) - 127.5) / 127.5 | ||
|
||
for epoch in range(n_epochs): | ||
|
||
# Select a random half batch of images | ||
idx = np.random.randint(0, X.shape[0], batch_size) | ||
imgs = X[idx] | ||
|
||
# Train the Autoencoder | ||
loss, _ = self.autoencoder.train_on_batch(imgs, imgs) | ||
|
||
# Display the progress | ||
print ("%d [D loss: %f]" % (epoch, loss)) | ||
|
||
# If at save interval => save generated image samples | ||
if epoch % save_interval == 0: | ||
self.save_imgs(epoch, X) | ||
|
||
def save_imgs(self, epoch, X): | ||
r, c = 5, 5 # Grid size | ||
# Select a random half batch of images | ||
idx = np.random.randint(0, X.shape[0], r*c) | ||
imgs = X[idx] | ||
# Generate images and reshape to image shape | ||
gen_imgs = self.autoencoder.predict(imgs).reshape((-1, self.img_rows, self.img_cols)) | ||
|
||
# Rescale images 0 - 1 | ||
gen_imgs = 0.5 * gen_imgs + 0.5 | ||
|
||
fig, axs = plt.subplots(r, c) | ||
plt.suptitle("Autoencoder") | ||
cnt = 0 | ||
for i in range(r): | ||
for j in range(c): | ||
axs[i,j].imshow(gen_imgs[cnt,:,:], cmap='gray') | ||
axs[i,j].axis('off') | ||
cnt += 1 | ||
fig.savefig("ae_%d.png" % epoch) | ||
plt.close() | ||
|
||
|
||
if __name__ == '__main__': | ||
ae = Autoencoder() | ||
ae.train(n_epochs=200000, batch_size=64, save_interval=400) |