<jupyter_start><jupyter_text>Adversarial Auto Encoder  Importing libraries<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
from glob import glob
from PIL import Image
from time import time
import os
os.chdir('C:/Users/Nicolas/Documents/Data/Faces')
import argparse
import math
import itertools
from sklearn.model_selection import train_test_split

import torchvision.transforms as transforms
from torchvision.utils import save_image

from torch.utils.data import DataLoader
from torchvision import datasets
from torch.autograd import Variable

import torch.nn as nn
import torch.nn.functional as F
import torch<jupyter_output><empty_output><jupyter_text>Loading all file names<jupyter_code>files = glob('combined/*.jpg')
files = np.random.permutation(files)
files[:5]<jupyter_output><empty_output><jupyter_text>Keeping all correctly formatted labels<jupyter_code>np.unique([i[-34] for i in files], return_counts=True)<jupyter_output><empty_output><jupyter_text>Removing problematic target names<jupyter_code>faces = [i for i in files if (i[-34] in ('0', '1')) and len(i[-37:-35].strip('\\').strip('d'))  == 2 ]
y = [i[-34] for i in files if (i[-34] in ('0', '1')) and len(i[-37:-35].strip('\\').strip('d')) > 1 ]
sex = ['men', 'women']
assert len(y) == len(faces), 'The X and Y are not of the same length!'<jupyter_output><empty_output><jupyter_text>This is the shape width/height<jupyter_code>dim = 60<jupyter_output><empty_output><jupyter_text>Cropping function<jupyter_code>def crop(img):
    if img.shape[0]<img.shape[1]:
        x = img.shape[0]
        y = img.shape[1]
        crop_img = img[: , int(y/2-x/2):int(y/2+x/2)]
    else:
        x = img.shape[1]
        y = img.shape[0]
        crop_img = img[int(y/2-x/2):int(y/2+x/2) , :]

    return crop_img<jupyter_output><empty_output><jupyter_text>Loading and cropping images<jupyter_code>print('Scaling...', end='')
start = time()
x = []
num_to_load = int(len(faces)/5) # len(faces)  
for ix, file in enumerate(faces[:num_to_load]): 
    image = plt.imread(file, 'jpg')
    image = Image.fromarray(image).resize((dim, dim)).convert('L')
    image = crop(np.array(image))
    x.append(image)
print(f'\rDone. {int(time() - start)} seconds')
y = y[:num_to_load]<jupyter_output>Done. 5 seconds<jupyter_text>Turning the pictures into arrays<jupyter_code>x = np.array(x, dtype=np.float32).reshape(-1, 1, 60, 60)
y = np.array(y, dtype=np.float32)
labels = y.copy()<jupyter_output><empty_output><jupyter_text>Turning the targets into a 2D matrix<jupyter_code>assert x.ndim == 4, 'The input is the wrong shape!'
yy, xx = y.nbytes, x.nbytes
print(f'The size of X is {xx:,} bytes and the size of Y is {yy:,} bytes.')
files, faces = None, None<jupyter_output><empty_output><jupyter_text>Displaying the pictures<jupyter_code>fig = plt.figure(figsize=(12, 12))
for i in range(1, 5):
    plt.subplot(1, 5, i)
    rand = np.random.randint(0, x.shape[0])
    ax = plt.imshow(x[rand][0, :, :], cmap='gray')
    plt.title('<{}>'.format(sex[int(labels[rand])].capitalize()))
    yticks = plt.xticks([])
    yticks = plt.yticks([])
# x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=2e-1)
# x, y = None, None
print('Scaling...', end='')
image_size = x.shape[1] * x.shape[1] 
x = x.astype('float32') / 255 
print('\rDone.     ')
if torch.cuda.is_available():
    # x_train = torch.from_numpy(x_train) 
    # x_test = torch.from_numpy(x_test) 
    # y_train = torch.from_numpy(y_train) 
    # y_test = torch.from_numpy(y_test)
    x = torch.from_numpy(x) 
    y = torch.from_numpy(y)
    print('Tensors successfully flushed to CUDA.')
else:
    print('CUDA not available!')<jupyter_output>Tensors successfully flushed to CUDA.<jupyter_text>Making a dataset class<jupyter_code>class Face():
    
    def __init__(self):
        self.len = x.shape[0]
        self.x = x
        self.y = y
        
    def __getitem__(self, index):
        return x[index], y[index].unsqueeze(0)
    
    def __len__(self):
        return self.len<jupyter_output><empty_output><jupyter_text>Instantiating the class<jupyter_code>train = Face()<jupyter_output><empty_output><jupyter_text>Parsing the args<jupyter_code>os.makedirs("images", exist_ok=True)
parser = argparse.ArgumentParser()
parser.add_argument("--n_epochs", type=int, default=25, help="number of epochs of training")
parser.add_argument("--batch_size", type=int, default=32, help="size of the batches")
parser.add_argument("--lr", type=float, default=0.005, help="adam: learning rate")
parser.add_argument("--b1", type=float, default=0.3, help="adam: decay of first order momentum of gradient")
parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient")
parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation")
parser.add_argument("--latent_dim", type=int, default=3, help="dimensionality of the latent code")
parser.add_argument("--img_size", type=int, default=60, help="size of each image dimension")
parser.add_argument("--channels", type=int, default=1, help="number of image channels")
parser.add_argument("--sample_interval", type=int, default=50, help="interval between image sampling")
# opt = parser.parse_args()
opt, unknown = parser.parse_known_args()
print(opt)

img_shape = (opt.channels, opt.img_size, opt.img_size)<jupyter_output>Namespace(b1=0.3, b2=0.999, batch_size=32, channels=1, img_size=60, latent_dim=3, lr=0.005, n_cpu=8, n_epochs=25, sample_interval=1)<jupyter_text>Reparametrization<jupyter_code>cuda = True if torch.cuda.is_available() else False
def reparameterization(mu, logvar):
    std = torch.exp(logvar / 2)
    sampled_z = Variable(Tensor(np.random.normal(0, 1, (mu.size(0), opt.latent_dim))))
    z = sampled_z * std + mu
    return z<jupyter_output><empty_output><jupyter_text>Encoder<jupyter_code>class Encoder(nn.Module):
    def __init__(self):
        super(Encoder, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(int(np.prod(img_shape)), 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 512),
            nn.BatchNorm1d(512),
            nn.LeakyReLU(0.2, inplace=True),
        )

        self.mu = nn.Linear(512, opt.latent_dim)
        self.logvar = nn.Linear(512, opt.latent_dim)

    def forward(self, img):
        img_flat = img.view(img.shape[0], -1)
        x = self.model(img_flat)
        mu = self.mu(x)
        logvar = self.logvar(x)
        z = reparameterization(mu, logvar)
        return z<jupyter_output><empty_output><jupyter_text>Encoder<jupyter_code>class Decoder(nn.Module):
    def __init__(self):
        super(Decoder, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(opt.latent_dim, 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 512),
            nn.BatchNorm1d(512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, int(np.prod(img_shape))),
            nn.Tanh(),
        )

    def forward(self, z):
        img_flat = self.model(z)
        img = img_flat.view(img_flat.shape[0], *img_shape)
        return img<jupyter_output><empty_output><jupyter_text>Discriminator<jupyter_code>class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(opt.latent_dim, 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(256, 1),
            nn.Sigmoid(),
        )

    def forward(self, z):
        validity = self.model(z)
        return validity<jupyter_output><empty_output><jupyter_text>Create loss function<jupyter_code># Use binary cross-entropy loss
adversarial_loss = torch.nn.BCELoss()
pixelwise_loss = torch.nn.L1Loss()<jupyter_output><empty_output><jupyter_text>Instatiate the classes<jupyter_code># Initialize generator and discriminator
encoder = Encoder()
decoder = Decoder()
discriminator = Discriminator()<jupyter_output><empty_output><jupyter_text>Send to cuda if possible<jupyter_code>if cuda:
    encoder.cuda()
    decoder.cuda()
    discriminator.cuda()
    adversarial_loss.cuda()
    pixelwise_loss.cuda()<jupyter_output><empty_output><jupyter_text>Make dir<jupyter_code># Configure data loader
os.makedirs("directory", exist_ok=True)
dataloader = torch.utils.data.DataLoader(train, batch_size=opt.batch_size,
    shuffle=True,
)<jupyter_output><empty_output><jupyter_text>Make pics<jupyter_code># Optimizers
optimizer_G = torch.optim.Adam(
    itertools.chain(encoder.parameters(), decoder.parameters()), lr=opt.lr, betas=(opt.b1, opt.b2)
)
optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))

Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor


def sample_image(n_row, batches_done):
    """Saves a grid of generated digits"""
    # Sample noise
    z = Variable(Tensor(np.random.normal(0, 1, (n_row ** 2, opt.latent_dim))))
    gen_imgs = decoder(z)
    save_image(gen_imgs.data, "images/%d.png" % batches_done, nrow=n_row, normalize=True)<jupyter_output><empty_output><jupyter_text>Train the model<jupyter_code>for epoch in range(opt.n_epochs):
    for i, (imgs, _) in enumerate(dataloader):

        # Adversarial ground truths
        valid = Variable(Tensor(imgs.shape[0], 1).fill_(1.0), requires_grad=False)
        fake = Variable(Tensor(imgs.shape[0], 1).fill_(0.0), requires_grad=False)

        # Configure input
        real_imgs = Variable(imgs.type(Tensor))

        # -----------------
        #  Train Generator
        # -----------------

        optimizer_G.zero_grad()

        encoded_imgs = encoder(real_imgs)
        decoded_imgs = decoder(encoded_imgs)

        # Loss measures generator's ability to fool the discriminator
        g_loss = 0.001 * adversarial_loss(discriminator(encoded_imgs), valid) + 0.999 * pixelwise_loss(
            decoded_imgs, real_imgs
        )

        g_loss.backward()
        optimizer_G.step()

        # ---------------------
        #  Train Discriminator
        # ---------------------

        optimizer_D.zero_grad()

        # Sample noise as discriminator ground truth
        z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim))))

        # Measure discriminator's ability to classify real from generated samples
        real_loss = adversarial_loss(discriminator(z), valid)
        fake_loss = adversarial_loss(discriminator(encoded_imgs.detach()), fake)
        d_loss = 0.5 * (real_loss + fake_loss)

        d_loss.backward()
        optimizer_D.step()
        
        batches_done = epoch * len(dataloader) + i
        if batches_done % opt.sample_interval == 0:
            sample_image(n_row=5, batches_done=batches_done)
            
    print(
        "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]"
        % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item())
    )<jupyter_output>[Epoch 0/25] [Batch 128/129] [D loss: 0.530735] [G loss: 0.227785]
[Epoch 1/25] [Batch 128/129] [D loss: 0.536842] [G loss: 0.189113]
[Epoch 2/25] [Batch 128/129] [D loss: 0.625455] [G loss: 0.176759]
[Epoch 3/25] [Batch 128/129] [D loss: 0.530406] [G loss: 0.189388]
[Epoch 4/25] [Batch 128/129] [D loss: 0.618144] [G loss: 0.180223]
[Epoch 5/25] [Batch 128/129] [D loss: 0.616816] [G loss: 0.163058]
[Epoch 6/25] [Batch 128/129] [D loss: 0.313410] [G loss: 0.199729]
[Epoch 7/25] [Batch 128/129] [D loss: 0.719056] [G loss: 0.186529]
[Epoch 8/25] [Batch 128/129] [D loss: 0.675545] [G loss: 0.175951]
[Epoch 9/25] [Batch 128/129] [D loss: 0.317447] [G loss: 0.186320]
[Epoch 10/25] [Batch 128/129] [D loss: 0.579522] [G loss: 0.165260]
[Epoch 11/25] [Batch 128/129] [D loss: 0.442489] [G loss: 0.187621]
[Epoch 12/25] [Batch 128/129] [D loss: 0.441387] [G loss: 0.142490]
[Epoch 13/25] [Batch 128/129] [D loss: 0.722367] [G loss: 0.113072]
[Epoch 14/25] [Batch 128/129] [D loss: 0.573351] [G loss: [...]<jupyter_text>Look at generated faces<jupyter_code>picture = plt.imread(r'C:\Users\Nicolas\Documents\Data\faces\images/3224.png')
plt.figure(figsize=(6, 6))
plt.imshow(picture)
plt.xticks([]), plt.yticks([])
plt.title('Generated Faces')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15250792618486303, 'fraction_numerical': 0.046093813511096655, 'mean_word_length': 3.828100470957614, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '24', 'dir': 'jupyter-structured-clean-dedup', 'id': '121290', 'license': 'MIT', 'n_tokens_mistral': 4950, 'n_tokens_neox': 4506, 'n_words': 917, 'path': 'Adversarial Auto Encoder.ipynb', 'repo_name': 'vincentfortin/data-augmentation-with-gan-and-vae', 'size': '12301'}