{"cells":[{"metadata":{},"cell_type":"markdown","source":"In this notebook, we will be using **Progressive Resizing** (technique made famous by Jeremy Howard). We will be using fastai library and pre-trained ResNet152. \n\nThis is the training notebook. You can find the [inference notebook here](https://www.kaggle.com/ankursingh12/fastai-plant2021-starter-inference).\n\nLets get started . . . \n\nFirst, we will to import fastai."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from fastai.vision.all import *\nimport gc\n\nseed = 42\nset_seed(seed, reproducible=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We are setting the seed for reproducibility. \n\nNext, we will initialize some path (& other) variables (for use throughout the notebook)\n\nPS: I will be using my version for the dataset. I have resized all the images so that its much faster to load them into the RAM. You can find the dataset [here](https://www.kaggle.com/ankursingh12/resized-plant2021). "},{"metadata":{"trusted":true},"cell_type":"code","source":"path = Path('../input/plant-pathology-2021-fgvc8')\ndata_path = Path('../input/resized-plant2021')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Data\n\nEnough prep-work! Lets read our data . . ."},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv(path/'train.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"hmm, just image names and their label. Looks simple ? Not so soon. The labels are space-delimited strings. Its a multi-label problem. \n\nWe will use Fastai's datablock API to load our data. DataBlock API is simply amazing. Infinitely  flexibility and incredibly powerful. To use the datablock API, you need to define some functions."},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_x(x): return str(data_path/'img_sz_640') + os.path.sep + x['image']\ndef get_y(y): return y['labels']\n\ndef get_data(df, size=224, bs=64):\n    datablock = DataBlock(blocks=(ImageBlock, CategoryBlock),\n                   splitter=RandomSplitter(seed=seed),\n                   get_x=get_x, get_y=get_y,\n                   item_tfms = RandomResizedCrop(size+52),\n                   batch_tfms=[*aug_transforms(mult=2.0,flip_vert=True, size=size), \n                               Normalize.from_stats(*imagenet_stats)])\n    \n    return datablock.dataloaders(df, bs=bs)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Don't worry a lot if the above code looks cryptic. You can read the [6th notebook (or chapter)](https://github.com/fastai/fastbook/blob/master/06_multicat.ipynb) in fastbook for details. It explains the topic in the most simplest way possible. And once you master datablock API, you will feel like a Ninja (trust me on this)!\n\nYou are amazing! Now lets create our dataloaders, & then take a look at some images."},{"metadata":{"trusted":true},"cell_type":"code","source":"dls = get_data(df)\ndls.show_batch(max_n=9)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Looks good to me, what do you think?\n\nWe are done with data, time for some training."},{"metadata":{},"cell_type":"markdown","source":"### Model\n\nFastai has an awesome class which puts everything together, called `cnn_learner`. Here we are using ResNet152. "},{"metadata":{"trusted":true},"cell_type":"code","source":"f1score = F1Score(average='macro')\nmetrics = [accuracy, f1score]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We are using `accuracy_multi` and `f1score` metrics, because its a multi-label problem and the evaluation metric for the competition is *F1Score*.\n\nFinally, lets train (technically, fine-tune 🤯) our model."},{"metadata":{},"cell_type":"markdown","source":"## Progressive Resizing\n\nIn Progressive resizing, we first train the model on smaller images and then progressively increase the size. \n\n**Philosophy:** Its much faster to train models on smaller image sizes. Also, the model sees more details as we increase the size. Hence, we can train the model much faster. \n\nWe will start with 128x128 and gradually take the image size to 528x528"},{"metadata":{"trusted":true},"cell_type":"code","source":"## Size 128x128\ndls = get_data(df, 128, 64)\nlearn = cnn_learner(dls, resnet152, metrics=metrics).to_fp16()\nlearn.fine_tune(1, 1e-3, wd=0.5)\nlearn.save('restnet_v1')\ndel learn\ntorch.cuda.empty_cache()\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Size 256x256\ndls = get_data(df, 256, 32)\nlearn = cnn_learner(dls, resnet152, metrics=metrics)\nlearn.load('restnet_v1').to_fp16();\nlearn.freeze() \nlearn.fine_tune(4, 1e-3, wd=0.5)\nlearn.save('restnet_v2')\ndel learn\ntorch.cuda.empty_cache()\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Size 448x448\ndls = get_data(df, 448, 16)\nlearn = cnn_learner(dls, resnet152, metrics=metrics)\nlearn.load('restnet_v2').to_fp16();\nlearn.unfreeze()\nlearn.fit_one_cycle(3, slice(1e-5, 1e-4), wd=0.5)\nlearn.save('restnet_v3')\ndel learn\ntorch.cuda.empty_cache() \ngc.collect() ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Size 528x528\ndls = get_data(df, 528, 16)\nlearn = cnn_learner(dls, resnet152, metrics=metrics)\nlearn.load('restnet_v3').to_fp16();\nlearn.unfreeze()\nlearn.fit_one_cycle(3, slice(1e-5, 1e-4), wd=0.5) \nlearn.save('restnet_v4') ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Okay, done with training! Lets look at some predictions . . ."},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.show_results()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Amazing! Lets export the model so that we can deploy it to production 😂. Just kidding, we will (only) use it for inference."},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.export(f'resnet152_12c.pkl')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Fastai is extremely flexible and powerful at the same time. This is just the baseline notebook. You can easily build on top of it. Here are some things that you can experiment with:\n\n- Preprocess and Feature Engineering\n- Data Augmentation and External Datasets\n- Different Model Architectures\n- Training Schedule, Optimizer, etc\n- Postprocess\n\nYou can find the [inference notebook here](https://www.kaggle.com/ankursingh12/fastai-plant2021-starter-inference). Stay tuned for more!\n\nHope you had fun reading the notebook. Kindly consider **upvoting**."}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}