Skip to content

Commit

Permalink
Shortened .md with instructions, removed HTML and fancy formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
shreyas-kowshik committed Mar 25, 2019
1 parent 3f6f894 commit c555552
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 393 deletions.
27 changes: 5 additions & 22 deletions vision/mnist/DCGAN/dcgan.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,4 @@
# # ***Generative Adversarial Network Tutorial***

# Generative Adversarial Nets (GAN), are generative models used to infer a complicated probability distribution.

# We have two networks competing against each other - The Generator and the discriminator.

# ![GAN](GAN-1.jpg)

# The first net generates data from randomly sampled noise, and the second net tries to tell the difference between the real data and the fake data generated by the first net.

# The formulation per se involves the following min-max objective :

# ![gan_loss](gan.png)

# At equilibrium, the discriminator will output a probability of 0.5 for each generated image.


# <b><u>Get the imports done</b></u>
# Get the imports done
using Flux, Flux.Data.MNIST
using Flux: @epochs, back!, testmode!, throttle
using Base.Iterators: partition
Expand All @@ -25,7 +8,7 @@ using CuArrays
using Images
using Statistics

# <b><u>Define the hyperparameters</u></b>
# Define the hyperparameters
BATCH_SIZE = 128
NUM_EPOCHS = 15
noise_dim = 100
Expand All @@ -36,7 +19,7 @@ verbose_freq = 100
dis_lr = 0.0001f0 # Discriminator Learning Rate
gen_lr = 0.0001f0 # Generator Learning Rate

# <b><u>Loading Data</u></b>
# Loading Data

# We use Flux's built in MNIST Loader
imgs = MNIST.images()
Expand All @@ -50,7 +33,7 @@ dist = Normal(0.0,1.0) # Standard Normal noise is found to give better results
expand_dims(x,n::Int) = reshape(x,ones(Int64,n)...,size(x)...)
squeeze(x) = dropdims(x, dims = tuple(findall(size(x) .== 1)...))

# <b><u>The Generator</u></b>
# The Generator
generator = Chain(
Dense(noise_dim, 1024, leakyrelu),
x->expand_dims(x,1),
Expand All @@ -68,7 +51,7 @@ generator = Chain(
ConvTranspose((4,4), 64=>1, tanh; stride=(2,2), pad=(1,1))
) |> gpu

# <b><u>The Discriminator</u></b>
# The Discriminator
discriminator = Chain(
Conv((3,3), 1=>32, leakyrelu;pad = 1),
x->meanpool(x, (2,2)),
Expand Down
177 changes: 3 additions & 174 deletions vision/mnist/DCGAN/dcgan.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ***Generative Adversarial Network Tutorial***
# Generative Adversarial Network Tutorial

Generative Adversarial Nets (GAN), are generative models used to infer a complicated probability distribution.

Expand All @@ -14,181 +14,10 @@ The formulation per se involves the following min-max objective :

At equilibrium, the discriminator will output a probability of 0.5 for each generated image.

<b><u>Get the imports done</b></u>
## Run the script

```julia
using Flux, Flux.Data.MNIST
using Flux: @epochs, back!, testmode!, throttle
using Base.Iterators: partition
using Distributions: Uniform,Normal
using CUDAnative: tanh, log, exp
using CuArrays
using Images
using Statistics
```

<b><u>Define the hyperparameters</u></b>

```julia
BATCH_SIZE = 128
NUM_EPOCHS = 15
noise_dim = 100
channels = 128
hidden_dim = 7 * 7 * channels
training_steps = 0
verbose_freq = 100
dis_lr = 0.0001f0 # Discriminator Learning Rate
gen_lr = 0.0001f0 # Generator Learning Rate
```

<b><u>Loading Data</u></b>

We use Flux's built in MNIST Loader

```julia
imgs = MNIST.images()
```

Partition into batches of size 'BATCH_SIZE'

```julia
data = [reshape(float(hcat(vec.(imgs)...)),28,28,1,:) for imgs in partition(imgs, BATCH_SIZE)]
```

Define out distribution for random sampling for the generator to sample noise from

```julia
dist = Normal(0.0,1.0) # Standard Normal noise is found to give better results
```

<b><u>The Generator</u></b>

```julia
generator = Chain(
Dense(noise_dim, 1024, leakyrelu),
BatchNorm(1024),
Dense(1024, hidden_dim, leakyrelu),
BatchNorm(hidden_dim),
x->reshape(x,7,7,channels,:),
ConvTranspose((4,4), channels=>64, relu; stride=(2,2), pad=(1,1)),
BatchNorm(64),
ConvTranspose((4,4), 64=>1, tanh; stride=(2,2), pad=(1,1))
)
```

<b><u>The Discriminator</u></b>

```julia
discriminator = Chain(
Conv((3,3), 1=>32, leakyrelu;pad = 1),
x->meanpool(x, (2,2)),
Conv((3,3), 32=>64, leakyrelu;pad = 1),
x->meanpool(x, (2,2)),
x->reshape(x,7*7*64,:),
Dense(7*7*64, 1024, leakyrelu),
BatchNorm(1024),
Dense(1024, 1,sigmoid)
)
```

<b>Define the optimizers</b>

```julia
opt_gen = ADAM(params(generator),gen_lr, β1 = 0.5)
opt_disc = ADAM(params(discriminator),dis_lr, β1 = 0.5)
```

<b>Utility functions to zero out our model gradients</b>

```julia
function nullify_grad!(p)
if typeof(p) <: TrackedArray
p.grad .= 0.0f0
end
return p
end

function zero_grad!(model)
model = mapleaves(nullify_grad!, model)
end
```

<b>Creating and Saving Utilities</b>

```julia
img(x) = Gray.(reshape((x+1)/2, 28, 28)) # For denormalizing the generated image

function sample()
noise = [rand(dist, noise_dim, 1) for i=1:9] # Sample 9 digits
noise = gpu.(noise) # Add to GPU

testmode!(generator)
fake_imgs = img.(map(x -> gpu(generator(x).data), noise)) # Generate a new image from random noise
testmode!(generator, false)

img_grid = vcat([hcat(imgs...) for imgs in partition(fake_imgs, 3)]...) # Create grid for saving
end

cd(@__DIR__)
```

We use the <b>Binary Cross Entropy Loss</b>

```julia
function bce(ŷ, y)
mean(-y.*log.(ŷ) - (1 .- y .+ 1f-10).*log.(1 .-.+ 1f-10))
end

function train(x)
global training_steps

z = rand(dist, noise_dim, BATCH_SIZE) |> gpu
inp = 2x .- 1 |> gpu # Normalize images to [-1,1]

zero_grad!(discriminator)

D_real = discriminator(inp) # D(x)
real_labels = ones(size(D_real)) |> gpu


D_real_loss = bce(D_real,real_labels)

fake_x = generator(z) # G(z)
D_fake = discriminator(fake_x) # D(G(z))
fake_labels = zeros(size(D_fake)) |> gpu

D_fake_loss = bce(D_fake,fake_labels)

D_loss = D_real_loss + D_fake_loss
Flux.back!(D_loss)
opt_disc() # Optimize the discriminator

zero_grad!(generator)

fake_x = generator(z) # G(z)
D_fake = discriminator(fake_x) # D(G(z))
real_labels = ones(size(D_fake)) |> gpu

G_loss = bce(D_fake,real_labels)

Flux.back!(G_loss)
opt_gen() # Optimise the generator

if training_steps % verbose_freq == 0
println("D Loss: $(D_loss.data) | G loss: $(G_loss.data)")
end

training_steps += 1
end

for e = 1:NUM_EPOCHS
for imgs in data
train(imgs)
end
println("Epoch $e over.")
end

save("sample_dcgan.png", sample())#-
julia dcgan.jl
```

*This page was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*
Expand Down
21 changes: 6 additions & 15 deletions vision/mnist/cGAN/cgan.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
# # ***Conditional Generative Adversarial Network Tutorial***

# A cGAN is a GAN wherein both the generator and the discriminator are fed prior labels along with the image and random noise.

# It models the conditional probabilities conditioned on the labels.

# ![cGAN](cGAN.jpg)

# <b><u>Get the imports done</b></u>
# Get the imports done
using Flux, Flux.Data.MNIST,Flux
using Flux: @epochs, back!, testmode!, throttle
using Base.Iterators: partition,flatten
Expand All @@ -15,7 +7,7 @@ using Distributions: Normal
using Statistics
using Images

# <b><u>Define the hyperparameters</u></b>
# Define the hyperparameters
NUM_EPOCHS = 5000
BATCH_SIZE = 100
NOISE_DIM = 100
Expand All @@ -24,12 +16,12 @@ dis_lr = 0.0001f0 # discriminator learning rate
training_steps = 0
verbose_freq = 2

# <b><u>Loading Data</u></b>
# Loading Data
@info("Loading data set")
train_labels = MNIST.labels()[1:100] |> gpu
train_imgs = MNIST.images()[1:100] |> gpu

# <b><u>Bundle images together with labels and group into minibatches</u></b>
# Bundle images together with labels and group into minibatches
function make_minibatch(X, Y, idxs)
X_batch = Array{Float32}(undef, 784, length(idxs))
for i in 1:length(idxs)
Expand All @@ -45,13 +37,13 @@ train_set = [make_minibatch(train_imgs, train_labels, i) for i in mb_idxs]
# Define out distribution for random sampling for the generator to sample noise from
dist = Normal(0.0,1.0) # Standard Normal noise is found to give better results

# <b><u>The Generator</u></b>
# The Generator
generator = Chain(Dense(NOISE_DIM + 10,1200,leakyrelu),
Dense(1200,1000,leakyrelu),
Dense(1000,784,tanh)
) |> gpu

# <b><u>The Discriminator</u></b>
# The Discriminator
discriminator = Chain(Dense(794,512,leakyrelu),
Dense(512,128,leakyrelu),
Dense(128,1,sigmoid)
Expand Down Expand Up @@ -91,7 +83,6 @@ function sample()
fake_imgs = img.(map(x -> gpu(generator(x).data), noise)) # Generate a new image from random noise
testmode!(generator, false)

# img_grid = vcat([hcat(imgs...) for imgs in partition(fake_imgs, 3)]...) # Create grid for saving
img_grid = fake_imgs[1]
end

Expand Down
Loading

0 comments on commit c555552

Please sign in to comment.