{"cells":[{"metadata":{"_uuid":"4d62ffdb23c156b4ae88a8398634a5484e5b15c0"},"cell_type":"markdown","source":"Bagging several runs\n- Trying to ensemble modes 1, 3, and 4 with weights 3, 2, and 1 respectively\n\n11/6/2018 7:09AM\n- Ensemble of runs 1 and 10 with equal weighting between them\n\n11/9/2018 6:58AM\n- Ensemble of runs 1 and 11 with equal weighting\n\n11/9/2018/5:26PM\n- Setting threshold to 0.3\n- Change weighting from equal to 1/3 model1 and 2/3 model11"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"scrolled":true},"cell_type":"code","source":"from fastai.conv_learner import *\nfrom fastai.dataset import *\n\nimport pandas as pd \nimport numpy as np \n\nfrom time import time\nimport os\nfrom tqdm import tnrange, tqdm_notebook\nfrom scipy import ndimage\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"24945ffba4f23f6a3dbe4c8da6a5a5e4011f0bd6"},"cell_type":"code","source":"start = time()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"041a3ac6f5b4cb13d0d1873546e9ae7901081991","scrolled":true},"cell_type":"code","source":"os.listdir('../input/airbus-ship-detection')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"af2ba40c0442f3e0a90cabd14fd366c398f6841f"},"cell_type":"code","source":"os.listdir('../input/segmentation-mod1')","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"PATH = './'\nTRAIN = '../input/airbus-ship-detection/train_v2'\nTEST = '../input/airbus-ship-detection/test_v2'\nDETECTION = '../input/shipclassifier/test_sub2.csv'\nSEGMENTATION= '../input/airbus-ship-detection/train_ship_segmentations_v2.csv'\nMODELS = '../input/segmentation-mod1'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dca23d72582de6a82dc8d50dda558dd11697424d"},"cell_type":"code","source":"nw = 2\narch = resnet34","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a7d59877165d2ca5fcc9e83141557d2d4b0b0fb7"},"cell_type":"code","source":"train_names = [f for f in os.listdir(TRAIN)]\ntest_names = [f for f in os.listdir(TEST)]\ntr_n, val_n = train_test_split(train_names, test_size=0.05, random_state=42)\nclass_df = pd.read_csv(DETECTION)\nsegmentation_df = pd.read_csv(SEGMENTATION).set_index('ImageId')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a38887aea588f6818e35dffb60ec0c69a8863312"},"cell_type":"code","source":"test_names = list(class_df[class_df['EncodedPixels'].isnull()]['ImageId'])\ntest_names_nothing = list(class_df[~class_df['EncodedPixels'].isnull()]['ImageId'])\n# test_names = test_names[:20]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":false,"_uuid":"218faaa5a2a58e6a8955e1b152afa0ea746a7e86"},"cell_type":"code","source":"print(\"Only around %s of the test images have ships in them\" % (str(round(len(test_names) / class_df.shape[0], 3) * 100) + ' %'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7965717e932d323455a0d87ec1da133f2d7db916"},"cell_type":"code","source":"# We can remove the images without ships, the classifier will take care of them\ndef cut_empty(names):\n    return [name for name in names \n            if(type(segmentation_df.loc[name]['EncodedPixels']) != float)]\n\ntr_n_cut = cut_empty(tr_n)\nval_n_cut = cut_empty(val_n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5ba6a95686c3dfa89223ef9ae0dfc686566f8a9a"},"cell_type":"code","source":"def get_mask(img_id, df):\n    shape = (768,768)\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    masks = df.loc[img_id]['EncodedPixels']\n    if(type(masks) == float): return img.reshape(shape)\n    if(type(masks) == str): masks = [masks]\n    for mask in masks:\n        s = mask.split()\n        for i in range(len(s)//2):\n            start = int(s[2*i]) - 1\n            length = int(s[2*i+1])\n            img[start:start+length] = 1\n    return img.reshape(shape).T","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"10132a79198b0b25af13d58ff624ee4d5c94bb51"},"cell_type":"code","source":"class pdFilesDataset(FilesDataset):\n    def __init__(self, fnames, path, transform):\n        self.segmentation_df = pd.read_csv(SEGMENTATION).set_index('ImageId')\n        super().__init__(fnames, transform, path)\n    \n    def get_x(self, i):\n        img = open_image(os.path.join(self.path, self.fnames[i]))\n        if self.sz == 768: return img \n        else: return cv2.resize(img, (self.sz, self.sz))\n    \n    def get_y(self, i):\n        mask = np.zeros((768,768), dtype=np.uint8) if (self.path == TEST) \\\n            else get_mask(self.fnames[i], self.segmentation_df)\n        img = Image.fromarray(mask).resize((self.sz, self.sz)).convert('RGB')\n        return np.array(img).astype(np.float32)\n    \n    def get_c(self): return 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c9f6f6b850782963c40577e50c8175fbf46a7dbf"},"cell_type":"code","source":"def get_data(sz,bs):\n    tfms = tfms_from_model(arch, sz, crop_type=CropType.NO, tfm_y=TfmType.CLASS)\n    tr_names = tr_n if (len(tr_n_cut)%bs == 0) else tr_n[:-(len(tr_n_cut)%bs)] #cut incomplete batch\n    ds = ImageData.get_ds(pdFilesDataset, (tr_names,TRAIN), \n                (val_n_cut,TRAIN), tfms, test=(test_names,TEST))\n    md = ImageData(PATH, ds, bs, num_workers=nw, classes=None)\n    return md","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"17286209c2a8d8fe4cbb34be869df4de45732731"},"cell_type":"code","source":"cut,lr_cut = model_meta[arch]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f761137ebacccb7a339f8a690326596b902bc3cd"},"cell_type":"code","source":"def get_base(pre=True):              #load ResNet34 model\n    layers = cut_model(arch(pre), cut)\n    return nn.Sequential(*layers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"babd54706a30a59725e2258a825993b8c29df2a8"},"cell_type":"code","source":"class UnetBlock(nn.Module):\n    def __init__(self, up_in, x_in, n_out):\n        super().__init__()\n        up_out = x_out = n_out//2\n        self.x_conv  = nn.Conv2d(x_in,  x_out,  1)\n        self.tr_conv = nn.ConvTranspose2d(up_in, up_out, 2, stride=2)\n        self.bn = nn.BatchNorm2d(n_out)\n        \n    def forward(self, up_p, x_p):\n        up_p = self.tr_conv(up_p)\n        x_p = self.x_conv(x_p)\n        cat_p = torch.cat([up_p,x_p], dim=1)\n        return self.bn(F.relu(cat_p))\n\nclass SaveFeatures():\n    features=None\n    def __init__(self, m): self.hook = m.register_forward_hook(self.hook_fn)\n    def hook_fn(self, module, input, output): self.features = output\n    def remove(self): self.hook.remove()\n    \nclass Unet34(nn.Module):\n    def __init__(self, rn):\n        super().__init__()\n        self.rn = rn\n        self.sfs = [SaveFeatures(rn[i]) for i in [2,4,5,6]]\n        self.up1 = UnetBlock(512,256,256)\n        self.up2 = UnetBlock(256,128,256)\n        self.up3 = UnetBlock(256,64,256)\n        self.up4 = UnetBlock(256,64,256)\n        self.up5 = nn.ConvTranspose2d(256, 1, 2, stride=2)\n        \n    def forward(self,x):\n        x = F.relu(self.rn(x))\n        x = self.up1(x, self.sfs[3].features)\n        x = self.up2(x, self.sfs[2].features)\n        x = self.up3(x, self.sfs[1].features)\n        x = self.up4(x, self.sfs[0].features)\n        x = self.up5(x)\n        return x[:,0]\n    \n    def close(self):\n        for sf in self.sfs: sf.remove()\n            \nclass UnetModel():\n    def __init__(self,model,name='Unet'):\n        self.model,self.name = model,name\n\n    def get_layer_groups(self, precompute):\n        lgs = list(split_by_idxs(children(self.model.rn), [lr_cut]))\n        return lgs + [children(self.model)[1:]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6f31ac87e9c1e91973e051641d9f85b176c21c57"},"cell_type":"code","source":"def IoU(pred, targs):\n    pred = (pred > 0.5).astype(float)\n    intersection = (pred*targs).sum()\n    return intersection / ((pred+targs).sum() - intersection + 1.0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"af7fd0148a2e4153cb31bf4dbb3a5ec290c2701b"},"cell_type":"code","source":"def get_score(pred, true):\n    n_th = 10\n    b = 4\n    thresholds = [0.5 + 0.05*i for i in range(n_th)]\n    n_masks = len(true)\n    n_pred = len(pred)\n    ious = []\n    score = 0\n    for mask in true:\n        buf = []\n        for p in pred: buf.append(IoU(p,mask))\n        ious.append(buf)\n    for t in thresholds:   \n        tp, fp, fn = 0, 0, 0\n        for i in range(n_masks):\n            match = False\n            for j in range(n_pred):\n                if ious[i][j] > t: match = True\n            if not match: fn += 1\n        \n        for j in range(n_pred):\n            match = False\n            for i in range(n_masks):\n                if ious[i][j] > t: match = True\n            if match: tp += 1\n            else: fp += 1\n        score += ((b+1)*tp)/((b+1)*tp + b*fn + fp)       \n    return score/n_th","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"48f8244f193283baeb95e6343e69f98e00434218"},"cell_type":"code","source":"def split_mask(mask):\n    threshold = 0.3\n    threshold_obj = 30 #ignor predictions composed of \"threshold_obj\" pixels or less\n    labled,n_objs = ndimage.label(mask > threshold)\n    result = []\n    for i in range(n_objs):\n        obj = (labled == i + 1).astype(int)\n        if(obj.sum() > threshold_obj): result.append(obj)\n    return result","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a1a158d12204375bf223af08e861acfc4622185c"},"cell_type":"code","source":"def get_mask_ind(img_id, df, shape = (768,768)): #return mask for each ship\n    masks = df.loc[img_id]['EncodedPixels']\n    if(type(masks) == float): return []\n    if(type(masks) == str): masks = [masks]\n    result = []\n    for mask in masks:\n        img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n        s = mask.split()\n        for i in range(len(s)//2):\n            start = int(s[2*i]) - 1\n            length = int(s[2*i+1])\n            img[start:start+length] = 1\n        result.append(img.reshape(shape).T)\n    return result","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"318cdce2708c01a56fb666157a6e2cc4ed24dee7"},"cell_type":"code","source":"class Score_eval():\n    def __init__(self):\n        self.segmentation_df = pd.read_csv(SEGMENTATION).set_index('ImageId')\n        self.score, self.count = 0.0, 0\n        \n    def put(self,pred,name):\n        true = get_mask_ind(name, self.segmentation_df)\n        self.score += get_score(pred,true)\n        self.count += 1\n        \n    def evaluate(self):\n        return self.score/self.count","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a737f8093c010bd739464dfc4ea9b000e1a365a6"},"cell_type":"code","source":"def aug_unit(x,fwd=True,mask=False):\n    return x\n\ndef aug_flipV(x,fwd=True,mask=False):\n    return x.flip(2) if mask else x.flip(3)\n\ndef aug_flipH(x,fwd=True,mask=False):\n    return x.flip(1) if mask else x.flip(2)\n\ndef aug_T(x,fwd=True,mask=False):\n    return torch.transpose(x,1,2) if mask else torch.transpose(x,2,3)\n\ndef aug_rot_2(x,fwd=True,mask=False): #rotate pi/2\n    return aug_flipV(aug_flipH(x,fwd,mask),fwd,mask)\n\ndef aug_rot_4cr(x,fwd=True,mask=False): #rotate pi/4 counterclockwise\n    return aug_flipV(aug_T(x,fwd,mask),fwd,mask) if fwd else \\\n        aug_T(aug_flipV(x,fwd,mask),fwd,mask)\n\ndef aug_rot_4cw(x,fwd=True,mask=False): #rotate pi/4 clockwise\n    return aug_flipH(aug_T(x,fwd,mask),fwd,mask) if fwd else \\\n        aug_T(aug_flipH(x,fwd,mask),fwd,mask)\n\ndef aug_rot_2T(x,fwd=True,mask=False): #transpose and rotate pi/2\n    return aug_rot_2(aug_T(x,fwd,mask),fwd,mask)\n\ntrms_side_on = [aug_unit,aug_flipH]\ntrms_top_down = [aug_unit,aug_flipV]\ntrms_dihedral = [aug_unit,aug_flipH,aug_flipV,aug_T,aug_rot_2,aug_rot_2T,\n                 aug_rot_4cw,aug_rot_4cr]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"24d8486d1b2e222d807525b334c1f34321b4a491","scrolled":false},"cell_type":"code","source":"def enc_img(img):\n    return torch.transpose(torch.tensor(img),0,2).unsqueeze(0)\n\ndef dec_img(img):\n    return to_np(torch.transpose(img.squeeze(0),0,2))\n\ndef display_augs(x,augs=aug_unit):\n    columns = 4\n    n = len(augs)\n    rows = n//4 + 1\n    fig=plt.figure(figsize=(columns*4, rows*4))\n    img = enc_img(x)\n    for i in range(rows):\n        for j in range(columns):\n            idx = j+i*columns\n            if idx >= n: break\n            fig.add_subplot(rows, columns, idx+1)\n            plt.axis('off')\n            plt.imshow(dec_img(augs[idx](img)))\n    plt.show()\n    \nimg = np.array(Image.open(os.path.join(TEST, test_names[5])))\ndisplay_augs(img,trms_dihedral)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0fd555395004c747f5e2cfc3ebd7445638a0fdcf"},"cell_type":"code","source":"model_weighting = [('Dice_Unet34_768_1', 1), ('Dice_Unet34_768_11_p3', 1)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"470e74947920f3aa75bf98f737037c936cbdffc4"},"cell_type":"code","source":"def model_pred(learner, dl, F_save): #if use train dl, disable shuffling\n    learner.model.eval();\n    name_list = dl.dataset.fnames\n    num_batchs = len(dl)\n    t = tqdm(iter(dl), leave=False, total=num_batchs)\n    count = 0\n    for x,y in t:\n        py = to_np(torch.sigmoid(learn.model(V(x))))\n        batch_size = len(py)\n        for i in range(batch_size):\n            F_save(py[i],to_np(y[i]),name_list[count])\n            count += 1\n            \ndef pred_aug(learner, x,aug=[aug_unit]):\n    pred = []\n    for aug_cur in aug:\n        py = to_np(aug_cur(torch.sigmoid(learner.model(V(aug_cur(x)))),\n                           fwd=False, mask=True))\n        pred.append(py)\n    pred = np.stack(pred, axis=0).mean(axis=0)\n    return pred\n\n#if use train dl, disable shuffling\ndef model_pred_aug(learner1, learner2, dl, F_save, aug=[aug_unit]):\n#     for learner in learners:\n#         learner.model.eval()\n    learner1.model.eval()\n    learner2.model.eval()\n    name_list = dl.dataset.fnames\n    num_batchs = len(dl)\n    t = tqdm(iter(dl), leave=False, total=num_batchs)\n    count = 0\n    for x,y in t:\n        pred1 = pred_aug(learner1,x,aug)\n        pred1 = [i / 3 for i in pred1]\n        pred2 = pred_aug(learner2,x,aug)\n        pred2 = [i * 2 / 3 for i in pred2]\n        pred_full = [sum([x,y]) for x,y in zip(pred1,pred2)]\n        batch_size = len(pred_full)\n        for i in range(batch_size):\n            F_save(pred_full[i],to_np(y[i]),name_list[count])\n            count += 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"234c877b074889194ef164a4dc58d53156ca751e"},"cell_type":"code","source":"m = to_gpu(Unet34(get_base(False)))\nmodels = UnetModel(m)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"883fcff99b5d3288f4405bd95c0f155344024cc0"},"cell_type":"code","source":"sz = 768 #image size\nbs = 8  #batch size\nmd = get_data(sz,bs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"559cd3ab2a4c960b6d7d6273d1d0b32f05ba509e"},"cell_type":"code","source":"learn1 = ConvLearner(md, models)\nlearn1.models_path = '../input/segmentation-mod1'\nlearn1.load(model_weighting[0][0])\nlearn1.models_path = PATH\nlearn1.set_data(md)\nlearn2 = ConvLearner(md, models)\nlearn2.models_path = '../input/segmentation-mod1'\nlearn2.load(model_weighting[1][0])\nlearn2.models_path = PATH\nlearn2.set_data(md)\n# learn3 = ConvLearner(md, models)\n# learn3.models_path = '../input/segmentation-mod1'\n# learn3.load(model_weighting[2][0])\n# learn3.models_path = PATH\n# learn3.set_data(md)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"57ceee846cc14493e2e97620d5f59559bc145fc2"},"cell_type":"code","source":"def decode_mask(mask, shape=(768, 768)):\n    pixels = mask.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6659adbcb93ec35429946e3261909e0014fea82b"},"cell_type":"code","source":"ship_list_dict = []\nfor name in test_names_nothing:\n    ship_list_dict.append({'ImageId':name, 'EncodedPixels':np.nan})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f562a33cf9fe87b4cee7b6a30e0243272f2ec125"},"cell_type":"code","source":"def enc_test(yp, y, name):\n    masks = split_mask(yp)\n    if(len(masks) == 0): \n        ship_list_dict.append({'ImageId':name,'EncodedPixels':np.nan})\n    for mask in masks:\n        ship_list_dict.append({'ImageId':name,'EncodedPixels':decode_mask(mask)})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"97c87a7b75522ffbf1467d56eae8c2a197c43f43"},"cell_type":"code","source":"model_pred_aug(learn1, learn2, md.test_dl, enc_test, trms_dihedral)\npred_df = pd.DataFrame(ship_list_dict)\npred_df.to_csv('submission.csv', index=False, header=True)\nend = time() \nprint(\"Finished in %s minutes\" % str(round((end-start) / 60, 3)))","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}