{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Introduction\n\nThis is the first time that I particpate in a computer vision related competition, and boy it is hard. I don't have much background information to tackle that task at hand, and the stream of information I'm trying to ingest is HUGE!\n\nSo I decided to take a detour from the required objective and try something else that I can get more easily familiar with, and I hope that it can still translate into more understanding of the competition, and give me a little bit of confidence to jump into the main task of the competition.\n\nWithout further ado, let's get started.","metadata":{}},{"cell_type":"code","source":"!pip install --user torch==1.9.0 torchvision==0.10.0 torchaudio==0.9.0 torchtext==0.10.0\nfrom fastai.vision.all import *\n%config Completer.use_jedi = False","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-03T12:29:36.774485Z","iopub.execute_input":"2022-03-03T12:29:36.775249Z","iopub.status.idle":"2022-03-03T12:30:35.937245Z","shell.execute_reply.started":"2022-03-03T12:29:36.775098Z","shell.execute_reply":"2022-03-03T12:30:35.936516Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('../input/happy-whale-and-dolphin/train.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:35.938960Z","iopub.execute_input":"2022-03-03T12:30:35.939205Z","iopub.status.idle":"2022-03-03T12:30:36.046881Z","shell.execute_reply.started":"2022-03-03T12:30:35.939172Z","shell.execute_reply":"2022-03-03T12:30:36.046121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.shape","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.048010Z","iopub.execute_input":"2022-03-03T12:30:36.048357Z","iopub.status.idle":"2022-03-03T12:30:36.054155Z","shell.execute_reply.started":"2022-03-03T12:30:36.048319Z","shell.execute_reply":"2022-03-03T12:30:36.053412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.species.nunique()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.056441Z","iopub.execute_input":"2022-03-03T12:30:36.056894Z","iopub.status.idle":"2022-03-03T12:30:36.074080Z","shell.execute_reply.started":"2022-03-03T12:30:36.056857Z","shell.execute_reply":"2022-03-03T12:30:36.073270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.species.value_counts().sort_index()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.076692Z","iopub.execute_input":"2022-03-03T12:30:36.076878Z","iopub.status.idle":"2022-03-03T12:30:36.095417Z","shell.execute_reply.started":"2022-03-03T12:30:36.076856Z","shell.execute_reply":"2022-03-03T12:30:36.094652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.loc[:, 'species'] = df.species.replace({'bottlenose_dolpin': 'bottlenose_dolphin',\n                                           'kiler_whale': 'killer_whale'})","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.096763Z","iopub.execute_input":"2022-03-03T12:30:36.097020Z","iopub.status.idle":"2022-03-03T12:30:36.113525Z","shell.execute_reply.started":"2022-03-03T12:30:36.096985Z","shell.execute_reply":"2022-03-03T12:30:36.112845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.species.value_counts().sort_index()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.114796Z","iopub.execute_input":"2022-03-03T12:30:36.115270Z","iopub.status.idle":"2022-03-03T12:30:36.128600Z","shell.execute_reply.started":"2022-03-03T12:30:36.115214Z","shell.execute_reply":"2022-03-03T12:30:36.127822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\nplt.figure(figsize=(10, 6))\ndf['species'].value_counts().sort_values(ascending=True).plot(kind='barh');","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.129939Z","iopub.execute_input":"2022-03-03T12:30:36.130434Z","iopub.status.idle":"2022-03-03T12:30:36.596038Z","shell.execute_reply.started":"2022-03-03T12:30:36.130283Z","shell.execute_reply":"2022-03-03T12:30:36.595298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## How can I make the validation set?\n\nWell I guess that depends on the task. The task that I made up here is species classification, and if this data reflects the distribution of real life whales and dolphins, then the validation set should also have a similar distribution.\n\nFor example, by looking into the wikipedia entry of [frasers dolphins](https://en.wikipedia.org/wiki/Fraser%27s_dolphin), we can see that their sightings are rare, and therefore their small value in the dataset is justified.\n\nAnyways, I'll use fastai's RandomSplitter to generate a validation set on the fly, and to make a fast prototype, I shall make another sample of the dataset and call it the dev set, which should allow fast training to test out any new ideas.","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n_, dev, _ , _ = train_test_split(df, df['species'], test_size=0.1)\n\ndev.shape","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.597494Z","iopub.execute_input":"2022-03-03T12:30:36.598058Z","iopub.status.idle":"2022-03-03T12:30:36.630905Z","shell.execute_reply.started":"2022-03-03T12:30:36.598018Z","shell.execute_reply":"2022-03-03T12:30:36.629457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now let's use fastai datablock api to get us off the ground fast.","metadata":{}},{"cell_type":"code","source":"path = Path(\"../input/jpeg-happywhale-256x256/train_images-256-256/train_images-256-256\")\n\ndev['image_path'] = dev['image'].apply(lambda f: path/f)\n\n\ndblock = DataBlock(blocks=(ImageBlock, CategoryBlock), \n                   get_x=ColReader('image_path'),\n                   get_y=lambda r: r['species'],\n                   splitter=RandomSplitter(seed=42),\n                   item_tfms=Resize(460),\n                   batch_tfms=aug_transforms(size=224))\n# dblock.summary(dev)\ndsets = dblock.datasets(dev)\ndls = dblock.dataloaders(dev)","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:36.634087Z","iopub.execute_input":"2022-03-03T12:30:36.634699Z","iopub.status.idle":"2022-03-03T12:30:40.509264Z","shell.execute_reply.started":"2022-03-03T12:30:36.634644Z","shell.execute_reply":"2022-03-03T12:30:40.508513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dls.show_batch(max_n=20)","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:40.510380Z","iopub.execute_input":"2022-03-03T12:30:40.511388Z","iopub.status.idle":"2022-03-03T12:30:42.982766Z","shell.execute_reply.started":"2022-03-03T12:30:40.511346Z","shell.execute_reply":"2022-03-03T12:30:42.976952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn = cnn_learner(dls, resnet34, metrics=[accuracy, error_rate])\nlearn.lr_find()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:30:42.983739Z","iopub.execute_input":"2022-03-03T12:30:42.984168Z","iopub.status.idle":"2022-03-03T12:31:40.330888Z","shell.execute_reply.started":"2022-03-03T12:30:42.983935Z","shell.execute_reply":"2022-03-03T12:31:40.330111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fine_tune(2, base_lr=3e-3)","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:33:17.239299Z","iopub.execute_input":"2022-03-03T12:33:17.239621Z","iopub.status.idle":"2022-03-03T12:35:11.878532Z","shell.execute_reply.started":"2022-03-03T12:33:17.239580Z","shell.execute_reply":"2022-03-03T12:35:11.877717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The model seems to be improving, so let's bump it up with some more epochs for the head.","metadata":{}},{"cell_type":"code","source":"learn.freeze()\nlearn.fit_one_cycle(3, 3e-3)","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:37:32.595210Z","iopub.execute_input":"2022-03-03T12:37:32.595658Z","iopub.status.idle":"2022-03-03T12:39:21.042867Z","shell.execute_reply.started":"2022-03-03T12:37:32.595618Z","shell.execute_reply":"2022-03-03T12:39:21.042113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now let's give some love to the pretrained layers.","metadata":{}},{"cell_type":"code","source":"learn.unfreeze()\nlearn.lr_find()","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:39:59.799083Z","iopub.execute_input":"2022-03-03T12:39:59.799887Z","iopub.status.idle":"2022-03-03T12:40:27.230888Z","shell.execute_reply.started":"2022-03-03T12:39:59.799834Z","shell.execute_reply":"2022-03-03T12:40:27.230109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.fit_one_cycle(6, lr_max=slice(1e-6, 1e-4))","metadata":{"execution":{"iopub.status.busy":"2022-03-03T12:42:30.411177Z","iopub.execute_input":"2022-03-03T12:42:30.411743Z","iopub.status.idle":"2022-03-03T12:46:15.332563Z","shell.execute_reply.started":"2022-03-03T12:42:30.411705Z","shell.execute_reply":"2022-03-03T12:46:15.331820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So it seems that we are bound to around 91% accuracy using this architecture and a 9% subset of the data for training. Which isn't bad given that we have conjured this up in a couple of minutes.\n\n## Possible Use Case\n\nI think that if in case of using metric learning and knn for selecting the top 5 similar images, one could use an accurate enough classifier to classify the current image, and match it only with other images of the same classification.\n\nThis could possibly be a use case for this kind of model.\n\n\nAnyways, thanks for reading.","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}