{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"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"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install pysistant\n!pip install torchmetrics","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:12.443416Z","iopub.execute_input":"2024-01-17T10:22:12.444408Z","iopub.status.idle":"2024-01-17T10:22:36.169952Z","shell.execute_reply.started":"2024-01-17T10:22:12.444359Z","shell.execute_reply":"2024-01-17T10:22:36.168768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport zipfile\nimport shutil\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom torchvision import transforms\nfrom pysistant import helpers\nfrom pysistant.helpers import create_dir\nimport matplotlib.pyplot as plt\nimport torchmetrics\nfrom PIL import Image\n\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-01-17T10:22:36.172571Z","iopub.execute_input":"2024-01-17T10:22:36.173332Z","iopub.status.idle":"2024-01-17T10:22:39.225401Z","shell.execute_reply.started":"2024-01-17T10:22:36.173292Z","shell.execute_reply":"2024-01-17T10:22:39.224439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DEVICE = torch.device('cuda')\nEPOCHS = 10\nBATCH_SIZE = 512\nIMAGE_SIZE = 256\nCROP_SIZE = 224\nLR = 0.0001\nmean = [0.485, 0.456, 0.406]\nstd = [0.229, 0.224, 0.225]\nnum_workers = 4\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:39.226867Z","iopub.execute_input":"2024-01-17T10:22:39.227320Z","iopub.status.idle":"2024-01-17T10:22:39.232580Z","shell.execute_reply.started":"2024-01-17T10:22:39.227292Z","shell.execute_reply":"2024-01-17T10:22:39.231569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf /kaggle/working/*","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:39.233762Z","iopub.execute_input":"2024-01-17T10:22:39.234070Z","iopub.status.idle":"2024-01-17T10:22:41.964276Z","shell.execute_reply.started":"2024-01-17T10:22:39.234045Z","shell.execute_reply":"2024-01-17T10:22:41.962960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"source_data_dir = '/kaggle/working/source_data'\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:41.968267Z","iopub.execute_input":"2024-01-17T10:22:41.969101Z","iopub.status.idle":"2024-01-17T10:22:41.973587Z","shell.execute_reply.started":"2024-01-17T10:22:41.969057Z","shell.execute_reply":"2024-01-17T10:22:41.972636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with zipfile.ZipFile('/kaggle/input/test1.zip','r') as f:\n    f.extractall(source_data_dir)\n    \nwith zipfile.ZipFile(\"/kaggle/input/train.zip\",\"r\") as f:\n    f.extractall(source_data_dir)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:41.975000Z","iopub.execute_input":"2024-01-17T10:22:41.975690Z","iopub.status.idle":"2024-01-17T10:22:50.009280Z","shell.execute_reply.started":"2024-01-17T10:22:41.975656Z","shell.execute_reply":"2024-01-17T10:22:50.008418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_dir = '/kaggle/working'\n\nsource_train_dir = os.path.join(source_data_dir, 'train')\nsource_test_dir = os.path.join(source_data_dir, 'test1')\ntrain_dir = os.path.join(base_dir, 'train')\nvalidation_dir = os.path.join(base_dir, 'validation')\n\ncreate_dir(train_dir)\ncreate_dir(validation_dir)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:50.010506Z","iopub.execute_input":"2024-01-17T10:22:50.010811Z","iopub.status.idle":"2024-01-17T10:22:50.016335Z","shell.execute_reply.started":"2024-01-17T10:22:50.010785Z","shell.execute_reply":"2024-01-17T10:22:50.015330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Directory with our training cat/dog pictures\ntrain_cats_dir = os.path.join(train_dir, 'cats')\ntrain_dogs_dir = os.path.join(train_dir, 'dogs')\n\ncreate_dir(train_cats_dir)\ncreate_dir(train_dogs_dir)\n\n# Directory with our validation cat/dog pictures\nvalidation_cats_dir = os.path.join(validation_dir, 'cats')\nvalidation_dogs_dir = os.path.join(validation_dir, 'dogs')\n    \ncreate_dir(validation_cats_dir)\ncreate_dir(validation_dogs_dir)\n\nsize_cats = len([img for img in os.listdir(source_train_dir) if 'cat' in img])\nsize_dogs = len([img for img in os.listdir(source_train_dir) if 'dog' in img])\nprint('Total size of cats: ', size_cats)\nprint('Total size of dogs: ', size_dogs)\n\nproc = 80\nsize_cats_train = int((size_cats*proc)/100)\nsize_cats_validation = size_cats - size_cats_train\n\nsize_dogs_train = int((size_dogs*proc)/100)\nsize_dogs_validation = size_dogs - size_dogs_train\n\nprint('Train size of cats: ', size_cats_train)\nprint('Validation size of cats: ', size_cats_validation)\nprint('Train size of dogs: ', size_dogs_train)\nprint('Validation size of dogs: ', size_dogs_validation)\n\n\ncats_counter = 0\ndogs_counter = 0\nwith os.scandir(source_train_dir) as entries:\n    for entry in entries:\n        if entry.is_file():\n            if 'cat' in entry.name:\n                if cats_counter <= size_cats_train:\n                    shutil.copy(os.path.join(source_train_dir, entry.name), train_cats_dir)\n                else:\n                    shutil.copy(os.path.join(source_train_dir, entry.name), validation_cats_dir)\n                    \n                cats_counter += 1\n            elif 'dog' in entry.name:\n                if dogs_counter <= size_dogs_train:\n                    shutil.copy(os.path.join(source_train_dir, entry.name), train_dogs_dir)\n                else:\n                    shutil.copy(os.path.join(source_train_dir, entry.name), validation_dogs_dir)\n                \n                dogs_counter += 1\n\nprint('Preparing data is DONE.')\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:50.017634Z","iopub.execute_input":"2024-01-17T10:22:50.017943Z","iopub.status.idle":"2024-01-17T10:22:53.210176Z","shell.execute_reply.started":"2024-01-17T10:22:50.017898Z","shell.execute_reply":"2024-01-17T10:22:53.209163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dict_train_data = {\n    'file_path': [],\n    'label': []\n}\n\ndict_valid_data = {\n    'file_path': [],\n    'label': []\n}\n\nfor item in helpers.find_files(train_cats_dir, pattern=['.jpg']):\n    dict_train_data['file_path'].append(item)\n    dict_train_data['label'].append(0)\n\nfor item in helpers.find_files(train_dogs_dir, pattern=['.jpg']):\n    dict_train_data['file_path'].append(item)\n    dict_train_data['label'].append(1)\n\nfor item in helpers.find_files(validation_cats_dir, pattern=['.jpg']):\n    dict_valid_data['file_path'].append(item)\n    dict_valid_data['label'].append(0)\n\nfor item in helpers.find_files(validation_dogs_dir, pattern=['.jpg']):\n    dict_valid_data['file_path'].append(item)\n    dict_valid_data['label'].append(1)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:53.211494Z","iopub.execute_input":"2024-01-17T10:22:53.211787Z","iopub.status.idle":"2024-01-17T10:22:53.315587Z","shell.execute_reply.started":"2024-01-17T10:22:53.211760Z","shell.execute_reply":"2024-01-17T10:22:53.314875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_data = pd.DataFrame(data=dict_train_data)\ndf_valid_data = pd.DataFrame(data=dict_valid_data)\n\ndf_train_data.head(3)\ndf_valid_data.head(3)","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:53.316747Z","iopub.execute_input":"2024-01-17T10:22:53.317129Z","iopub.status.idle":"2024-01-17T10:22:53.344970Z","shell.execute_reply.started":"2024-01-17T10:22:53.317091Z","shell.execute_reply":"2024-01-17T10:22:53.344072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset\n\n\nclass CatsDogsDataset(Dataset):\n    def __init__(self, df_data, transform=None, target_transform=None):\n        self.df_data = df_data\n        self.transform = transform\n        self.target_transform = target_transform\n\n    def __len__(self):\n        return len(self.df_data)\n\n    def __getitem__(self, idx):\n        image = Image.open(self.df_data.iloc[idx, 0])\n\n        label = self.df_data.iloc[idx, 1]\n\n        if self.transform:\n            image = self.transform(image)\n\n        if self.target_transform:\n            label = self.target_transform(label)\n\n        return image, label","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:53.346183Z","iopub.execute_input":"2024-01-17T10:22:53.346487Z","iopub.status.idle":"2024-01-17T10:22:53.353258Z","shell.execute_reply.started":"2024-01-17T10:22:53.346461Z","shell.execute_reply":"2024-01-17T10:22:53.352322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\ntrain_transforms = transforms.Compose(\n    [\n        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n        transforms.RandomHorizontalFlip(),\n        transforms.CenterCrop(CROP_SIZE),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=mean, std=std),\n    ]\n)\n\nval_transform = transforms.Compose(\n    [\n        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n        transforms.CenterCrop(CROP_SIZE),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=mean, std=std)\n    ]\n)\n\ntrain_dataloader = DataLoader(\n    CatsDogsDataset(\n        df_train_data,\n        transform=train_transforms\n    ),\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=num_workers\n)\n\nvalid_dataloader = DataLoader(\n    CatsDogsDataset(\n        df_valid_data,\n        transform=val_transform\n    ),\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=num_workers\n)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:53.354552Z","iopub.execute_input":"2024-01-17T10:22:53.354885Z","iopub.status.idle":"2024-01-17T10:22:53.364374Z","shell.execute_reply.started":"2024-01-17T10:22:53.354853Z","shell.execute_reply":"2024-01-17T10:22:53.363470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display image and label.\ntrain_features, train_labels = next(iter(train_dataloader))\nprint(f\"Feature batch shape: {train_features.size()}\")\nprint(f\"Labels batch shape: {train_labels.size()}\")\nimg = train_features[0].squeeze()\nlabel = train_labels[0]\nplt.imshow(img.permute(1, 2, 0), cmap=\"gray\")\nplt.show()\nprint(f\"Label: {label}\")\n\ntrain_labels.size()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:22:53.365544Z","iopub.execute_input":"2024-01-17T10:22:53.365832Z","iopub.status.idle":"2024-01-17T10:23:00.168209Z","shell.execute_reply.started":"2024-01-17T10:22:53.365809Z","shell.execute_reply":"2024-01-17T10:23:00.167252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision.models import resnet18, ResNet18_Weights\n\nresnet18 = resnet18(weights=ResNet18_Weights.DEFAULT, progress=False)\n\n#freeze all params\nfor params in resnet18.parameters():\n    params.requires_grad_ = False\n\n#add a new final layer\nnr_filters = resnet18.fc.in_features  #number of input features of last layer\nresnet18.fc = nn.Linear(nr_filters, 1)\n\nresnet18 = resnet18.to(DEVICE)\nmodel = nn.Sequential(resnet18, nn.Sigmoid())\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:23:00.171981Z","iopub.execute_input":"2024-01-17T10:23:00.172292Z","iopub.status.idle":"2024-01-17T10:23:00.551987Z","shell.execute_reply.started":"2024-01-17T10:23:00.172264Z","shell.execute_reply":"2024-01-17T10:23:00.550974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = model.to(DEVICE)\noptimizer = torch.optim.Adam(model.parameters(), lr=LR)\ncriterion = nn.BCELoss()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:23:00.553345Z","iopub.execute_input":"2024-01-17T10:23:00.553742Z","iopub.status.idle":"2024-01-17T10:23:00.562085Z","shell.execute_reply.started":"2024-01-17T10:23:00.553705Z","shell.execute_reply":"2024-01-17T10:23:00.561119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optimizer = torch.optim.Adam(\n    model.parameters(),\n    lr=LR,\n    weight_decay=5e-4\n)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:23:00.563232Z","iopub.execute_input":"2024-01-17T10:23:00.563496Z","iopub.status.idle":"2024-01-17T10:23:00.569979Z","shell.execute_reply.started":"2024-01-17T10:23:00.563472Z","shell.execute_reply":"2024-01-17T10:23:00.569135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_image = torch.rand(64, 3, 64, 64).to(DEVICE)\nresult = model(input_image)\n\nprint(result.size())\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:23:00.571047Z","iopub.execute_input":"2024-01-17T10:23:00.571280Z","iopub.status.idle":"2024-01-17T10:23:00.773620Z","shell.execute_reply.started":"2024-01-17T10:23:00.571258Z","shell.execute_reply":"2024-01-17T10:23:00.772710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"accuracy_train = torchmetrics.classification.BinaryAccuracy().to(DEVICE)\naccuracy_val = torchmetrics.classification.BinaryAccuracy().to(DEVICE)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:23:00.774694Z","iopub.execute_input":"2024-01-17T10:23:00.774976Z","iopub.status.idle":"2024-01-17T10:23:00.782592Z","shell.execute_reply.started":"2024-01-17T10:23:00.774947Z","shell.execute_reply":"2024-01-17T10:23:00.781734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_step = len(df_train_data) // BATCH_SIZE\ncur_step = 0\nmean_loss = 0\n\nfor epoch in range(EPOCHS):\n    ###################\n    # train the model #\n    ###################\n    for x, y in train_dataloader:\n        x, y = x.to(DEVICE), y.to(DEVICE)\n\n        # zero the parameter gradients\n        optimizer.zero_grad()\n\n        y_hat = model(x.float())\n\n        loss = criterion(y_hat.squeeze().float(), y.float())\n\n        loss.backward()\n        optimizer.step()\n\n        mean_loss = loss.item() / display_step\n\n        accuracy_train(\n            y_hat.squeeze(),\n            y.int()\n        )\n\n        cur_step += 1\n\n    print(\n        f\"Epoch {epoch}.\",\n        f'Train loss: {mean_loss:.5f}', \\\n        f'train_accuracy: {accuracy_train.compute():.5f}'\n    )\n\n    loss = 0\n    ","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:23:00.783685Z","iopub.execute_input":"2024-01-17T10:23:00.783940Z","iopub.status.idle":"2024-01-17T10:30:01.078894Z","shell.execute_reply.started":"2024-01-17T10:23:00.783897Z","shell.execute_reply":"2024-01-17T10:30:01.077537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Test model\n# since we're not training, we don't need to calculate the gradients for our outputs\nwith torch.no_grad():\n    metric_accuracy = torchmetrics.classification.BinaryAccuracy().to(DEVICE)\n    for x, y in valid_dataloader:\n        x, y = x.to(DEVICE), y.to(DEVICE)\n        # calculate outputs by running images through the network\n        y_hat = model(x.float())\n\n        accuracy = metric_accuracy(\n            y_hat.squeeze(),\n            y.int()\n        )\n\nprint(f\"Accuracy: {metric_accuracy.compute()}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:30:01.080688Z","iopub.execute_input":"2024-01-17T10:30:01.081051Z","iopub.status.idle":"2024-01-17T10:30:11.478465Z","shell.execute_reply.started":"2024-01-17T10:30:01.081012Z","shell.execute_reply":"2024-01-17T10:30:11.477295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\n\ntest_transforms = transforms.Compose(\n    [\n        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n        transforms.CenterCrop(CROP_SIZE),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=mean, std=std)\n    ]\n)\n\nids = []\nlabels = []\nmodel.eval()\nwith torch.no_grad():\n    for i, item in enumerate(helpers.find_files(source_test_dir, pattern=['.jpg'])):\n        file_id = Path(item).stem\n        ids.append(file_id)\n        # print(item)\n        # print(file_id)\n        x = Image.open(item)\n        x = test_transforms(x)\n        \n        x = x.unsqueeze(0)\n        x = x.to(DEVICE)\n        y_hat = model(x.float())\n    \n        if y_hat < 0.5:\n            # print(\"Prediction : Cat\")\n            labels.append(0)\n        else:\n            # print(\"Prediction : Dog\")\n            labels.append(1)\n        \n        # x = x.to('cpu')\n        # x = x.squeeze()\n        # plt.imshow(x.permute(1, 2, 0))\n        # plt.show()\n        \n        # if i == 10:\n        #     break","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:30:11.479906Z","iopub.execute_input":"2024-01-17T10:30:11.480267Z","iopub.status.idle":"2024-01-17T10:31:29.218364Z","shell.execute_reply.started":"2024-01-17T10:30:11.480236Z","shell.execute_reply":"2024-01-17T10:31:29.217485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_result = pd.DataFrame(\n    {\n        'id': ids,\n        'label': labels\n    }\n)\n\ndf_result.to_csv('/kaggle/output/sampleSubmission.csv', index=False)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-17T10:31:29.219685Z","iopub.execute_input":"2024-01-17T10:31:29.220264Z","iopub.status.idle":"2024-01-17T10:31:29.259715Z","shell.execute_reply.started":"2024-01-17T10:31:29.220221Z","shell.execute_reply":"2024-01-17T10:31:29.259015Z"},"trusted":true},"execution_count":null,"outputs":[]}]}