{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"## Modules\nimport torch\nimport numpy as np\nfrom fastai import *\nfrom fastai.vision import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## EfficientNet\n# https://www.kaggle.com/chopinforest/efficientnetb4-fastai-blindness-detection/data\nimport sys\nsys.path.append('../input/efficientnet-pytorch/efficientnet-pytorch/EfficientNet-PyTorch-master')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Random State\nSEED = 4\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)\ntorch.cuda.manual_seed(SEED)\ntorch.backends.cudnn.deterministic = True","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Prepare Data\nimport pandas as pd\n\ntrain = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\n\ntrain.diagnosis.hist(); train.diagnosis.value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Our models will have a tendency to overfit to classes 0 and 2. A stratified train/test split will provide a validation set with a similar distribution as the training data, but will improperly test the model's ability to classify the disease intensity across the board. We need a validation set that will represent the model's true discriminative power. \n\nLet's take 15% of each class stratified, but limit the over-represented classes (0 and 2) to 15% of the least-represented class (3). "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train/Test Split\nlimit = int(193 * 0.15)\nzer = train[train.diagnosis == 0].sample(n=limit)\none = train[train.diagnosis == 1].sample(frac=0.15)\ntwo = train[train.diagnosis == 2].sample(n=limit)\nthr = train[train.diagnosis == 3].sample(frac=0.15)\nfou = train[train.diagnosis == 4].sample(frac=0.15)\nvalid = pd.concat([zer, one, two, thr, fou])\ntrain = train.drop(valid.index)\n\ntrain['is_valid'] = False\nvalid['is_valid'] = True\n\ntrain.diagnosis.hist(); valid.diagnosis.hist()\n\ntrain = pd.concat([train, valid])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Append File Extensions\nappend_ext = lambda fname: fname + '.jpeg' if '_' in fname else fname + '.png'\ntrain.id_code = train.id_code.apply(append_ext)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Extract\n! tar -xzf ../input/aptos2019-224/train_images.tar.gz -C ./","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data Loader\n# https://www.kaggle.com/drhabib/starter-kernel-for-0-79\n\nbs = 128\ntfms = get_transforms(do_flip=True, flip_vert=True, max_rotate=180, max_zoom=1.1,\n                      max_lighting=0.2, max_warp=0., p_affine=0.75, p_lighting=0.5)\ndata = (ImageList.from_df(train, path='./train_images', cols='id_code')\n        .split_from_df()\n        .label_from_df(label_cls=CategoryList) \n        .transform(tfms, padding_mode='zeros')\n        .databunch(bs=bs)\n        .normalize(imagenet_stats))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Training\n# QWK\nimport torch\nfrom sklearn.metrics import cohen_kappa_score as cks\n\ndef qwk(y_pred, y_true):\n    score = cks(torch.argmax(y_pred, dim=-1), y_true, weights='quadratic')\n    return torch.tensor(score, device='cuda:0')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Model\nfrom efficientnet_pytorch import EfficientNet\n\nmodel = EfficientNet.from_name('efficientnet-b0')\nmodel.load_state_dict(torch.load('../input/efficientnet-pytorch/efficientnet-b0-08094119.pth'))\nin_features = model._fc.in_features\nmodel._fc = nn.Linear(in_features, 5)  # Classification","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Model and Learner\nfrom fastai.callbacks import *\n\nsgd = partial(optim.SGD, momentum=0.9, weight_decay=1e-5, nesterov=True)\nlearn = Learner(\n    data, model, opt_func=sgd, metrics=[qwk],\n    path='./', callback_fns=[CSVLogger]).to_fp16()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train\nepochs = 30\nlength = len(learn.data.train_dl) * epochs\nanneal = [TrainingPhase(length).schedule_hp('lr', (1e-2, 1e-3), anneal=annealing_cos)]\ncallbacks = [GeneralScheduler(learn, anneal),\n             SaveModelCallback(learn, monitor='qwk', name='best_qwk')]\nlearn.fit(epochs, callbacks=callbacks)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Export Model\nlearn.load('best_qwk')\nlearn.export()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Cleanup\nimport shutil\nshutil.rmtree('./models')\nshutil.rmtree('./train_images')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"}},"nbformat":4,"nbformat_minor":1}