{"cells":[{"metadata":{"_uuid":"c582ea53f6490460e4edc8cfae8d10fcecc61b24"},"cell_type":"markdown","source":"## General information\n\nCamera Traps (or Wild Cams) enable the automatic collection of large quantities of image data. Biologists all over the world use camera traps to monitor biodiversity and population density of animal species\nAs biologists try to expand the scope of these models from specific regions where they have collected training data to nearby areas they are faced with an interesting probem: how do you classify a species in a new region that you may not have seen in previous training data?\n\nIn this challenge the training data and test data are from different regions, namely The American Southwest and the American Northwest.\n\nWe have 23 classes for which we need to make a classification. Using external data is allowed.\n\n![](https://camo.githubusercontent.com/3398bff8743feb9e94ffbeae1c2c32cdbda97b20/68747470733a2f2f7261776769742e636f6d2f7669736970656469612f6977696c6463616d5f636f6d702f736172612f6173736574732f6977696c6463616d5f323031395f62616e6e65722e6a7067)"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# libraries\nimport numpy as np\nimport pandas as pd\nimport os\nimport cv2\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import roc_auc_score\nimport torch\nfrom torch.utils.data import TensorDataset, DataLoader,Dataset\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.transforms as transforms\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nimport time \nfrom PIL import Image\ntrain_on_gpu = True\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau, CosineAnnealingLR\nfrom sklearn.metrics import accuracy_score\nimport cv2\n\nimport altair as alt\nfrom  altair.vega import v3\nfrom IPython.display import HTML\nimport json","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"!pip install albumentations > /dev/null 2>&1\n!pip install pretrainedmodels > /dev/null 2>&1\n!pip install kekas > /dev/null 2>&1\n!pip install adabound > /dev/null 2>&1","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"eeda4a795f889fe5ded937968fa4375af3e2dff2"},"cell_type":"code","source":"import albumentations\nfrom albumentations import torch as AT\nimport pretrainedmodels\nimport adabound\n\nfrom kekas import Keker, DataOwner, DataKek\nfrom kekas.transformations import Transformer, to_torch, normalize\nfrom kekas.metrics import accuracy\nfrom kekas.modules import Flatten, AdaptiveConcatPool2d\nfrom kekas.callbacks import Callback, Callbacks, DebuggerCallback\nfrom kekas.utils import DotDict","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"a3affb4868c94b8cd3ac83660c14fde44b86e729"},"cell_type":"code","source":"# Preparing altair. I use code from this great kernel: https://www.kaggle.com/notslush/altair-visualization-2018-stackoverflow-survey\n\nvega_url = 'https://cdn.jsdelivr.net/npm/vega@' + v3.SCHEMA_VERSION\nvega_lib_url = 'https://cdn.jsdelivr.net/npm/vega-lib'\nvega_lite_url = 'https://cdn.jsdelivr.net/npm/vega-lite@' + alt.SCHEMA_VERSION\nvega_embed_url = 'https://cdn.jsdelivr.net/npm/vega-embed@3'\nnoext = \"?noext\"\n\npaths = {\n    'vega': vega_url + noext,\n    'vega-lib': vega_lib_url + noext,\n    'vega-lite': vega_lite_url + noext,\n    'vega-embed': vega_embed_url + noext\n}\n\nworkaround = \"\"\"\nrequirejs.config({{\n    baseUrl: 'https://cdn.jsdelivr.net/npm/',\n    paths: {}\n}});\n\"\"\"\n\n#------------------------------------------------ Defs for future rendering\ndef add_autoincrement(render_func):\n    # Keep track of unique <div/> IDs\n    cache = {}\n    def wrapped(chart, id=\"vega-chart\", autoincrement=True):\n        if autoincrement:\n            if id in cache:\n                counter = 1 + cache[id]\n                cache[id] = counter\n            else:\n                cache[id] = 0\n            actual_id = id if cache[id] == 0 else id + '-' + str(cache[id])\n        else:\n            if id not in cache:\n                cache[id] = 0\n            actual_id = id\n        return render_func(chart, id=actual_id)\n    # Cache will stay outside and \n    return wrapped\n            \n@add_autoincrement\ndef render(chart, id=\"vega-chart\"):\n    chart_str = \"\"\"\n    <div id=\"{id}\"></div><script>\n    require([\"vega-embed\"], function(vg_embed) {{\n        const spec = {chart};     \n        vg_embed(\"#{id}\", spec, {{defaultStyle: true}}).catch(console.warn);\n        console.log(\"anything?\");\n    }});\n    console.log(\"really...anything?\");\n    </script>\n    \"\"\"\n    return HTML(\n        chart_str.format(\n            id=id,\n            chart=json.dumps(chart) if isinstance(chart, dict) else chart.to_json(indent=None)\n        )\n    )\n\nHTML(\"\".join((\n    \"<script>\",\n    workaround.format(json.dumps(paths)),\n    \"</script>\",\n)))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ede6347177ceb76b7a5624e01552f30c582d1a42"},"cell_type":"markdown","source":"## Data overview"},{"metadata":{"trusted":true,"_uuid":"5762b70747bfe50c5122a86c5bee5ca0b4580b91"},"cell_type":"code","source":"os.listdir('../input/')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"27b43e8a2b524b52f38d4bebfdce6ccca04de833"},"cell_type":"markdown","source":"We have separate `csv` files for train and test data and folders with images.\n\nClass names are presented as a string in the description of the competition, let's convert this into a dictionary."},{"metadata":{"trusted":true,"_uuid":"a5532a7f99175b4d7ce18a2db027ffd2828baa7d"},"cell_type":"code","source":"classes = \"\"\"empty, 0\ndeer, 1\nmoose, 2\nsquirrel, 3\nrodent, 4\nsmall_mammal, 5\nelk, 6\npronghorn_antelope, 7\nrabbit, 8\nbighorn_sheep, 9\nfox, 10\ncoyote, 11\nblack_bear, 12\nraccoon, 13\nskunk, 14\nwolf, 15\nbobcat, 16\ncat, 17\ndog, 18\nopossum, 19\nbison, 20\nmountain_goat, 21\nmountain_lion, 22\"\"\".split('\\n')\nclasses = {int(i.split(', ')[1]): i.split(', ')[0] for i in classes}\nclasses","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"fa02197ff7eccf442635b06a7ef8ab4f8c706196"},"cell_type":"code","source":"train = pd.read_csv('../input/train.csv')\ntest = pd.read_csv('../input/test.csv')\nsub = pd.read_csv('../input/sample_submission.csv')\ntrain['classes'] = train['category_id'].apply(lambda x: classes[x])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b3c09278a14aa0daf990eb89016b894d9f687414"},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b558a75107200bbccfd70fb0820cb2e4d32b4058"},"cell_type":"markdown","source":"Here we have timestamps, locations, rights holder, info about the sequence of photos and height/width."},{"metadata":{"trusted":true,"_uuid":"fa90e56efe674581e1aa7da2182a11149106b268"},"cell_type":"code","source":"train.classes.unique()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"60069f7ac0c3641d17a46889127403f3037a4fc9"},"cell_type":"markdown","source":"And we have only 14 classes of 23 in train data. It seems that using external data is necessary. Let's see how far can we go without it."},{"metadata":{"trusted":true,"scrolled":false,"_uuid":"f00784cd04ceeb9d0453565d219191958ac1fb39"},"cell_type":"code","source":"fig = plt.figure(figsize=(25, 60))\nimgs = [np.random.choice(train.loc[train['classes'] == i, 'file_name'], 4) for i in train.classes.unique()]\nimgs = [i for j in imgs for i in j]\nlabels = [[i] * 4 for i in train.classes.unique()]\nlabels = [i for j in labels for i in j]\nfor idx, img in enumerate(imgs):\n    ax = fig.add_subplot(14, 4, idx + 1, xticks=[], yticks=[])\n    im = Image.open(\"../input/train_images/\" + img)\n    plt.imshow(im)\n    ax.set_title(f'Label: {labels[idx]}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dae4025c677d1eb2cb8d856d7764b8cb3eadd8b6"},"cell_type":"code","source":"target_count = train['classes'].value_counts().reset_index().rename(columns={'index': 'target'})\nrender(alt.Chart(target_count).mark_bar().encode(\n    y=alt.Y(\"target:N\", axis=alt.Axis(title='Surface'), sort=list(target_count['target'])),\n    x=alt.X('classes:Q', axis=alt.Axis(title='Count')),\n    tooltip=['target', 'classes']\n).properties(title=\"Counts of target classes\", width=400).interactive())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a058a2d10966c14070c5cb7bb4ded936b20a8607"},"cell_type":"markdown","source":"We can see that working with this data is quite difficult. Class disbalance is huge and there are a lot of empty pictures. Also the photos themselves present a challenge - animals can be in a small part of the screen and be obscured."},{"metadata":{"trusted":true,"_uuid":"f95190e8543ab009332e4f03af229b478c3762ef"},"cell_type":"code","source":"lc = pd.crosstab(train['location'], train['classes']).reset_index()\nlc = pd.melt(lc, 'location', lc.columns.tolist()[1:], 'class', 'count')\nlc = lc.loc[lc['class'] != 'empty']\nrender(alt.Chart(lc).mark_circle().encode(\n    y='location:N',\n    x='class',\n    size='count',\n    tooltip=['location', 'class', 'count']\n).properties(title=\"Animals and locations\", width=400).interactive())","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}