{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"# version 11\n# ---------------------------------\n# - Conditional SAGAN baseline, sticking to the paper \n# - add minibatch std dist\n# - instead of avg pool in disc\n# - add gaussian noise std 0.05 in disc\n# - RALS\n# - num epochs = 500","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"COMPUTE_LB = False","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import time\nkernel_start_time = time.perf_counter()\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom IPython.display import SVG, display\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os, time, glob, shutil\nstarttime = time.time()\n\nimport warnings\nwarnings.simplefilter(\"ignore\")\n\nfrom pathlib import Path\nimport xml.etree.ElementTree as ET # for parsing XML\nfrom PIL import Image # to read images\nimport glob\nfrom tqdm import tqdm\n\nimport matplotlib.pyplot as plt\nimport matplotlib.animation as animation\nfrom IPython.display import HTML\n\nfrom argparse import Namespace\nimport numpy as np\nimport random\nimport torch\nfrom torch import nn, optim\nimport torch.nn.functional as F\n\nimport torchvision\nfrom torchvision import datasets, transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision.utils import save_image\nimport torchvision.utils as vutils\n\nfrom ignite.contrib.handlers import ProgressBar\nfrom ignite.engine import Engine, Events\nfrom ignite.handlers import ModelCheckpoint, Timer\nfrom ignite.metrics import RunningAverage","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"args = Namespace(\n    seed=123,\n    disable_cuda=False,\n    device=None,\n    debug=False,\n    num_workers=4,\n    # use this for exp name\n    CKPT_PREFIX = 'sagan_hinge_loss',\n    exp_name = None,\n\n    ########## Ignite Stuff ###################\n    PRINT_FREQ = 600,\n    FAKE_IMG_FNAME = 'fake_sample_epoch_{:04d}.png',\n    REAL_IMG_FNAME = 'real_sample_epoch_{:04d}.png',\n    LOGS_FNAME = 'logs.tsv',\n    PLOT_FNAME = 'plot.svg',\n    SAMPLES_FNAME = 'samples.svg',\n    output_dir = '../output_dir/',\n    alpha = 0.98, # smoothing constant for exponential moving average\n    \n    ######### Dataset Related #################\n    shuffle=True,\n    datapath=Path('../input/all-dogs/all-dogs/'),\n    root_images=Path(\"../input/all-dogs/all-dogs\"),\n    root_annots=Path(\"../input/annotation/Annotation/\"),\n    \n    ######### Training Params ######################\n    num_epochs=500,\n    lrD=4e-4,\n    lrG=1e-4,\n    beta1 = 0., #SAGAN params (wuuuud?)\n    beta2 = 0.9,\n    batch_size=32,\n    weight_decay=0.001,\n    log_interval=100,\n    num_disc_update=1,\n\n    ######### Model Params #########################\n    num_classes=120,\n    image_size=64,\n    in_channels=3,\n    num_feature_maps_gen=64,\n    num_feature_maps_disc=64,\n    latent_dim=128,\n    input_dim=64*64,\n    hidden_size=400,    \n    dropout_p=0.2,\n)\nargs.exp_name = args.CKPT_PREFIX + f\"_{args.num_epochs}ep_{args.batch_size}bs_{args.num_disc_update}ndisc\"\nprint(\"=\"*100)\nprint(args.exp_name)\nprint(\"=\"*100)\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\ndef seed_everything(seed=args.seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\nseed_everything()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"### All utility functions\ndef get_bbox(img_path):\n    \"image path as input and return list of bounding boxes around dogs (could be more than one per image)\"\n    annotation_basename = os.path.splitext(os.path.basename(img_path))[0]\n    annotation_dirname = next(dirname for dirname in os.listdir(args.root_annots) if dirname.startswith(annotation_basename.split('_')[0]))\n    annotation_filename = os.path.join(args.root_annots, annotation_dirname, annotation_basename)\n    tree = ET.parse(annotation_filename)\n    root = tree.getroot()\n    objects = root.findall('object')\n    bboxes = []\n    for o in objects:\n        bndbox = o.find('bndbox')\n        xmin = int(bndbox.find('xmin').text)\n        ymin = int(bndbox.find('ymin').text)\n        xmax = int(bndbox.find('xmax').text)\n        ymax = int(bndbox.find('ymax').text)\n        w = np.min((xmax - xmin, ymax - ymin))\n        bboxes.append((xmin, ymin, xmin+w, ymin+w))\n    return bboxes\n\ndef doggo_loader(img_path):\n    img = torchvision.datasets.folder.default_loader(img_path) # default loader\n    bbox = get_bbox(img_path)[-1]\n    return img.crop(bbox)\n\ndef clear_output_dir():\n    try:\n        shutil.rmtree(args.output_dir)\n    except FileNotFoundError:\n        pass\n\ndef check_gen_samples(dataloader, img_list):\n    \"Plot tile of real and generated images\"\n    \n    real_batch = next(iter(dataloader))\n    # Plot the real images\n    plt.figure(figsize=(15,15))\n    plt.subplot(1,2,1)\n    plt.axis(\"off\")\n    plt.title(\"Real Images\")\n    plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], padding=5, normalize=True).cpu(),(1,2,0)))\n\n    # Plot the fake images from the last epoch\n    plt.subplot(1,2,2)\n    plt.axis(\"off\")\n    plt.title(\"Fake Images\")\n    plt.imshow(np.transpose(img_list[-1],(1,2,0)))\n    plt.show()\n    \n# custom weights initialization called on netG and netD\ndef weights_init(m):\n    classname = m.__class__.__name__\n    if classname.find('Conv') != -1:\n        nn.init.normal_(m.weight.data, 0.0, 0.02)\n    elif classname.find('BatchNorm') != -1:\n        nn.init.normal_(m.weight.data, 1.0, 0.02)\n        nn.init.constant_(m.bias.data, 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DogDataset(Dataset):\n    def __init__(self, img_dir, transform1, transform2=None):\n        self.img_dir = img_dir\n        self.img_names = os.listdir(img_dir)\n        self.transform1 = transform1\n        self.transform2 = transform2\n        \n        self.imgs = []\n        self.labels = []\n        for img_name in tqdm(self.img_names):\n            img_path = os.path.join(img_dir, img_name)\n            img = Image.open(img_path)\n            annotation_basename = os.path.splitext(os.path.basename(img_path))[0]\n            annotation_dirname = next(dirname for dirname in os.listdir(args.root_annots) if dirname.startswith(annotation_basename.split('_')[0]))\n            annotation_filename = os.path.join(args.root_annots, annotation_dirname, annotation_basename)\n            tree = ET.parse(annotation_filename)\n            root = tree.getroot()\n            objects = root.findall('object')\n            bboxes = []\n            for o in objects:\n                bndbox = o.find('bndbox')\n                xmin = int(bndbox.find('xmin').text)\n                ymin = int(bndbox.find('ymin').text)\n                xmax = int(bndbox.find('xmax').text)\n                ymax = int(bndbox.find('ymax').text)\n                w = np.min((xmax - xmin, ymax - ymin))\n                bbox = (xmin, ymin, xmin+w, ymin+w)\n                img_crop = img.crop(bbox)\n                \n                self.imgs.append(self.transform1(img_crop))\n                self.labels.append(annotation_dirname.split('-')[1].lower())\n                \n    def __getitem__(self, index):\n        img = self.imgs[index]\n        label = self.labels[index]\n        \n        if self.transform2 is not None:\n            img = self.transform2(img)\n        \n        return img, label\n\n    def __len__(self):\n        return len(self.imgs)\n\ndef get_transforms():\n    \n    # this normalizes pixel values between [-1,1]\n    # https://www.kaggle.com/jesucristo/gan-introduction565419\n    # GANHACK #1\n    normalize = transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n    random_transforms = [transforms.ColorJitter(), \n                         transforms.RandomRotation(degrees=1)]\n    random_cropper = [torchvision.transforms.CenterCrop(args.image_size), torchvision.transforms.RandomCrop(args.image_size)]\n\n\n    # First preprocessing of data\n    transform1 = transforms.Compose([\n        transforms.Resize(args.image_size),\n        transforms.CenterCrop(args.image_size),\n    ])\n\n    transform2 = transforms.Compose([\n        transforms.RandomHorizontalFlip(p=0.5),\n        transforms.RandomApply(random_transforms, p=0.3),\n        transforms.ToTensor(),\n        normalize]) \n    \n    return transform1, transform2\n\ntransform1, transform2 = get_transforms()\ntrain_data = DogDataset(img_dir=args.root_images,\n                        transform1=transform1,\n                        transform2=transform2)\n\ndecoded_dog_labels = {i:breed for i, breed in enumerate(sorted(set(train_data.labels)))}\nencoded_dog_labels = {breed:i for i, breed in enumerate(sorted(set(train_data.labels)))}\ntrain_data.labels = [encoded_dog_labels[l] for l in train_data.labels] # encode dog labels in the data generator\ndataloader = torch.utils.data.DataLoader(train_data, \n                                         shuffle=True,\n                                         batch_size=args.batch_size, \n                                         num_workers=args.num_workers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def init_weights(m):\n    if type(m) == nn.Linear or type(m) == nn.Conv2d:\n        nn.init.xavier_uniform_(m.weight)\n        m.bias.data.fill_(0.)\n\n\ndef snconv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True):\n    return nn.utils.spectral_norm(nn.Conv2d(in_channels=in_channels, \n                                            out_channels=out_channels, \n                                            kernel_size=kernel_size,\n                                            stride=stride, \n                                            padding=padding, \n                                            dilation=dilation, \n                                            groups=groups, \n                                            bias=bias))\n\n\ndef snlinear(in_features, out_features):\n    return nn.utils.spectral_norm(nn.Linear(in_features=in_features, out_features=out_features))\n\n\ndef sn_embedding(num_embeddings, embedding_dim):\n    return nn.utils.spectral_norm(nn.Embedding(num_embeddings=num_embeddings, embedding_dim=embedding_dim))\n\n# ----------------------------------------------------------------------------\n# Pixelwise feature vector normalization.\n# reference: https://github.com/tkarras/progressive_growing_of_gans/blob/master/networks.py#L120\n# ----------------------------------------------------------------------------\nclass PixelwiseNorm(nn.Module):\n    def __init__(self):\n        super(PixelwiseNorm, self).__init__()\n\n    def forward(self, x, alpha=1e-8):\n        \"\"\"\n        forward pass of the module\n        :param x: input activations volume\n        :param alpha: small number for numerical stability\n        :return: y => pixel normalized activations\n        \"\"\"\n        y = x.pow(2.).mean(dim=1, keepdim=True).add(alpha).sqrt()  # [N1HW]\n        y = x / y  # normalize the input x volume\n        return y\n    \nclass MinibatchStdDev(nn.Module):\n    \"\"\"\n    Minibatch standard deviation layer for the discriminator\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        derived class constructor\n        \"\"\"\n        super(MinibatchStdDev, self).__init__()\n\n    def forward(self, x, alpha=1e-8):\n        \"\"\"\n        forward pass of the layer\n        :param x: input activation volume\n        :param alpha: small number for numerical stability\n        :return: y => x appended with standard deviation constant map\n        \"\"\"\n        batch_size, _, height, width = x.shape\n        # [B x C x H x W] Subtract mean over batch.\n        y = x - x.mean(dim=0, keepdim=True)\n        # [1 x C x H x W]  Calc standard deviation over batch\n        y = torch.sqrt(y.pow(2.).mean(dim=0, keepdim=False) + alpha)\n\n        # [1]  Take average over feature_maps and pixels.\n        y = y.mean().view(1, 1, 1, 1)\n\n        # [B x 1 x H x W]  Replicate over group and pixels.\n        y = y.repeat(batch_size,1, height, width)\n\n        # [B x C x H x W]  Append as new feature_map.\n        y = torch.cat([x, y], 1)\n        # return the computed values:\n        return y    \n    \n    \nclass GaussianNoise(nn.Module):\n    \"\"\"Gaussian noise regularizer.\n\n    Args:\n        sigma (float, optional): relative standard deviation used to generate the\n            noise. Relative means that it will be multiplied by the magnitude of\n            the value your are adding the noise to. This means that sigma can be\n            the same regardless of the scale of the vector.\n        is_relative_detach (bool, optional): whether to detach the variable before\n            computing the scale of the noise. If `False` then the scale of the noise\n            won't be seen as a constant but something to optimize: this will bias the\n            network to generate vectors with smaller values.\n    \"\"\"\n\n    def __init__(self, sigma=0.1, is_relative_detach=True):\n        super().__init__()\n        self.sigma = sigma\n        self.is_relative_detach = is_relative_detach\n        self.noise = torch.tensor(0.).to(device)\n\n    def forward(self, x):\n        if self.training and self.sigma != 0:\n            scale = self.sigma * x.detach() if self.is_relative_detach else self.sigma * x\n            sampled_noise = self.noise.repeat(*x.size()).normal_() * scale\n            x = x + sampled_noise\n        return x \n\nclass ConditionalBatchNorm2d(nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.num_features = num_features\n        self.bn = nn.BatchNorm2d(num_features)\n        self.embed = nn.Embedding(num_classes, num_features * 2)\n        self.embed.weight.data[:, :num_features].fill_(1.)  # Initialize scale to 1\n        self.embed.weight.data[:, num_features:].zero_()    # Initialize bias at 0\n\n    def forward(self, x, y):\n        out = self.bn(x)\n        gamma, beta = self.embed(y).chunk(2, 1)\n        out = gamma.view(-1, self.num_features, 1, 1) * out + beta.view(-1, self.num_features, 1, 1)\n        return out    \n\nclass Self_Attn(nn.Module):\n    \"\"\" Self attention Layer\"\"\"\n\n    def __init__(self, in_channels):\n        super(Self_Attn, self).__init__()\n        self.in_channels = in_channels\n        self.snconv1x1_theta = snconv2d(in_channels=in_channels, \n                                        out_channels=in_channels//8, \n                                        kernel_size=1, stride=1, padding=0)\n        self.snconv1x1_phi = snconv2d(in_channels=in_channels, \n                                      out_channels=in_channels//8, \n                                      kernel_size=1, stride=1, padding=0)\n        self.snconv1x1_g = snconv2d(in_channels=in_channels, \n                                    out_channels=in_channels//2, \n                                    kernel_size=1, stride=1, padding=0)\n        self.snconv1x1_attn = snconv2d(in_channels=in_channels//2, \n                                       out_channels=in_channels, \n                                       kernel_size=1, stride=1, padding=0)\n        self.maxpool = nn.MaxPool2d(2, stride=2, padding=0)\n        self.softmax  = nn.Softmax(dim=-1)\n        self.sigma = nn.Parameter(torch.zeros(1))\n\n    def forward(self, x):\n        \"\"\"\n            inputs :\n                x : input feature maps(B X C X W X H)\n            returns :\n                out : self attention value + input feature \n                attention: B X N X N (N is Width*Height)\n        \"\"\"\n        _, ch, h, w = x.size()\n        # Theta path\n        theta = self.snconv1x1_theta(x)\n        theta = theta.view(-1, ch//8, h*w)\n        # Phi path\n        phi = self.snconv1x1_phi(x)\n        phi = self.maxpool(phi)\n        phi = phi.view(-1, ch//8, h*w//4)\n        # Attn map\n        attn = torch.bmm(theta.permute(0, 2, 1), phi)\n        attn = self.softmax(attn)\n        # g path\n        g = self.snconv1x1_g(x)\n        g = self.maxpool(g)\n        g = g.view(-1, ch//2, h*w//4)\n        # Attn_g\n        attn_g = torch.bmm(g, attn.permute(0, 2, 1))\n        attn_g = attn_g.view(-1, ch//2, h, w)\n        attn_g = self.snconv1x1_attn(attn_g)\n        # Out\n        out = x + self.sigma*attn_g\n        return out    \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class GenBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, num_classes):\n        super(GenBlock, self).__init__()\n        self.cond_bn1 = ConditionalBatchNorm2d(in_channels, num_classes)\n        self.relu = nn.ReLU(inplace=True)\n        self.ps1 = nn.PixelShuffle(2),\n        self.snconv2d1 = snconv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)\n        self.cond_bn2 = ConditionalBatchNorm2d(out_channels, num_classes)\n        self.snconv2d2 = snconv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)\n        self.snconv2d0 = snconv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=1, padding=0)\n\n    def forward(self, x, labels):\n        x0 = x\n\n        x = self.cond_bn1(x, labels)\n        x = self.relu(x)\n        x = F.interpolate(x, scale_factor=2, mode='nearest') # upsample\n        x = self.snconv2d1(x)\n        x = self.cond_bn2(x, labels)\n        x = self.relu(x)\n        x = self.snconv2d2(x)\n\n        x0 = F.interpolate(x0, scale_factor=2, mode='nearest') # upsample\n        x0 = self.snconv2d0(x0)\n\n        out = x + x0\n        return out\n    \nclass DiscOptBlock(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super(DiscOptBlock, self).__init__()\n        self.snconv2d1 = snconv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)\n        self.relu = nn.ReLU(inplace=True)\n        self.snconv2d2 = snconv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)\n        self.downsample = nn.AvgPool2d(2)\n        self.snconv2d0 = snconv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=1, padding=0)\n\n    def forward(self, x):\n        x0 = x\n\n        x = self.snconv2d1(x)\n        x = self.relu(x)\n        x = self.snconv2d2(x)\n        x = self.downsample(x)\n\n        x0 = self.downsample(x0)\n        x0 = self.snconv2d0(x0)\n\n        out = x + x0\n        return out\n\n\nclass DiscBlock(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super(DiscBlock, self).__init__()\n        self.relu = nn.LeakyReLU(0.2, inplace=True)\n        self.snconv2d1 = snconv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)\n        self.snconv2d2 = snconv2d(in_channels=out_channels, out_channels=out_channels, kernel_size=3, stride=1, padding=1)\n        self.downsample = nn.AvgPool2d(2)\n        self.ch_mismatch = False\n        if in_channels != out_channels:\n            self.ch_mismatch = True\n        self.snconv2d0 = snconv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=1, padding=0)\n\n    def forward(self, x, downsample=True):\n        x0 = x\n\n        x = self.relu(x)\n        x = self.snconv2d1(x)\n        x = self.relu(x)\n        x = self.snconv2d2(x)\n        if downsample:\n            x = self.downsample(x)\n\n        if downsample or self.ch_mismatch:\n            x0 = self.snconv2d0(x0)\n            if downsample:\n                x0 = self.downsample(x0)\n\n        out = x + x0\n        return out\n    \nclass Generator(nn.Module):\n    \"\"\"Generator.\"\"\"\n\n    def __init__(self):\n        super(Generator, self).__init__()\n\n        self.z_dim = args.latent_dim\n        self.g_conv_dim = args.num_feature_maps_gen\n        \n        self.snlinear0 = snlinear(in_features=self.z_dim, out_features=self.g_conv_dim*8*4*4)\n        self.block1 = GenBlock(self.g_conv_dim*8, self.g_conv_dim*8, args.num_classes)\n        self.block2 = GenBlock(self.g_conv_dim*8, self.g_conv_dim*4, args.num_classes)\n        self.block3 = GenBlock(self.g_conv_dim*4, self.g_conv_dim*2, args.num_classes)\n        self.self_attn = Self_Attn(self.g_conv_dim*2)\n        self.block4 = GenBlock(self.g_conv_dim*2, self.g_conv_dim, args.num_classes)\n#         self.block5 = GenBlock(self.g_conv_dim, self.g_conv_dim, args.num_classes)\n        self.bn = nn.BatchNorm2d(self.g_conv_dim, eps=1e-5, momentum=0.0001, affine=True)\n        self.relu = nn.ReLU(inplace=True)\n        self.snconv2d1 = snconv2d(in_channels=self.g_conv_dim, out_channels=3, kernel_size=3, stride=1, padding=1)\n        self.tanh = nn.Tanh()\n\n        # Weight init\n        self.apply(init_weights)\n\n    def forward(self, z, labels):\n#         import pdb; pdb.set_trace()\n        # n x z_dim\n        act0 = self.snlinear0(z)            # n x g_conv_dim*8*2*2\n        act0 = act0.view(-1, self.g_conv_dim*8, 4, 4) # n x g_conv_dim*16 x 2 x 2\n        act1 = self.block1(act0, labels)    # n x g_conv_dim*8 x 4 x 4\n        act2 = self.block2(act1, labels)    # n x g_conv_dim*4 x 8 x 8\n        act3 = self.block3(act2, labels)    # n x g_conv_dim*2 x 16 x 16\n        act3 = self.self_attn(act3)         # n x g_conv_dim*2 x 16 x 16\n        act4 = self.block4(act3, labels)    # n x g_conv_dim*1 x 32 x 32\n#         act5 = self.block5(act4, labels)    # n x g_conv_dim  x 64 x 64\n#         act5 = self.bn(act4)                # n x g_conv_dim  x 64 x 64\n        act5 = self.relu(act4)              # n x g_conv_dim  x 64 x 64\n        act6 = self.snconv2d1(act5)         # n x 3 x 64 x 64\n        act6 = self.tanh(act6)              # n x 3 x 64 x 64\n        return act6\n\n    \nclass Discriminator(nn.Module):\n    \"\"\"Discriminator.\"\"\"\n\n    def __init__(self):\n        super(Discriminator, self).__init__()\n        self.d_conv_dim = args.num_feature_maps_disc\n        self.opt_block1 = DiscOptBlock(3, self.d_conv_dim)\n        self.block1 = DiscBlock(self.d_conv_dim, self.d_conv_dim*2)\n        self.self_attn = Self_Attn(self.d_conv_dim*2)\n        self.block2 = DiscBlock(self.d_conv_dim*2, self.d_conv_dim*4)\n        self.block3 = DiscBlock(self.d_conv_dim*4, self.d_conv_dim*4)\n        self.block4 = DiscBlock(self.d_conv_dim*4, self.d_conv_dim*8)\n        self.block5 = DiscBlock(self.d_conv_dim*8, self.d_conv_dim*8)\n        self.relu = nn.ReLU(inplace=True)\n        self.snlinear1 = snlinear(in_features=self.d_conv_dim*8, out_features=1)\n        self.sn_embedding1 = sn_embedding(args.num_classes, self.d_conv_dim*8)\n\n        # Weight init\n        self.apply(init_weights)\n        nn.init.xavier_uniform_(self.sn_embedding1.weight)\n\n    def forward(self, x, labels):\n        # n x 3 x 64 x 64\n        h0 = self.opt_block1(x) # n x d_conv_dim   x 32 x 32\n        h1 = self.block1(h0)    # n x d_conv_dim*2 x 16 x 16\n        h1 = self.self_attn(h1) # n x d_conv_dim*2 x 16 x 16\n        h2 = self.block2(h1)    # n x d_conv_dim*4 x 8 x 8\n        h3 = self.block3(h2)    # n x d_conv_dim*4 x  4 x  4\n        h4 = self.block4(h3)    # n x d_conv_dim*8 x 2 x  2\n        h5 = self.block5(h4, downsample=False)  # n x d_conv_dim*8 x 2 x 2\n        h5 = self.relu(h5)              # n x d_conv_dim*8 x 2 x 2\n        h6 = torch.sum(h5, dim=[2,3])   # n x d_conv_dim*8\n        output1 = torch.squeeze(self.snlinear1(h6)) # n x 1\n        # Projection\n        h_labels = self.sn_embedding1(labels)   # n x d_conv_dim*8\n        proj = torch.mul(h6, h_labels)          # n x d_conv_dim*8\n        output2 = torch.sum(proj, dim=[1])      # n x 1\n        # Out\n        output = output1 + output2              # n x 1\n        return output","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"netG = Generator().to(device)\nnetD = Discriminator().to(device)\n        \nweights_init(netG)\nweights_init(netD)\nprint(\"Generator parameters:    \", sum(p.numel() for p in netG.parameters() if p.requires_grad))\nprint(\"Discriminator parameters:\", sum(p.numel() for p in netD.parameters() if p.requires_grad))\n\nfixed_noise = torch.randn(64, args.latent_dim, device=device)\ndog_labels = torch.randint(0, len(encoded_dog_labels), (64, ), device=device)\n\n# Establish convention for real and fake labels during training\nreal_label = 0.9\nfake_label = 0.0\n\nBCE_stable = nn.BCEWithLogitsLoss()\noptimizerD = optim.Adam(netD.parameters(), lr=args.lrD, betas=(args.beta1, args.beta2))\noptimizerG = optim.Adam(netG.parameters(), lr=args.lrG, betas=(args.beta1, args.beta2))\n\ndef step(engine, batch):\n    def train_D(images, labels):\n        \"\"\"\n        Run 1 step of training for discriminator\n        Input:\n            images: batch of images (reshaped to [batch_size, -1])\n        Output:\n            D_loss: non-saturing loss for discriminator,\n            -E[log( sigmoid(D(x) - E[D(G(z))]) )]\n              - E[log(1 - sigmoid(D(G(z)) - E[D(x)]))]\n        \"\"\"\n        noise = torch.randn(args.batch_size, args.latent_dim, device=device)\n        G_output = netG(noise, labels)\n        \n        # classify the generated and real batch images\n        Dx_score = netD(images, labels) # D(x)\n        DG_score = netD(G_output, labels) # D(G(z))\n        \n        # Compute RA Hinge loss\n        D_loss = (torch.mean(torch.nn.ReLU()(1.0 - (Dx_score - torch.mean(DG_score)))) + \n                  torch.mean(torch.nn.ReLU()(1.0 + (DG_score - torch.mean(Dx_score)))))/2\n        \n        return D_loss, F.sigmoid(Dx_score).mean().item(), F.sigmoid(DG_score).mean().item()\n    \n    def train_G(images, labels):\n        \"\"\" Run 1 step of training for generator\n            Input:\n                images: batch of images reshaped to [batch_size, -1]\n            Output:\n                G_loss: non-saturating loss for how well G(z) fools D,\n                -E[log(sigmoid(D(G(z))-E[D(x)]))]\n                    -E[log(1-sigmoid(D(x)-E[D(G(z))]))]\n        \"\"\"\n        noise = torch.randn(args.batch_size, args.latent_dim, device=device)\n        G_output = netG(noise, labels) # G(z)\n                  \n        Dx_score = netD(images, labels) # D(x)\n        DG_score = netD(G_output, labels) # D(G(z))\n        \n        # Compute RA NS loss for G                \n        G_loss = (torch.mean(torch.nn.ReLU()(1.0 + (Dx_score - torch.mean(DG_score)))) + \n                  torch.mean(torch.nn.ReLU()(1.0 - (DG_score - torch.mean(Dx_score)))))/2\n        \n        return G_loss, F.sigmoid(DG_score).mean().item()\n    \n    images, labels = batch[0].to(device), batch[1].to(device)\n    args.batch_size = images.size(0)\n    D_step_loss = []\n    for _ in range(args.num_disc_update):\n        netD.zero_grad()\n        \n        D_loss, Dx_score, DG_score1 = train_D(images, labels)\n        D_loss.backward()\n        optimizerD.step()\n        D_step_loss.append(D_loss.item())\n                    \n    # update G\n    netG.zero_grad()\n\n    G_loss, DG_score2 = train_G(images, labels)\n    G_loss.backward()\n    optimizerG.step()\n        \n    return {\n            'D_loss': np.mean(D_step_loss),\n            'G_loss': G_loss.item(),\n            'Dx_score': Dx_score,\n            'DG_score1': DG_score1,\n            'DG_score2': DG_score2\n    }","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"clear_output_dir()\n\n# ignite objects\ntrainer = Engine(step)\ncheckpoint_handler = ModelCheckpoint(args.output_dir, \n                                     args.CKPT_PREFIX, \n                                     save_interval=1, \n                                     n_saved=10, \n                                     require_empty=False)\ntimer = Timer(average=True)\n\n# attach running average metrics\nmonitoring_metrics = ['D_loss', 'G_loss', 'Dx_score', 'DG_score1', 'DG_score2']\nRunningAverage(alpha=args.alpha, output_transform=lambda x: x['D_loss']).attach(trainer, 'D_loss')\nRunningAverage(alpha=args.alpha, output_transform=lambda x: x['G_loss']).attach(trainer, 'G_loss')\nRunningAverage(alpha=args.alpha, output_transform=lambda x: x['Dx_score']).attach(trainer, 'Dx_score')\nRunningAverage(alpha=args.alpha, output_transform=lambda x: x['DG_score1']).attach(trainer, 'DG_score1')\nRunningAverage(alpha=args.alpha, output_transform=lambda x: x['DG_score2']).attach(trainer, 'DG_score2')\n\n# attach progress bar\npbar = ProgressBar()\npbar.attach(trainer, metric_names=monitoring_metrics)\n\n# adding handlers using `trainer.on` decorator API\n@trainer.on(Events.ITERATION_COMPLETED)\ndef print_logs(engine):\n    if (engine.state.iteration - 1) % args.PRINT_FREQ == 0:\n        fname = os.path.join(args.output_dir, args.LOGS_FNAME)\n        columns = [\"iteration\", ] + list(engine.state.metrics.keys())\n        values = [str(engine.state.iteration), ] + \\\n                 [str(round(value, 5)) for value in engine.state.metrics.values()]\n        with open(fname, 'a') as f:\n            if f.tell() == 0:\n                print('\\t'.join(columns), file=f)\n            print('\\t'.join(values), file=f)\n\n        message = '[{epoch}/{max_epoch}][{i}/{max_i}]'.format(epoch=engine.state.epoch,\n                                                              max_epoch=args.num_epochs,\n                                                              i=(engine.state.iteration % len(dataloader)),\n                                                              max_i=len(dataloader))\n        for name, value in zip(columns, values):\n            message += ' | {name}: {value}'.format(name=name, value=value)\n        pbar.log_message(message)\n\n@trainer.on(Events.EPOCH_COMPLETED)\ndef save_fake_example(engine):\n    fake = netG(fixed_noise, dog_labels).detach().cpu()\n    path = os.path.join(args.output_dir, args.FAKE_IMG_FNAME.format(engine.state.epoch))\n    vutils.save_image((fake+1.)/2., path, normalize=True)\n    \n@trainer.on(Events.EPOCH_COMPLETED)\ndef save_real_example(engine):\n    img, _ = engine.state.batch\n    path = os.path.join(args.output_dir, args.REAL_IMG_FNAME.format(engine.state.epoch))\n    vutils.save_image(img, path, normalize=True)\n\n@trainer.on(Events.EPOCH_COMPLETED)\ndef display_images(engine):\n    if engine.state.epoch % 10 == 0:\n        display(Image.open(os.path.join(args.output_dir, args.REAL_IMG_FNAME.format(engine.state.epoch))))\n        display(Image.open(os.path.join(args.output_dir, args.FAKE_IMG_FNAME.format(engine.state.epoch))))    \n    \n# adding handlers using `trainer.add_event_handler` method API\ntrainer.add_event_handler(event_name=Events.EPOCH_COMPLETED, \n                          handler=checkpoint_handler,\n                          to_save={\n                              'netG': netG,\n                              'netD': netD\n                          })\n\n# automatically adding handlers via a special `attach` method of `Timer` handler\ntimer.attach(trainer, \n             start=Events.EPOCH_STARTED, \n             resume=Events.EPOCH_STARTED,\n             pause=Events.EPOCH_COMPLETED, \n             step=Events.EPOCH_COMPLETED)\n\n@trainer.on(Events.EPOCH_COMPLETED)\ndef print_times(engine):\n    pbar.log_message(f'Epoch {engine.state.epoch} done. Time per epoch: {timer.value()/60:.3f}[min]')\n    timer.reset()\n    \n@trainer.on(Events.EPOCH_COMPLETED)\ndef create_plots(engine):\n    try:\n        import matplotlib as mpl\n        mpl.use('agg')\n\n        import numpy as np\n        import pandas as pd\n        import matplotlib.pyplot as plt\n\n    except ImportError:\n        warnings.warn('Loss plots will not be generated -- pandas or matplotlib not found')\n\n    else:\n        df = pd.read_csv(os.path.join(args.output_dir, args.LOGS_FNAME), delimiter='\\t', index_col='iteration')\n        _ = df.loc[:, list(engine.state.metrics.keys())].plot(subplots=True, figsize=(10, 10))\n        _ = plt.xlabel('Iteration number')\n        fig = plt.gcf()\n        path = os.path.join(args.output_dir, args.PLOT_FNAME)\n        fig.savefig(path)\n        \n@trainer.on(Events.EPOCH_STARTED)\ndef handle_timeout(engine):\n    if time.perf_counter() - kernel_start_time > 31000:\n        print(\"Time limit reached! Stopping kernel!\")\n        engine.terminate()\n\n        create_plots(engine)\n        checkpoint_handler(engine, {\n            'netG_exception': netG,\n            'netD_exception': netD\n        })\n        \n@trainer.on(Events.EXCEPTION_RAISED)\ndef handle_exception(engine, e):\n    if isinstance(e, KeyboardInterrupt) and (engine.state.iteration > 1):\n        engine.terminate()\n        warnings.warn('KeyboardInterrupt caught. Exiting gracefully.')\n\n        create_plots(engine)\n        checkpoint_handler(engine, {\n            'netG_exception': netG,\n            'netD_exception': netD\n        })\n\n    else:\n        raise e\n        \ntrainer.run(dataloader, args.num_epochs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# analysize logs\ndisplay(SVG(\"../output_dir/plot.svg\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(Image.open(os.path.join(args.output_dir, args.REAL_IMG_FNAME.format(trainer.state.epoch-1))))\ndisplay(Image.open(os.path.join(args.output_dir, args.FAKE_IMG_FNAME.format(trainer.state.epoch-1))))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def mse(imageA, imageB):\n        err = np.sum((imageA.astype(\"float\") - imageB.astype(\"float\")) ** 2)\n        err /= float(imageA.shape[0] * imageA.shape[1])\n        return err\n\ndef analyse_generated_by_class(n_images=5):\n    good_breeds = []\n    for l in range(len(decoded_dog_labels)):\n        sample = []\n        for _ in range(n_images):\n            noise = torch.randn(1, args.latent_dim, device=device)\n            dog_label = torch.full((1,) , l, device=device, dtype=torch.long)\n            gen_image = netG(noise, dog_label).to(\"cpu\").clone().detach().squeeze(0)\n            gen_image = gen_image.numpy().transpose(1, 2, 0)\n            sample.append(gen_image)\n        \n        # compare two images generated for the same label, if they're very similar => mode collapse\n        d = np.round(np.sum([mse(sample[k], sample[k+1]) for k in range(len(sample)-1)])/n_images, 1)\n        if d < 1.1: continue  # had mode colapse(discard)\n            \n        print(f\"Generated breed({d}): \", decoded_dog_labels[l])\n        l_noise = torch.randn(n_images, args.latent_dim, device=device)\n        l_labels = torch.randint(0, len(encoded_dog_labels), (n_images, ), device=device)\n            \n        fake = netG(l_noise, l_labels).detach().cpu()\n        path = os.path.join(args.output_dir, f'img_{l}.png')\n        vutils.save_image((fake+1.)/2., path, normalize=True)\n        display(Image.open(os.path.join(args.output_dir, f'img_{l}.png')))    \n        \n        good_breeds.append(l)\n    return good_breeds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from scipy.stats import truncnorm\n\ndef truncated_normal(size, threshold=1):\n    values = truncnorm.rvs(-threshold, threshold, size=size)\n    return values\n\ndef create_submit(good_breeds):\n    print(\"Creating submit\")\n    os.makedirs('../output_images', exist_ok=True)\n    im_batch_size = 50\n    n_images = 10000\n    \n    all_dog_labels = np.random.choice(good_breeds, size=n_images, replace=True)\n    for i_batch in range(0, n_images, im_batch_size):\n#         z = truncated_normal((im_batch_size, args.latent_dim, 1, 1), threshold=1)\n#         noise = torch.from_numpy(z).float().to(device)\n        noise = torch.randn(im_batch_size, args.latent_dim, device=device)\n        dog_labels = torch.from_numpy(all_dog_labels[i_batch: (i_batch+im_batch_size)]).to(device)\n        gen_images = netG(noise, dog_labels)\n        gen_images = (gen_images.to(\"cpu\").clone().detach() + 1) / 2\n        for ii, img in enumerate(gen_images):\n            save_image(gen_images[ii, :, :, :], os.path.join('../output_images', f'image_{i_batch + ii:05d}.png'))\n            \n    import shutil\n    shutil.make_archive('images', 'zip', '../output_images')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"good_breeds = analyse_generated_by_class(6)\ncreate_submit(good_breeds)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\n# if not os.path.exists('../output_images'):\n#     os.mkdir('../output_images')\n# im_batch_size = 50\n# n_images=10000\n# for i_batch in range(0, n_images, im_batch_size):\n# #     z = truncated_normal((im_batch_size, args.latent_dim, 1, 1), threshold=1)\n# #     gen_z = torch.from_numpy(z).float().to(device)\n#     gen_z = torch.randn(im_batch_size, args.latent_dim, 1, 1, device=device)\n#     gen_images = (netG(gen_z)+1.)/2. # denormalize\n#     images = gen_images.to(\"cpu\").clone().detach()\n#     images = images.numpy().transpose(0, 2, 3, 1)\n#     for i_image in range(gen_images.size(0)):\n#         save_image(gen_images[i_image, :, :, :], os.path.join('../output_images', f'image_{i_batch+i_image:05d}.png'))\n\n\n# import shutil\n# shutil.make_archive('images', 'zip', '../output_images')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#####################\n### Eval Code\n#####################\n\nimport numpy as np\nimport os\nimport gzip, pickle\nimport tensorflow as tf\nfrom scipy import linalg\nimport pathlib\nimport urllib\nimport warnings\n# from tqdm import tqdm\nfrom PIL import Image\n\nclass KernelEvalException(Exception):\n    pass\n\nmodel_params = {\n    'Inception': {\n        'name': 'Inception', \n        'imsize': 64,\n        'output_layer': 'Pretrained_Net/pool_3:0', \n        'input_layer': 'Pretrained_Net/ExpandDims:0',\n        'output_shape': 2048,\n        'cosine_distance_eps': 0.1\n        }\n}\n\ndef create_model_graph(pth):\n    \"\"\"Creates a graph from saved GraphDef file.\"\"\"\n    # Creates graph from saved graph_def.pb.\n    with tf.gfile.FastGFile( pth, 'rb') as f:\n        graph_def = tf.GraphDef()\n        graph_def.ParseFromString( f.read())\n        _ = tf.import_graph_def( graph_def, name='Pretrained_Net')\n\ndef _get_model_layer(sess, model_name):\n    # layername = 'Pretrained_Net/final_layer/Mean:0'\n    layername = model_params[model_name]['output_layer']\n    layer = sess.graph.get_tensor_by_name(layername)\n    ops = layer.graph.get_operations()\n    for op_idx, op in enumerate(ops):\n        for o in op.outputs:\n            shape = o.get_shape()\n            if shape._dims != []:\n              shape = [s.value for s in shape]\n              new_shape = []\n              for j, s in enumerate(shape):\n                if s == 1 and j == 0:\n                  new_shape.append(None)\n                else:\n                  new_shape.append(s)\n              o.__dict__['_shape_val'] = tf.TensorShape(new_shape)\n    return layer\n\ndef get_activations(images, sess, model_name, batch_size=50, verbose=False):\n    \"\"\"Calculates the activations of the pool_3 layer for all images.\n\n    Params:\n    -- images      : Numpy array of dimension (n_images, hi, wi, 3). The values\n                     must lie between 0 and 256.\n    -- sess        : current session\n    -- batch_size  : the images numpy array is split into batches with batch size\n                     batch_size. A reasonable batch size depends on the disposable hardware.\n    -- verbose    : If set to True and parameter out_step is given, the number of calculated\n                     batches is reported.\n    Returns:\n    -- A numpy array of dimension (num images, 2048) that contains the\n       activations of the given tensor when feeding inception with the query tensor.\n    \"\"\"\n\n    inception_layer = _get_model_layer(sess, model_name)\n    n_images = images.shape[0]\n    if batch_size > n_images:\n        print(\"warning: batch size is bigger than the data size. setting batch size to data size\")\n        batch_size = n_images\n    n_batches = n_images//batch_size + 1\n    pred_arr = np.empty((n_images,model_params[model_name]['output_shape']))\n    for i in tqdm(range(n_batches)):\n        if verbose:\n            print(\"\\rPropagating batch %d/%d\" % (i+1, n_batches), end=\"\", flush=True)\n        start = i*batch_size\n        if start+batch_size < n_images:\n            end = start+batch_size\n        else:\n            end = n_images\n                    \n        batch = images[start:end]\n        pred = sess.run(inception_layer, {model_params[model_name]['input_layer']: batch})\n        pred_arr[start:end] = pred.reshape(-1,model_params[model_name]['output_shape'])\n    if verbose:\n        print(\" done\")\n    return pred_arr\n\n\n# def calculate_memorization_distance(features1, features2):\n#     neigh = NearestNeighbors(n_neighbors=1, algorithm='kd_tree', metric='euclidean')\n#     neigh.fit(features2) \n#     d, _ = neigh.kneighbors(features1, return_distance=True)\n#     print('d.shape=',d.shape)\n#     return np.mean(d)\n\ndef normalize_rows(x: np.ndarray):\n    \"\"\"\n    function that normalizes each row of the matrix x to have unit length.\n\n    Args:\n     ``x``: A numpy matrix of shape (n, m)\n\n    Returns:\n     ``x``: The normalized (by row) numpy matrix.\n    \"\"\"\n    return np.nan_to_num(x/np.linalg.norm(x, ord=2, axis=1, keepdims=True))\n\n\ndef cosine_distance(features1, features2):\n    # print('rows of zeros in features1 = ',sum(np.sum(features1, axis=1) == 0))\n    # print('rows of zeros in features2 = ',sum(np.sum(features2, axis=1) == 0))\n    features1_nozero = features1[np.sum(features1, axis=1) != 0]\n    features2_nozero = features2[np.sum(features2, axis=1) != 0]\n    norm_f1 = normalize_rows(features1_nozero)\n    norm_f2 = normalize_rows(features2_nozero)\n\n    d = 1.0-np.abs(np.matmul(norm_f1, norm_f2.T))\n    print('d.shape=',d.shape)\n    print('np.min(d, axis=1).shape=',np.min(d, axis=1).shape)\n    mean_min_d = np.mean(np.min(d, axis=1))\n    print('distance=',mean_min_d)\n    return mean_min_d\n\n\ndef distance_thresholding(d, eps):\n    if d < eps:\n        return d\n    else:\n        return 1\n\ndef calculate_frechet_distance(mu1, sigma1, mu2, sigma2, eps=1e-6):\n    \"\"\"Numpy implementation of the Frechet Distance.\n    The Frechet distance between two multivariate Gaussians X_1 ~ N(mu_1, C_1)\n    and X_2 ~ N(mu_2, C_2) is\n            d^2 = ||mu_1 - mu_2||^2 + Tr(C_1 + C_2 - 2*sqrt(C_1*C_2)).\n            \n    Stable version by Dougal J. Sutherland.\n\n    Params:\n    -- mu1 : Numpy array containing the activations of the pool_3 layer of the\n             inception net ( like returned by the function 'get_predictions')\n             for generated samples.\n    -- mu2   : The sample mean over activations of the pool_3 layer, precalcualted\n               on an representive data set.\n    -- sigma1: The covariance matrix over activations of the pool_3 layer for\n               generated samples.\n    -- sigma2: The covariance matrix over activations of the pool_3 layer,\n               precalcualted on an representive data set.\n\n    Returns:\n    --   : The Frechet Distance.\n    \"\"\"\n\n    mu1 = np.atleast_1d(mu1)\n    mu2 = np.atleast_1d(mu2)\n\n    sigma1 = np.atleast_2d(sigma1)\n    sigma2 = np.atleast_2d(sigma2)\n\n    assert mu1.shape == mu2.shape, \"Training and test mean vectors have different lengths\"\n    assert sigma1.shape == sigma2.shape, \"Training and test covariances have different dimensions\"\n\n    diff = mu1 - mu2\n\n    # product might be almost singular\n    covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False)\n    if not np.isfinite(covmean).all():\n        msg = \"fid calculation produces singular product; adding %s to diagonal of cov estimates\" % eps\n        warnings.warn(msg)\n        offset = np.eye(sigma1.shape[0]) * eps\n        # covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset))\n        covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset))\n    \n    # numerical error might give slight imaginary component\n    if np.iscomplexobj(covmean):\n        if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3):\n            m = np.max(np.abs(covmean.imag))\n            raise ValueError(\"Imaginary component {}\".format(m))\n        covmean = covmean.real\n\n    # covmean = tf.linalg.sqrtm(tf.linalg.matmul(sigma1,sigma2))\n\n    print('covmean.shape=',covmean.shape)\n    # tr_covmean = tf.linalg.trace(covmean)\n\n    tr_covmean = np.trace(covmean)\n    return diff.dot(diff) + np.trace(sigma1) + np.trace(sigma2) - 2 * tr_covmean\n    # return diff.dot(diff) + tf.linalg.trace(sigma1) + tf.linalg.trace(sigma2) - 2 * tr_covmean\n#-------------------------------------------------------------------------------\n\n\ndef calculate_activation_statistics(images, sess, model_name, batch_size=50, verbose=False):\n    \"\"\"Calculation of the statistics used by the FID.\n    Params:\n    -- images      : Numpy array of dimension (n_images, hi, wi, 3). The values\n                     must lie between 0 and 255.\n    -- sess        : current session\n    -- batch_size  : the images numpy array is split into batches with batch size\n                     batch_size. A reasonable batch size depends on the available hardware.\n    -- verbose     : If set to True and parameter out_step is given, the number of calculated\n                     batches is reported.\n    Returns:\n    -- mu    : The mean over samples of the activations of the pool_3 layer of\n               the incption model.\n    -- sigma : The covariance matrix of the activations of the pool_3 layer of\n               the incption model.\n    \"\"\"\n    act = get_activations(images, sess, model_name, batch_size, verbose)\n    mu = np.mean(act, axis=0)\n    sigma = np.cov(act, rowvar=False)\n    return mu, sigma, act\n    \ndef _handle_path_memorization(path, sess, model_name, is_checksize, is_check_png):\n    path = pathlib.Path(path)\n    files = list(path.glob('*.jpg')) + list(path.glob('*.png'))\n    imsize = model_params[model_name]['imsize']\n\n    # In production we don't resize input images. This is just for demo purpose. \n    x = np.array([np.array(img_read_checks(fn, imsize, is_checksize, imsize, is_check_png)) for fn in files])\n    m, s, features = calculate_activation_statistics(x, sess, model_name)\n    del x #clean up memory\n    return m, s, features\n\n# check for image size\ndef img_read_checks(filename, resize_to, is_checksize=False, check_imsize = 64, is_check_png = False):\n    im = Image.open(str(filename))\n    if is_checksize and im.size != (check_imsize,check_imsize):\n        raise KernelEvalException('The images are not of size '+str(check_imsize))\n    \n    if is_check_png and im.format != 'PNG':\n        raise KernelEvalException('Only PNG images should be submitted.')\n\n    if resize_to is None:\n        return im\n    else:\n        return im.resize((resize_to,resize_to),Image.ANTIALIAS)\n\ndef calculate_kid_given_paths(paths, model_name, model_path, feature_path=None, mm=[], ss=[], ff=[]):\n    ''' Calculates the KID of two paths. '''\n    tf.reset_default_graph()\n    create_model_graph(str(model_path))\n    with tf.Session() as sess:\n        sess.run(tf.global_variables_initializer())\n        m1, s1, features1 = _handle_path_memorization(paths[0], sess, model_name, is_checksize = True, is_check_png = True)\n        if len(mm) != 0:\n            m2 = mm\n            s2 = ss\n            features2 = ff\n        elif feature_path is None:\n            m2, s2, features2 = _handle_path_memorization(paths[1], sess, model_name, is_checksize = False, is_check_png = False)\n        else:\n            with np.load(feature_path) as f:\n                m2, s2, features2 = f['m'], f['s'], f['features']\n\n        print('m1,m2 shape=',(m1.shape,m2.shape),'s1,s2=',(s1.shape,s2.shape))\n        print('starting calculating FID')\n        fid_value = calculate_frechet_distance(m1, s1, m2, s2)\n        print('done with FID, starting distance calculation')\n        distance = cosine_distance(features1, features2)        \n        return fid_value, distance, m2, s2, features2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if COMPUTE_LB:\n    # UNCOMPRESS OUR IMGAES\n    shutil.unpack_archive('images.zip', extract_dir='../tmp/images2')\n\n    # COMPUTE LB SCORE\n    m2 = []; s2 =[]; f2 = []\n    user_images_unzipped_path = '../tmp/images2/'\n    images_path = [user_images_unzipped_path,'../input/generative-dog-images/all-dogs/all-dogs/']\n    public_path = '../input/dog-face-generation-competition-kid-metric-input/classify_image_graph_def.pb'\n\n    fid_epsilon = 10e-15\n\n    fid_value_public, distance_public, m2, s2, f2 = calculate_kid_given_paths(images_path, 'Inception', public_path, mm=m2, ss=s2, ff=f2)\n    distance_public = distance_thresholding(distance_public, model_params['Inception']['cosine_distance_eps'])\n    print(\"FID_public: \", fid_value_public, \"distance_public: \", distance_public, \"multiplied_public: \",\n            fid_value_public /(distance_public + fid_epsilon))\n    \n    # REMOVE FILES TO PREVENT KERNEL ERROR OF TOO MANY FILES\n    ! rm -r ../tmp","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f\"Done in {(time.time() - starttime)/60:.4f} minutes.\")","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}