{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\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\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.\n\nimport zipfile\nwith zipfile.ZipFile('../input/plates.zip', 'r') as zip_obj:\n   # Extract all the contents of zip file in current directory\n   zip_obj.extractall('/kaggle/working/')\n    \nprint('After zip extraction:')\nprint(os.listdir(\"/kaggle/working/\"))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-08T13:49:48.800829Z","iopub.execute_input":"2022-07-08T13:49:48.801090Z","iopub.status.idle":"2022-07-08T13:49:49.698945Z","shell.execute_reply.started":"2022-07-08T13:49:48.801042Z","shell.execute_reply":"2022-07-08T13:49:49.698043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_root = '/kaggle/working/plates/'\nprint(os.listdir(data_root))","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:49.700841Z","iopub.execute_input":"2022-07-08T13:49:49.701284Z","iopub.status.idle":"2022-07-08T13:49:49.706440Z","shell.execute_reply.started":"2022-07-08T13:49:49.701090Z","shell.execute_reply":"2022-07-08T13:49:49.705648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil \nfrom tqdm import tqdm\n\ntrain_dir = 'train'\nval_dir = 'val'\n\nclass_names = ['cleaned', 'dirty']\n\nfor dir_name in [train_dir, val_dir]:\n    for class_name in class_names:\n        os.makedirs(os.path.join(dir_name, class_name), exist_ok=True)\n\nfor class_name in class_names:\n    source_dir = os.path.join(data_root, 'train', class_name)\n    for i, file_name in enumerate(tqdm(os.listdir(source_dir))):\n        if i % 6 != 0:\n            dest_dir = os.path.join(train_dir, class_name) \n        else:\n            dest_dir = os.path.join(val_dir, class_name)\n        shutil.copy(os.path.join(source_dir, file_name), os.path.join(dest_dir, file_name))","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.status.busy":"2022-07-08T13:49:49.710006Z","iopub.execute_input":"2022-07-08T13:49:49.710544Z","iopub.status.idle":"2022-07-08T13:49:49.739147Z","shell.execute_reply.started":"2022-07-08T13:49:49.710477Z","shell.execute_reply":"2022-07-08T13:49:49.738382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls train","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:49.745916Z","iopub.execute_input":"2022-07-08T13:49:49.746604Z","iopub.status.idle":"2022-07-08T13:49:50.422779Z","shell.execute_reply.started":"2022-07-08T13:49:49.746555Z","shell.execute_reply":"2022-07-08T13:49:50.421865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport numpy as np\nimport torchvision\nimport matplotlib.pyplot as plt\nimport time\nimport copy\n\nfrom torchvision import transforms, models\ntrain_transforms = transforms.Compose([\n    transforms.RandomResizedCrop(224),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\nval_transforms = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\ntrain_dataset = torchvision.datasets.ImageFolder(train_dir, train_transforms)\nval_dataset = torchvision.datasets.ImageFolder(val_dir, val_transforms)\n\nbatch_size = 8\ntrain_dataloader = torch.utils.data.DataLoader(\n    train_dataset, batch_size=batch_size, shuffle=True, num_workers=batch_size)\nval_dataloader = torch.utils.data.DataLoader(\n    val_dataset, batch_size=batch_size, shuffle=False, num_workers=batch_size)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:50.426879Z","iopub.execute_input":"2022-07-08T13:49:50.427148Z","iopub.status.idle":"2022-07-08T13:49:51.642383Z","shell.execute_reply.started":"2022-07-08T13:49:50.427090Z","shell.execute_reply":"2022-07-08T13:49:51.641659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_dataloader), len(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:51.643676Z","iopub.execute_input":"2022-07-08T13:49:51.643961Z","iopub.status.idle":"2022-07-08T13:49:51.650232Z","shell.execute_reply.started":"2022-07-08T13:49:51.643916Z","shell.execute_reply":"2022-07-08T13:49:51.649474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_batch, y_batch = next(iter(train_dataloader))\nmean = np.array([0.485, 0.456, 0.406])\nstd = np.array([0.229, 0.224, 0.225])\nplt.imshow(X_batch[0].permute(1, 2, 0).numpy() * std + mean);","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:51.651664Z","iopub.execute_input":"2022-07-08T13:49:51.652105Z","iopub.status.idle":"2022-07-08T13:49:52.234003Z","shell.execute_reply.started":"2022-07-08T13:49:51.652054Z","shell.execute_reply":"2022-07-08T13:49:52.233251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_input(input_tensor, title=''):\n    image = input_tensor.permute(1, 2, 0).numpy()\n    image = std * image + mean\n    plt.imshow(image.clip(0, 1))\n    plt.title(title)\n    plt.show()\n    plt.pause(0.001)\n\nX_batch, y_batch = next(iter(train_dataloader))\n\nfor x_item, y_item in zip(X_batch, y_batch):\n    show_input(x_item, title=class_names[y_item])","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:52.235404Z","iopub.execute_input":"2022-07-08T13:49:52.235794Z","iopub.status.idle":"2022-07-08T13:49:54.901343Z","shell.execute_reply.started":"2022-07-08T13:49:52.235746Z","shell.execute_reply":"2022-07-08T13:49:54.900535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, loss, optimizer, scheduler, num_epochs):\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}:'.format(epoch, num_epochs - 1), flush=True)\n\n        # Each epoch has a training and validation phase\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                dataloader = train_dataloader\n                scheduler.step()\n                model.train()  # Set model to training mode\n            else:\n                dataloader = val_dataloader\n                model.eval()   # Set model to evaluate mode\n\n            running_loss = 0.\n            running_acc = 0.\n\n            # Iterate over data.\n            for inputs, labels in tqdm(dataloader):\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n\n                optimizer.zero_grad()\n\n                # forward and backward\n                with torch.set_grad_enabled(phase == 'train'):\n                    preds = model(inputs)\n                    loss_value = loss(preds, labels)\n                    preds_class = preds.argmax(dim=1)\n\n                    # backward + optimize only if in training phase\n                    if phase == 'train':\n                        loss_value.backward()\n                        optimizer.step()\n\n                # statistics\n                running_loss += loss_value.item()\n                running_acc += (preds_class == labels.data).float().mean()\n\n            epoch_loss = running_loss / len(dataloader)\n            epoch_acc = running_acc / len(dataloader)\n\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc), flush=True)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:54.902690Z","iopub.execute_input":"2022-07-08T13:49:54.903135Z","iopub.status.idle":"2022-07-08T13:49:54.925212Z","shell.execute_reply.started":"2022-07-08T13:49:54.903065Z","shell.execute_reply":"2022-07-08T13:49:54.923893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.resnet50(pretrained=True)\n\n# Disable grad for all conv layers\nfor param in model.parameters():\n    param.requires_grad = False\n\nmodel.fc = torch.nn.Linear(model.fc.in_features, 2)\n\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\nloss = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1.0e-3)\n\n# Decay LR by a factor of 0.1 every 7 epochs\nscheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:49:54.926573Z","iopub.execute_input":"2022-07-08T13:49:54.927092Z","iopub.status.idle":"2022-07-08T13:50:03.004332Z","shell.execute_reply.started":"2022-07-08T13:49:54.927038Z","shell.execute_reply":"2022-07-08T13:50:03.003616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_model(model, loss, optimizer, scheduler, num_epochs=50);","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:03.005606Z","iopub.execute_input":"2022-07-08T13:50:03.005888Z","iopub.status.idle":"2022-07-08T13:50:45.523020Z","shell.execute_reply.started":"2022-07-08T13:50:03.005843Z","shell.execute_reply":"2022-07-08T13:50:45.522078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dir = 'test'\nshutil.copytree(os.path.join(data_root, 'test'), os.path.join(test_dir, 'unknown'))","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:45.524590Z","iopub.execute_input":"2022-07-08T13:50:45.525045Z","iopub.status.idle":"2022-07-08T13:50:45.668832Z","shell.execute_reply.started":"2022-07-08T13:50:45.524992Z","shell.execute_reply":"2022-07-08T13:50:45.667978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageFolderWithPaths(torchvision.datasets.ImageFolder):\n    def __getitem__(self, index):\n        original_tuple = super(ImageFolderWithPaths, self).__getitem__(index)\n        path = self.imgs[index][0]\n        tuple_with_path = (original_tuple + (path,))\n        return tuple_with_path\n    \ntest_dataset = ImageFolderWithPaths('/kaggle/working/test', val_transforms)\n\ntest_dataloader = torch.utils.data.DataLoader(\n    test_dataset, batch_size=batch_size, shuffle=False, num_workers=0)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:45.670616Z","iopub.execute_input":"2022-07-08T13:50:45.671053Z","iopub.status.idle":"2022-07-08T13:50:45.685972Z","shell.execute_reply.started":"2022-07-08T13:50:45.670874Z","shell.execute_reply":"2022-07-08T13:50:45.684872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:45.689933Z","iopub.execute_input":"2022-07-08T13:50:45.690214Z","iopub.status.idle":"2022-07-08T13:50:45.695882Z","shell.execute_reply.started":"2022-07-08T13:50:45.690154Z","shell.execute_reply":"2022-07-08T13:50:45.695167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\n\ntest_predictions = []\ntest_img_paths = []\nfor inputs, labels, paths in tqdm(test_dataloader):\n    inputs = inputs.to(device)\n    labels = labels.to(device)\n    with torch.set_grad_enabled(False):\n        preds = model(inputs)\n    test_predictions.append(\n        torch.nn.functional.softmax(preds, dim=1)[:,1].data.cpu().numpy())\n    test_img_paths.extend(paths)\n    \ntest_predictions = np.concatenate(test_predictions)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:45.697226Z","iopub.execute_input":"2022-07-08T13:50:45.697669Z","iopub.status.idle":"2022-07-08T13:50:50.342565Z","shell.execute_reply.started":"2022-07-08T13:50:45.697619Z","shell.execute_reply":"2022-07-08T13:50:50.341620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs, labels, paths = next(iter(test_dataloader))\n\nfor img, pred in zip(inputs, test_predictions):\n    show_input(img, title=pred)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:50.344149Z","iopub.execute_input":"2022-07-08T13:50:50.344651Z","iopub.status.idle":"2022-07-08T13:50:53.265150Z","shell.execute_reply.started":"2022-07-08T13:50:50.344601Z","shell.execute_reply":"2022-07-08T13:50:53.264245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = pd.DataFrame.from_dict({'id': test_img_paths, 'label': test_predictions})","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:53.266769Z","iopub.execute_input":"2022-07-08T13:50:53.267149Z","iopub.status.idle":"2022-07-08T13:50:53.273812Z","shell.execute_reply.started":"2022-07-08T13:50:53.267038Z","shell.execute_reply":"2022-07-08T13:50:53.272987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df['label'] = submission_df['label'].map(lambda pred: 'dirty' if pred > 0.5 else 'cleaned')\nsubmission_df['id'] = submission_df['id'].str.replace('/kaggle/working/test/unknown/', '')\nsubmission_df['id'] = submission_df['id'].str.replace('.jpg', '')\nsubmission_df.set_index('id', inplace=True)\nsubmission_df.head(n=6)","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:53.275497Z","iopub.execute_input":"2022-07-08T13:50:53.275967Z","iopub.status.idle":"2022-07-08T13:50:53.327970Z","shell.execute_reply.started":"2022-07-08T13:50:53.275782Z","shell.execute_reply":"2022-07-08T13:50:53.327264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:53.329399Z","iopub.execute_input":"2022-07-08T13:50:53.329917Z","iopub.status.idle":"2022-07-08T13:50:53.499305Z","shell.execute_reply.started":"2022-07-08T13:50:53.329868Z","shell.execute_reply":"2022-07-08T13:50:53.498580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf train val test","metadata":{"execution":{"iopub.status.busy":"2022-07-08T13:50:53.503855Z","iopub.execute_input":"2022-07-08T13:50:53.504329Z","iopub.status.idle":"2022-07-08T13:50:54.217180Z","shell.execute_reply.started":"2022-07-08T13:50:53.504079Z","shell.execute_reply":"2022-07-08T13:50:54.216169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}