{"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":"from __future__ import print_function\nfrom __future__ import division\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport os\nimport random\nimport PIL\n\nfrom skimage.io import imread, imshow, concatenate_images\nfrom skimage import io, transform\nfrom skimage.measure import label, regionprops\n\nfrom tabulate import tabulate\n\nfrom pandas.core.internals.construction import fill_masked_arrays\nimport imageio\nfrom glob import glob\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision\nfrom torchvision import datasets, models, transforms\nfrom torchvision import transforms\nfrom torchvision import datasets\n\nimport time\nimport os\nimport copy\nimport random","metadata":{"id":"pbI2cfRF97Uh","execution":{"iopub.status.busy":"2022-05-12T15:26:35.846136Z","iopub.execute_input":"2022-05-12T15:26:35.846663Z","iopub.status.idle":"2022-05-12T15:26:35.853360Z","shell.execute_reply.started":"2022-05-12T15:26:35.846625Z","shell.execute_reply":"2022-05-12T15:26:35.852695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Take a first look at the data","metadata":{}},{"cell_type":"code","source":"train = os.listdir(\"../input/ships-and-ts/train_v2\")","metadata":{"execution":{"iopub.status.busy":"2022-05-12T15:26:37.279073Z","iopub.execute_input":"2022-05-12T15:26:37.279637Z","iopub.status.idle":"2022-05-12T15:26:37.299130Z","shell.execute_reply.started":"2022-05-12T15:26:37.279598Z","shell.execute_reply":"2022-05-12T15:26:37.298386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Count data files: {len(train)}\")","metadata":{"id":"udEpWdoq-_tW","outputId":"94aa2755-7490-4489-ac0b-da7a8084ec30","execution":{"iopub.status.busy":"2022-05-12T15:26:39.391809Z","iopub.execute_input":"2022-05-12T15:26:39.392529Z","iopub.status.idle":"2022-05-12T15:26:39.397374Z","shell.execute_reply.started":"2022-05-12T15:26:39.392477Z","shell.execute_reply":"2022-05-12T15:26:39.396695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(\"../input/ships-and-ts/train_ship_segmentations_v2.csv\", index_col=0).dropna()\ndisplay(df.head())","metadata":{"id":"8PxKhP1XEjBD","outputId":"ba83eb8b-d99c-4c37-d82b-52fb0591dc70","execution":{"iopub.status.busy":"2022-05-12T15:26:41.163630Z","iopub.execute_input":"2022-05-12T15:26:41.164320Z","iopub.status.idle":"2022-05-12T15:26:41.185836Z","shell.execute_reply.started":"2022-05-12T15:26:41.164283Z","shell.execute_reply":"2022-05-12T15:26:41.185040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_for_count = pd.read_csv(os.path.join('../input/ships-and-ts/train_ship_segmentations_v2.csv'))\nprint(f\"Count images in segmentation file {df_for_count['ImageId'].value_counts().shape[0]}\")","metadata":{"id":"ua-pYMXZG_yq","outputId":"22cb6570-c0ba-4edf-ec66-b047e6c097eb","execution":{"iopub.status.busy":"2022-05-12T15:26:43.614643Z","iopub.execute_input":"2022-05-12T15:26:43.615289Z","iopub.status.idle":"2022-05-12T15:26:43.632835Z","shell.execute_reply.started":"2022-05-12T15:26:43.615247Z","shell.execute_reply":"2022-05-12T15:26:43.632081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with_ships = df_for_count.dropna()\nwith_ships = with_ships.groupby('ImageId').size().reset_index(name='counts')\nwithout_ships = df_for_count[df_for_count['EncodedPixels'].isna()]","metadata":{"execution":{"iopub.status.busy":"2022-05-12T15:26:45.898380Z","iopub.execute_input":"2022-05-12T15:26:45.898839Z","iopub.status.idle":"2022-05-12T15:26:45.910661Z","shell.execute_reply.started":"2022-05-12T15:26:45.898795Z","shell.execute_reply":"2022-05-12T15:26:45.909895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Images with ships: {with_ships.shape[0]}\")\nprint(f\"Images without ships on it: {without_ships.shape[0]}\")\nprint(f\"Proportion: {round(with_ships.shape[0] / without_ships.shape[0], 3)}\")","metadata":{"execution":{"iopub.status.busy":"2022-05-12T15:26:47.845476Z","iopub.execute_input":"2022-05-12T15:26:47.846344Z","iopub.status.idle":"2022-05-12T15:26:47.852305Z","shell.execute_reply.started":"2022-05-12T15:26:47.846300Z","shell.execute_reply":"2022-05-12T15:26:47.851497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15, 6))\nplt.subplot(1,2,1)\nplt.bar(['With ships','Without ships'], [len(with_ships),len(without_ships)], color = ['blue','green'])\nplt.ylabel('Number of images')\nplt.title('Train availability comparison')\nplt.grid()","metadata":{"id":"e0IMNSs4Hb8U","outputId":"98d33af3-65c8-4ce8-87dd-8d1255ba3757","execution":{"iopub.status.busy":"2022-05-12T15:27:51.382309Z","iopub.execute_input":"2022-05-12T15:27:51.382598Z","iopub.status.idle":"2022-05-12T15:27:51.583338Z","shell.execute_reply.started":"2022-05-12T15:27:51.382565Z","shell.execute_reply":"2022-05-12T15:27:51.582532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusion: my dataset is not very cool, but it is too irrational to make it better only for the classifier.","metadata":{}},{"cell_type":"code","source":"counts = with_ships['counts'].value_counts(sort=False)\nprint(tabulate([(i, counts[i]) for i in range(1,16)], headers=['num of ships','num of images']))","metadata":{"id":"nUdaTeuKIlrs","outputId":"34db2611-591f-4718-db59-94a25a08bf64","execution":{"iopub.status.busy":"2022-05-12T15:27:55.348002Z","iopub.execute_input":"2022-05-12T15:27:55.348262Z","iopub.status.idle":"2022-05-12T15:27:55.354954Z","shell.execute_reply.started":"2022-05-12T15:27:55.348233Z","shell.execute_reply":"2022-05-12T15:27:55.354197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"w, h = 3, 3\nload_img = lambda filename: np.array(PIL.Image.open(f\"../input/ships-and-ts/train_v2/{filename}\").resize((200, 200)))\n_, axes_list = plt.subplots(h, w, figsize=(2*w, 2*h))\n\nfor axes in axes_list:\n    for ax in axes:\n        ax.axis('off')\n        img = np.random.choice(train)\n        ax.imshow(load_img(img))\n        ax.set_title(img)","metadata":{"id":"kBR0vJ4ADkTY","outputId":"e573668f-14ba-45e1-b8d3-2787ae2d3b7f","execution":{"iopub.status.busy":"2022-05-12T15:27:59.122072Z","iopub.execute_input":"2022-05-12T15:27:59.122610Z","iopub.status.idle":"2022-05-12T15:27:59.786577Z","shell.execute_reply.started":"2022-05-12T15:27:59.122571Z","shell.execute_reply":"2022-05-12T15:27:59.785897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Dimensions: {PIL.Image.open(\"../input/ships-and-ts/train_v2/000155de5.jpg\").size}')","metadata":{"id":"QsBl3FUsC6FG","outputId":"51bdc956-8c3a-431e-8955-006482084a69","execution":{"iopub.status.busy":"2022-05-12T14:43:45.276050Z","iopub.execute_input":"2022-05-12T14:43:45.276273Z","iopub.status.idle":"2022-05-12T14:43:45.287266Z","shell.execute_reply.started":"2022-05-12T14:43:45.276240Z","shell.execute_reply":"2022-05-12T14:43:45.286543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoader\n","metadata":{"id":"iV6ocxuknA0_"}},{"cell_type":"code","source":"def make_classes(csv_file, start, lenght):\n    img_labels = pd.read_csv(csv_file, index_col=0)\n    img_labels['Class'] = img_labels['EncodedPixels'].notnull()\n    img_labels = img_labels.groupby(\"ImageId\").agg(['first'])\n    img_labels = img_labels.drop(['EncodedPixels'], axis = 1)\n    img_labels.columns = ['Class']\n    return img_labels[start: start + lenght + 1]\n\nclass Ships_Dataset(Dataset):\n    def __init__(self, csv_file, data_folder, start, lenght, transform=None):\n        self.labels = make_classes(csv_file, start, lenght)\n        self.transform = transform\n        self.data_folder = data_folder\n        \n    def __len__(self):\n        return len(self.labels)\n    \n    def __getitem__(self, idx):\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n        img_name = os.path.join(self.data_folder,\n                            self.labels.index[idx])\n        image = io.imread(img_name)\n        label = self.labels.iloc[idx][0]\n        label = label.astype('int')\n        if self.transform:\n            image = self.transform(image)\n        return image, label","metadata":{"id":"onssY6KsnKx1","execution":{"iopub.status.busy":"2022-05-12T14:43:45.288431Z","iopub.execute_input":"2022-05-12T14:43:45.288618Z","iopub.status.idle":"2022-05-12T14:43:45.298965Z","shell.execute_reply.started":"2022-05-12T14:43:45.288594Z","shell.execute_reply":"2022-05-12T14:43:45.298116Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Parameters for the model","metadata":{}},{"cell_type":"code","source":"num_classes = 2\nbatch_size = 30\nnum_epochs = 35\nfeature_extract = True","metadata":{"execution":{"iopub.status.busy":"2022-05-12T14:43:45.300449Z","iopub.execute_input":"2022-05-12T14:43:45.300744Z","iopub.status.idle":"2022-05-12T14:43:45.307330Z","shell.execute_reply.started":"2022-05-12T14:43:45.300695Z","shell.execute_reply":"2022-05-12T14:43:45.306600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Function for training the model and displaying statistics","metadata":{}},{"cell_type":"code","source":"def train_model(model, dataloaders, criterion, optimizer, num_epochs=25):\n    since = time.time()\n    val_acc_history = []\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n        print('-' * 10)\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()\n            else:\n                model.eval()\n            running_loss = 0.0\n            running_corrects = 0\n            for (inputs, labels) in dataloaders[phase]:\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n                optimizer.zero_grad()\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(inputs)\n                    loss = criterion(outputs, labels)\n                    _, preds = torch.max(outputs, 1)\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n            epoch_loss = running_loss / len(dataloaders[phase].dataset)\n            epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = copy.deepcopy(model.state_dict())\n            if phase == 'val':\n                val_acc_history.append(epoch_acc)\n        print()\n    time_elapsed = time.time() - since\n    print(f'Training time: {time_elapsed // 60}m {time_elapsed % 60}s')\n    print(f'Best score: {best_acc}')\n    model.load_state_dict(best_model_wts)\n    \n    return model, val_acc_history","metadata":{"execution":{"iopub.status.busy":"2022-05-12T14:43:45.308669Z","iopub.execute_input":"2022-05-12T14:43:45.309231Z","iopub.status.idle":"2022-05-12T14:43:45.322373Z","shell.execute_reply.started":"2022-05-12T14:43:45.309190Z","shell.execute_reply":"2022-05-12T14:43:45.321689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Init the model","metadata":{}},{"cell_type":"code","source":"def set_parameter_requires_grad(model, feature_extracting):\n    if feature_extracting:\n        for param in model.parameters():\n            param.requires_grad = False\n\ndef initialize_model(num_classes, feature_extract, use_pretrained=True):\n    model_ft = models.densenet121(pretrained=use_pretrained)\n    set_parameter_requires_grad(model_ft, feature_extract)\n    num_ftrs = model_ft.classifier.in_features\n    model_ft.classifier = nn.Linear(num_ftrs, num_classes)\n    input_size = 224\n    return model_ft, input_size\n\nmodel_ft, input_size = initialize_model(num_classes, feature_extract, use_pretrained=True)","metadata":{"execution":{"iopub.status.busy":"2022-05-12T14:43:45.323565Z","iopub.execute_input":"2022-05-12T14:43:45.324080Z","iopub.status.idle":"2022-05-12T14:43:48.319732Z","shell.execute_reply.started":"2022-05-12T14:43:45.324041Z","shell.execute_reply":"2022-05-12T14:43:48.319023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Transform data","metadata":{}},{"cell_type":"code","source":"data_transforms = transforms.Compose([\n        transforms.ToPILImage(),\n        transforms.Resize(input_size),\n        transforms.CenterCrop(input_size),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\n\ndata = {\n    'train':\n    Ships_Dataset('../input/ships-and-ts/train_ship_segmentations_v2.csv', '../input/ships-and-ts/train_v2', 0, 1500,  transform=data_transforms),\n    'val':\n    Ships_Dataset('../input/ships-and-ts/train_ship_segmentations_v2.csv', '../input/ships-and-ts/train_v2', 1500, 500,  transform=data_transforms)\n\n}\n\ndataloaders_dict = {\n    'train': DataLoader(data['train'], batch_size=batch_size, shuffle=True),\n    'val': DataLoader(data['val'], batch_size=batch_size, shuffle=True)\n}\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-05-12T14:43:48.320845Z","iopub.execute_input":"2022-05-12T14:43:48.321096Z","iopub.status.idle":"2022-05-12T14:43:48.425637Z","shell.execute_reply.started":"2022-05-12T14:43:48.321062Z","shell.execute_reply":"2022-05-12T14:43:48.424894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Optimizer","metadata":{}},{"cell_type":"code","source":"model_ft = model_ft.to(device)\nparams_to_update = model_ft.parameters()\noptimizer_ft = optim.SGD(params_to_update, lr=0.001, momentum=0.9)","metadata":{"execution":{"iopub.status.busy":"2022-05-12T14:43:48.426812Z","iopub.execute_input":"2022-05-12T14:43:48.428153Z","iopub.status.idle":"2022-05-12T14:43:51.697170Z","shell.execute_reply.started":"2022-05-12T14:43:48.428113Z","shell.execute_reply":"2022-05-12T14:43:51.696412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train model","metadata":{}},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\nmodel_ft, hist = train_model(model_ft, dataloaders_dict, criterion, optimizer_ft, num_epochs=num_epochs)","metadata":{"execution":{"iopub.status.busy":"2022-05-12T14:43:51.698418Z","iopub.execute_input":"2022-05-12T14:43:51.698642Z","iopub.status.idle":"2022-05-12T15:05:07.175479Z","shell.execute_reply.started":"2022-05-12T14:43:51.698611Z","shell.execute_reply":"2022-05-12T15:05:07.174695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Save model","metadata":{}},{"cell_type":"code","source":"save_path = './ships_model.pth'\ntorch.save(model_ft.state_dict(), save_path)","metadata":{"execution":{"iopub.status.busy":"2022-05-12T15:05:07.176924Z","iopub.execute_input":"2022-05-12T15:05:07.177767Z","iopub.status.idle":"2022-05-12T15:05:07.299617Z","shell.execute_reply.started":"2022-05-12T15:05:07.177725Z","shell.execute_reply":"2022-05-12T15:05:07.298693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visualize accuracy","metadata":{}},{"cell_type":"code","source":"hist_list = [h.cpu().numpy() for h in hist]\nplt.figure(figsize=(16, 7))\nplt.plot(hist_list)\nplt.xlabel('Iteration')\nplt.ylabel('Accuracy')\nplt.title('Learning progress and epochs comparison')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-05-12T15:05:07.301288Z","iopub.execute_input":"2022-05-12T15:05:07.301689Z","iopub.status.idle":"2022-05-12T15:05:07.538784Z","shell.execute_reply.started":"2022-05-12T15:05:07.301648Z","shell.execute_reply":"2022-05-12T15:05:07.537362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n### Test model and visualize predictions","metadata":{}},{"cell_type":"code","source":"model = initialize_model(num_classes, feature_extract, use_pretrained=True)[0]\nmodel_dict = torch.load('../input/model-ships/ships_model.pth')\nmodel.load_state_dict(model_dict)\nmodel.eval()\n\nfilenames = os.listdir('../input/test-for-ships-and-ts')\npreds_list = []\nimages_list = []\n\nfor i in range(16):\n    id = random.randint(0, 2024)\n    input_image = PIL.Image.open(f'../input/test-for-ships-and-ts/{filenames[id]}')\n    \n    preprocess = transforms.Compose([\n        transforms.Resize(256),\n        transforms.CenterCrop(224),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ])\n    input_tensor = preprocess(input_image)\n    input_batch = input_tensor.unsqueeze(0)\n\n    if torch.cuda.is_available():\n        input_batch = input_batch.to('cuda')\n        model.to('cuda')\n\n    with torch.no_grad():\n        output = model(input_batch)\n    _, preds = torch.max(output, 1)\n\n    preds_list.append(preds[0])\n    images_list.append(input_image)\n\nw, h = 4, 4\n_, axes_list = plt.subplots(h, w, figsize=(2*w, 2*h))\nphoto_index = 0\nfor axes in axes_list:\n    for ax in axes:\n        ax.axis('off')\n        ax.imshow(images_list[photo_index])\n        ax.set_title(f'{preds_list[photo_index] == 1}')\n        photo_index += 1","metadata":{"execution":{"iopub.status.busy":"2022-05-12T15:08:16.913261Z","iopub.execute_input":"2022-05-12T15:08:16.913530Z","iopub.status.idle":"2022-05-12T15:08:19.813111Z","shell.execute_reply.started":"2022-05-12T15:08:16.913500Z","shell.execute_reply":"2022-05-12T15:08:19.809133Z"},"trusted":true},"execution_count":null,"outputs":[]}]}