{"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":"markdown","source":"# pip-installs and load libraries","metadata":{}},{"cell_type":"code","source":"!pip install tensorflow\n!pip install patchify\n!pip install segmentation-models","metadata":{"execution":{"iopub.status.busy":"2023-06-15T08:26:07.803713Z","iopub.execute_input":"2023-06-15T08:26:07.804059Z","iopub.status.idle":"2023-06-15T08:26:37.845363Z","shell.execute_reply.started":"2023-06-15T08:26:07.804037Z","shell.execute_reply":"2023-06-15T08:26:37.844311Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%env SM_FRAMEWORK=tf.keras\nimport segmentation_models as sm\nimport tensorflow as tf\nimport keras\nimport albumentations as A\nimport torch\nimport csv\nfrom torch import nn\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nimport numpy as np\nimport random\nfrom random import randrange, shuffle\nfrom matplotlib import pyplot as plt\nimport matplotlib.patches as patches\nfrom torchvision import transforms\nfrom torchvision.transforms.functional import rotate\nimport torchvision\nimport cv2\nimport time, glob\nimport PIL\nimport pandas as pd \nimport torch.utils.data as data\nimport csv\nimport glob\nimport os\nfrom sklearn.model_selection import train_test_split\nimport pickle\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\nfrom patchify import patchify, unpatchify\n\n\nos.environ['CUDA_VISIBLE_DEVICES'] = '0'\nROOT_DIR = \"../input/airbus-ship-detection\"\ntest_folder = os.path.join(ROOT_DIR, 'test_v2')\ntrain_folder = os.path.join(ROOT_DIR, 'train_v2')","metadata":{"execution":{"iopub.status.busy":"2023-06-15T08:26:37.847401Z","iopub.execute_input":"2023-06-15T08:26:37.847740Z","iopub.status.idle":"2023-06-15T08:26:52.070223Z","shell.execute_reply.started":"2023-06-15T08:26:37.847708Z","shell.execute_reply":"2023-06-15T08:26:52.068998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in tqdm(range(10)):\n    print(i)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T08:26:52.071651Z","iopub.execute_input":"2023-06-15T08:26:52.072323Z","iopub.status.idle":"2023-06-15T08:26:52.094741Z","shell.execute_reply.started":"2023-06-15T08:26:52.072300Z","shell.execute_reply":"2023-06-15T08:26:52.093547Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Check file sizes","metadata":{}},{"cell_type":"code","source":"file_sizes = []\nfor filename in tqdm(os.listdir(train_folder)):\n    file_sizes.append(os.stat(os.path.join(train_folder, filename)).st_size / 1024)","metadata":{"execution":{"iopub.status.busy":"2023-06-13T09:09:29.395904Z","iopub.execute_input":"2023-06-13T09:09:29.396293Z","iopub.status.idle":"2023-06-13T09:18:21.403917Z","shell.execute_reply.started":"2023-06-13T09:09:29.396265Z","shell.execute_reply":"2023-06-13T09:18:21.402534Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.mean(file_sizes), np.std(file_sizes), np.min(file_sizes), np.max(file_sizes)","metadata":{"execution":{"iopub.status.busy":"2023-06-13T09:26:33.476885Z","iopub.execute_input":"2023-06-13T09:26:33.477374Z","iopub.status.idle":"2023-06-13T09:26:33.584700Z","shell.execute_reply.started":"2023-06-13T09:26:33.477338Z","shell.execute_reply":"2023-06-13T09:26:33.583529Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(list(filter(lambda x: x < 50, file_sizes)))","metadata":{"execution":{"iopub.status.busy":"2023-06-13T09:27:11.655228Z","iopub.execute_input":"2023-06-13T09:27:11.655657Z","iopub.status.idle":"2023-06-13T09:27:11.691994Z","shell.execute_reply.started":"2023-06-13T09:27:11.655625Z","shell.execute_reply":"2023-06-13T09:27:11.690733Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Finding\n\nNo empty files","metadata":{}},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"markdown","source":"## 1. Check image shapes, to confirm they are all 768x768x3","metadata":{}},{"cell_type":"code","source":"for folder in [test_folder, train_folder]:\n    for filename in tqdm(os.listdir(folder)):\n        img = PIL.Image.open(os.path.join(folder, filename))\n        if img.size != (768, 768):\n            print(f\"{filename} in {folder} has size {img.size}\")","metadata":{"execution":{"iopub.status.busy":"2023-06-15T08:28:19.640640Z","iopub.execute_input":"2023-06-15T08:28:19.641042Z","iopub.status.idle":"2023-06-15T09:02:04.713601Z","shell.execute_reply.started":"2023-06-15T08:28:19.641010Z","shell.execute_reply":"2023-06-15T09:02:04.711447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Ships distribution","metadata":{}},{"cell_type":"code","source":"def load_df(file=\"train\"):\n    df = pd.read_csv(f\"/kaggle/input/airbus-ship-detection/train_ship_segmentations_v2.csv\")\n    df['HasShip'] = df['EncodedPixels'].notnull()\n    df = df.groupby(\"ImageId\").agg({'HasShip': ['first', 'sum']}) # counts amount of ships per image, sets ImageId to index\n    df.columns = ['HasShip', 'TotalShips']\n    return df\n\ndef show_df(df):\n    \"\"\"\n    Prints and displays the ship/no-ship ratio and the ship count distribution of df\n    \"\"\"\n    total = len(df)\n    ship = df['HasShip'].sum()\n    no_ship = total - ship\n    total_ships = int(df['TotalShips'].sum())\n        \n    print(f\"Images: {total} \\nShips:  {total_ships}\")\n    print(f\"Images with ships:    {round(ship/total,2)} ({ship})\")\n    print(f\"Images with no ships: {round(no_ship/total,2)} ({no_ship})\")\n    \n    _, axes = plt.subplots(nrows=1, ncols=2, figsize=(30, 8), gridspec_kw = {'width_ratios':[1, 3]})\n    \n    # Plot ship/no-ship with a bar plot\n    ship_ratio = df['HasShip'].value_counts() / total\n    ship_ratio = ship_ratio.rename(index={True: 'Ship', False: 'No Ship'})\n    ship_ratio.plot.bar(ax=axes[0], color=['red', 'lime'], rot=0, title=\"Ship/No-ship distribution\");\n    \n    # Plot TotalShips distribution with a bar plot\n    total_ships_distribution = df.loc[df['HasShip'], 'TotalShips'].value_counts().sort_index() / ship\n    total_ships_distribution.plot(kind='bar', ax=axes[1], rot=0, title=\"Total ships distribution\");\n\ndf_train = load_df(\"train\")\nshow_df(df_train)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:02:04.718992Z","iopub.execute_input":"2023-06-15T09:02:04.719441Z","iopub.status.idle":"2023-06-15T09:02:06.742690Z","shell.execute_reply.started":"2023-06-15T09:02:04.719398Z","shell.execute_reply":"2023-06-15T09:02:06.741676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Finding 1\n\n### **22%** of train images contains ships and **>60%** of them contains only **1** ship. Therefore high chance that we have pixels-imbalance","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"../input/airbus-ship-detection/train_ship_segmentations_v2.csv\", index_col=0).dropna()\ndisplay(df.head())","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:02:06.744367Z","iopub.execute_input":"2023-06-15T09:02:06.744973Z","iopub.status.idle":"2023-06-15T09:02:07.369271Z","shell.execute_reply.started":"2023-06-15T09:02:06.744916Z","shell.execute_reply":"2023-06-15T09:02:07.367996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Patch image into squares, same ship's distribution analysis ","metadata":{}},{"cell_type":"code","source":"def rle_to_pixels(rle_code):\n    '''\n    Transforms a RLE code string into a list of pixels of a (768, 768) canvas\n    '''\n    rle_code = [int(i) for i in rle_code.split()]\n    pixels = [(pixel_position % 768, pixel_position // 768) \n                 for start, length in list(zip(rle_code[0:-1:2], rle_code[1::2])) \n                 for pixel_position in range(start, start + length)]\n    return pixels\n\ndef show_pixels_distribution(df):\n    \"\"\"\n    Prints the amount of ship and no-ship pixels in the df\n    \"\"\"\n    # Total images in the df\n    n_images = df['ImageId'].nunique() \n    \n    # Total pixels in the df\n    total_pixels = n_images * 768 * 768 \n\n    # Keep only rows with RLE boxes, transform them into list of pixels, sum the lengths of those lists\n    ship_pixels = df['EncodedPixels'].dropna().apply(rle_to_pixels).str.len().sum() \n\n    ratio = ship_pixels / total_pixels\n    print(f\"Ship: {round(ratio, 3)} ({ship_pixels})\")\n    print(f\"No ship: {round(1 - ratio, 3)} ({total_pixels - ship_pixels})\")\n    \n    \n# rle_to_pixels(' '.join(df['EncodedPixels']['000194a2d.jpg']))[0:3]\ndf_train = pd.read_csv(f\"/kaggle/input/airbus-ship-detection/train_ship_segmentations_v2.csv\")\n\nshow_pixels_distribution(df_train)\ndel df_train","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:02:07.372390Z","iopub.execute_input":"2023-06-15T09:02:07.372790Z","iopub.status.idle":"2023-06-15T09:02:43.148075Z","shell.execute_reply.started":"2023-06-15T09:02:07.372761Z","shell.execute_reply":"2023-06-15T09:02:43.146946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Finding\n\nThere is pixels-imbalance - ships are 0.1% of all pixels. To mitigate that at the data level we may\n\n1) Remove images with small portion of ship pixels\n\n2) Crop or resize images\n\nAt the model level we may take an advantage from binary focal loss","metadata":{}},{"cell_type":"code","source":"load_img = lambda filename: np.array(PIL.Image.open(os.path.join(train_folder, filename)))\n\ndef quadr_distibution(df, step=256):\n    total_area = 0\n    total_ships_area = 0\n    total_quadr_ship = 0\n    total_quadr = 0\n    \n    mask = np.zeros((768, 768))\n    print(df.shape)\n    new_paths = []\n    bad_labeling = []\n    for img_id in tqdm(np.unique(df.index)):\n        img = load_img(img_id)\n        mask = np.zeros((768, 768))\n        masks = rle_to_pixels(' '.join(df['EncodedPixels'][img_id]))\n        try:\n            mask[tuple(zip(*masks))] = 1\n            patch_img = patchify(img, (step,step, 3), step=step)\n            patch_mask = patchify(mask, (step,step), step=step)\n            total_quadr += (img.shape[0] // step) * (img.shape[1] // step)\n            for i in range(img.shape[0] // step):\n                for j in range(img.shape[1] // step):\n                    sm = patch_mask[i][j].sum()\n                    if sm != 0:\n                        new_paths.append((img_id, i, j))\n                        total_quadr_ship += 1\n                        total_area += step * step\n                        total_ships_area += sm\n        except:\n            print(f'bad encoding at {img_id}')\n            bad_labeling.append(img_id)\n        \n    print(f\"ships: {round(total_ships_area / total_area, 3)}\")\n    print(f\"no-ships: {round((total_area - total_ships_area) / total_area, 3)}\")\n    print(f\"quadr_ship: {total_quadr_ship}, ratio = {round(total_quadr_ship / total_quadr, 3)}\")\n    return new_paths\nsix_paths = []\nsix_paths = quadr_distibution(df.dropna()[:], 128)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:02:43.149497Z","iopub.execute_input":"2023-06-15T09:02:43.150170Z","iopub.status.idle":"2023-06-15T09:13:02.413578Z","shell.execute_reply.started":"2023-06-15T09:02:43.150139Z","shell.execute_reply":"2023-06-15T09:13:02.412011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Finding 2\n\nThere are several bad encoding - index is out of the image, I skip them. Then I try to split image into 6x6 squares each 128x128, and check ship-pixels distribution there. Once I count only images with ships I get **4.1%** of ship pixels. This has to a) speed up model training; b) Help with convergance","metadata":{}},{"cell_type":"code","source":"print(len(six_paths))\nwith open('six_paths.pkl', 'wb') as f:\n    pickle.dump(six_paths, f)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:13:02.422163Z","iopub.execute_input":"2023-06-15T09:13:02.422442Z","iopub.status.idle":"2023-06-15T09:13:02.473405Z","shell.execute_reply.started":"2023-06-15T09:13:02.422417Z","shell.execute_reply":"2023-06-15T09:13:02.472337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4. Conclusion at EDA part","metadata":{}},{"cell_type":"markdown","source":"# Data preparation","metadata":{}},{"cell_type":"markdown","source":"## 1. Data loaders and train/val split","metadata":{}},{"cell_type":"markdown","source":"For proper train-valid split I split them by inage_path, so no overlap (any hidden information) between train and validation. Proportion is **95%/5%**.","metadata":{}},{"cell_type":"code","source":"with open('/kaggle/input/six-paths-93504/six_paths (1).pkl', 'rb') as f:\n    six_paths = pickle.load(f)\nprint(len(six_paths))","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:14:43.974185Z","iopub.execute_input":"2023-06-15T09:14:43.974670Z","iopub.status.idle":"2023-06-15T09:14:44.046479Z","shell.execute_reply.started":"2023-06-15T09:14:43.974633Z","shell.execute_reply":"2023-06-15T09:14:44.045491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_paths = [x[0] for x in six_paths]\nunique_imgs = np.unique(all_paths)\n\npercentile = 0.05\nunique_train, unique_val = train_test_split(unique_imgs, test_size=percentile, random_state=42)\n\ntrain_imgs, val_imgs = [], []\nfor path in tqdm(six_paths):\n    if path[0] in unique_val:\n        val_imgs.append(path)\n    else:\n        train_imgs.append(path)\nlen(train_imgs), len(val_imgs)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:14:45.927968Z","iopub.execute_input":"2023-06-15T09:14:45.928394Z","iopub.status.idle":"2023-06-15T09:14:48.440117Z","shell.execute_reply.started":"2023-06-15T09:14:45.928358Z","shell.execute_reply":"2023-06-15T09:14:48.438950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Finding\n\nI found out that there are images (squares) in train that has small portion of ship-pixels on it. So basically I decide to filter out squares that contains **<30** ship-pixels. Also I created a set with **11k** training samples that has **>=50** pixels (I will use it during model experiments)","metadata":{}},{"cell_type":"code","source":"min_area = 30\nareas = []\ncnt_removed = 0\nnew_train = []\nfor path in tqdm(train_imgs):\n    pxls = rle_to_pixels(' '.join(df['EncodedPixels'][path[0]]))\n    mask = np.zeros((768, 768))\n    mask[tuple(zip(*pxls))] = 1\n    step = 128\n    patch_mask = patchify(mask, (step,step), step=step)\n    area = patch_mask[path[1]][path[2]].sum()\n    \n    if area < min_area:\n        cnt_removed += 1\n    else:\n        new_train.append(path)\n    if area == 0:\n        print(path)\n    areas.append(area)\nprint(cnt_removed, cnt_removed / len(train_imgs))","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:15:11.083838Z","iopub.execute_input":"2023-06-15T09:15:11.084248Z","iopub.status.idle":"2023-06-15T09:28:21.775709Z","shell.execute_reply.started":"2023-06-15T09:15:11.084219Z","shell.execute_reply":"2023-06-15T09:28:21.774932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_small_amount = False\nif train_small_amount:\n    new_imgs = list(filter(lambda pp: pp[1] >= 0.1 * 128 * 128, zip(train_imgs, areas)))\n    len(new_imgs)\n    train_imgs = [x[0] for x in new_imgs]","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:39:14.630053Z","iopub.execute_input":"2023-06-15T09:39:14.631507Z","iopub.status.idle":"2023-06-15T09:39:14.637430Z","shell.execute_reply.started":"2023-06-15T09:39:14.631455Z","shell.execute_reply":"2023-06-15T09:39:14.636000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_imgs = new_train\nlen(train_imgs)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:39:25.080241Z","iopub.execute_input":"2023-06-15T09:39:25.080636Z","iopub.status.idle":"2023-06-15T09:39:25.089097Z","shell.execute_reply.started":"2023-06-15T09:39:25.080598Z","shell.execute_reply":"2023-06-15T09:39:25.087491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(areas))\nwith open('areas.pkl', 'wb') as f:\n    pickle.dump(areas, f)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:39:29.253295Z","iopub.execute_input":"2023-06-15T09:39:29.253705Z","iopub.status.idle":"2023-06-15T09:39:29.498049Z","shell.execute_reply.started":"2023-06-15T09:39:29.253675Z","shell.execute_reply":"2023-06-15T09:39:29.496292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(val_imgs))\nwith open('val_imgs.pkl', 'wb') as f:\n    pickle.dump(val_imgs, f)\nprint(len(train_imgs))\nwith open('train_imgs.pkl', 'wb') as f:\n    pickle.dump(train_imgs, f)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:39:44.329066Z","iopub.execute_input":"2023-06-15T09:39:44.329470Z","iopub.status.idle":"2023-06-15T09:39:44.355999Z","shell.execute_reply.started":"2023-06-15T09:39:44.329440Z","shell.execute_reply":"2023-06-15T09:39:44.354260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('/kaggle/input/airbus-loads/train_imgs.pkl', 'rb') as f:\n    train_imgs = pickle.load(f)\nwith open('/kaggle/input/airbus-loads/val_imgs.pkl', 'rb') as f:\n    val_imgs = pickle.load(f)\nlen(train_imgs), len(val_imgs)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:39:49.331101Z","iopub.execute_input":"2023-06-15T09:39:49.331470Z","iopub.status.idle":"2023-06-15T09:39:49.380714Z","shell.execute_reply.started":"2023-06-15T09:39:49.331444Z","shell.execute_reply":"2023-06-15T09:39:49.379964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check that all masks in train contains >= 30 ship px\nused_id = {}\nfor path in tqdm(train_imgs):\n    if path in used_id.keys():\n        continue\n    used_id[path] = \"used\"\n    qi, qj = path[1:]\n    pxls = rle_to_pixels(' '.join(df['EncodedPixels'][path[0]]))\n    mask = np.zeros((768, 768))\n    mask[tuple(zip(*pxls))] = 1\n    step = 128\n    patch_mask = patchify(mask, (step,step), step=step)\n    if patch_mask[qi][qj].sum() < 30:\n        print(f\"Bad at {path}\")","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:41:48.548903Z","iopub.execute_input":"2023-06-15T09:41:48.549307Z","iopub.status.idle":"2023-06-15T09:53:27.764362Z","shell.execute_reply.started":"2023-06-15T09:41:48.549283Z","shell.execute_reply":"2023-06-15T09:53:27.763324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To make it convenient I introduce custom dataset and dataloader which is suitable with [segmentation_models](https://github.com/qubvel/segmentation_models) library","metadata":{}},{"cell_type":"code","source":"class Dataloder(keras.utils.Sequence):\n    def __init__(self, dataset, batch_size=1, shuffle=False):\n        self.dataset = dataset\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.indexes = np.arange(len(dataset))\n\n        self.on_epoch_end()\n\n    def __getitem__(self, i):    \n        start = i * self.batch_size\n        stop = (i + 1) * self.batch_size\n        data = []\n        for j in range(start, stop):\n            data.append(self.dataset[j])\n        \n        batch = [np.stack(samples, axis=0) for samples in zip(*data)]\n        return batch\n    \n    def __len__(self):\n        return len(self.indexes) // self.batch_size\n    \n    def on_epoch_end(self):\n        if self.shuffle:\n            self.indexes = np.random.permutation(self.indexes)   ","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:53:27.765833Z","iopub.execute_input":"2023-06-15T09:53:27.766117Z","iopub.status.idle":"2023-06-15T09:53:27.775831Z","shell.execute_reply.started":"2023-06-15T09:53:27.766094Z","shell.execute_reply":"2023-06-15T09:53:27.774307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AirbusShipDataset():\n    \n    def __init__(self, root_paths, paths, labels_csv=None, transform=None,train=True,size=768,preprocessing_fn=None, augmentation=None):\n        self.root_paths = root_paths\n        self.paths = paths\n\n        if labels_csv:\n            self.masks = pd.read_csv(labels_csv)\n            self.masks = self.masks[~self.masks.EncodedPixels.isna()] \n        else:\n            self.masks = pd.DataFrame()\n        self.transform = transform\n        self.train = train\n        self.size = size\n\n        self.preprocessing_fn = preprocessing_fn\n        self.augmentation = augmentation\n\n    def __len__(self):\n        return len(self.paths)\n    \n    def getranditem(self):\n        ImageId, qi, qj = self.paths[randrange(self.__len__())]\n         \n        all_masks = np.zeros((768, 768))\n        img_masks = rle_to_pixels(' '.join(df['EncodedPixels'][ImageId]))\n        all_masks[tuple(zip(*img_masks))] = 1\n        \n        img_path = f\"{ROOT_DIR}/{self.root_paths}/{ImageId}\"\n        image = cv2.imread(img_path)\n\n        step = 128\n        patch_img = patchify(image, (step,step, 3), step=step)\n        patch_mask = patchify(all_masks, (step,step), step=step)\n        return patch_img[qi][qj][0], patch_mask[qi][qj]\n    \n    def __getitem__(self, idx):\n        ImageId, qi, qj = self.paths[idx]\n\n        all_masks = np.zeros((768, 768))\n        img_masks = rle_to_pixels(' '.join(df['EncodedPixels'][ImageId]))\n        all_masks[tuple(zip(*img_masks))] = 1\n\n        img_path = f\"{ROOT_DIR}/{self.root_paths}/{ImageId}\"\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)\n        \n        step = 128\n        patch_img = patchify(image, (step,step, 3), step=step)\n        patch_mask = patchify(all_masks, (step,step), step=step)\n        image, all_masks = patch_img[qi][qj][0], patch_mask[qi][qj]\n                \n        if self.augmentation and self.train:\n            sample = self.augmentation(image=image, mask=all_masks)\n            image, all_masks = sample['image'], sample['mask']\n        \n        if not self.train:\n            x =  image.transpose([2, 0, 1]).astype(np.float32)\n            x = x.astype(np.float32)\n            tf.cast(x, tf.float32)\n            return x, ImageId\n        \n        if self.preprocessing_fn is not None:\n            image = np.array(image)\n            sample = self.preprocessing_fn(image = image, mask=all_masks)\n            image, all_masks = sample['image'], sample['mask']\n        \n        image = image.astype(np.float32)\n        all_masks = all_masks.astype(np.float32)\n        tf.cast(image, tf.float32)\n        tf.cast(all_masks, tf.float32)     \n        return image, all_masks","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:53:27.778005Z","iopub.execute_input":"2023-06-15T09:53:27.778407Z","iopub.status.idle":"2023-06-15T09:53:27.799094Z","shell.execute_reply.started":"2023-06-15T09:53:27.778378Z","shell.execute_reply":"2023-06-15T09:53:27.797748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Check training samples","metadata":{}},{"cell_type":"markdown","source":"For training set I introduce basic augmentation - Flip, Rotate, Noise, Blur, Contrast - without Scaling / Shifting / Crops. ","metadata":{}},{"cell_type":"code","source":"BACKBONE = 'efficientnetb3'\npreprocess_input = sm.get_preprocessing(BACKBONE)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:53:27.803392Z","iopub.execute_input":"2023-06-15T09:53:27.804070Z","iopub.status.idle":"2023-06-15T09:53:27.818891Z","shell.execute_reply.started":"2023-06-15T09:53:27.804033Z","shell.execute_reply":"2023-06-15T09:53:27.817869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def round_clip_0_1(x, **kwargs):\n    return x.round().clip(0, 1)\n\n# define heavy augmentations\ndef get_training_augmentation():\n    train_transform = [\n        A.HorizontalFlip(p=0.5),\n        A.ShiftScaleRotate(scale_limit=0.0, rotate_limit=120, shift_limit=0.0, p=0.5),\n#         A.PadIfNeeded(min_height=320, min_width=320, always_apply=True, border_mode=0),\n#         A.RandomCrop(height=320, width=320, always_apply=True),\n        A.IAAAdditiveGaussianNoise(p=0.2),\n        A.IAAPerspective(p=0.5),\n        A.OneOf(\n            [\n                A.CLAHE(p=1),\n                A.RandomBrightness(p=1),\n                A.RandomGamma(p=1),\n            ],\n            p=0.9,\n        ),\n        A.OneOf(\n            [\n                A.IAASharpen(p=1),\n                A.Blur(blur_limit=3, p=1),\n                A.MotionBlur(blur_limit=3, p=1),\n            ],\n            p=0.9,\n        ),\n        A.OneOf(\n            [\n                A.RandomContrast(p=1),\n                A.HueSaturationValue(p=1),\n            ],\n            p=0.9,\n        ),\n        A.Lambda(mask=round_clip_0_1)\n    ]\n    return A.Compose(train_transform)\n\n\ndef get_validation_augmentation():\n    test_transform = []\n    return A.Compose(test_transform)\n\ndef get_preprocessing(preprocessing_fn):\n    _transform = [\n        A.Lambda(image=preprocessing_fn),\n    ]\n    return A.Compose(_transform)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:53:27.820145Z","iopub.execute_input":"2023-06-15T09:53:27.820427Z","iopub.status.idle":"2023-06-15T09:53:27.835472Z","shell.execute_reply.started":"2023-06-15T09:53:27.820405Z","shell.execute_reply":"2023-06-15T09:53:27.834564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainAirbusShipDataset = AirbusShipDataset(\"train_v2\",\n                                           train_imgs[:], \n                                           f\"{ROOT_DIR}/train_ship_segmentations_v2.csv\", \n                                           transform = None,\n                                           train=True,\n                                           preprocessing_fn=get_preprocessing(preprocess_input),\n                                           augmentation=get_training_augmentation()\n                                          )","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:53:27.836678Z","iopub.execute_input":"2023-06-15T09:53:27.837130Z","iopub.status.idle":"2023-06-15T09:53:28.570346Z","shell.execute_reply.started":"2023-06-15T09:53:27.837104Z","shell.execute_reply":"2023-06-15T09:53:28.569171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rle_encoder(image_mask):\n    \n    \"\"\" Change from 2d to 1d (x_size*y_size, 1) \n        for example: [[1, 2] , [3, 4]] -> [1,2,3,4] \n    \n    \"\"\"\n    size = image_mask.shape[0]*image_mask.shape[1]\n\n    \"\"\" Transpose operation \"\"\"\n    image_mask = image_mask.T\n    image_mask = image_mask.reshape(size)\n    result = \"\"\n    pointer = 0\n    count = 0\n    for pointer in range(size):\n\n        if image_mask[pointer]:\n            count += 1\n        elif count > 0:\n            result += f\"{pointer-count + 1} {count} \"\n            count = 0\n\n    return result if len(result) > 0 else np.nan\n\n\ndef rle_decoder(encodedPixels:list,shape:tuple):\n    x_size = shape[0]\n    y_size = shape[1]\n    img_mask = np.zeros(x_size*y_size, dtype=np.uint8)\n    \n    for encoded in encodedPixels:\n        mask_list = encoded.split()\n        \n        for inx in range(0,len(mask_list),2):\n            location = int(mask_list[inx]) - 1\n            length = int(mask_list[inx+1])\n            for l in range(location,location+length):\n                try:\n                    img_mask[l] = 1;\n                except IndexError as e:\n                    print(l)\n                    print(location,location+length)\n                    raise e\n            \n    \"\"\" Change from 1d to 2d (x_size,y_size) \n        for example: [1,2,3,4] - > [[1, 2] , [3, 4]]\n    \n    \"\"\"\n    img_mask = img_mask.reshape((x_size,y_size))\n    \n    \"\"\" Transpose operation \"\"\"\n    img_mask = img_mask.T\n\n    return img_mask","metadata":{"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2023-06-15T09:53:28.571538Z","iopub.execute_input":"2023-06-15T09:53:28.571871Z","iopub.status.idle":"2023-06-15T09:53:28.583514Z","shell.execute_reply.started":"2023-06-15T09:53:28.571843Z","shell.execute_reply":"2023-06-15T09:53:28.582046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(2, 5,figsize=(12, 6))\nfor i in range(5):\n    img, mask = trainAirbusShipDataset.getranditem()\n    axs[0][i].imshow(img)\n    axs[1][i].imshow(mask, cmap=\"gray\")\n    print(mask.sum())\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:53:28.584912Z","iopub.execute_input":"2023-06-15T09:53:28.585287Z","iopub.status.idle":"2023-06-15T09:53:29.961877Z","shell.execute_reply.started":"2023-06-15T09:53:28.585259Z","shell.execute_reply":"2023-06-15T09:53:29.960610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Check valid samples","metadata":{}},{"cell_type":"code","source":"validAirbusShipDataset = AirbusShipDataset(\"train_v2\",\n                                           val_imgs[:], \n                                           f\"{ROOT_DIR}/train_ship_segmentations_v2.csv\", \n                                           transform = None,\n                                           train=True,\n                                           preprocessing_fn=get_preprocessing(preprocess_input),\n                                           augmentation=get_validation_augmentation(),\n                                          )","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:57:51.944691Z","iopub.execute_input":"2023-06-15T09:57:51.945100Z","iopub.status.idle":"2023-06-15T09:57:52.681428Z","shell.execute_reply.started":"2023-06-15T09:57:51.945075Z","shell.execute_reply":"2023-06-15T09:57:52.679853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(2, 5,figsize=(12, 6))\nfor i in range(5):\n    img, mask = validAirbusShipDataset.getranditem()\n    axs[0][i].imshow(img)\n    axs[1][i].imshow(mask, cmap=\"gray\")\n    print(mask.sum())\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:57:53.028873Z","iopub.execute_input":"2023-06-15T09:57:53.029733Z","iopub.status.idle":"2023-06-15T09:57:54.338341Z","shell.execute_reply.started":"2023-06-15T09:57:53.029689Z","shell.execute_reply":"2023-06-15T09:57:54.337013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model training","metadata":{}},{"cell_type":"markdown","source":"## 1. Specify model architecture and run fit","metadata":{}},{"cell_type":"markdown","source":"Basic idea of model training - to use U-net with encoder weights (transfer learning), then freeze encoder and train only decoder part. Once it converges try to unfreeze leyer-by-layer from last to the first in encoder\n\n### Spoiler\n\nModel training takes much GPU time which is limited at Kaggle. There are some experiments to find out coverges speed, but setting high lr is not a panacea","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 128\nLR = 3e-3\nEPOCHS = 2\n\nn_classes = 1\nactivation = 'sigmoid'\nmodel = sm.Unet(BACKBONE, classes=n_classes, activation=activation, encoder_weights='imagenet', encoder_freeze=True)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:58:00.783945Z","iopub.execute_input":"2023-06-15T09:58:00.784328Z","iopub.status.idle":"2023-06-15T09:58:06.594712Z","shell.execute_reply.started":"2023-06-15T09:58:00.784303Z","shell.execute_reply":"2023-06-15T09:58:06.593131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras import backend as K\n\nfrom keras import backend as K\nimport numpy as np\nimport tensorflow as tf\nfrom scipy.ndimage import distance_transform_edt as distance\n\n\ndef calc_dist_map(seg):\n    res = np.zeros_like(seg)\n    posmask = seg.astype(np.bool)\n\n    if posmask.any():\n        negmask = ~posmask\n        res = distance(negmask) * negmask - (distance(posmask) - 1) * posmask\n\n    return res\n\n\ndef calc_dist_map_batch(y_true):\n    y_true_numpy = y_true.numpy()\n    return np.array([calc_dist_map(y)\n                     for y in y_true_numpy]).reshape(y_true.shape).astype(np.float32)\n\n\ndef surface_loss_keras(y_true, y_pred):\n    y_true_dist_map = tf.py_function(func=calc_dist_map_batch,\n                                     inp=[y_true],\n                                     Tout=tf.float32)\n    multipled = y_pred * y_true_dist_map\n    return K.mean(multipled)\n\n\nclass MixedLoss(nn.Module):\n    def __init__(self, dc_loss=sm.losses.DiceLoss(), focal_loss=sm.losses.BinaryFocalLoss()):\n        super().__init__()\n        self.dc_loss = dc_loss\n        self.focal_loss = focal_loss\n        \n    def __call__(self, gt, pr):\n#         return - tf.math.log(self.dc_loss.__call__(gt, pr)) + self.focal_loss.__call__(gt, pr)\n        return surface_loss_keras(gt, pr)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:58:06.597111Z","iopub.execute_input":"2023-06-15T09:58:06.597542Z","iopub.status.idle":"2023-06-15T09:58:06.607565Z","shell.execute_reply.started":"2023-06-15T09:58:06.597510Z","shell.execute_reply":"2023-06-15T09:58:06.606460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from keras.models import load_model\n# model.load_weights('/kaggle/input/airbus-models/best_model_24_05876_val.h5')","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:58:16.478102Z","iopub.execute_input":"2023-06-15T09:58:16.478469Z","iopub.status.idle":"2023-06-15T09:58:16.483859Z","shell.execute_reply.started":"2023-06-15T09:58:16.478445Z","shell.execute_reply":"2023-06-15T09:58:16.482748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optim = keras.optimizers.Adagrad(LR)\nalpha = 1.\ntotal_loss = sm.losses.DiceLoss()\n# total_loss = MixedLoss()\nmetrics = [sm.metrics.IOUScore(threshold=0.5), sm.losses.DiceLoss(), sm.losses.BinaryFocalLoss(alpha)]\n\nmodel.compile(optim, total_loss, metrics)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:58:18.673229Z","iopub.execute_input":"2023-06-15T09:58:18.673599Z","iopub.status.idle":"2023-06-15T09:58:18.702160Z","shell.execute_reply.started":"2023-06-15T09:58:18.673573Z","shell.execute_reply":"2023-06-15T09:58:18.701077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = trainAirbusShipDataset\nvalid_dataset = validAirbusShipDataset\n\ntrain_dataloader = Dataloder(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\nvalid_dataloader = Dataloder(valid_dataset, batch_size=BATCH_SIZE, shuffle=False)\n\ncallbacks = [\n    keras.callbacks.ModelCheckpoint('./best_model.h5', save_weights_only=True, save_best_only=True, mode='min'),\n    keras.callbacks.ReduceLROnPlateau(),\n    tf.keras.callbacks.TensorBoard(update_freq=\"batch\")\n]","metadata":{"execution":{"iopub.status.busy":"2023-06-15T09:58:19.710131Z","iopub.execute_input":"2023-06-15T09:58:19.710539Z","iopub.status.idle":"2023-06-15T09:58:19.718942Z","shell.execute_reply.started":"2023-06-15T09:58:19.710509Z","shell.execute_reply":"2023-06-15T09:58:19.717964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tf.device('/GPU:0'):\n    history = model.fit(\n        train_dataloader, \n        steps_per_epoch=len(train_dataloader), \n        epochs=EPOCHS, \n        callbacks=callbacks, \n        validation_data=valid_dataloader, \n        validation_steps=len(valid_dataloader),\n    )","metadata":{"execution":{"iopub.status.busy":"2023-06-14T08:46:17.555517Z","iopub.execute_input":"2023-06-14T08:46:17.555894Z","iopub.status.idle":"2023-06-14T09:49:31.439809Z","shell.execute_reply.started":"2023-06-14T08:46:17.555864Z","shell.execute_reply":"2023-06-14T09:49:31.438942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Experiments\n\nI have experimented with training data, losses and training procedures.\n\n### Training data\n\nAt first I have tried to train a model with 768x768 images. The bottleneck here was batch_size (which is 2 or 4 without out-of-memory error) that makes training so long. After that I brought to idea of spliting initial images into 128x128 images which allows to increase batch size up to 128. With some cleaning (remove low ship-pixels proportion images - < 30 pixels) it takes ~30 mins for epoch. The best model was trained for 4 epochs that took ~2.5 hours (with validation part) and best model is undertrained. I have tried to make cleaning more rough (<50 pixels), but valid loss converged much slower even for 25 epochs, however it still goes down as train loss. For one epoch it took 7-10 mins without validation, so for training 25_epoch it took ~4 hours. I guess it might be reduced once I specified higher learning rate at the very beginning. I set lr=3e-4 and I had to increase it after each 5 epochs 3 times.\n\n### Losses\n\nThere is basic DiceLoss which is ok to boost IoU score. Since there is pixels-imbalance there is binary focal loss metric. I did some experiments to combine these two metrics but it coverges much slower that pure DiceLoss despite of magnitude parameter. Also boosting Focal loss doesn't lead to straightforward IoU increase in this case.\n\nThe alernative is using [boundary loss](https://github.com/LIVIAETS/boundary-loss) that started to boost IoU score much faster than DiceLoss(0.11 vs 0.07 at 50-th batch). Nevertheless, after 2-4 epochs validation IoU was 40-50 and improvements slowed down.\n\nAlso I searched for other notebooks and found out FocalLoss - log(DiceLoss) but it didnt work nice, I just was curious whether non-monotonic loss might help someone - seems that no \n\n### Training procedures\n\nHere is no magic. I just proceeded training once model didn't converge. Also I have tried to pretrain model on 7-10 mins dataset to show images with more ship-pixels and then go back to 30 mins dataset. It performed not better then pure 4-epochs dice loss training procedure","metadata":{}},{"cell_type":"code","source":"# Plot training & validation iou_score values\nplt.figure(figsize=(30, 5))\nplt.subplot(121)\nplt.plot(history.history['iou_score'])\nplt.plot(history.history['val_iou_score'])\nplt.title('Model iou_score')\nplt.ylabel('iou_score')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Test'], loc='upper left')\n\n# Plot training & validation loss values\nplt.subplot(122)\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Model loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Test'], loc='upper left')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-13T11:36:52.649076Z","iopub.execute_input":"2023-06-13T11:36:52.650115Z","iopub.status.idle":"2023-06-13T11:36:53.211043Z","shell.execute_reply.started":"2023-06-13T11:36:52.650079Z","shell.execute_reply":"2023-06-13T11:36:53.210108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights('25-dice-small_train+2-usual_3e-3.h5')","metadata":{"execution":{"iopub.status.busy":"2023-06-14T09:49:52.971746Z","iopub.execute_input":"2023-06-14T09:49:52.972863Z","iopub.status.idle":"2023-06-14T09:49:53.612926Z","shell.execute_reply.started":"2023-06-14T09:49:52.972819Z","shell.execute_reply":"2023-06-14T09:49:53.611781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model evaluations ","metadata":{}},{"cell_type":"code","source":"from keras.models import load_model\n\nscores = {}\nfor model_path in os.listdir('/kaggle/input/airbus-models'):\n    if model_path not in scores.keys():\n        print(model_path)\n        model.load_weights(os.path.join('/kaggle/input/airbus-models', model_path))\n        print(f\"Evaluating {model_path}...\")\n        scores[model_path] = model.evaluate(valid_dataloader)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:01:35.921499Z","iopub.execute_input":"2023-06-15T10:01:35.921895Z","iopub.status.idle":"2023-06-15T10:30:38.658217Z","shell.execute_reply.started":"2023-06-15T10:01:35.921870Z","shell.execute_reply":"2023-06-15T10:30:38.656591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_weights(\"/kaggle/input/airbus-loads/best_model (1).h5\")\nmodel.evaluate(valid_dataloader)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:34:04.126300Z","iopub.execute_input":"2023-06-15T10:34:04.126757Z","iopub.status.idle":"2023-06-15T10:38:31.232810Z","shell.execute_reply.started":"2023-06-15T10:34:04.126718Z","shell.execute_reply":"2023-06-15T10:38:31.231410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Airbus-models dataset contains model I've obtained during experiments\n\n## Models\n\n### best_model.h5\nTrained for 2 epochs with Adam optimizer and DiceLoss loss\n\n\n### best_model (2)_maybe_best.h5\nTrained for 4 epochs with Adam optimizer and DiceLoss loss\n\n### best_model (3).h5\nExperimes with another losses\n\n### best_model_24_05876_val.h5\n\n25-dice-small_train.h5 model that is stopped at 24 epoch. 25-th epoch suprisingly dropped validation metric, maybe because of setting high lr \n\n### 25-dice-small_train2-usual_3e-3.h5\n\nProceed 25-dice-small_train.h5 model with 2 epochs from best_model.h5\n\n### 25-dice-small_train.h5\n\nTrained for 25 epochs with small train daat (images that contains >= 50 ship pixels. Good train IoU (>70), but poor validation despite validation is diminishing at each epoch\n\n### best_model (1).h5\n\n3 epochs","metadata":{}},{"cell_type":"markdown","source":"# Inference part","metadata":{}},{"cell_type":"markdown","source":"## 1. Check valid samples prediction","metadata":{}},{"cell_type":"code","source":"fig, axs = plt.subplots(3, 12,figsize=(24, 6))\n\nbatch, mask = valid_dataloader[0]\nthreshold = 0.5\npred = model.predict(batch)\npred[pred >= threshold] = 1\npred[pred < threshold] = 0\n\nfor i in range(12):\n    axs[0][i].imshow(batch[i])\n    axs[1][i].imshow(mask[i], cmap=\"gray\")\n    axs[2][i].imshow(np.squeeze(pred)[i], cmap=\"gray\")\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:30:38.661303Z","iopub.execute_input":"2023-06-15T10:30:38.661709Z","iopub.status.idle":"2023-06-15T10:30:53.205835Z","shell.execute_reply.started":"2023-06-15T10:30:38.661677Z","shell.execute_reply":"2023-06-15T10:30:53.204783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Inference code for test file","metadata":{}},{"cell_type":"code","source":"class TestDataset():\n    \n    def __init__(self, root_paths, paths, preprocessing_fn=None, split_into_squares=False, limit=None):\n        self.root_paths = root_paths\n        self.paths = paths[:limit] if split_into_squares == False else [(x,i,j) for x in paths[:limit] for i in range(6) for j in range(6)] \n        self.preprocessing_fn = preprocessing_fn\n       \n    def __len__(self):\n        return len(self.paths)\n    \n    def getranditem(self):\n        ImageId, qi, qj = self.paths[randrange(self.__len__())]\n         \n        img_path = f\"{ROOT_DIR}/{self.root_paths}/{ImageId}\"\n        image = cv2.imread(img_path)\n\n        step = 128\n        patch_img = patchify(image, (step,step, 3), step=step)\n        return patch_img[qi][qj][0], (ImageId, qi, qj)\n    \n    def __getitem__(self, idx):\n        ImageId, qi, qj = self.paths[idx]\n#         if not self.masks.empty:\n#             img_masks = self.masks.loc[self.masks['ImageId'] == ImageId, 'EncodedPixels'].tolist()\n#             all_masks = rle_decoder(img_masks, (768, 768))\n\n        img_path = f\"{ROOT_DIR}/{self.root_paths}/{ImageId}\"\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)\n        \n        step = 128\n        patch_img = patchify(image, (step,step, 3), step=step)\n        image = patch_img[qi][qj][0]                \n        \n        if self.preprocessing_fn is not None:\n            image = np.array(image)\n            sample = self.preprocessing_fn(image = image)\n            image = sample['image']\n        \n#         if not self.train:\n#             x =  image.transpose([2, 0, 1]).astype(np.float32)\n#             x = x.astype(np.float32)\n#             tf.cast(x, tf.float32)\n#             return x, ImageId\n        \n        image = image.astype(np.float32)\n        tf.cast(image, tf.float32)\n        return image, (ImageId, qi, qj)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:41:59.807829Z","iopub.execute_input":"2023-06-15T10:41:59.808326Z","iopub.status.idle":"2023-06-15T10:41:59.819867Z","shell.execute_reply.started":"2023-06-15T10:41:59.808289Z","shell.execute_reply":"2023-06-15T10:41:59.818991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_up_prediction(predictions):\n    num_images = predictions.shape[0] // 36\n    images_batch = predictions.squeeze().reshape((num_images, 36,128,128))\n    result = []\n#     print(images_batch.shape)\n    for batch in images_batch:\n#         print(batch.shape)\n        img = unpatchify(batch.reshape(6, 6, 128, 128), (768, 768))\n        threshold = 0.5\n        img[img >= threshold] = 1\n        img[img < threshold] = 0\n        result.append(img)\n    return result","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:50:17.415676Z","iopub.execute_input":"2023-06-15T10:50:17.416068Z","iopub.status.idle":"2023-06-15T10:50:17.422087Z","shell.execute_reply.started":"2023-06-15T10:50:17.416039Z","shell.execute_reply":"2023-06-15T10:50:17.421259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"testAirbusShipDataset = TestDataset(\"test_v2\",\n                                    os.listdir(test_folder), \n                                    preprocessing_fn=get_preprocessing(preprocess_input),\n                                    split_into_squares = True,\n                                    limit=100\n                                    )","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:42:02.855287Z","iopub.execute_input":"2023-06-15T10:42:02.855800Z","iopub.status.idle":"2023-06-15T10:42:02.872774Z","shell.execute_reply.started":"2023-06-15T10:42:02.855763Z","shell.execute_reply":"2023-06-15T10:42:02.870562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataloader = Dataloder(testAirbusShipDataset, batch_size=36, shuffle=False)\npredictions = model.predict(test_dataloader)","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:42:04.163140Z","iopub.execute_input":"2023-06-15T10:42:04.163637Z","iopub.status.idle":"2023-06-15T10:44:27.219957Z","shell.execute_reply.started":"2023-06-15T10:42:04.163597Z","shell.execute_reply":"2023-06-15T10:44:27.218047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions.shape","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:44:27.222347Z","iopub.execute_input":"2023-06-15T10:44:27.222758Z","iopub.status.idle":"2023-06-15T10:44:27.230494Z","shell.execute_reply.started":"2023-06-15T10:44:27.222724Z","shell.execute_reply":"2023-06-15T10:44:27.229048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions.squeeze().reshape((100, 36,128,128)).shape","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:48:43.914403Z","iopub.execute_input":"2023-06-15T10:48:43.914823Z","iopub.status.idle":"2023-06-15T10:48:43.922984Z","shell.execute_reply.started":"2023-06-15T10:48:43.914791Z","shell.execute_reply":"2023-06-15T10:48:43.921260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"maked_up = make_up_prediction(predictions)\nlen(maked_up), maked_up[0].shape","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:50:35.511372Z","iopub.execute_input":"2023-06-15T10:50:35.511785Z","iopub.status.idle":"2023-06-15T10:50:36.146339Z","shell.execute_reply.started":"2023-06-15T10:50:35.511754Z","shell.execute_reply":"2023-06-15T10:50:36.144967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(5, 5,figsize=(12, 12))\n\nfor i in range(25):\n    axs[i // 5][i % 5].imshow(maked_up[i], cmap=\"gray\")\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:54:13.555880Z","iopub.execute_input":"2023-06-15T10:54:13.556315Z","iopub.status.idle":"2023-06-15T10:54:18.169835Z","shell.execute_reply.started":"2023-06-15T10:54:13.556283Z","shell.execute_reply":"2023-06-15T10:54:18.168542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(5, 5,figsize=(12, 12))\n\nfor i in range(25):\n    im = PIL.Image.open(os.path.join(test_folder, os.listdir(test_folder)[i]))\n    axs[i // 5][i % 5].imshow(im)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-15T10:57:02.069243Z","iopub.execute_input":"2023-06-15T10:57:02.069701Z","iopub.status.idle":"2023-06-15T10:57:07.652540Z","shell.execute_reply.started":"2023-06-15T10:57:02.069666Z","shell.execute_reply":"2023-06-15T10:57:07.651042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = []\nthreshold = 0.5\n\nwith torch.no_grad():\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n    for batch_idx, (images, paths) in tqdm(enumerate(testLoaderAirbusShipDataset)):\n        images = images.to(device)\n        predictions[predictions >= threshold] = 1\n        predictions[predictions < threshold] = 0\n\n        for pred,path in zip(predictions,paths):\n            img_array = pred.squeeze().cpu().numpy()\n            submission.append({\"ImageId\":path,\"EncodedPixels\":rle_encoder(img_array)})\n\n","metadata":{},"execution_count":null,"outputs":[]}]}