{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":15062,"databundleVersionId":545987,"sourceType":"competition"}],"dockerImageVersionId":31154,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os, zipfile, glob, random\nimport numpy as np\nfrom PIL import Image\nimport xml.etree.ElementTree as ET\nimport matplotlib.pyplot as plt\n\n# --- User settings (keep your flags) ---\nComputeLB = False\nDogsOnly = False\n\n# --- base root depending on context (Kaggle vs local) ---\nif ComputeLB:\n    ROOT = '/kaggle/input/generative-dog-images'\nelse:\n    ROOT = '/kaggle/input/generative-dog-images/'\n\nprint(\"Initial ROOT:\", ROOT)\n\n# --- helper: try to find an images folder ---\ndef find_images_dir(root):\n    # Common possibilities\n    candidates = [\n        os.path.join(root, 'all-dogs', 'all-dogs'),\n        os.path.join(root, 'all-dogs'),\n        os.path.join(root, 'all_dogs'),\n        root\n    ]\n    # Also search recursively for a folder with many .jpg files\n    for c in candidates:\n        if os.path.isdir(c):\n            jpgs = glob.glob(os.path.join(c, '*.jpg'))\n            if len(jpgs) > 50:\n                return c\n    # fallback: walk to find dir with many jpgs\n    for dirpath, dirnames, filenames in os.walk(root):\n        jpgs = [f for f in filenames if f.lower().endswith('.jpg')]\n        if len(jpgs) > 50:\n            return dirpath\n    return None\n\n# --- look for zipped dataset and extract if necessary ---\nall_dogs_zip_candidates = [\n    os.path.join(ROOT, 'all-dogs.zip'),\n    os.path.join(ROOT, 'All-Dogs.zip'),\n    os.path.join(ROOT, 'all-dogs_all-dogs.zip')\n]\nfor zpath in all_dogs_zip_candidates:\n    if os.path.isfile(zpath):\n        print(\"Found zip at:\", zpath, \" -> extracting to /tmp/all-dogs_extracted\")\n        extract_to = '/tmp/all-dogs_extracted'\n        os.makedirs(extract_to, exist_ok=True)\n        with zipfile.ZipFile(zpath, 'r') as z:\n            z.extractall(extract_to)\n        # reset ROOT to extracted folder for scanning\n        ROOT = extract_to + '/'\n        break\n\nIMG_DIR = find_images_dir(ROOT)\nif IMG_DIR is None:\n    raise FileNotFoundError(f\"Could not find images folder under {ROOT}. Try checking file tree or adjust ROOT.\")\nprint(\"Using image directory:\", IMG_DIR)\n\n# --- annotation directory (if DogsOnly) ---\nANN_DIR = None\nif DogsOnly:\n    # possible annotation path\n    cand = os.path.join(ROOT, 'annotation', 'Annotation')\n    if os.path.isdir(cand):\n        ANN_DIR = cand\n    else:\n        # try to find folder named 'Annotation' recursively\n        for dirpath, dirnames, filenames in os.walk(ROOT):\n            if 'Annotation' in dirnames:\n                ANN_DIR = os.path.join(dirpath, 'Annotation')\n                break\n    if ANN_DIR is None:\n        raise FileNotFoundError(f\"Could not find annotation folder under {ROOT}. Needed for DogsOnly=True.\")\n\nprint(\"Annotation directory:\", ANN_DIR)\n\n# --- gather image file list ---\nIMAGES = sorted(glob.glob(os.path.join(IMG_DIR, '*.jpg')))\nn_total = len(IMAGES)\nprint(\"Found\", n_total, \"jpg images.\")\n\n# --- parameters ---\nMAX_IMAGES = 10000  # you used 10000; change as needed\nsel_count = min(MAX_IMAGES, n_total)\nprint(\"Selecting\", sel_count, \"images.\")\n\n# choose a random subset like your original code\nrandom.seed(810)\nindices = random.sample(range(n_total), sel_count)\n\n# --- processing ---\nimages_list = []\nnames_list = []\n\nfor idx, i in enumerate(indices):\n    image_path = IMAGES[i]\n    try:\n        img = Image.open(image_path).convert('RGB')\n    except Exception as e:\n        print(\"skip (open error):\", image_path, e)\n        continue\n\n    if DogsOnly:\n        # expect annotation file path based on filename without extension\n        fname = os.path.splitext(os.path.basename(image_path))[0]\n        # search for annotation file - could be in breed subfolders\n        ann_file = None\n        for root_dir, dirs, files in os.walk(ANN_DIR):\n            # many annotation files end with the same base name (no extension)\n            if fname in files:\n                ann_file = os.path.join(root_dir, fname)\n                break\n        if ann_file is None:\n            # skip images without annotation\n            continue\n        try:\n            tree = ET.parse(ann_file)\n            r = tree.getroot()\n            objects = r.findall('object')\n            for o in objects:\n                bndbox = o.find('bndbox')\n                xmin = int(float(bndbox.find('xmin').text))\n                ymin = int(float(bndbox.find('ymin').text))\n                xmax = int(float(bndbox.find('xmax').text))\n                ymax = int(float(bndbox.find('ymax').text))\n                w = min((xmax - xmin, ymax - ymin))\n                img2 = img.crop((xmin, ymin, xmin + w, ymin + w))\n                img2 = img2.resize((64, 64), Image.LANCZOS)\n                images_list.append(np.asarray(img2, dtype=np.uint8))\n                # breed could be derived from ann file path (parent folder)\n                breed = os.path.basename(os.path.dirname(ann_file))\n                names_list.append(breed)\n        except Exception as e:\n            print(\"skip (annotation parse error):\", ann_file, e)\n            continue\n    else:\n        # random crop/resizing logic similar to your original\n        w, h = img.size\n        if (idx % 2 == 0) or (idx % 3 == 0):\n            w2 = 100\n            h2 = int(h / (w / 100)) if w != 0 else h\n            a = 18; b = 0\n        else:\n            a = 0; b = 0\n            if w < h:\n                w2 = 64\n                h2 = int((64 / w) * h) if w != 0 else h\n                b = (h2 - 64) // 2\n            else:\n                h2 = 64\n                w2 = int((64 / h) * w) if h != 0 else w\n                a = (w2 - 64) // 2\n        try:\n            img2 = img.resize((w2, h2), Image.LANCZOS)\n            img2 = img2.crop((0 + a, 0 + b, 64 + a, 64 + b))\n            images_list.append(np.asarray(img2, dtype=np.uint8))\n            names_list.append(os.path.basename(image_path))\n        except Exception as e:\n            print(\"skip (resize/crop error):\", image_path, e)\n            continue\n\nprint(\"Collected\", len(images_list), \"processed images.\")\n\n# convert to numpy array\nif len(images_list) == 0:\n    raise RuntimeError(\"No processed images collected. Check DogsOnly flag and annotation availability.\")\nimagesIn = np.stack(images_list, axis=0)  # shape (N,64,64,3)\nnamesIn = np.array(names_list)\n\n# --- display random samples ---\nimport matplotlib.pyplot as plt\nrnd = np.random.randint(0, len(imagesIn), size=min(25, len(imagesIn)))\nfor k in range(5):\n    plt.figure(figsize=(15,3))\n    for j in range(5):\n        idx_plot = rnd[k*5 + j] if (k*5 + j) < len(rnd) else rnd[0]\n        plt.subplot(1,5,j+1)\n        plt.axis('off')\n        if not DogsOnly:\n            plt.title(namesIn[idx_plot], fontsize=9)\n        else:\n            # if breed names have format 'n02085620-Chihuahua' this keeps after '-'\n            nm = namesIn[idx_plot]\n            if '-' in nm:\n                try:\n                    plt.title(nm.split('-')[1], fontsize=9)\n                except:\n                    plt.title(nm, fontsize=9)\n            else:\n                plt.title(nm, fontsize=9)\n        plt.imshow(imagesIn[idx_plot])\n    plt.show()\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:18:38.655627Z","iopub.execute_input":"2025-11-06T11:18:38.655910Z","iopub.status.idle":"2025-11-06T11:19:31.292115Z","shell.execute_reply.started":"2025-11-06T11:18:38.655875Z","shell.execute_reply":"2025-11-06T11:19:31.291363Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import gzip, pickle\nimport os\nimport numpy as np\nimport pandas as pd\nimport random\nimport shutil\nimport numpy as np\nimport os\n\nimport torch\nfrom torch import nn, optim\nimport torch.nn.functional as F\nfrom torchvision import datasets, transforms\nfrom torchvision.utils import save_image\nfrom torch.utils.data import Dataset, DataLoader\n\n\nfrom scipy import linalg\nimport pathlib\nimport urllib\nimport warnings\nfrom PIL import Image\nfrom tqdm import tqdm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:21:33.121066Z","iopub.execute_input":"2025-11-06T11:21:33.121872Z","iopub.status.idle":"2025-11-06T11:21:40.446797Z","shell.execute_reply.started":"2025-11-06T11:21:33.121840Z","shell.execute_reply":"2025-11-06T11:21:40.446182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class dog_dataset(Dataset):\n    def __init__(self, train_y, train_X, zeros, device):\n        self.train_y = torch.Tensor(train_y).to(device)\n        self.train_X = torch.Tensor(train_X).to(device)\n        self.zeros = torch.Tensor(zeros).to(device)\n        \n    def __len__(self):\n        return len(train_y)\n\n    def __getitem__(self, idx):\n        return self.train_y[idx], self.train_X[idx], self.zeros[idx]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:22:06.843905Z","iopub.execute_input":"2025-11-06T11:22:06.844621Z","iopub.status.idle":"2025-11-06T11:22:06.849128Z","shell.execute_reply.started":"2025-11-06T11:22:06.844597Z","shell.execute_reply":"2025-11-06T11:22:06.848364Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nbs = 256\n\ntrain_y = (imagesIn[:10000,:,:,:]/255.).reshape((-1,12288))\ntrain_X = np.zeros((10000,10000))\nfor i in range(10000): train_X[i,i] = 1\nzeros = np.zeros((10000,12288))\n\ndata_set = dog_dataset(train_y, train_X, zeros, device)    \ndata_loader = DataLoader(data_set, bs)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:22:09.535661Z","iopub.execute_input":"2025-11-06T11:22:09.535982Z","iopub.status.idle":"2025-11-06T11:22:11.551467Z","shell.execute_reply.started":"2025-11-06T11:22:09.535963Z","shell.execute_reply":"2025-11-06T11:22:11.550843Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Sanity check\nprint(train_y.shape, train_X.shape, zeros.shape)\nprint(train_y[0].shape, train_X[0].shape, zeros[0].shape)\nprint(len(train_y), len(train_X), len(zeros))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:22:14.233797Z","iopub.execute_input":"2025-11-06T11:22:14.234415Z","iopub.status.idle":"2025-11-06T11:22:14.238614Z","shell.execute_reply.started":"2025-11-06T11:22:14.234393Z","shell.execute_reply":"2025-11-06T11:22:14.237840Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Discriminator","metadata":{}},{"cell_type":"code","source":"class Discriminator(nn.Module):\n\n    def __init__(self):\n        super(Discriminator, self).__init__()\n        self.fc1 = nn.Linear(10000, 12288)\n        self.conv1 = nn.Conv2d(1, 1, (2, 1), bias=False)\n        \n    def forward(self, imgs, imgnames):\n        x = self.fc1(imgnames)\n        x = torch.sigmoid(x)\n        x = torch.cat((imgs, x), dim=1).view(-1, 1, 2, 12288)\n        x = self.conv1(x)\n        return x.view(-1, 12288)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:22:16.935114Z","iopub.execute_input":"2025-11-06T11:22:16.935750Z","iopub.status.idle":"2025-11-06T11:22:16.941037Z","shell.execute_reply.started":"2025-11-06T11:22:16.935723Z","shell.execute_reply":"2025-11-06T11:22:16.940252Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train discriminator\nWe are training the discriminator ahead of generator here. It can be done together with the generator but I am imitating what Chris did.","metadata":{}},{"cell_type":"code","source":"lr = 0.001\nepochs = 500\n\nnetD = Discriminator().to(device)\noptimizerD = optim.Adam(netD.parameters(), lr=lr)\ncriteria = nn.BCELoss()\nnetD.conv1.weight = nn.Parameter(torch.Tensor([[[[ -1.0],\n                                    [1.0]]]]).to(device))    \nfor param in netD.conv1.parameters():\n    param.requires_grad = False ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:22:20.103590Z","iopub.execute_input":"2025-11-06T11:22:20.104087Z","iopub.status.idle":"2025-11-06T11:22:21.284915Z","shell.execute_reply.started":"2025-11-06T11:22:20.104064Z","shell.execute_reply":"2025-11-06T11:22:21.284282Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# TRAIN DISCRIMINATOR NETWORK\nfor k in tqdm(range(epochs)):\n    for i, (y, X, Zeros) in enumerate(data_loader):\n        netD.zero_grad()\n        y_pred = netD(Zeros, X)\n        loss = criteria(y_pred, y)\n        loss.backward()\n        optimizerD.step()\n    if (k + 1) % 5 == 0:    \n        print(f\"Epoch: {k+1}/{epochs} | Loss: {loss}\")   ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:22:24.863627Z","iopub.execute_input":"2025-11-06T11:22:24.864205Z","iopub.status.idle":"2025-11-06T11:43:35.695711Z","shell.execute_reply.started":"2025-11-06T11:22:24.864182Z","shell.execute_reply":"2025-11-06T11:43:35.695033Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Discriminator recall from memory","metadata":{}},{"cell_type":"code","source":"for k in range(5):\n    plt.figure(figsize=(15,3))\n    for j in range(5):\n        xx = torch.Tensor(np.zeros((10000))).to(device)\n        xx[np.random.randint(10000)] = 1\n        plt.subplot(1,5,j+1)\n#         img = netD([zeros[0,:].reshape((-1,12288)),xx.reshape((-1,10000))]).reshape((-1,64,64,3))\n        img = netD(torch.Tensor(zeros[0,:]).to(device).reshape((-1,12288)),xx.reshape((-1,10000))).reshape((-1,64,64,3))\n        img = img.detach().cpu().numpy()\n        img = Image.fromarray((255 * img).astype('uint8').reshape((64,64,3)))\n        plt.imshow(img)\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:43:35.696841Z","iopub.execute_input":"2025-11-06T11:43:35.697064Z","iopub.status.idle":"2025-11-06T11:43:38.321412Z","shell.execute_reply.started":"2025-11-06T11:43:35.697047Z","shell.execute_reply":"2025-11-06T11:43:38.320653Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Generator","metadata":{}},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self):\n        super(Generator, self).__init__()\n        self.fc1 = nn.Linear(10000, 12288)\n        \n    def forward(self, imgnames):\n        x = self.fc1(imgnames)\n        return x, imgnames.view(-1, 10000)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:43:54.656839Z","iopub.execute_input":"2025-11-06T11:43:54.657219Z","iopub.status.idle":"2025-11-06T11:43:54.662029Z","shell.execute_reply.started":"2025-11-06T11:43:54.657194Z","shell.execute_reply":"2025-11-06T11:43:54.661257Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_image():\n    plt.figure(figsize=(15,3))\n    for j in range(5):\n        with torch.no_grad():\n            xx = np.zeros((10000))\n            xx[np.random.randint(10000)] = 1\n            plt.subplot(1,5,j+1)\n            inp = torch.Tensor(xx.reshape((-1,10000))).to(device)\n            img = netG(inp)[0].reshape((-1,64,64,3)).to(\"cpu\").clone().detach().numpy()\n            img = Image.fromarray( (img).astype('uint8').reshape((64,64,3)))\n            plt.axis('off')\n            plt.imshow(img)\n    plt.show()  \n    \ndef show_d_images(imgs, title):\n    with torch.no_grad():\n        imgs = imgs.reshape((-1,64,64,3))\n        plt.figure(figsize=(15,3))\n        for j in range(5):\n            plt.subplot(1,5,j+1)\n            img = imgs[j].detach().cpu().numpy()\n            img = Image.fromarray((255*img).astype('uint8').reshape((64,64,3)))\n            plt.title(title)\n            plt.imshow(img)\n        plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:43:57.695186Z","iopub.execute_input":"2025-11-06T11:43:57.695937Z","iopub.status.idle":"2025-11-06T11:43:57.703263Z","shell.execute_reply.started":"2025-11-06T11:43:57.695910Z","shell.execute_reply":"2025-11-06T11:43:57.702509Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lr = 0.01\nbeta1 = 0.5\nnetG = Generator().to(device)\noptimizerG = optim.Adam(netG.parameters(), lr=lr)\ncriterion = nn.MSELoss()\n\nnetD.conv1.weight = nn.Parameter(torch.Tensor([[[[ -1.],\n                                    [1.]]]]).to(device))\n\n# Discriminator is already trained\nfor param in netD.parameters():\n    param.requires_grad = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:44:00.620984Z","iopub.execute_input":"2025-11-06T11:44:00.621580Z","iopub.status.idle":"2025-11-06T11:44:01.797446Z","shell.execute_reply.started":"2025-11-06T11:44:00.621555Z","shell.execute_reply":"2025-11-06T11:44:01.796749Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 70\nfor epoch in tqdm(range(epochs)):\n    for i, (y, X, Zeros) in enumerate(data_loader):\n        ############################|\n        # (2) Train only the Generator\n        ############################\n        netG.zero_grad()\n        fake, seed = netG(X)\n        y_pred = netD(Zeros, seed)\n        errG = criterion(fake, y_pred)\n        errG.backward()\n        optimizerG.step()\n    if (epoch+1) % 5 == 0:    \n        print(f\"Epoch: {epoch+1}: G_Loss: {errG}\")\n        show_d_images(fake, \"Generator output\")         ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:44:05.775077Z","iopub.execute_input":"2025-11-06T11:44:05.775734Z","iopub.status.idle":"2025-11-06T11:47:52.078834Z","shell.execute_reply.started":"2025-11-06T11:44:05.775701Z","shell.execute_reply":"2025-11-06T11:47:52.078048Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# DogGenerator class","metadata":{}},{"cell_type":"code","source":"class DogGenerator():\n    index = 0   \n    t = [\n        transforms.RandomCrop((48, 48), padding=None, pad_if_needed=True, fill=0, padding_mode='symmetric'),\n        transforms.Resize((64,64))\n    ]\n    tfms = transforms.Compose([\n                                transforms.RandomHorizontalFlip(p=0.5),\n#                                 transforms.RandomApply(t, p=0.5),\n                                transforms.ColorJitter(brightness=(1,1.3), contrast=(1,1.3), saturation=0, hue=0)\n                               ])\n    def getDog(self,seed):\n        xx = torch.Tensor(np.zeros((10000))).to(device)\n        xx[self.index] = 0.999999\n        xx[np.random.randint(10000)] = 0.000001\n        img = netG(xx.reshape((-1,10000)))[0].reshape((64,64,3)).detach().cpu().numpy() * 255\n        self.index = (self.index+1)%10000\n        return self.tfms(Image.fromarray( img.astype('uint8')))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:50:19.932546Z","iopub.execute_input":"2025-11-06T11:50:19.933310Z","iopub.status.idle":"2025-11-06T11:50:19.939384Z","shell.execute_reply.started":"2025-11-06T11:50:19.933286Z","shell.execute_reply":"2025-11-06T11:50:19.938662Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"d = DogGenerator()\nfor k in range(3):\n    plt.figure(figsize=(20,5))\n    for j in range(5):\n        plt.subplot(1,5,j+1)\n        img = d.getDog(seed = np.random.normal(0,1,100))\n        plt.axis('off')\n        plt.imshow(img)\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:50:23.062543Z","iopub.execute_input":"2025-11-06T11:50:23.062780Z","iopub.status.idle":"2025-11-06T11:50:23.497283Z","shell.execute_reply.started":"2025-11-06T11:50:23.062765Z","shell.execute_reply":"2025-11-06T11:50:23.496591Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Creat, zip and submit the images","metadata":{}},{"cell_type":"code","source":"z = zipfile.PyZipFile('images.zip', mode='w')\nd = DogGenerator()\nfor k in range(10000):\n    img = d.getDog(np.random.normal(0,1,100))\n    f = str(k)+'.png'\n    img.save(f,'PNG'); z.write(f); os.remove(f)\nz.close()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-06T11:50:31.956645Z","iopub.execute_input":"2025-11-06T11:50:31.957214Z","iopub.status.idle":"2025-11-06T11:51:07.628421Z","shell.execute_reply.started":"2025-11-06T11:50:31.957185Z","shell.execute_reply":"2025-11-06T11:51:07.627768Z"}},"outputs":[],"execution_count":null}]}