{"cells":[{"metadata":{"_uuid":"84af4fad3760fe14e9fac9600db3eea2a4d2d38b","trusted":true},"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9b0f39480c912b963c128fc9aba7ba5e8e8790db","trusted":true},"cell_type":"code","source":"import os\nfrom pathlib import Path\nimport numpy as np\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nfrom fastai import *\nfrom fastai.vision import *\nfrom fastai.vision.image import *","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"578592d89c312a4dd1d49500dc31b1153007441d","trusted":true},"cell_type":"code","source":"import cv2\n\n# adapted from https://www.kaggle.com/iafoss/pretrained-resnet34-with-rgby-0-460-public-lb\ndef open_4_channel(fname):\n    fname = str(fname)\n    suffix = '.png'\n    # strip extension before adding color\n    if fname.endswith('.png') or fname.endswith('.tif'):\n        suffix = fname[-4:]\n        fname = fname[:-4]\n\n    colors = ['red','green','blue','yellow']\n    flags = cv2.IMREAD_GRAYSCALE\n    img = [cv2.imread(fname+'_'+color+suffix, flags).astype(np.float32)/255\n           for color in colors]\n    \n    x = np.stack(img, axis=-1)\n    return Image(pil2tensor(x, np.float32).float())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dfd4c9562fe1998c433f20740890c9489c246e66","trusted":true},"cell_type":"code","source":"import torchvision\n\n\nRESNET_ENCODERS = {\n    34: torchvision.models.resnet34,\n    50: torchvision.models.resnet50,\n    101: torchvision.models.resnet101,\n    152: torchvision.models.resnet152,\n}\n\n\nclass Resnet4Channel(nn.Module):\n    def __init__(self, encoder_depth=34, pretrained=True, num_classes=28, copy_extra_channel=False, adjust_first_layer=False):\n        super().__init__()\n\n        encoder = RESNET_ENCODERS[encoder_depth](pretrained=pretrained)\n        \n        # we initialize this conv to take in 4 channels instead of 3\n        # we keeping corresponding weights and initializing new weights with zeros\n        # this trick taken from https://www.kaggle.com/iafoss/pretrained-resnet34-with-rgby-0-460-public-lb\n        w = encoder.conv1.weight\n        self.conv1 = nn.Conv2d(4, 64, kernel_size=7, stride=2, padding=3,\n                               bias=False)\n        if copy_extra_channel:\n            to_concat = w[:, :1, :, :].clone() \n        else:\n            to_concat = torch.zeros(64,1,7,7)\n        self.conv1.weight = nn.Parameter(torch.cat((w,to_concat),dim=1) * (0.75 if adjust_first_layer else 1.))\n        \n        self.bn1 = encoder.bn1\n        self.relu = nn.ReLU(inplace=True) \n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n\n        self.layer1 = encoder.layer1\n        self.layer2 = encoder.layer2\n        self.layer3 = encoder.layer3\n        self.layer4 = encoder.layer4\n        \n        self.avgpool = encoder.avgpool\n        self.fc = nn.Linear(512 * (1 if encoder_depth==34 else 4), num_classes)\n        \n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.view(x.size(0), -1)\n        x = self.fc(x)\n\n        return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"421b54b4eacdb0fbb968b6cfc6efaf81e5a79bf7","trusted":true},"cell_type":"code","source":"bs = 64","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"366daf5b625090b1daa6ffdcff40aa2fbd795ac0","trusted":true},"cell_type":"code","source":"path = Path('/kaggle/input/')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"811c6e37deba202dcd6aeb6316ba229e3c870c45","trusted":true},"cell_type":"code","source":"df = pd.read_csv(path/'train.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"133d8c5fe465edaba2abf617bcf30192c18a76d2","trusted":true},"cell_type":"code","source":"np.random.seed(42)\nsrc = (ImageItemList.from_csv(path, 'train.csv', folder='train', suffix='.png')\n       .random_split_by_pct(0.2)\n       .label_from_df(sep=' ',  classes=[str(i) for i in range(28)]))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"79b9d3ae823c5629200369fba7f041fffaf176e6","trusted":true},"cell_type":"code","source":"src.train.x.create_func = open_4_channel\nsrc.train.x.open = open_4_channel","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2f5b64d0dd9bb9276d2ef467df30090bf4cada20","trusted":true},"cell_type":"code","source":"src.valid.x.create_func = open_4_channel\nsrc.valid.x.open = open_4_channel","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8432bb36a87fa1f67991a3da98df4bbfdeafa1e7","trusted":true},"cell_type":"code","source":"test_ids = list(sorted({fname.split('_')[0] for fname in os.listdir(path/'test')}))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"90d387bee47d397197262f3d2878276f7f18fe1e","trusted":true},"cell_type":"code","source":"test_fnames = [path/'test'/test_id for test_id in test_ids]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f4dc8a3242ac6f3752586e8568699fee18066be8","trusted":true},"cell_type":"code","source":"test_fnames[:5]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"66a7ee9d95af8f2466630e6ba83e5f4148414d98","trusted":true},"cell_type":"code","source":"src.add_test(test_fnames, label='0');","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"da327815e7e8838f509fea020fa740467b448a25","trusted":true},"cell_type":"code","source":"src.test.x.create_func = open_4_channel\nsrc.test.x.open = open_4_channel","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"66c6ae2dfc261c3bb8441dd378cea4600eed4582","trusted":true},"cell_type":"code","source":"protein_stats = ([0.08069, 0.05258, 0.05487, 0.08282], [0.13704, 0.10145, 0.15313, 0.13814])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"97076b09aae64afd7f3ef9693cede40cc48d2170","trusted":true},"cell_type":"code","source":"trn_tfms,_ = get_transforms(do_flip=True, flip_vert=True, max_rotate=30., max_zoom=1,\n                      max_lighting=0.05, max_warp=0.)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b3ade52b2a865b88640a23ee611075f7b3843fe3","trusted":true},"cell_type":"code","source":"data = (src.transform((trn_tfms, _), size=224)\n        .databunch(num_workers=0).normalize(protein_stats))","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"_uuid":"6960bd15aa8cc8dd2186f35943cec58aa372a39c","trusted":true},"cell_type":"code","source":"data.show_batch(rows=3, figsize=(12,9))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5a4f5c25ba6c1046f319340fd4fe50b258d7b333","trusted":true},"cell_type":"code","source":"def resnet50(pretrained):\n    return Resnet4Channel(encoder_depth=50)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fbac05ed2ecc263c0a49d90fa2aa7c93caa730e7","trusted":true},"cell_type":"code","source":"# copied from https://github.com/fastai/fastai/blob/master/fastai/vision/learner.py\ndef _resnet_split(m): return (m[0][6],m[1])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"08a347185653eb01711d0ba29ac6ece1d35dcd5f","trusted":true},"cell_type":"code","source":"f1_score = partial(fbeta, thresh=0.2, beta=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5612414a8bfc88b3d588a10d981fc25231ce633a","trusted":true},"cell_type":"code","source":"learn = create_cnn(\n    data,\n    resnet50,\n    cut=-2,\n    split_on=_resnet_split,\n    loss_func=F.binary_cross_entropy_with_logits,\n    path=path,    \n    metrics=[f1_score],\n    model_dir=\"/tmp/models/\"\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d1e652b3ab6b11d253d653550e5c9c392a08417e","trusted":true},"cell_type":"code","source":"learn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ae6f5b9ec71977f52eec63b0420cbb71527051e9","trusted":false},"cell_type":"code","source":"learn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ad57339f8d10b4a8cd464a427acb262a07d8e878","trusted":false},"cell_type":"code","source":"lr = 3e-2","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"455d0e242a4596050726c3f79ab0f192c2771dd3","trusted":false},"cell_type":"code","source":"learn.fit_one_cycle(1, slice(lr))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7e9ef764547ac7ce7cf7a1a7351bee56851f2478","trusted":false},"cell_type":"code","source":"learn.save('stage-1-rn50-test')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d1668987e5d94e99a2983bfd7ef12e6504683c18","trusted":false},"cell_type":"code","source":"learn.unfreeze()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5a7b19f731d999610a9869eba53e7e0f2183b824","trusted":false},"cell_type":"code","source":"learn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"83ab66d8803a1babc9c4b5ef2a1f8c1945348229","trusted":false},"cell_type":"code","source":"learn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a099e61282cb48b29fe4738685b6721a87b6e136","trusted":false},"cell_type":"code","source":"learn.fit_one_cycle(2, slice(3e-5, lr/5))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"402a910bd69d418b3068c7e5a99cf08085bfb1dd","trusted":false},"cell_type":"code","source":"learn.save('stage-2-rn50-test')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7faca9cc29a386474d4eaba305ef45080372df22","trusted":false},"cell_type":"code","source":"preds,_ = learn.get_preds(DatasetType.Test)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f388bcfcc5d93fe60dd06a44e3fe98954b01b0f8","trusted":true},"cell_type":"code","source":"pred_labels = [' '.join(list([str(i) for i in np.nonzero(row>0.2)[0]])) for row in np.array(preds)]\ndf = pd.DataFrame({'Id':test_ids,'Predicted':pred_labels})\ndf.to_csv('submission.csv', header=True, index=False)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fdb6396415a511a0647482ae27cacb39e0639d3d","trusted":false},"cell_type":"code","source":"","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}