{"cells":[{"metadata":{"trusted":true,"_uuid":"d6f60b9310cb530e5fcc85996e34dcd72a682ed9","collapsed":true},"cell_type":"markdown","source":"# About\nThis kernel applies the techniques from [fastai's deep learning for coders](http://course.fast.ai) course to the dogbreed dataset"},{"metadata":{"_uuid":"afcd8e8dd979b486f79ab93024919385512f8b6c"},"cell_type":"markdown","source":"# Setup"},{"metadata":{"trusted":true,"_uuid":"5a674f59254a466d513b1da27f29c376a4189077"},"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from fastai.imports import *\nfrom fastai.torch_imports import *\nfrom fastai.transforms import *\nfrom fastai.conv_learner import *\nfrom fastai.model import *\nfrom fastai.dataset import *\nfrom fastai.sgdr import *\nfrom fastai.plots import *\n\nimport numpy as np\nimport pandas as pd\nimport os","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f80a0d652ce47b635762c588a08a7cd3f1228c10"},"cell_type":"code","source":"# make sure CUDA is available and enabled\nprint(torch.cuda.is_available(), torch.backends.cudnn.enabled)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"757c972a4a09135d485312103733c6c913bba44f"},"cell_type":"markdown","source":"## Helper functions to deal with Kaggle's file system limitations"},{"metadata":{"trusted":true,"_uuid":"452e9c56eef7dbfec1cf8d4b79ba87ddbd4d34e6"},"cell_type":"code","source":"comp_name = \"dog_breed\"\ninput_path = \"../input/\"\nwd = \"/kaggle/working/\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"33212a6282001211ee99774fa9025d13d0180eb1"},"cell_type":"code","source":"def create_symlnk(src_dir, src_name, dst_name, dst_dir=wd, target_is_dir=False):\n    \"\"\"\n    If symbolic link does not already exist, create it by pointing dst_dir/lnk_name to src_dir/lnk_name\n    \"\"\"\n    if not os.path.exists(dst_dir + dst_name):\n        os.symlink(src=src_dir + src_name, dst = dst_dir + src_name, target_is_directory=target_is_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"773368f01443c76f8542d12ea4f408f28ae576be"},"cell_type":"code","source":"def clean_up(wd=wd):\n    \"\"\"\n    Delete all temporary directories and symlinks in working directory (wd)\n    \"\"\"\n    for root, dirs, files in os.walk(wd):\n        try:\n            for d in dirs:\n                if os.path.islink(d):\n                    os.unlink(d)\n                else:\n                    shutil.rmtree(d)\n            for f in files:\n                if os.path.islink(f):\n                    os.unlink(f)\n                else:\n                    print(f)\n        except FileNotFoundError as e:\n            print(e)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7dd5fe0af3d0f43f557f79f4737064daee5fb80c"},"cell_type":"code","source":"create_symlnk(input_path, \"train\", \"train\", target_is_dir=True)\ncreate_symlnk(input_path, \"test\", \"test\", target_is_dir=True)\ncreate_symlnk(input_path, \"labels.csv\", \"labels.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7f66d48f5f81dd239b83aa829c1d9930fbb0a09e"},"cell_type":"code","source":"# perform sanity check\n!ls -alh","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"markdown","source":"# Exploration"},{"metadata":{"trusted":true,"_uuid":"e77d0fe71a92829af547b49f9aaf258ffd74ea26"},"cell_type":"code","source":"label_df = pd.read_csv(f\"{wd}labels.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7f36a34cbbc85776a3da8f37ca60425a1dad9ddb"},"cell_type":"code","source":"label_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f5bab0c79e4a021acd527a9d3eb81d091c9b680f"},"cell_type":"code","source":"label_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f96bf5c4965083ee33a6df7bd6f735d1a1b36e0e"},"cell_type":"code","source":"label_df.pivot_table(index=\"breed\", aggfunc=len).sort_values(\"id\", ascending=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9b07ba79cdeecae7176fcafda71961cc4563218d"},"cell_type":"code","source":"# create validation dataset\nval_idxs = get_cv_idxs(label_df.shape[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e1481b420fcf11165bc1db7b624d7548db5a1acb"},"cell_type":"code","source":"# define architecture\narch = resnet101\nsz = 224\nbs = 64","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b9851b602583e0d39dd94ffec360e7e14e9716c4"},"cell_type":"code","source":"# load data\ntfms = tfms_from_model(arch, sz, aug_tfms=transforms_side_on, max_zoom=1.1)\ndata = ImageClassifierData.from_csv(path=wd, folder=\"train\", csv_fname=f\"{wd}labels.csv\", tfms=tfms, val_idxs=val_idxs, suffix=\".jpg\", test_name=\"test\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e7739489ca1f7c4123578e9cb3ef0062f3d41ead"},"cell_type":"code","source":"[print(len(e)) for e in [data.trn_ds, data.val_ds, data.test_ds]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ecbfe0cbfecdfbfe6a1d4a19b5e26a96fe53c1e1"},"cell_type":"code","source":"# look at an actual image\nfn = wd + data.trn_ds.fnames[-1]\nimg = PIL.Image.open(fn); img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3107ad0563db465cdb5217304c3b6df17910f9c2"},"cell_type":"code","source":"img.size","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f5d247eb0edcae92e07995860005a2d7ddd926cd"},"cell_type":"markdown","source":"# Preprocess data"},{"metadata":{"trusted":true,"_uuid":"e1fff62362c444062c7c1eddd8c8d62e113deaca"},"cell_type":"code","source":"def get_data(sz=sz, bs=bs, data=data):\n    \"\"\"\n    Load images via fastai's ImageClassifierData.from_csv() object defined as 'data' before\n    Return images if size bigger than 300 pixels, else resize to 340 pixels\n    \"\"\"\n    return data if sz > 300 else data.resize(340, new_path=wd)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c8e8aa073a39ab3df1dba5dcdb29a655a95d868a"},"cell_type":"code","source":"data2 = get_data()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a1d286b831d6c6d09a82b244076e09662a9ad2da"},"cell_type":"markdown","source":"# Model"},{"metadata":{"_uuid":"de7ee619b3d13ce5a8ff484a62aef5617774510d"},"cell_type":"markdown","source":"## Baseline"},{"metadata":{"trusted":true,"_uuid":"178af9dd4f5a7b82cb0dcf094c3b3103354fbe8d"},"cell_type":"code","source":"learn = ConvLearner.pretrained(arch, data2, precompute=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"06feb6b93e91d6c2728b351bb0e1e50fa83b640d"},"cell_type":"code","source":"lrf = learn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a69becfb315d7d9481bbaabd7c9802c9751e9378"},"cell_type":"code","source":"learn.sched.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a7a55d205a5749ac1ba1eaa8c826e99700497c64"},"cell_type":"code","source":"# fit baseline model without data augmentation\nlearn.fit(1e-1, 2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0a9d9f105d5a5da7f31e7975e33e344d44c35ae4"},"cell_type":"code","source":"# disable precompute and fit model with data augmentation\nlearn.precompute=False\nlearn.fit(1e-1, 5, cycle_len=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b533f0001b6d6ff19a5dda4de2c07b5f40557be2"},"cell_type":"code","source":"#learn.save(\"224_pre\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d93d31a409cc634270fd46bccd9924c41af6cea9"},"cell_type":"code","source":"#learn.load(\"224_pre\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5f4ba2030fbaea81340da1823316d3f058b97d02"},"cell_type":"markdown","source":"## Model with increased image size"},{"metadata":{"trusted":true,"_uuid":"86b9abea409c3955703094aff35d83b53806ffb6"},"cell_type":"code","source":"learn.set_data(get_data(299, bs))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ec48978bef80f3dc596bdd9c1e3222bcbfc1b1b6"},"cell_type":"code","source":"learn.fit(1e-1, 3, cycle_len=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ff5c07603b8e2f26a18ea3e0922d1915fd335de4"},"cell_type":"code","source":"from sklearn.metrics import log_loss\n\nlog_preds, y = learn.TTA()\nprobs = np.mean(np.exp(log_preds), 0)\naccuracy_np(probs, y), log_loss(y, probs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"978ec932c90ceb52b3e1ff736c8be521a48caf3c"},"cell_type":"code","source":"#learn.save(\"299_pre\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e334a8a3bbfd69afa26d4635a0e6d0463de0c23f"},"cell_type":"code","source":"#learn.load(\"299_pre\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"636b1434ef412b390e54f00604f3546d39d47b60"},"cell_type":"markdown","source":"## Prediction on test set"},{"metadata":{"trusted":true,"_uuid":"7f461be7ef885644ebef38e764827a8a1623e2d5"},"cell_type":"code","source":"log_preds_test, y_test = learn.TTA(is_test=True)\nprobs_test = np.mean(np.exp(log_preds_test), 0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f5572c87471970966f5440ba0c73c2e6359660a7"},"cell_type":"markdown","source":"# Submission"},{"metadata":{"trusted":true,"_uuid":"ef430d71dafafb5b71ae84c7570d2f298cc18ccd"},"cell_type":"code","source":"df = pd.DataFrame(probs_test)\ndf.columns = data.classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"69ae992a321efb9b18164776dc089d3d53c235bb"},"cell_type":"code","source":"# insert clean ids - without folder prefix and .jpg suffix - of images as first column\ndf.insert(0, \"id\", [e[5:-4] for e in data.test_ds.fnames])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"87acfa74126c554b5fa3a6f74046a56a11d83b22"},"cell_type":"code","source":"df.to_csv(f\"sub_{comp_name}_{str(arch.__name__)}.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d7f6b351e772bd99810de6e7e6d74a80cba5aa59"},"cell_type":"markdown","source":"# Cleanup"},{"metadata":{"trusted":true,"_uuid":"fb18a2bc3f3988a89d66b069030deeefa6674e7d"},"cell_type":"code","source":"clean_up()","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}