{"cells":[{"metadata":{"_uuid":"eb81e8c36d6afa77a069840c00e938f27662eb84"},"cell_type":"markdown","source":"## Multi-label classification"},{"metadata":{"trusted":true,"_uuid":"59c7a8ec8c4a213b0ecffbb608dcde2f15f8f881"},"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1f61452ce03ba3d660213c5fbcee1e4a86d539b4"},"cell_type":"code","source":"!pip install fastai==0.7.0 --no-deps\n!pip install torch==0.4.1 torchvision==0.2.1\n\nfrom fastai.conv_learner import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dd96af55e101624816db66a42405b56ebaeedc23"},"cell_type":"code","source":"print(os.listdir(\"../input/\"))\nPATH = '../input/planet-understanding-the-amazon-from-space/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bdf55ddb21956ccbb76e9393a881239e3ebe4c06"},"cell_type":"code","source":"TMP_PATH = \"/tmp/tmp\"\nMODEL_PATH = \"/tmp/model\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c72d71168b06c0ea027b0c89e3b7069e5772f67a"},"cell_type":"code","source":"ls {PATH}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f0db5223e2b25531172d29b64e3abebacfe00bd5"},"cell_type":"code","source":"df = pd.read_csv(PATH+'sample_submission_v2.csv')\ndf.head(5)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"508d4c1acd59c049668ec6a20cdd563e72a3e2e3"},"cell_type":"markdown","source":"## Multi-label versus single-label classification"},{"metadata":{"trusted":true,"_uuid":"86898402cfaf40dd19d14d07a7ea14360ae1f6a4"},"cell_type":"code","source":"from fastai.plots import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a99e7bd6d63676b28b967d783861fa72be5d84a5"},"cell_type":"code","source":"def get_1st(path): return glob(f'{path}/*.*')[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7dfbae4f5915c2b8d704236ced03b19ea4167b59"},"cell_type":"code","source":"dc_path = '../input/newdogscats/dogscats/dogscats/train/'\nlist_paths = [get_1st(f\"{dc_path}cats\"), get_1st(f\"{dc_path}dogs\")]\nplots_from_files(list_paths, titles=[\"cat\", \"dog\"], maintitle=\"Single-label classification\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6952ac370c507ae8b43fd57a77a67e5f0352d914"},"cell_type":"markdown","source":"In single-label classification each sample belongs to one class. In the previous example, each image is either a *dog* or a *cat*."},{"metadata":{"trusted":true,"_uuid":"d91729c6d1ea092c12ba8a5e38d71b138078d8a7"},"cell_type":"code","source":"list_paths = [f\"{PATH}train-jpg/train_0.jpg\", f\"{PATH}train-jpg/train_1.jpg\"]\ntitles=[\"haze primary\", \"agriculture clear primary water\"]\nplots_from_files(list_paths, titles=titles, maintitle=\"Multi-label classification\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7deaef96834452dbd5d881bed04010eb939d0ee3"},"cell_type":"markdown","source":"In multi-label classification each sample can belong to one or more classes. In the previous example, the first images belongs to two classes: *haze* and *primary*. The second image belongs to four classes: *agriculture*, *clear*, *primary* and  *water*."},{"metadata":{"_uuid":"5ee39882680727347876c7f38a09a558a9c09578"},"cell_type":"markdown","source":"## Multi-label models for Planet dataset"},{"metadata":{"trusted":true,"_uuid":"f1c6a393498e63f1abf91cc4f0c9bd5f3a6cb8db"},"cell_type":"code","source":"# planet.py\n\nfrom fastai.imports import *\nfrom fastai.transforms import *\nfrom fastai.dataset import *\nfrom sklearn.metrics import fbeta_score\nimport warnings\n\ndef f2(preds, targs, start=0.17, end=0.24, step=0.01):\n    with warnings.catch_warnings():\n        warnings.simplefilter(\"ignore\")\n        return max([fbeta_score(targs, (preds>th), 2, average='samples')\n                    for th in np.arange(start,end,step)])\n\nmetrics=[f2]\nf_model = resnet34","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2bed4537cff6a89810487422b9f3ff96c6cff7b0"},"cell_type":"code","source":"label_csv = f'{PATH}train_v2.csv'\nn = len(list(open(label_csv)))-1\nval_idxs = get_cv_idxs(n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"abfff1da7c6e2f24c67894e7cdd7079f23cacfcd"},"cell_type":"markdown","source":"We use a different set of data augmentations for this dataset - we also allow vertical flips, since we don't expect vertical orientation of satellite images to change our classifications."},{"metadata":{"trusted":true,"_uuid":"60f6ef4831b9920cfbc4a2ab4f464713a480173b"},"cell_type":"code","source":"def get_data(sz):\n    tfms = tfms_from_model(f_model, sz, aug_tfms=transforms_top_down, max_zoom=1.05)\n    return ImageClassifierData.from_csv(PATH, 'train-jpg', label_csv, tfms=tfms,\n                    suffix='.jpg', val_idxs=val_idxs, test_name='test-jpg-v2')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ce62d48f4e78b1bdb3b87926be43683c33fb9376"},"cell_type":"code","source":"data = get_data(256)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"17e837b6160c80506444fb9f0e7664814e5626dd"},"cell_type":"code","source":"x,y = next(iter(data.val_dl))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d73c17e2bda6f25fd937ed752b3c7c4b85866325"},"cell_type":"code","source":"y","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cb756c38878953d057a36a284aa3850027fa8d45"},"cell_type":"code","source":"list(zip(data.classes, y[0]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ccb47a961eaf13098302314ce239564bae74285f"},"cell_type":"code","source":"plt.imshow(data.val_ds.denorm(to_np(x))[0]*1.4);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0e0b51614192860d1e94614f638a875970ffaffe"},"cell_type":"code","source":"sz=64","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"71aa581cd6f2fc04b09ead3154c93694474abeda"},"cell_type":"code","source":"data = get_data(sz)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2875c7055fc665f79a8bc8fbe7f7f1b0c0a519c0"},"cell_type":"code","source":"data = data.resize(int(sz*1.3), TMP_PATH)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"adc16b9cd94113bc05eeecd48b3168d6de879dd6"},"cell_type":"code","source":"learn = ConvLearner.pretrained(f_model, data, metrics=metrics)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e4d8758b5c17118ae27a68d8bef0bf13b9e36ff1"},"cell_type":"code","source":"lrf=learn.lr_find()\nlearn.sched.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3c3d8e2ccf6ce8a3943c5206534e5f882a8c6c52"},"cell_type":"code","source":"lr = 0.2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"96c13d74bd7f391d0b2aaa5bd34db26a393aaeb8"},"cell_type":"code","source":"learn.fit(lr, 3, cycle_len=1, cycle_mult=2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e94cd1ce5fbcbdad1dc35573bda5a5d46a6f6ee2"},"cell_type":"code","source":"lrs = np.array([lr/9,lr/3,lr])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"91b411601892bd92951478d83405dfcfa7ad32d0"},"cell_type":"code","source":"learn.unfreeze()\nlearn.fit(lrs, 3, cycle_len=1, cycle_mult=2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c20936f99e79a03a341a77ac2953fe6f2ae494f1"},"cell_type":"code","source":"learn.save(f'{sz}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3ef6dfe3c7e688b1791b2b8c4674fabf85f76909"},"cell_type":"code","source":"learn.sched.plot_loss()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6e02b9c6eb0a0fae67e6ba1fc278382f2841c2ce"},"cell_type":"code","source":"sz=128","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7696d29e2334835ade5046f39d8b7113d6fe8641","scrolled":true},"cell_type":"code","source":"learn.set_data(get_data(sz))\nlearn.freeze()\nlearn.fit(lr, 3, cycle_len=1, cycle_mult=2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ac4b6c9b974a3986f972a8a094bd81f5b62540f4"},"cell_type":"code","source":"learn.unfreeze()\nlearn.fit(lrs, 3, cycle_len=1, cycle_mult=2)\nlearn.save(f'{sz}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e5c805968620bb52c43b696ef30630ade4268da1"},"cell_type":"code","source":"sz=256","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"372ffe8879b13f68b8bf3c65fc9b42fbd18e28ac"},"cell_type":"code","source":"learn.set_data(get_data(sz))\nlearn.freeze()\nlearn.fit(lr, 3, cycle_len=1, cycle_mult=2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"560503e5bd1b127dbf1b30a9b3778c3e9dcaba41"},"cell_type":"code","source":"learn.unfreeze()\nlearn.fit(lrs, 3, cycle_len=1, cycle_mult=2)\nlearn.save(f'{sz}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"09d854204e9db737ca25ddb7f44f996222dea52d"},"cell_type":"code","source":"multi_preds, y = learn.TTA()\npreds = np.mean(multi_preds, 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0d087b6322d328c29a20801f18e0997e5516c669"},"cell_type":"code","source":"f2(preds,y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"36ab99e2a478711cbd82311ffa09d385157f5014"},"cell_type":"code","source":"multi_preds, y = learn.TTA(is_test=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dffb8f119149bb436e23eacbcd1443b0e6989a06"},"cell_type":"code","source":"preds = np.mean(multi_preds, 0)\npreds.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3dfa15c3ee7f2e282fd14cc70354b016075ff7f6"},"cell_type":"code","source":"test_fnames = [os.path.basename(f).split(\".\")[0] for f in data.test_ds.fnames]\nclasses = np.array(data.classes, dtype=str)\nres = [\" \".join(classes[np.where(pp > 0.2)]) for pp in preds] \ntest_df = pd.DataFrame(res, index=test_fnames, columns=['tags'])\ntest_df.head(5)\ntest_df.to_csv('submission.csv', index_label='image_name')\ndf = pd.read_csv('submission.csv')\ndf.head(20)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d908f64d4e114f2f3754060ca8a1cfd5717234ca"},"cell_type":"markdown","source":"### End"}],"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}