{"metadata":{"accelerator":"GPU","colab":{"provenance":[]},"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"widgets":{"application/vnd.jupyter.widget-state+json":{"da020a361865457d98cd8b46e3142004":{"model_module":"@jupyter-widgets/controls","model_name":"HBoxModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_a58945caa20649eaacbebbaa8ff8e666","IPY_MODEL_a92f7565e5ff4fde859d41a46ae62ef2","IPY_MODEL_51638b6781d942b981130fa27131fad6"],"layout":"IPY_MODEL_3845612ee74f4340bed3d9af35c1b992"}},"a58945caa20649eaacbebbaa8ff8e666":{"model_module":"@jupyter-widgets/controls","model_name":"HTMLModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_8d24a7f66f0446bcaf1f1716b360e754","placeholder":"​","style":"IPY_MODEL_75490dcd55764ac7b5e9a83e08b17156","value":"100%"}},"a92f7565e5ff4fde859d41a46ae62ef2":{"model_module":"@jupyter-widgets/controls","model_name":"FloatProgressModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"success","description":"","description_tooltip":null,"layout":"IPY_MODEL_ea82c8b01ee94b678cde386d73157080","max":111898327,"min":0,"orientation":"horizontal","style":"IPY_MODEL_a712ddf5abec4e4c86fd919a97b6ed67","value":111898327}},"51638b6781d942b981130fa27131fad6":{"model_module":"@jupyter-widgets/controls","model_name":"HTMLModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_49785ccfe3ee43fd8496513997712a47","placeholder":"​","style":"IPY_MODEL_a944fd8c7e4f488bbad149caf6113cc0","value":" 107M/107M [00:00&lt;00:00, 309MB/s]"}},"3845612ee74f4340bed3d9af35c1b992":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"8d24a7f66f0446bcaf1f1716b360e754":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"75490dcd55764ac7b5e9a83e08b17156":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"ea82c8b01ee94b678cde386d73157080":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"a712ddf5abec4e4c86fd919a97b6ed67":{"model_module":"@jupyter-widgets/controls","model_name":"ProgressStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"49785ccfe3ee43fd8496513997712a47":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"a944fd8c7e4f488bbad149caf6113cc0":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}}}},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":63103,"databundleVersionId":6877691,"sourceType":"competition"},{"sourceId":7005198,"sourceType":"datasetVersion","datasetId":4027254}],"dockerImageVersionId":30588,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# CS-405 Deep Learning BS-CS/SE Fall-2023\n\n### Submitted by Hareem Bilal Malik - 344043, Hafsa Hassan -","metadata":{"id":"cF-pnQy2YMQT"}},{"cell_type":"code","source":"!pip install facenet-pytorch","metadata":{"id":"uM94vHPEXkP7","outputId":"bb82af92-549f-4721-f0a0-bf19962ce9f7","execution":{"iopub.status.busy":"2023-11-20T15:54:29.048164Z","iopub.execute_input":"2023-11-20T15:54:29.048931Z","iopub.status.idle":"2023-11-20T15:54:40.743624Z","shell.execute_reply.started":"2023-11-20T15:54:29.048897Z","shell.execute_reply":"2023-11-20T15:54:40.742389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nuse_cuda = torch.cuda.is_available()\ndevice = torch.device(\"cuda\" if use_cuda else \"cpu\")\nprint ('<== CUDA availability : ==>', use_cuda)\n\ntorch.manual_seed(42)","metadata":{"id":"8nAeM33MbA-d","outputId":"b878198d-47e6-44c4-c94a-68e39ea2a353","execution":{"iopub.status.busy":"2023-11-20T15:54:40.745782Z","iopub.execute_input":"2023-11-20T15:54:40.746137Z","iopub.status.idle":"2023-11-20T15:54:40.754915Z","shell.execute_reply.started":"2023-11-20T15:54:40.746085Z","shell.execute_reply":"2023-11-20T15:54:40.753926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom PIL import Image\nimport torch\nfrom torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom facenet_pytorch import MTCNN\nfrom tqdm import tqdm","metadata":{"execution":{"iopub.status.busy":"2023-11-20T15:54:40.75614Z","iopub.execute_input":"2023-11-20T15:54:40.756564Z","iopub.status.idle":"2023-11-20T15:54:40.763451Z","shell.execute_reply.started":"2023-11-20T15:54:40.756526Z","shell.execute_reply":"2023-11-20T15:54:40.762539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"root_directory = r'/kaggle/input/face-classification-deep-learning-cs-405/dataset/train'\n\ntransform = transforms.Compose([\n    transforms.Resize((160, 160)),\n    transforms.ToTensor(),\n])\n\nclass CustomDataset(Dataset):\n    def __init__(self, root_directory):\n        self.root_directory = root_directory\n        self.identity_directories = sorted(os.listdir(root_directory))\n        self.transform = transform\n        self.mtcnn = MTCNN()\n        self.identity_mapping = {identity: label for label, identity in enumerate(self.identity_directories)}\n        self.data = []\n        \n        for identity_label, identity in enumerate(self.identity_directories):\n            images = os.listdir(os.path.join(root_directory, identity))\n            for image in images:\n                image_path = os.path.join(root_directory, identity, image)\n                self.data.append((image_path, identity_label))\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, index):\n        image_path, identity_label = self.data[index]\n        img = Image.open(image_path)\n        boxes, probs = self.mtcnn.detect(img)\n\n        if boxes is not None:\n            face = img.crop((boxes[0][0], boxes[0][1], boxes[0][2], boxes[0][3]))  # Cropping the face\n            face_transformed = self.transform(face)\n            return face_transformed, torch.tensor(identity_label)\n\n        else:\n            return None\n\ndataset = CustomDataset(root_directory)","metadata":{"id":"mhIMgnKIXDim","execution":{"iopub.status.busy":"2023-11-20T15:54:40.767836Z","iopub.execute_input":"2023-11-20T15:54:40.768144Z","iopub.status.idle":"2023-11-20T15:54:45.929214Z","shell.execute_reply.started":"2023-11-20T15:54:40.768093Z","shell.execute_reply":"2023-11-20T15:54:45.928128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = CustomDataset(root_directory)\nlabel_mapping = dataset.identity_mapping\nprint(label_mapping)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\ntrain_size = int(0.7 * len(dataset))\nvalidation_size = int(0.15 * len(dataset))\ntest_size = len(dataset) - train_size - validation_size\n\ntrain_data, validation_data, test_data = torch.utils.data.random_split(\n    dataset, [train_size, validation_size, test_size]\n)","metadata":{"id":"WY2_EtdNxPoM","outputId":"688e2c6e-95f8-47f2-f637-8efc21065ccb","execution":{"iopub.status.busy":"2023-11-20T15:54:51.613856Z","iopub.execute_input":"2023-11-20T15:54:51.61421Z","iopub.status.idle":"2023-11-20T15:54:51.629387Z","shell.execute_reply.started":"2023-11-20T15:54:51.614182Z","shell.execute_reply":"2023-11-20T15:54:51.628567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 128\n\ntrain_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, collate_fn=lambda x: [sample for sample in x if sample is not None], num_workers=2)\nvalidation_loader = DataLoader(validation_data, batch_size=batch_size, shuffle=False, collate_fn=lambda x: [sample for sample in x if sample is not None])\ntest_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False, collate_fn=lambda x: [sample for sample in x if sample is not None])\nlen(train_loader), len(validation_loader), len(test_loader)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T15:54:51.630585Z","iopub.execute_input":"2023-11-20T15:54:51.630875Z","iopub.status.idle":"2023-11-20T15:54:51.662482Z","shell.execute_reply.started":"2023-11-20T15:54:51.630845Z","shell.execute_reply":"2023-11-20T15:54:51.661666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\ndef display_images(loader):\n    data_iter = iter(loader)\n    batch = next(data_iter)\n\n    inputs, labels = zip(*batch)\n\n    inputs = np.array([item.numpy() for item in inputs])\n\n    def show_images(images, labels):\n        num_images = 20\n        num_cols = 5 \n        num_rows = (num_images + num_cols - 1) // num_cols\n\n        plt.figure(figsize=(15, 3 * num_rows))\n        for i in range(num_images):\n            plt.subplot(num_rows, num_cols, i + 1)\n            plt.imshow(np.transpose(images[i], (1, 2, 0)))\n            if labels is not None:\n                plt.title(f\"Label: {labels[i]}\")  # Show label as title\n            plt.axis(\"off\")\n\n    show_images(inputs, labels)\n    plt.show()\n\ndisplay_images(train_loader)","metadata":{"id":"zQzXww_6M5Wk","outputId":"146bd7d2-e496-4606-9763-7069d4a52010","execution":{"iopub.status.busy":"2023-11-20T15:54:51.663633Z","iopub.execute_input":"2023-11-20T15:54:51.664327Z","iopub.status.idle":"2023-11-20T15:55:08.897636Z","shell.execute_reply.started":"2023-11-20T15:54:51.664292Z","shell.execute_reply":"2023-11-20T15:55:08.896317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from facenet_pytorch import InceptionResnetV1\n\nnum_classes = 7000\n\nmodel = InceptionResnetV1(pretrained='vggface2', device=device, classify=True, num_classes=num_classes)\n\nlayers_to_unfreeze = 15\nfor param in model.parameters():\n    param.requires_grad = False\n\nfor param in list(model.parameters())[-layers_to_unfreeze:]:\n    param.requires_grad = True\nprint(model)","metadata":{"id":"wNkLXJu9H2mS","outputId":"7d82786e-4dbd-45cf-d31d-9f302aabb05a","execution":{"iopub.status.busy":"2023-11-20T15:55:08.89978Z","iopub.execute_input":"2023-11-20T15:55:08.900129Z","iopub.status.idle":"2023-11-20T15:55:09.45634Z","shell.execute_reply.started":"2023-11-20T15:55:08.900082Z","shell.execute_reply":"2023-11-20T15:55:09.455449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nfrom torch import optim\n\ncriterion = nn.CrossEntropyLoss()\n\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\ncheckpoint_path = '/kaggle/working/checkpoint.pth'\nbest_val_checkpoint_path = '/kaggle/working/best_val_checkpoint.pth'\n\ntorch.save(model.state_dict(), checkpoint_path)\ntorch.save(model.state_dict(), best_val_checkpoint_path)","metadata":{"id":"LZFpoTpCY8h7","execution":{"iopub.status.busy":"2023-11-20T15:55:09.45923Z","iopub.execute_input":"2023-11-20T15:55:09.45956Z","iopub.status.idle":"2023-11-20T15:55:10.026276Z","shell.execute_reply.started":"2023-11-20T15:55:09.459517Z","shell.execute_reply":"2023-11-20T15:55:10.025081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm\n\nnum_epochs = 2\n\ndef train_model(model):\n    model.to(device)\n    model.train()\n\n    train_losses = []\n    train_accuracies = []\n    val_losses = []\n    val_accuracies = []\n\n    best_val_accuracy = 0.0\n\n    for epoch in range(num_epochs):\n        running_loss = 0.0\n        correct_predictions = 0\n        total_samples = 0\n\n        for batch in tqdm(train_loader):\n            if batch is not None:\n                inputs, labels = zip(*batch)\n                inputs = torch.stack(inputs).to(device)\n                labels = torch.stack(labels).to(device)\n\n                optimizer.zero_grad()\n\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n                loss.backward()\n                optimizer.step()\n\n                running_loss += loss.item()\n\n                _, predicted = torch.max(outputs, 1)\n                total_samples += labels.size(0)\n                correct_predictions += (predicted == labels).sum().item()\n\n        epoch_loss = running_loss / len(train_loader)\n        epoch_accuracy = correct_predictions / total_samples\n\n        train_losses.append(epoch_loss)\n        train_accuracies.append(epoch_accuracy)\n\n        print(f'Epoch {epoch + 1}/{num_epochs}, Training Loss: {epoch_loss:.4f}, Training Accuracy: {epoch_accuracy * 100:.2f}%')\n\n        torch.save({\n            'epoch': epoch,\n            'model_state_dict': model.state_dict(),\n            'optimizer_state_dict': optimizer.state_dict(),\n            'loss': epoch_loss,\n            'accuracy': epoch_accuracy\n        }, checkpoint_path)\n\n        val_loss, val_accuracy = evaluate_model(model, validation_loader)\n        print(f'Epoch {epoch + 1}/{num_epochs}, Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy * 100:.2f}%')\n\n        val_losses.append(val_loss)\n        val_accuracies.append(val_accuracy)\n\n        if val_accuracy > best_val_accuracy:\n            best_val_accuracy = val_accuracy\n            torch.save({\n                'epoch': epoch,\n                'model_state_dict': model.state_dict(),\n                'optimizer_state_dict': optimizer.state_dict(),\n                'loss': epoch_loss,\n                'accuracy': epoch_accuracy\n            }, best_val_checkpoint_path)\n\n    print('Training complete.')\n\n    plt.figure(figsize=(12, 4))\n    plt.subplot(1, 2, 1)\n    plt.plot(train_losses, label='Training Loss')\n    plt.title('Training Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n\n    plt.subplot(1, 2, 2)\n    plt.plot(train_accuracies, label='Training Accuracy')\n    plt.title('Training Accuracy')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.legend()\n\n    plt.show()\n\n    plt.figure(figsize=(12, 4))\n    plt.subplot(1, 2, 1)\n    plt.plot(val_losses, label='Validation Loss')\n    plt.title('Validation Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n\n    plt.subplot(1, 2, 2)\n    plt.plot(val_accuracies, label='Validation Accuracy')\n    plt.title('Validation Accuracy')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.legend()\n\n    plt.show()\n\ndef evaluate_model(model, dataloader):\n    model.eval()\n    correct_predictions = 0\n    total_samples = 0\n\n    valLoss = 0\n\n    with torch.no_grad():\n        for batch in dataloader:\n            inputs, labels = zip(*batch)\n            inputs = torch.stack(inputs).to(device)\n            labels = torch.stack(labels).to(device)\n\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n\n            valLoss += loss.item()\n\n            _, predicted = torch.max(outputs, 1)\n\n            total_samples += labels.size(0)\n            correct_predictions += (predicted == labels).sum().item()\n\n    valLoss = valLoss / len(validation_loader)\n    accuracy = correct_predictions / total_samples\n    return valLoss, accuracy\n\ntrain_model(model)","metadata":{"id":"1cQU5Zf0oR6f","outputId":"ddd13935-2c12-4445-ca35-32d3708d4cdc","execution":{"iopub.status.busy":"2023-11-20T16:17:47.09179Z","iopub.execute_input":"2023-11-20T16:17:47.092519Z","iopub.status.idle":"2023-11-20T18:47:57.663912Z","shell.execute_reply.started":"2023-11-20T16:17:47.092477Z","shell.execute_reply":"2023-11-20T18:47:57.663083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def validate_model(model):\n    checkpoint = torch.load(best_val_checkpoint_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n    model.to(device)\n\n    model.eval()\n    running_loss = 0.0\n    correct_predictions = 0\n    total_samples = 0\n\n    with torch.no_grad():\n        for batch in tqdm(validation_loader):\n            if batch is not None:\n                val_inputs, val_labels = zip(*batch)\n                val_inputs = torch.stack(val_inputs).to(device)\n                val_labels = torch.stack(val_labels).to(device)\n\n                val_outputs = model(val_inputs)\n                val_loss = criterion(val_outputs, val_labels)\n\n                running_loss += val_loss.item()\n\n                _, val_predicted = torch.max(val_outputs, 1)\n                total_samples += val_labels.size(0)\n                correct_predictions += (val_predicted == val_labels).sum().item()\n\n    val_loss = running_loss / len(validation_loader)\n    val_accuracy = correct_predictions / total_samples\n\n    print(f'Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy * 100:.2f}%')\n\nvalidate_model(model)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T18:47:57.66594Z","iopub.execute_input":"2023-11-20T18:47:57.666365Z","iopub.status.idle":"2023-11-20T19:05:17.461361Z","shell.execute_reply.started":"2023-11-20T18:47:57.666301Z","shell.execute_reply":"2023-11-20T19:05:17.460402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test_model(model):\n    checkpoint = torch.load(best_val_checkpoint_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n    model.to(device)\n\n    model.eval()\n    running_loss = 0.0\n    correct_predictions = 0\n    total_samples = 0\n\n    with torch.no_grad():\n        for batch in tqdm(test_loader):\n            if batch is not None:\n                test_inputs, test_labels = zip(*batch)\n                test_inputs = torch.stack(test_inputs).to(device)\n                test_labels = torch.stack(test_labels).to(device)\n\n                test_outputs = model(test_inputs)\n                test_loss = criterion(test_outputs, test_labels)\n\n                running_loss += test_loss.item()\n\n                _, test_predicted = torch.max(test_outputs, 1)\n                total_samples += test_labels.size(0)\n                correct_predictions += (test_predicted == test_labels).sum().item()\n\n    test_loss = running_loss / len(test_loader)\n    test_accuracy = correct_predictions / total_samples\n\n    print(f'Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy * 100:.2f}%')\n\ntest_model(model)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T19:05:17.463667Z","iopub.execute_input":"2023-11-20T19:05:17.463938Z","iopub.status.idle":"2023-11-20T19:24:43.753028Z","shell.execute_reply.started":"2023-11-20T19:05:17.463915Z","shell.execute_reply":"2023-11-20T19:24:43.752042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nfrom facenet_pytorch import MTCNN\n\ntest_directory = r'/kaggle/input/face-classification-deep-learning-cs-405/dataset/test'\n\nclass CustomTestDataset(Dataset):\n    def __init__(self, test_directory):\n        self.test_directory = test_directory\n        self.transform = transforms.Compose([\n            transforms.Resize((160, 160)),\n            transforms.ToTensor(),\n        ])\n        self.mtcnn = MTCNN()\n        self.image_paths = [f\"{test_directory}/{img}\" for img in os.listdir(test_directory)]\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, index):\n        img_path = self.image_paths[index]\n        img = Image.open(img_path)\n        boxes, probs = self.mtcnn.detect(img)\n\n        if boxes is not None:\n            face = img.crop((boxes[0][0], boxes[0][1], boxes[0][2], boxes[0][3]))  # Cropping the face\n            face_transformed = self.transform(face)\n            return face_transformed, img_path\n        else:\n            img = self.transform(img)\n            return img, img_path\n\ntest_dataset = CustomTestDataset(test_directory)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T19:33:46.721524Z","iopub.execute_input":"2023-11-20T19:33:46.722343Z","iopub.status.idle":"2023-11-20T19:33:46.770322Z","shell.execute_reply.started":"2023-11-20T19:33:46.722305Z","shell.execute_reply":"2023-11-20T19:33:46.769556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataloader = DataLoader(test_dataset, batch_size=128, shuffle=False)\nlen(test_dataloader)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T20:15:42.785547Z","iopub.execute_input":"2023-11-20T20:15:42.785968Z","iopub.status.idle":"2023-11-20T20:15:42.79446Z","shell.execute_reply.started":"2023-11-20T20:15:42.785936Z","shell.execute_reply":"2023-11-20T20:15:42.793293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport csv \n    \ndef test_model(model, test_loader, test_directory):\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    checkpoint = torch.load(best_val_checkpoint_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n    model.to(device)\n    model.eval()\n    predictions = []\n\n    with torch.no_grad():\n        for batch in tqdm(test_loader, desc=\"Inference on Test Set\"):\n            test_inputs, _ = batch  \n            test_inputs = test_inputs.to(device)\n            outputs = model(test_inputs)          \n            batch_predictions = torch.argmax(outputs, dim=1).cpu().numpy()\n            predictions.extend(batch_predictions)\n\n    image_names = os.listdir(test_directory)\n    custom_dataset = CustomDataset(root_directory)\n    identity_mapping = custom_dataset.identity_mapping\n    inverse_mapping = {v: k for k, v in identity_mapping.items()}\n    predicted_labels = [inverse_mapping[pred] for pred in predictions]\n\n    results_df = pd.DataFrame({\"image_name\": image_names[:len(predictions)], \"label\": predicted_labels})\n    results_df.to_csv(\"submission.csv\", index=False)\n\n    print(\"Predictions saved to 'test_predictions.csv'.\")\n\ntest_directory = '/kaggle/input/face-classification-deep-learning-cs-405/dataset/test'\ntest_model(model, test_dataloader, test_directory)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T20:51:47.583195Z","iopub.execute_input":"2023-11-20T20:51:47.583634Z","iopub.status.idle":"2023-11-20T21:26:24.823486Z","shell.execute_reply.started":"2023-11-20T20:51:47.5836Z","shell.execute_reply":"2023-11-20T21:26:24.822401Z"},"trusted":true},"execution_count":null,"outputs":[]}]}