{"cells":[{"metadata":{"trusted":true,"_uuid":"6647367ea48bfe9d31003f3936245489659bfca8"},"cell_type":"markdown","source":"[Dog breed identification](https://www.kaggle.com/c/dog-breed-identification) using Fast ai v1 "},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport os\nprint(os.listdir(\"../input\"))\n\n#Updating to follow flow in Course v3\n#https://github.com/fastai/course-v3/blob/master/nbs/dl1/lesson1-pets.ipynb","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9b2a9abaecdd94a418cf72051a55f8902f25dc29"},"cell_type":"code","source":"# This file contains all the main external libs we'll use - fastai v1\nfrom fastai import *\nfrom fastai.vision import *\nfrom fastai.metrics import error_rate","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fa804d38474795671eac4b64cff8cbec244d7257"},"cell_type":"code","source":"path = Path(\"/kaggle/input/dog-breed-identification/\")\n# 32 when testing 224 when for real - better way from course is to reduce the batch size to 32\n#sz=32 \nbs = 16\nsz=224\nTMP_PATH = \"/tmp/tmp\"\nMODEL_PATH = \"/tmp/model/\"\narch = 'resnet34'\ncomp_name = \"dog_breed\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2175c75a4b1b028542f3195793017d779ad6dd32"},"cell_type":"code","source":"path.ls()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"346d5d4cc100ff87a9f95d82084c3c6f2c981a35"},"cell_type":"code","source":"label_df = pd.read_csv(path/'labels.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e3ad89bf39ef50f07edb87049e3b1282fc84c8f8"},"cell_type":"code","source":"#what does the csv file look like id is the file name (minus .jpg), breed is the classification\nlabel_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"de5eb24d75b9b0f1c63ad6362d7d1d2e4be3347f"},"cell_type":"code","source":"# GPU required\ntorch.cuda.is_available()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6be0da39effaf445a4dd5ca33650bd6fda97f7f0"},"cell_type":"code","source":"torch.backends.cudnn.enabled","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3517a2bb4366e196935d0a1bd3da9e3d512d4ffb"},"cell_type":"code","source":"# Fix to enable Resnet to live on Kaggle - creates a writable location for the models\ncache_dir = os.path.expanduser(os.path.join('~', '.torch'))\nif not os.path.exists(cache_dir):\n    os.makedirs(cache_dir)\n   # print(\"directory created :\" .cache_dir)\nmodels_dir = os.path.join(cache_dir, 'models')\nif not os.path.exists(models_dir):\n    os.makedirs(models_dir)\n  #  print(\"directory created :\" . cache_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"775c470a84c972565af40d6a9ee81a1fd75b9fe4"},"cell_type":"code","source":"#copying model to writable location\n#cd /kaggle/working\nshutil.copy(\"/kaggle/input/resnet34/resnet34.pth\", \"/tmp/.torch/models/resnet34-333f7ec4.pth\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e8dd331e24548f5e1d4583ef1fd779ea0427807b"},"cell_type":"code","source":"#crashes with too many workers (remove numworkers while testing with a small image size ~ 64), keep for the bigger images for accuracy\ntfms = get_transforms(do_flip=True, max_zoom=1.1)\n\ndata = ImageDataBunch.from_csv(path, ds_tfms=tfms, folder=\"train\", test='test', suffix='.jpg', bs=bs, size=sz, num_workers=0).normalize(imagenet_stats) \n#data = ImageDataBunch.from_csv(PATH, ds_tfms=tfms, folder=\"train\", test='test', suffix='.jpg', size=sz)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"39773d5fdd9e647ba07582c05826521ef327c740"},"cell_type":"code","source":"data.show_batch(rows=3, figsize=(7,6))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"993afa4aa618b3464c83bcdd1f2ffec8d310a7b0"},"cell_type":"code","source":"#label_df.pivot_table(index='breed', aggfunc=len).sort_values('id', ascending=False) - show the summary from the table\n#To save space:\nprint(data.classes)\nlen(data.classes),data.c","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"42e76ebaca2c181138f5a6e0d23ce5282d6977cf"},"cell_type":"code","source":"#img = plt.imread(f'{PATH}train/{label_df.iloc[0,0]}.jpg')\nimg = plt.imread(path/f'train/{label_df.iloc[0,0]}.jpg')\nplt.imshow(img);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8afd87ef89e3d9aa718705a6ea7ced753262241b"},"cell_type":"code","source":"img.size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3d20a981e495de488733bc6063a15a2fb6c1925d"},"cell_type":"code","source":"#Look at the distribution of the size of the images\nsize_d = {}\nfor index, row in label_df.iterrows():\n    size_d[index] = PIL.Image.open(path/f'train/{row[0]}.jpg').size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b02cfeb3820b41e7c2e08788bc7ac24d4d9ee302"},"cell_type":"code","source":"row_sz,col_sz = list(zip(*size_d.values()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8fd5558611f34722c23f3ebb793e07c7ffdb5304"},"cell_type":"code","source":"row_sz=np.array(row_sz);col_sz=np.array(col_sz)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d1207e8dd112b7fe5fa2e2178b1f0271eff215a5"},"cell_type":"code","source":"row_sz[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7fc5a0e18085785a1abafc8310f8f8052e4885b9"},"cell_type":"code","source":"col_sz[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ce7616c883a04a9da2d0d783dc7e05f249148cb0"},"cell_type":"code","source":"plt.hist(row_sz[row_sz<1000])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8c2a68fd4515768ca4d1bca23bf9d4551bd61d63"},"cell_type":"code","source":"plt.hist(col_sz[col_sz<1000])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c929a0dcd6ddb0dcac4f0cd2733fcb8386b1e06e"},"cell_type":"code","source":"len(data.classes), data.classes[:5]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f82f601b633ad240f373c25c8b90719bc7fdeec7"},"cell_type":"markdown","source":"**Initial model**"},{"metadata":{"trusted":true,"_uuid":"eb207878fc6831360335d626c8859755746f5063","scrolled":true},"cell_type":"code","source":"learn = cnn_learner(data, models.resnet34, metrics=error_rate, model_dir=MODEL_PATH)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6c66ac11fa3b3b40e6831f40da89f75f43e87ff3"},"cell_type":"code","source":"learn.fit_one_cycle(4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7efb5cf1c6a9e295ca0b45401bb330adf9342b6b"},"cell_type":"code","source":"#learn.save('stage-1')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1f54c829c9e084fe17ae46172d16df904984b627"},"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\n\nlosses,idxs = interp.top_losses()\n\nlen(data.valid_ds)==len(losses)==len(idxs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9e5bad6761a856af1ec6ae8c8dafaf963755a206"},"cell_type":"code","source":"interp.plot_top_losses(9, figsize=(15,11))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3a7d2555dbe847929855010a7bb81a77df96d460"},"cell_type":"code","source":"interp.most_confused(min_val=2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"92e8164b5fcc6fe0497b6baedfeac93506938461"},"cell_type":"markdown","source":"Unfreezing, fine-tuning, and learning rates\n\nSince our model is working as we expect it to, we will unfreeze our model and train some more."},{"metadata":{"trusted":true,"_uuid":"7ef60c370441d4e74d84fb0c1042f4fab3fe7b11"},"cell_type":"code","source":"learn.unfreeze()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"44f49523f08d2af968e1cac6ac1281a1e770a4bb"},"cell_type":"code","source":"learn.fit_one_cycle(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6e50745076460be57beade8836db254164bdf883"},"cell_type":"code","source":"#learn.load('stage-1');\nlearn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ad8d9c4931b34b4d713a33bfe9b88f9b2d8d3e26"},"cell_type":"code","source":"learn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"12b2dd918a7a2ce678681498b55d2cc5315a6711","scrolled":true},"cell_type":"code","source":"learn.lr_find()\nlearn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"63da91c13e33d0906494b1714cc03550ef9e10c0"},"cell_type":"code","source":"learn.unfreeze()\nlearn.fit_one_cycle(2, max_lr=slice(1e-6,1e-5))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c399cf3970b1241e5312f093fe0219c91306d6f1"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2de33ec44bf532b548ca3df73b67e61aa8644766"},"cell_type":"code","source":"#learn.fit_one_cycle(4,max_lr=(1e-2, (1e-2)/2, (1e-2)/3))\n#learn.fit_one_cycle(1,max_lr=(1e-2, (1e-2)/2, (1e-2)/3)) # for testing\n#learn.recorder.plot_losses()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0177882dc4eb37e8bbb8de22eecd7d910c7e8d58"},"cell_type":"code","source":"preds,y,losses = learn.get_preds(with_loss=True)\ninterp = ClassificationInterpretation(learn, preds, y, losses)\ninterp.plot_top_losses(9, figsize=(14,14))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2b976284e89887a3ded42cffe7d95377b15d5147"},"cell_type":"code","source":"predictions = learn.get_preds(ds_type=DatasetType.Test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"44047cf78fe93879870e8a63c0953a00efe05a6b"},"cell_type":"code","source":"test_df = pd.read_csv(path/'sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b5c2ed688e743626a1df7886a208a3438890fabf"},"cell_type":"code","source":"submission_columns = data.classes.copy()\nsubmission_columns.insert(0, 'id')\ndf = pd.DataFrame(columns=submission_columns)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9efab014e6f9e4dd1db079c4b1912889b37459d9"},"cell_type":"code","source":"for idx in range(len(predictions[0])):\n#for idx in range(3):\n    probs = predictions[0][idx].tolist()\n    formatted_probs = [\"%.17f\" % member for member in probs]\n    filename = [test_df['id'][idx]]\n    df.loc[idx] = filename + formatted_probs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dc073daa004001001a6753097dc892fa5bb1f6e9","scrolled":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f85d2a39ed96616997b9aa3238fbea5a44ab866c"},"cell_type":"code","source":"# Submission\ndf.to_csv(f\"sub_{comp_name}_{arch}.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2c69ae2058ae607741d60c2edca0a0f0a6fd76b1"},"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}