{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"},{"sourceId":242592,"sourceType":"datasetVersion","datasetId":102285},{"sourceId":10208512,"sourceType":"datasetVersion","datasetId":6309126}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\nprint(device)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:07:57.963938Z","iopub.execute_input":"2024-12-15T15:07:57.964193Z","iopub.status.idle":"2024-12-15T15:08:01.292600Z","shell.execute_reply.started":"2024-12-15T15:07:57.964156Z","shell.execute_reply":"2024-12-15T15:08:01.291695Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\n\nfrom torch.utils.data import DataLoader, TensorDataset\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:01.294120Z","iopub.execute_input":"2024-12-15T15:08:01.294482Z","iopub.status.idle":"2024-12-15T15:08:01.635500Z","shell.execute_reply.started":"2024-12-15T15:08:01.294454Z","shell.execute_reply":"2024-12-15T15:08:01.634580Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Loading the training data\ntrain = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:01.636743Z","iopub.execute_input":"2024-12-15T15:08:01.637141Z","iopub.status.idle":"2024-12-15T15:08:05.144701Z","shell.execute_reply.started":"2024-12-15T15:08:01.637113Z","shell.execute_reply":"2024-12-15T15:08:05.143905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data = train.drop(labels = ['label'], axis = 1)\ntrain_data = train_data.values.reshape(-1, 28, 28)\ntrain_data = train_data/255.0\n\n#To create some space\ndel train ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.146439Z","iopub.execute_input":"2024-12-15T15:08:05.146710Z","iopub.status.idle":"2024-12-15T15:08:05.333918Z","shell.execute_reply.started":"2024-12-15T15:08:05.146685Z","shell.execute_reply":"2024-12-15T15:08:05.333160Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Just checking if the data type is as expected\nprint(isinstance(train_data, np.ndarray))\n\n#Checking the sanity of the shape of the training data\nprint(train_data.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.334841Z","iopub.execute_input":"2024-12-15T15:08:05.335081Z","iopub.status.idle":"2024-12-15T15:08:05.339770Z","shell.execute_reply.started":"2024-12-15T15:08:05.335056Z","shell.execute_reply":"2024-12-15T15:08:05.338828Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(train_data[7], cmap = 'gray')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.340882Z","iopub.execute_input":"2024-12-15T15:08:05.341174Z","iopub.status.idle":"2024-12-15T15:08:05.539418Z","shell.execute_reply.started":"2024-12-15T15:08:05.341141Z","shell.execute_reply":"2024-12-15T15:08:05.538602Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Converting to torch tensor\ntrain_data = torch.Tensor(train_data)\n\n#Checking to confirm dtype as tensor\nprint(isinstance(train_data, torch.Tensor))\n\nrandom_seed = 1\nbatch_size = 32\ntrain_dl = DataLoader(train_data, batch_size, shuffle = True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.540615Z","iopub.execute_input":"2024-12-15T15:08:05.540955Z","iopub.status.idle":"2024-12-15T15:08:05.631395Z","shell.execute_reply.started":"2024-12-15T15:08:05.540916Z","shell.execute_reply":"2024-12-15T15:08:05.630408Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def random_noise_generator(batch_size, dim):\n    return torch.rand(batch_size, dim)*2 - 1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.632622Z","iopub.execute_input":"2024-12-15T15:08:05.632938Z","iopub.status.idle":"2024-12-15T15:08:05.637073Z","shell.execute_reply.started":"2024-12-15T15:08:05.632897Z","shell.execute_reply":"2024-12-15T15:08:05.636098Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Just checking the noise generator and plotting one of its outputs\na = random_noise_generator(64, 100)\nb = a[2]\nb = b.reshape(10, 10)\nb = b.numpy()\nplt.imshow(b, cmap = 'gray')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.638214Z","iopub.execute_input":"2024-12-15T15:08:05.638479Z","iopub.status.idle":"2024-12-15T15:08:05.895213Z","shell.execute_reply.started":"2024-12-15T15:08:05.638451Z","shell.execute_reply":"2024-12-15T15:08:05.894407Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Comment this if you want to run the Basic GAN instead of the DCGAN\n\nclass Discriminator(nn.Module):\n    \n    def __init__(self):\n        super().__init__()\n        self.conv0 = nn.Conv2d(1, 32, kernel_size = 3, stride = 2, padding = 1)\n        #self.conv0_bn = nn.BatchNorm2d(32)\n        self.conv0_drop = nn.Dropout2d(0.25)\n        self.conv1 = nn.Conv2d(32, 64, kernel_size = 3, stride = 1, padding = 1)\n        #self.conv1_bn = nn.BatchNorm2d(64)\n        self.conv1_drop = nn.Dropout2d(0.25)\n        self.conv2 = nn.Conv2d(64, 128, kernel_size = 3, stride = 1, padding = 1)\n        #self.conv2_bn = nn.BatchNorm2d(128)\n        self.conv2_drop = nn.Dropout2d(0.25)\n        self.conv3 = nn.Conv2d(128, 256, kernel_size = 3, stride = 2, padding = 1)\n        #self.conv3_bn = nn.BatchNorm2d(256)\n        self.conv3_drop = nn.Dropout2d(0.25)\n        self.fc = nn.Linear(12544, 1)\n    \n    def forward(self, x):\n        x = x.view(-1, 1, 28, 28)\n        x = F.leaky_relu(self.conv0(x), 0.2)\n        #x = self.conv0_bn(x)\n        x = self.conv0_drop(x)\n        x = F.leaky_relu(self.conv1(x), 0.2)\n        #x = self.conv1_bn(x)\n        x = self.conv1_drop(x)\n        x = F.leaky_relu(self.conv2(x), 0.2)\n        #x = self.conv2_bn(x)\n        x = self.conv2_drop(x)\n        x = F.leaky_relu(self.conv3(x), 0.2)\n        #x = self.conv3_bn(x)\n        x = self.conv3_drop(x)\n        x = x.view(-1, self.num_flat_features(x))\n        x = self.fc(x)\n        \n        return x\n    \n    def num_flat_features(self, x):\n        size = x.size()[1:]\n        num_features = 1\n        for s in size:\n            num_features *= s\n        \n        return num_features","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.898396Z","iopub.execute_input":"2024-12-15T15:08:05.898663Z","iopub.status.idle":"2024-12-15T15:08:05.906745Z","shell.execute_reply.started":"2024-12-15T15:08:05.898638Z","shell.execute_reply":"2024-12-15T15:08:05.905960Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Comment this if you want to run the Basic GAN instead of the DCGAN\n\nclass Generator(nn.Module):\n    \n    def __init__(self):\n        super().__init__()\n        self.fc = nn.Linear(100, 256*7*7)\n        self.trans_conv1 = nn.ConvTranspose2d(256, 128, kernel_size = 3, stride = 2, padding = 1, output_padding = 1)\n        #self.trans_conv1_bn = nn.BatchNorm2d(128)\n        self.trans_conv2 = nn.ConvTranspose2d(128, 64, kernel_size = 3, stride = 1, padding = 1)\n        #self.trans_conv2_bn = nn.BatchNorm2d(64)\n        self.trans_conv3 = nn.ConvTranspose2d(64, 32, kernel_size = 3, stride = 1, padding = 1)\n        #self.trans_conv3_bn = nn.BatchNorm2d(32)\n        self.trans_conv4 = nn.ConvTranspose2d(32, 1, kernel_size = 3, stride = 2, padding = 1, output_padding = 1)\n    \n    def forward(self, x):\n        x = self.fc(x)\n        x = x.view(-1, 256, 7, 7)\n        x = F.relu(self.trans_conv1(x))\n        #x = self.trans_conv1_bn(x)\n        x = F.relu(self.trans_conv2(x))\n        #x = self.trans_conv2_bn(x)\n        x = F.relu(self.trans_conv3(x))\n        #x = self.trans_conv3_bn(x)\n        x = self.trans_conv4(x)\n        x = torch.tanh(x)\n        \n        return x        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.907888Z","iopub.execute_input":"2024-12-15T15:08:05.908179Z","iopub.status.idle":"2024-12-15T15:08:05.917584Z","shell.execute_reply.started":"2024-12-15T15:08:05.908153Z","shell.execute_reply":"2024-12-15T15:08:05.916875Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Uncomment this if you want to run the Basic GAN instead of the DCGAN\n\"\"\"\n#Creating instances of models\nD = Discriminator(input_disc, hidden_disc, output_disc)\nG = Generator(input_gen, hidden_gen, output_gen)\n\"\"\"\n\n#Comment the following 2 lines if you want to run the Basic GAN instead of the DCGAN\nD = Discriminator()\nG = Generator()\n\n#Sanity check of the model instances\nprint(D)\nprint(G)\n\n#Passing to the GPU\nD = D.to(device)\nG = G.to(device)\n\nD = D.float()\nG = G.float()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:05.918584Z","iopub.execute_input":"2024-12-15T15:08:05.918832Z","iopub.status.idle":"2024-12-15T15:08:06.101996Z","shell.execute_reply.started":"2024-12-15T15:08:05.918808Z","shell.execute_reply":"2024-12-15T15:08:06.101139Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Loss = nn.BCEWithLogitsLoss()\ndef discriminator_real_loss(real_out):\n    real_label = torch.ones(real_out.size()[0], 1).to(device)\n    real_loss = Loss(real_out.squeeze(), real_label.squeeze())\n    return real_loss\n\ndef discriminator_fake_loss(fake_out):\n    fake_label = torch.zeros(fake_out.size()[0], 1).to(device)\n    fake_loss = Loss(fake_out.squeeze(), fake_label.squeeze())\n    return fake_loss\n\ndef discriminator_loss(real_out, fake_out):\n    real_loss = discriminator_real_loss(real_out)\n    fake_loss = discriminator_fake_loss(fake_out)\n    total_loss = (real_loss + fake_loss)\n    return total_loss","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:06.103260Z","iopub.execute_input":"2024-12-15T15:08:06.103688Z","iopub.status.idle":"2024-12-15T15:08:06.110045Z","shell.execute_reply.started":"2024-12-15T15:08:06.103647Z","shell.execute_reply":"2024-12-15T15:08:06.109191Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def generator_loss(gen_disc_out):\n    label = torch.ones(gen_disc_out.size()[0], 1).to(device)\n    gen_loss = Loss(gen_disc_out.squeeze(), label.squeeze())\n    return gen_loss","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:06.111258Z","iopub.execute_input":"2024-12-15T15:08:06.111644Z","iopub.status.idle":"2024-12-15T15:08:06.124304Z","shell.execute_reply.started":"2024-12-15T15:08:06.111617Z","shell.execute_reply":"2024-12-15T15:08:06.123651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Important: If using Basic GAN instead of DCGAN, go for standard values lr = 0.001 and betas = (0.9, 0.999) \n\ndisc_opt = optim.Adam(D.parameters(), lr = 0.0002, betas = (0.5, 0.999))\ngen_opt = optim.Adam(G.parameters(), lr = 0.0002, betas = (0.5, 0.999))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:06.125397Z","iopub.execute_input":"2024-12-15T15:08:06.125750Z","iopub.status.idle":"2024-12-15T15:08:06.972840Z","shell.execute_reply.started":"2024-12-15T15:08:06.125712Z","shell.execute_reply":"2024-12-15T15:08:06.972107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train(D, G, disc_opt, gen_opt, train_dl, batch_size = 32, epochs = 25, gen_input_size = 100):\n    \n    disc_losses = []\n    gen_losses = []\n    \n    #Having a fixed sample to monitor the progress of the generator\n    sample_size = 16\n    fixed_samples = random_noise_generator(sample_size, gen_input_size)\n    fixed_samples = fixed_samples.to(device)\n    \n    #Going into training mode\n    D.train()\n    G.train()\n    \n    for epoch in range(epochs + 1):\n        \n        disc_loss_total = 0\n        gen_loss_total = 0\n        gen_out = 0\n        \n        for train_x in train_dl:\n            \n            #Discriminator training\n            disc_opt.zero_grad()\n            \n            train_x = train_x*2 - 1          #Converting the real images to have values between -1 and 1\n            train_x = train_x.to(device)     #Passing to GPU\n            real_out = D(train_x.float())    \n            \n            disc_gen_in = random_noise_generator(batch_size, gen_input_size)\n            disc_gen_in = disc_gen_in.to(device)   #Passing to GPU\n            \n            disc_gen_out = G(disc_gen_in.float()).detach()  #Detaching to avoid training the generator\n            fake_out = D(disc_gen_out.float())\n            \n            disc_loss = discriminator_loss(real_out, fake_out)  #Loss calculation\n            disc_loss_total += disc_loss\n            disc_loss.backward()\n            disc_opt.step()  \n        \n            #Generator training\n            gen_opt.zero_grad()\n            \n            \n            gen_out = G(disc_gen_in.float())     #Feeding noise into the generator\n            gen_disc_out = D(gen_out.float())       #Passing into the discrminator\n            \n            gen_loss = generator_loss(gen_disc_out)  #Generator loss calculation\n            gen_loss_total += gen_loss\n            gen_loss.backward()\n            gen_opt.step()\n        \n        disc_losses.append(disc_loss_total)\n        gen_losses.append(gen_loss_total)\n        \n        #Plotting samples every 5 epochs\n        if epoch%5 == 0:\n            G.eval()                    #Going into eval mode to get sample images         \n            samples = G(fixed_samples.float())\n            G.train()                   #Going back into train mode\n            \n            fig, axes = plt.subplots(figsize=(7,7), nrows=4, ncols=4, sharey=True, sharex=True)\n            for ax, img in zip(axes.flatten(), samples):\n               img = img.cpu().detach()\n               ax.xaxis.set_visible(False)\n               ax.yaxis.set_visible(False)\n               im = ax.imshow(img.reshape((28,28)), cmap='Greys_r')\n        \n        \n        #Printing losses every epoch\n        print(\"Epoch \", epoch, \": Discriminator Loss = \", disc_loss_total/len(train_dl), \", Generator Loss = \", gen_loss_total/len(train_dl))    \n    \n    return disc_losses, gen_losses","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:06.974203Z","iopub.execute_input":"2024-12-15T15:08:06.974625Z","iopub.status.idle":"2024-12-15T15:08:06.984152Z","shell.execute_reply.started":"2024-12-15T15:08:06.974595Z","shell.execute_reply":"2024-12-15T15:08:06.983264Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"disc_losses, gen_losses = train(D, G, disc_opt, gen_opt, train_dl, batch_size)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T15:08:06.985627Z","iopub.execute_input":"2024-12-15T15:08:06.986001Z","iopub.status.idle":"2024-12-15T15:14:43.597485Z","shell.execute_reply.started":"2024-12-15T15:08:06.985961Z","shell.execute_reply":"2024-12-15T15:14:43.596609Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nimport torch\nfrom torchvision import transforms\nimport matplotlib.pyplot as plt\n\n# Define transformation for resizing and normalization\ntransform = transforms.Compose([\n    transforms.Grayscale(num_output_channels=1),  # Ensure image is single-channel\n    transforms.Resize((28, 28)),                 # Resize to match DCGAN input size\n    transforms.ToTensor(),                       # Convert to tensor\n    transforms.Normalize((0.5,), (0.5,))         # Normalize to [-1, 1] (tanh range)\n])\n\n# Function to classify an image as real or fake using the trained DCGAN discriminator\ndef classify_image(image_path, discriminator, transform):\n    # Open the image\n    img = Image.open(image_path).convert(\"RGB\")\n    \n    # Preprocess the image\n    img_tensor = transform(img).unsqueeze(0).to(device)  # Add batch dimension\n\n    # Display the resized image\n    plt.imshow(img_tensor.squeeze(0).squeeze(0).cpu().numpy(), cmap=\"gray\")\n    plt.title(\"Input Image (Resized to 28x28)\")\n    plt.axis(\"off\")\n    plt.show()\n\n    # Classify using the discriminator\n    with torch.no_grad():\n        output = torch.sigmoid(discriminator(img_tensor))  # Apply sigmoid for binary classification\n        classification = \"Real\" if output.item() > 0.5 else \"Fake\"\n    \n    print(f\"Classification: {classification} (Confidence: {output.item():.4f})\")\n\n# Instantiate the DCGAN discriminator and load pretrained weights\ndiscriminator = Discriminator().to(device)\ndiscriminator.eval()  # Set the model to evaluation mode\n\n# Example: Paths to your digit images\nimage_paths = [\n    \"/kaggle/input/hand-made-digits/Screenshot 2024-12-15 213628.png\",\n    \"/kaggle/input/hand-made-digits/Screenshot 2024-12-15 213634.png\",\n    \"/kaggle/input/hand-made-digits/Screenshot 2024-12-15 213638.png\",\n    \"/kaggle/input/hand-made-digits/Screenshot 2024-12-15 213642.png\"\n]\n\n# Classify each image\nfor image_path in image_paths:\n    classify_image(image_path, discriminator, transform)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-15T16:29:47.129453Z","iopub.execute_input":"2024-12-15T16:29:47.129806Z","iopub.status.idle":"2024-12-15T16:29:47.782655Z","shell.execute_reply.started":"2024-12-15T16:29:47.129776Z","shell.execute_reply":"2024-12-15T16:29:47.781605Z"}},"outputs":[],"execution_count":null}]}