From c555552eefe06c10db5212ad00bcc0e1cd972c14 Mon Sep 17 00:00:00 2001 From: Shreyas Date: Tue, 26 Mar 2019 01:00:05 +0530 Subject: [PATCH] Shortened .md with instructions, removed HTML and fancy formatting --- vision/mnist/DCGAN/dcgan.jl | 27 +----- vision/mnist/DCGAN/dcgan.md | 177 +--------------------------------- vision/mnist/cGAN/cgan.jl | 21 ++-- vision/mnist/cGAN/cgan.md | 185 +----------------------------------- 4 files changed, 17 insertions(+), 393 deletions(-) diff --git a/vision/mnist/DCGAN/dcgan.jl b/vision/mnist/DCGAN/dcgan.jl index 425d41ed3..8871860ab 100644 --- a/vision/mnist/DCGAN/dcgan.jl +++ b/vision/mnist/DCGAN/dcgan.jl @@ -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. - - -# Get the imports done +# Get the imports done using Flux, Flux.Data.MNIST using Flux: @epochs, back!, testmode!, throttle using Base.Iterators: partition @@ -25,7 +8,7 @@ using CuArrays using Images using Statistics -# Define the hyperparameters +# Define the hyperparameters BATCH_SIZE = 128 NUM_EPOCHS = 15 noise_dim = 100 @@ -36,7 +19,7 @@ verbose_freq = 100 dis_lr = 0.0001f0 # Discriminator Learning Rate gen_lr = 0.0001f0 # Generator Learning Rate -# Loading Data +# Loading Data # We use Flux's built in MNIST Loader imgs = MNIST.images() @@ -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)...)) -# The Generator +# The Generator generator = Chain( Dense(noise_dim, 1024, leakyrelu), x->expand_dims(x,1), @@ -68,7 +51,7 @@ generator = Chain( ConvTranspose((4,4), 64=>1, tanh; stride=(2,2), pad=(1,1)) ) |> gpu -# The Discriminator +# The Discriminator discriminator = Chain( Conv((3,3), 1=>32, leakyrelu;pad = 1), x->meanpool(x, (2,2)), diff --git a/vision/mnist/DCGAN/dcgan.md b/vision/mnist/DCGAN/dcgan.md index 04e7a96ff..0c8dc44d3 100644 --- a/vision/mnist/DCGAN/dcgan.md +++ b/vision/mnist/DCGAN/dcgan.md @@ -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. @@ -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. -Get the imports done +## 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 ``` - -Define the hyperparameters - -```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 -``` - -Loading Data - -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 -``` - -The Generator - -```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)) - ) -``` - -The Discriminator - -```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) - ) -``` - -Define the optimizers - -```julia -opt_gen = ADAM(params(generator),gen_lr, β1 = 0.5) -opt_disc = ADAM(params(discriminator),dis_lr, β1 = 0.5) -``` - -Utility functions to zero out our model gradients - -```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 -``` - -Creating and Saving Utilities - -```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 Binary Cross Entropy Loss - -```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).* diff --git a/vision/mnist/cGAN/cgan.jl b/vision/mnist/cGAN/cgan.jl index d1163547d..1fbaa78fc 100644 --- a/vision/mnist/cGAN/cgan.jl +++ b/vision/mnist/cGAN/cgan.jl @@ -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) - -# Get the imports done +# Get the imports done using Flux, Flux.Data.MNIST,Flux using Flux: @epochs, back!, testmode!, throttle using Base.Iterators: partition,flatten @@ -15,7 +7,7 @@ using Distributions: Normal using Statistics using Images -# Define the hyperparameters +# Define the hyperparameters NUM_EPOCHS = 5000 BATCH_SIZE = 100 NOISE_DIM = 100 @@ -24,12 +16,12 @@ dis_lr = 0.0001f0 # discriminator learning rate training_steps = 0 verbose_freq = 2 -# Loading Data +# Loading Data @info("Loading data set") train_labels = MNIST.labels()[1:100] |> gpu train_imgs = MNIST.images()[1:100] |> gpu -# Bundle images together with labels and group into minibatches +# 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) @@ -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 -# The Generator +# The Generator generator = Chain(Dense(NOISE_DIM + 10,1200,leakyrelu), Dense(1200,1000,leakyrelu), Dense(1000,784,tanh) ) |> gpu -# The Discriminator +# The Discriminator discriminator = Chain(Dense(794,512,leakyrelu), Dense(512,128,leakyrelu), Dense(128,1,sigmoid) @@ -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 diff --git a/vision/mnist/cGAN/cgan.md b/vision/mnist/cGAN/cgan.md index 8f8a8ad7f..e90f95ae3 100644 --- a/vision/mnist/cGAN/cgan.md +++ b/vision/mnist/cGAN/cgan.md @@ -1,4 +1,4 @@ -# ***Conditional Generative Adversarial Network Tutorial*** +# 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. @@ -6,189 +6,10 @@ It models the conditional probabilities conditioned on the labels. ![cGAN](cGAN.jpg) -Get the imports done +## Run the script -```julia -using Flux, Flux.Data.MNIST,Flux -using Flux: @epochs, back!, testmode!, throttle -using Base.Iterators: partition,flatten -using Flux: onehot,onehotbatch -using Distributions: Normal -using Statistics -using Images ``` - -Define the hyperparameters - -```julia -NUM_EPOCHS = 500 -BATCH_SIZE = 100 -NOISE_DIM = 100 -gen_lr = 0.0001f0 # Generator learning rate -dis_lr = 0.0001f0 # discriminator learning rate -training_steps = 0 -verbose_freq = 2 -``` - -Loading Data - -```julia -@info("Loading data set") -train_labels = MNIST.labels()[1:100] |> gpu -train_imgs = MNIST.images()[1:100] |> gpu -``` - -Bundle images together with labels and group into minibatches - -```julia -function make_minibatch(X, Y, idxs) - X_batch = Array{Float32}(undef, 784, length(idxs)) - for i in 1:length(idxs) - X_batch[:, i] = Float32.(reshape(X[idxs[i]],784)) - end - Y_batch = onehotbatch(Y[idxs], 0:9) - return vcat(X_batch, Y_batch) -end - -mb_idxs = partition(1:length(train_imgs), BATCH_SIZE) -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 - -```julia -dist = Normal(0.0,1.0) # Standard Normal noise is found to give better results -``` - -The Generator - -```julia -generator = Chain(Dense(NOISE_DIM + 10,1200,leakyrelu), - Dense(1200,1000,leakyrelu), - Dense(1000,784,tanh) - ) |> gpu -``` - -The Discriminator - -```julia -discriminator = Chain(Dense(794,512,leakyrelu), - Dense(512,128,leakyrelu), - Dense(128,1,sigmoid) - ) |> gpu -``` - -Define the optimizers - -```julia -opt_gen = ADAM(params(generator),gen_lr, β1 = 0.5) -opt_disc = ADAM(params(discriminator),dis_lr, β1 = 0.5) -``` - -Utility functions to zero out our model gradients - -```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 -``` - -Creating and Saving Utilities - -```julia -img(x) = Gray.(reshape((x.+1)/2, 28, 28, 1)) # For denormalizing the generated image - -function sample() - num_samples = 9 # Number of digits to sample - fake_labels = zeros(10,num_samples) - for i in 1:num_samples - fake_labels[rand(1:9),i] = 1 - end - - noise = [vcat(rand(dist, NOISE_DIM, 1),fake_labels[:,i]) for i=1:num_samples] # 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 - -```julia - img_grid = fake_imgs[1] -end - -cd(@__DIR__) -``` - -We use the Binary Cross Entropy Loss - -```julia -function bce(ŷ, y) - mean(-y.*log.(ŷ .+ 1f-10) - (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] - inp[end-9:end,:] = x[end-9:end,:] # The labels should not be modified - - labels = Float32.(x[end-9:end,:]) |> gpu # y - zero_grad!(discriminator) - zero_grad!(generator) - - D_real = discriminator(inp) # D(x|y) - real_labels = ones(size(D_real)) |> gpu - - D_real_loss = bce(D_real,real_labels) - - fake_x = generator(vcat(z,labels)) # G(z|y) - D_fake = discriminator(vcat(fake_x,labels)) # D(G(z|y)) - 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!(discriminator) - zero_grad!(generator) - - fake_x = generator(vcat(z,labels)) # G(z|y) - D_fake = discriminator(vcat(fake_x,labels)) # D(G(z|y)) - 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 - - println(training_steps) - training_steps += 1 -end - -for e = 1:NUM_EPOCHS - for data in train_set - train(data) - end - println("Epoch $e over.") -end - -save("sample_cgan.png", sample())#- +julia cgan.jl ``` *This page was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*