{"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":"In this notebook I've tried to adapt some popular solutions and also added some fixes, so it all works on new version of python.\n\nAlso, you can notice that there are few refactorings and also some new implementations, so feel free to copy and experiment on your own","metadata":{}},{"cell_type":"code","source":"import os\n\nimport numpy as np\nimport pandas as pd\n\nimport pandas as pd\nfrom matplotlib import pyplot as plt\n\nfrom fastai import *\nfrom fastai.vision import *\n\nimport json\n\nimport glob\n\nimport cv2\nimport torch\nfrom tqdm import tqdm_notebook\nfrom PIL import Image, ImageFile\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import models\nfrom sklearn.model_selection import train_test_split\nfrom torchvision import transforms\nfrom skimage import io\nImageFile.LOAD_TRUNCATED_IMAGES = True\n\n%matplotlib inline","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.status.busy":"2023-07-17T08:36:08.898787Z","iopub.execute_input":"2023-07-17T08:36:08.899179Z","iopub.status.idle":"2023-07-17T08:36:13.412603Z","shell.execute_reply.started":"2023-07-17T08:36:08.899148Z","shell.execute_reply":"2023-07-17T08:36:13.411563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def kaggle_commit_logger(str_to_log, need_print = True):\n    if need_print:\n        print(str_to_log)\n    os.system(f'echo {str_to_log}')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:13.414607Z","iopub.execute_input":"2023-07-17T08:36:13.415712Z","iopub.status.idle":"2023-07-17T08:36:13.422060Z","shell.execute_reply.started":"2023-07-17T08:36:13.415672Z","shell.execute_reply":"2023-07-17T08:36:13.420651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import json\nwith open(r'/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_train_annotations.json') as json_file:\n    train_data = json.load(json_file)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:13.424203Z","iopub.execute_input":"2023-07-17T08:36:13.424958Z","iopub.status.idle":"2023-07-17T08:36:14.874070Z","shell.execute_reply.started":"2023-07-17T08:36:13.424920Z","shell.execute_reply":"2023-07-17T08:36:14.872440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.DataFrame({'id': [item['id'] for item in train_data['annotations']],\n                                'category_id': [item['category_id'] for item in train_data['annotations']],\n                                'image_id': [item['image_id'] for item in train_data['annotations']],\n                                'file_name': [item['file_name'] for item in train_data['images']]})\n\ndf_train.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:27.654634Z","iopub.execute_input":"2023-07-17T08:36:27.654983Z","iopub.status.idle":"2023-07-17T08:36:27.894198Z","shell.execute_reply.started":"2023-07-17T08:36:27.654958Z","shell.execute_reply":"2023-07-17T08:36:27.892821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.shape","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:28.452417Z","iopub.execute_input":"2023-07-17T08:36:28.452802Z","iopub.status.idle":"2023-07-17T08:36:28.460337Z","shell.execute_reply.started":"2023-07-17T08:36:28.452772Z","shell.execute_reply":"2023-07-17T08:36:28.458711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_image = pd.DataFrame.from_records(train_data['images'])\n\nindices = [\n    df_train[df_train['image_id'] == _id].index\n    for _id in df_image[df_image['location'] == 537]['id'].values\n]\nfor the_index in indices:\n    df_train = df_train.drop(df_train.index[the_index])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:29.177975Z","iopub.execute_input":"2023-07-17T08:36:29.178322Z","iopub.status.idle":"2023-07-17T08:36:31.405868Z","shell.execute_reply.started":"2023-07-17T08:36:29.178294Z","shell.execute_reply":"2023-07-17T08:36:31.404902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.shape","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:31.407567Z","iopub.execute_input":"2023-07-17T08:36:31.408107Z","iopub.status.idle":"2023-07-17T08:36:31.415106Z","shell.execute_reply.started":"2023-07-17T08:36:31.408077Z","shell.execute_reply":"2023-07-17T08:36:31.413666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Image.open('../input/iwildcam-2020-fgvc7/train/8792549a-21bc-11ea-a13a-137349068a90.jpg')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:31.416873Z","iopub.execute_input":"2023-07-17T08:36:31.417187Z","iopub.status.idle":"2023-07-17T08:36:31.448948Z","shell.execute_reply.started":"2023-07-17T08:36:31.417155Z","shell.execute_reply":"2023-07-17T08:36:31.447436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nindices = []\nfrom tqdm import tqdm\n\nfor i in tqdm(df_train['file_name']):\n    try:\n        Image.open('/kaggle/input/iwildcam-2020-fgvc7/train/' + i)\n    except:        \n        print(i)\n        df_train.drop(df_train.loc[df_train['file_name']==i].index, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T08:36:31.451334Z","iopub.execute_input":"2023-07-17T08:36:31.451676Z","iopub.status.idle":"2023-07-17T09:19:48.797759Z","shell.execute_reply.started":"2023-07-17T08:36:31.451647Z","shell.execute_reply":"2023-07-17T09:19:48.795758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.shape","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:28:48.703651Z","iopub.execute_input":"2023-07-17T09:28:48.704109Z","iopub.status.idle":"2023-07-17T09:28:48.710413Z","shell.execute_reply.started":"2023-07-17T09:28:48.704075Z","shell.execute_reply":"2023-07-17T09:28:48.709509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open(r'/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_test_information.json') as f:\n    test_data = json.load(f)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:28:49.485198Z","iopub.execute_input":"2023-07-17T09:28:49.485574Z","iopub.status.idle":"2023-07-17T09:28:49.738580Z","shell.execute_reply.started":"2023-07-17T09:28:49.485549Z","shell.execute_reply":"2023-07-17T09:28:49.737620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = pd.DataFrame.from_records(test_data['images'])\ndf_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:28:50.042353Z","iopub.execute_input":"2023-07-17T09:28:50.042731Z","iopub.status.idle":"2023-07-17T09:28:50.219773Z","shell.execute_reply.started":"2023-07-17T09:28:50.042700Z","shell.execute_reply":"2023-07-17T09:28:50.218788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 64\nIMG_SIZE = 128\n\nN_EPOCHS = 4\n\nID_COLNAME = 'file_name'\nANSWER_COLNAME = 'category_id'\nTRAIN_IMGS_DIR = r'../input/iwildcam-2020-fgvc7/train/'\nTEST_IMGS_DIR = r'../input/iwildcam-2020-fgvc7/test/'","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:01.952374Z","iopub.execute_input":"2023-07-17T09:47:01.952702Z","iopub.status.idle":"2023-07-17T09:47:01.958309Z","shell.execute_reply.started":"2023-07-17T09:47:01.952680Z","shell.execute_reply":"2023-07-17T09:47:01.956856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, test_df = train_test_split(df_train[[ID_COLNAME, ANSWER_COLNAME]],\n                                     test_size = 0.25,                                     \n                                     shuffle = True\n                                    )\ntrain_df.head(5)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:03.022437Z","iopub.execute_input":"2023-07-17T09:47:03.022965Z","iopub.status.idle":"2023-07-17T09:47:03.097807Z","shell.execute_reply.started":"2023-07-17T09:47:03.022937Z","shell.execute_reply":"2023-07-17T09:47:03.096448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Outputing what classes do we have","metadata":{}},{"cell_type":"code","source":"CLASSES_TO_USE = df_train['category_id'].unique()\nCLASSES_TO_USE","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:04.528975Z","iopub.execute_input":"2023-07-17T09:47:04.529370Z","iopub.status.idle":"2023-07-17T09:47:04.539502Z","shell.execute_reply.started":"2023-07-17T09:47:04.529337Z","shell.execute_reply":"2023-07-17T09:47:04.538327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_CLASSES = len(CLASSES_TO_USE)\nNUM_CLASSES","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:04.995068Z","iopub.execute_input":"2023-07-17T09:47:04.995504Z","iopub.status.idle":"2023-07-17T09:47:05.003411Z","shell.execute_reply.started":"2023-07-17T09:47:04.995466Z","shell.execute_reply":"2023-07-17T09:47:05.001560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CLASSMAP = dict(list(zip(CLASSES_TO_USE, range(NUM_CLASSES))))\nREVERSE_CLASSMAP = dict([(v, k) for k, v in CLASSMAP.items()])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:05.561892Z","iopub.execute_input":"2023-07-17T09:47:05.562346Z","iopub.status.idle":"2023-07-17T09:47:05.569098Z","shell.execute_reply.started":"2023-07-17T09:47:05.562309Z","shell.execute_reply":"2023-07-17T09:47:05.567339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model=models.densenet201(pretrained='imagenet')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:06.394109Z","iopub.execute_input":"2023-07-17T09:47:06.394516Z","iopub.status.idle":"2023-07-17T09:47:06.854010Z","shell.execute_reply.started":"2023-07-17T09:47:06.394485Z","shell.execute_reply":"2023-07-17T09:47:06.852527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model = models.densenet121(pretrained='imagenet')","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-07-17T09:47:07.555791Z","iopub.execute_input":"2023-07-17T09:47:07.556222Z","iopub.status.idle":"2023-07-17T09:47:07.561322Z","shell.execute_reply.started":"2023-07-17T09:47:07.556188Z","shell.execute_reply":"2023-07-17T09:47:07.560039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"new_head = torch.nn.Linear(model.classifier.in_features, NUM_CLASSES)\nmodel.classifier = new_head","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:08.235699Z","iopub.execute_input":"2023-07-17T09:47:08.236053Z","iopub.status.idle":"2023-07-17T09:47:08.245062Z","shell.execute_reply.started":"2023-07-17T09:47:08.236029Z","shell.execute_reply":"2023-07-17T09:47:08.243571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.load_state_dict(torch.load('../input/iwild2020-torch/model'))","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:08.947414Z","iopub.execute_input":"2023-07-17T09:47:08.947744Z","iopub.status.idle":"2023-07-17T09:47:08.954290Z","shell.execute_reply.started":"2023-07-17T09:47:08.947720Z","shell.execute_reply":"2023-07-17T09:47:08.952439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    model.cuda();\nexcept:\n    pass","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:09.637365Z","iopub.execute_input":"2023-07-17T09:47:09.637704Z","iopub.status.idle":"2023-07-17T09:47:09.645172Z","shell.execute_reply.started":"2023-07-17T09:47:09.637678Z","shell.execute_reply":"2023-07-17T09:47:09.644360Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" The code starts by creating two transforms: a resize transform and a toTensor transform.\n \n The resize transform will enlarge the images by 50% and the toTensor transform will convert them from an image format to a tensor format.\n Next, the code creates two normalizers.\n \n The first normalizer will adjust the mean values of each image so that they are all equal.\n \n This is done using the transforms.Normalize() function.\n \n The second normalizer will adjust the standard deviation values of each image so that they are all equal.\n \n This is done using the transforms.Compose() function, which combines two other transforms together.\n \n Finally, the code creates two trains_augmentation transforms, one for adjusting the mean values and one for adjusting the standard deviation values.\n These transformations will combine together to create an overall train_augmentation transformation that adjusts both mean and standard deviation values in order to make all images look similar (normalized).\n \n The code will first resize the input images to their original dimensions (IMG_SIZE x IMG_SIZE).\n \n Next, it will apply the normalizer to each image.\n \n Finally, it will compose the two augmentations together, yielding a final transformation that resizes the images back down to their original size while maintaining their normalized values.","metadata":{}},{"cell_type":"code","source":"normalizer = transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                 std=[0.229, 0.224, 0.225])\n\ntrain_augmentation = transforms.Compose([\n    transforms.Resize((IMG_SIZE,IMG_SIZE)),\n    transforms.ToTensor(),\n    normalizer,\n])\n\nval_augmentation = transforms.Compose([\n    transforms.Resize((IMG_SIZE,IMG_SIZE)),\n    transforms.ToTensor(),\n    normalizer,\n])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:11.374919Z","iopub.execute_input":"2023-07-17T09:47:11.375250Z","iopub.status.idle":"2023-07-17T09:47:11.381930Z","shell.execute_reply.started":"2023-07-17T09:47:11.375226Z","shell.execute_reply":"2023-07-17T09:47:11.380836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code starts by creating a dataset object named \"IMetDataset\".\n-   The dataset contains data about images, along with information about the number of classes and the column names (id_colname and answer_colname).\n-   The __len__() method returns the size of the dataset.\n-   Next, the code gets an item from the dataset by using the idx parameter.\n-   This is done by using the index of the row in which the desired item is located (cur_idx_row), and then getting the value for img_id.\n-   This value is used to get an image filename (img_path) that will be opened in Image module.\n-   If transforms is not None, then this will be applied to img before it is returned as a result.\n-   If answer_colname is not specified, then all items in this dataset are returned as images without labels.\n-   However, if answer_colname exists, label will be initialized to 1 for each row where it appears in label_dict .\n-   Finally, these values are returned as a tuple (img , label) .\n-   The code initializes a dataset consisting of data from a file called \"images_dir\" and the number of classes (n_classes) to be processed.\n-   Additionally, the code defines three variables: id_colname, answer_colname, and label_dict.\n-   Next, the __len__() function is used to determine the size of the dataset.\n-   Finally, various methods are used to access specific data within the dataset.\n-   For example, __getitem__() is used to retrieve an image from the dataset based on its identifier (img_id).\n-   Similarly, __len__() is used to determine how many images were retrieved.\n-   Finally, label values are created for each class in label_dict using torch.zeros().","metadata":{}},{"cell_type":"code","source":"class IMetDataset(Dataset):\n    \n    def __init__(self,\n                 df,\n                 images_dir,\n                 n_classes = NUM_CLASSES,\n                 id_colname = ID_COLNAME,\n                 answer_colname = ANSWER_COLNAME,\n                 label_dict = CLASSMAP,\n                 transforms = None\n                ):\n        self.df = df\n        self.images_dir = images_dir\n        self.n_classes = n_classes\n        self.id_colname = id_colname\n        self.answer_colname = answer_colname\n        self.label_dict = label_dict\n        self.transforms = transforms\n    \n    def __len__(self):\n        return self.df.shape[0]\n    \n    def __getitem__(self, idx):        \n        cur_idx_row = self.df.iloc[idx]\n        img_id = cur_idx_row[self.id_colname]\n        img_name = img_id # + self.img_ext\n        img_path = os.path.join(self.images_dir, img_name)\n\n        img = Image.open(img_path)\n\n        if self.transforms is not None:\n            img = self.transforms(img)\n\n        if self.answer_colname is None:\n            return img, img_id\n        label = torch.zeros((self.n_classes,), dtype=torch.float32)\n        label[self.label_dict[cur_idx_row[self.answer_colname]]] = 1.0\n\n        return img, label  ","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:12.749826Z","iopub.execute_input":"2023-07-17T09:47:12.750836Z","iopub.status.idle":"2023-07-17T09:47:12.759579Z","shell.execute_reply.started":"2023-07-17T09:47:12.750785Z","shell.execute_reply":"2023-07-17T09:47:12.758536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = IMetDataset(train_df, TRAIN_IMGS_DIR, transforms = train_augmentation)\ntest_dataset = IMetDataset(test_df, TRAIN_IMGS_DIR, transforms = val_augmentation)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:13.510990Z","iopub.execute_input":"2023-07-17T09:47:13.511372Z","iopub.status.idle":"2023-07-17T09:47:13.516561Z","shell.execute_reply.started":"2023-07-17T09:47:13.511336Z","shell.execute_reply":"2023-07-17T09:47:13.515543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BS = 48\n\ntrain_loader = DataLoader(train_dataset, batch_size=BS, shuffle=True, num_workers=2, pin_memory=True)\ntest_loader = DataLoader(test_dataset, batch_size=BS, shuffle=False, num_workers=2, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:14.309895Z","iopub.execute_input":"2023-07-17T09:47:14.310534Z","iopub.status.idle":"2023-07-17T09:47:14.320497Z","shell.execute_reply.started":"2023-07-17T09:47:14.310498Z","shell.execute_reply":"2023-07-17T09:47:14.318163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def cuda(x):\n    return x.cuda(non_blocking=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:15.019874Z","iopub.execute_input":"2023-07-17T09:47:15.020775Z","iopub.status.idle":"2023-07-17T09:47:15.025547Z","shell.execute_reply.started":"2023-07-17T09:47:15.020743Z","shell.execute_reply":"2023-07-17T09:47:15.024308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code first calculates the fbeta_score for a training set of data (y_true and y_pred) using the beta function.\n-   This function takes in two floats as input, and returns a float value that represents how well the predicted value matches the actual value.\n-   The fbeta_score is then calculated by taking the mean of precision and recall values, which is then divided by beta2 to get a final score.\n-   Precision refers to how often the predicted values match the actual values, while recall refers to how often all of the predictions are true positives (i.e., they correspond to real data).\n-   A higher precision and recall means that more accurate predictions were made, while a lower precision and recall means that there were more false positives (predictions that matched data but was not actually correct).\n-   The code also calculates beta2, which is simply 1/beta.\n-   This number helps to adjust for bias in predictions when comparing different models or datasets.\n-   For example, if you have two models that predict outcomes differently based on some input variable(s), having a higher beta would make those models more similar so that their predictions would be more accurate overall.\n-   The code calculates the fbeta_score for a data set of y_true and y_pred values.\n-   The fbeta_score function takes in three arguments: y_true, y_pred, and beta.\n-   The beta argument is used to adjust the weighting of the predictions made by y_pred relative to the true value.\n-   The threshold argument sets a cutoff value for how much more likely a prediction is to be correct than not.\n-   Finally, the eps parameter sets the error rate that should be used when calculating the precision and recall values.\n-   The precision and recall values are then calculated using these formulas: precision = true_positive.div(y_pred.sum(dim=1).add(eps))","metadata":{}},{"cell_type":"code","source":"def f1_score(y_true, y_pred, threshold=0.5):\n    return fbeta_score(y_true, y_pred, 1, threshold)\n\n\ndef fbeta_score(y_true, y_pred, beta, threshold, eps=1e-9):\n    beta2 = beta**2\n\n    y_pred = torch.ge(y_pred.float(), threshold).float()\n    y_true = y_true.float()\n\n    true_positive = (y_pred * y_true).sum(dim=1)\n    precision = true_positive.div(y_pred.sum(dim=1).add(eps))\n    recall = true_positive.div(y_true.sum(dim=1).add(eps))\n\n    return torch.mean(\n        (precision*recall).\n        div(precision.mul(beta2) + recall + eps).\n        mul(1 + beta2))","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:16.091436Z","iopub.execute_input":"2023-07-17T09:47:16.092202Z","iopub.status.idle":"2023-07-17T09:47:16.099358Z","shell.execute_reply.started":"2023-07-17T09:47:16.092157Z","shell.execute_reply":"2023-07-17T09:47:16.098558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code starts by initializing the model.\n-   This is done by calling the train() function.\n-   The code then loops through each step in the training process, which consists of loading a data set and training the model on it.\n-   Each step in the training process involves loading features from a data set and assigning them to variables named features and targets .\n-   Then, the loss function is applied to these variables to calculate the overall loss for that step.\n-   Finally, an optimization algorithm is used to improve this loss value.\n-   If there are more steps left in the training process, then the code updates a log file called kaggle_commit_logger .\n-   This file contains information about what was done during that particular step of training (e.g., how much loss was incurred), as well as whether or not print output should be generated.\n-   The code will: -Initialize the model.\n-   -Start training the model on a data set.\n-   -Calculate the loss for each step of the training process.\n-   -If there are more steps to be processed, then the code will continue to train on those additional steps.\n-   -Once all steps have been processed, it will write out a log message detailing the loss and commit that information to a Kaggle commit logger.","metadata":{}},{"cell_type":"code","source":"import contextlib\ndef train_one_epoch(model, train_loader, criterion, optimizer, steps_upd_logging = 250):\n    model.train();\n\n    total_loss = 0.0\n\n    train_tqdm = tqdm_notebook(train_loader)\n\n\n    for step, (features, targets) in enumerate(train_tqdm):\n        with contextlib.suppress(Exception):\n            features, targets = cuda(features), cuda(targets)\n\n            optimizer.zero_grad()\n\n            logits = model(features)\n\n            loss = criterion(logits, targets)\n            loss.backward()\n            optimizer.step()\n\n            total_loss += loss.item()\n\n            if (step + 1) % steps_upd_logging == 0:\n                logstr = f'Train loss on step {step + 1} was {round(total_loss / (step + 1), 5)}'\n                train_tqdm.set_description(logstr)\n                kaggle_commit_logger(logstr, need_print=False)\n\n    return total_loss / (step + 1)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:17.214380Z","iopub.execute_input":"2023-07-17T09:47:17.215358Z","iopub.status.idle":"2023-07-17T09:47:17.223690Z","shell.execute_reply.started":"2023-07-17T09:47:17.215310Z","shell.execute_reply":"2023-07-17T09:47:17.222639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code begins by initializing some variables.\n-   The model variable is a function that will be used to evaluate the data.\n-   The valid_loader variable is a function that will be used to load the training data into memory.\n-   Next, the code creates an iterator over the training data.\n-   This iterator will be used to load each feature and target into memory.\n-   The next step in the code is to calculate the loss for each logistic regression model using the features and targets stored in memory from Step 1.\n-   The final step in this code is to create a list of all true positives (targets) and all false positives (features).\n-   Then, it calculates the mean f1 score for these two lists using torch.cat().\n-   Finally, it prints out the results of this calculation onscreen using kaggle_commit_logger().\n-   The code first validates the model using the valid_loader.\n-   This validator ensures that all of the data in the validation set is of the correct type (i.e.\n-   numeric).\n-   Next, it creates a test_loss variable to track how well the model performs on this validation set.\n-   Finally, it creates a list of targets and logs their corresponding logits values.\n-   Next, the code calculates the mean f1 score for all of these targets by taking their sum and dividing it by the number of items in each list.\n-   It then prints this value to a logstr variable for later use.\n-   Finally, it returns the test_loss value as well as its mean f1 score.","metadata":{}},{"cell_type":"code","source":"def validate(model, valid_loader, criterion, need_tqdm = False):\n    model.eval();\n\n    test_loss = 0.0\n    TH_TO_ACC = 0.5\n\n    true_ans_list = []\n    preds_cat = []\n\n    with torch.no_grad():\n        \n        valid_iterator = tqdm_notebook(valid_loader) if need_tqdm else valid_loader\n        for step, (features, targets) in enumerate(valid_iterator):\n            features, targets = cuda(features), cuda(targets)\n\n            logits = model(features)\n            loss = criterion(logits, targets)\n\n            test_loss += loss.item()\n            true_ans_list.append(targets)\n            preds_cat.append(torch.sigmoid(logits))\n\n        all_true_ans = torch.cat(true_ans_list)\n        all_preds = torch.cat(preds_cat)\n\n        f1_eval = f1_score(all_true_ans, all_preds).item()\n\n    logstr = f'Mean val f1: {round(f1_eval, 5)}'\n    kaggle_commit_logger(logstr)\n    return test_loss / (step + 1), f1_eval","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:18.970509Z","iopub.execute_input":"2023-07-17T09:47:18.971193Z","iopub.status.idle":"2023-07-17T09:47:18.980362Z","shell.execute_reply.started":"2023-07-17T09:47:18.971159Z","shell.execute_reply":"2023-07-17T09:47:18.979480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = torch.nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.0005)\nsheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=0.5, patience=5)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:19.478775Z","iopub.execute_input":"2023-07-17T09:47:19.479309Z","iopub.status.idle":"2023-07-17T09:47:19.487438Z","shell.execute_reply.started":"2023-07-17T09:47:19.479284Z","shell.execute_reply":"2023-07-17T09:47:19.486063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code starts by creating a few variables.\n-   The first is train_losses, which will store the average loss for each epoch of training.\n-   The second is valid_losses, which will store the average validation loss.\n-   The third is valid_f1s, which will store the average F1 score for each epoch of training.\n-   Next, the code begins to run the kaggle competition algorithm.\n-   First, it creates a commit log message that describes what happened during this particular epoch of training (epoch = 1 in this case).\n-   Then it calls the train_one_epoch() function to start training on the model using the test data and criterion specified in train_loader .\n-   The next line calculates mean train loss for this particular epoch.\n-   This value is stored in tr_loss .\n-   Finally, the commit log message is created and stored in tr_loss_logstr .\n-   Next, the code runs validate() on model and test data to check if they are equal.\n-   If they are not equal then an error occurs and sheduler prints out an error message.\n-   If they are equal then valid_loss , valid_f1 , and val_loss_logstr are updated with values from validate().\n-   Finally, step\n-   The code will: -Start at epoch 1 and keep track of the mean train loss for each epoch.\n-   -If the train loss is greater than the best model's f1 at any given epoch, then set the best model to be that particular epoch's model and set best_model_ep to that epoch.","metadata":{}},{"cell_type":"code","source":"%%time\n\nTRAIN_LOGGING_EACH = 500\n\ntrain_losses = []\nvalid_losses = []\nvalid_f1s = []\nbest_model_f1 = 0.0\nbest_model = None\nbest_model_ep = 0\n\nfor epoch in range(1, N_EPOCHS + 1):\n    ep_logstr = f\"Starting {epoch} epoch...\"\n    kaggle_commit_logger(ep_logstr)\n    tr_loss = train_one_epoch(model, train_loader, criterion, optimizer, TRAIN_LOGGING_EACH)\n    train_losses.append(tr_loss)\n    tr_loss_logstr = f'Mean train loss: {round(tr_loss,5)}'\n    kaggle_commit_logger(tr_loss_logstr)\n\n    valid_loss, valid_f1 = validate(model, test_loader, criterion)  \n    valid_losses.append(valid_loss)    \n    valid_f1s.append(valid_f1)       \n    val_loss_logstr = f'Mean valid loss: {round(valid_loss,5)}'\n    kaggle_commit_logger(val_loss_logstr)\n    sheduler.step(valid_loss)\n\n    if valid_f1 >= best_model_f1:    \n        best_model = model        \n        best_model_f1 = valid_f1        \n        best_model_ep = epoch        ","metadata":{"execution":{"iopub.status.busy":"2023-07-17T09:47:20.619614Z","iopub.execute_input":"2023-07-17T09:47:20.620163Z","iopub.status.idle":"2023-07-17T10:18:33.684725Z","shell.execute_reply.started":"2023-07-17T09:47:20.620133Z","shell.execute_reply":"2023-07-17T10:18:33.683042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(best_model.state_dict(), 'model')","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:02.297294Z","iopub.status.busy":"2023-07-12T09:51:02.294312Z","iopub.status.idle":"2023-07-12T09:51:02.489819Z","shell.execute_reply":"2023-07-12T09:51:02.488071Z","shell.execute_reply.started":"2023-07-12T09:51:02.297218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bestmodel_logstr = f'Best f1 is {round(best_model_f1, 5)} on epoch {best_model_ep}'\nkaggle_commit_logger(bestmodel_logstr)","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:02.492305Z","iopub.status.busy":"2023-07-12T09:51:02.491491Z","iopub.status.idle":"2023-07-12T09:51:02.501407Z","shell.execute_reply":"2023-07-12T09:51:02.500161Z","shell.execute_reply.started":"2023-07-12T09:51:02.492145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"xs = list(range(1, len(train_losses) + 1))\n\nplt.plot(xs, train_losses, label = 'Train loss');\n#plt.plot(xs, valid_losses, label = 'Val loss');\nplt.plot(xs, valid_f1s, label = 'Val f1');\nplt.legend();\nplt.xticks(xs);\nplt.xlabel('Epochs');","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:02.503564Z","iopub.status.busy":"2023-07-12T09:51:02.503046Z","iopub.status.idle":"2023-07-12T09:51:02.824018Z","shell.execute_reply":"2023-07-12T09:51:02.822940Z","shell.execute_reply.started":"2023-07-12T09:51:02.503530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SAMPLE_SUBMISSION_DF = pd.read_csv(r'../input/iwildcam-2020-fgvc7/sample_submission.csv')\nSAMPLE_SUBMISSION_DF.head()","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:02.825774Z","iopub.status.busy":"2023-07-12T09:51:02.825328Z","iopub.status.idle":"2023-07-12T09:51:02.973419Z","shell.execute_reply":"2023-07-12T09:51:02.972308Z","shell.execute_reply.started":"2023-07-12T09:51:02.825740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SAMPLE_SUBMISSION_DF.rename(columns={'Id':'file_name','Category':'category_id'}, inplace=True)\nSAMPLE_SUBMISSION_DF['file_name'] = SAMPLE_SUBMISSION_DF['file_name'] + '.jpg'\nSAMPLE_SUBMISSION_DF.head()","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:02.975216Z","iopub.status.busy":"2023-07-12T09:51:02.974801Z","iopub.status.idle":"2023-07-12T09:51:03.002177Z","shell.execute_reply":"2023-07-12T09:51:03.001045Z","shell.execute_reply.started":"2023-07-12T09:51:02.975177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subm_dataset = IMetDataset(SAMPLE_SUBMISSION_DF,\n                           TEST_IMGS_DIR,\n                           transforms = val_augmentation,\n                           answer_colname=None\n                          )\n\nSUMB_BS = 48\n\nsubm_dataloader = DataLoader(subm_dataset,\n                             batch_size=SUMB_BS,\n                             shuffle=False,\n                             pin_memory=True)","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:03.004402Z","iopub.status.busy":"2023-07-12T09:51:03.003980Z","iopub.status.idle":"2023-07-12T09:51:03.009900Z","shell.execute_reply":"2023-07-12T09:51:03.008727Z","shell.execute_reply.started":"2023-07-12T09:51:03.004367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code starts by loading the model into memory.\n-   Next, the code creates a list of predicates called \"preds_cat\".\n-   This list will store all of the predictions made by the model.\n-   The next step is to find the maximum value in this list for each dimension (1).\n-   This is done using torch.cat().\n-   The first argument is a list of lists and the second argument is a function that takes two arguments: first, a list of values, and second, an integer specifying how many dimensions to consider.\n-   In this case, we are only considering one dimension (the number of features).\n-   The result of this function is an int which represents the maximum value in that dimension.\n-   Finally, we convert this int into a numpy array so that we can work with it more easily.\n-   Next, we create another list called \"all_preds\".\n-   This list will contain all of the predictions made by the model.\n-   We then use torch.argmax() to find the maximum value in this list for each dimension (1).\n-   The result of this function is an int which represents the maximum value in that dimension.\n-   Finally, we convert this int into a numpy array so that we can work with it more easily.\n-   The code first retrieves the model from the Python environment.\n-   Next, it creates an empty list called preds_cat and adds all of the predicted values for each feature in the model to the list.\n-   Finally, it calculates the maximum value for all of the predictions in preds_cat and stores that value in all_preds.","metadata":{}},{"cell_type":"code","source":"def get_subm_answers(model, subm_dataloader, need_tqdm = False):\n    model.eval();\n    preds_cat = []\n    ids = []\n\n    with torch.no_grad():\n        \n        if need_tqdm:\n            subm_iterator = tqdm_notebook(subm_dataloader)\n        else:\n            subm_iterator = subm_dataloader\n\n        for features, subm_ids in subm_iterator:\n            features = cuda(features)\n\n            logits = model(features)\n            preds_cat.append(torch.sigmoid(logits))\n            ids += subm_ids\n\n        all_preds = torch.cat(preds_cat)\n        all_preds = torch.argmax(all_preds, dim=1).int().cpu().numpy()\n    return all_preds, ids","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:03.025245Z","iopub.status.busy":"2023-07-12T09:51:03.024868Z","iopub.status.idle":"2023-07-12T09:51:03.039537Z","shell.execute_reply":"2023-07-12T09:51:03.038410Z","shell.execute_reply.started":"2023-07-12T09:51:03.025215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nbest_model.cuda();\n\nsubm_preds, submids = get_subm_answers(best_model, subm_dataloader, True)","metadata":{"execution":{"iopub.execute_input":"2023-07-12T09:51:03.041661Z","iopub.status.busy":"2023-07-12T09:51:03.041231Z","iopub.status.idle":"2023-07-12T10:39:26.865296Z","shell.execute_reply":"2023-07-12T10:39:26.864187Z","shell.execute_reply.started":"2023-07-12T09:51:03.041626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(subm_preds)","metadata":{"execution":{"iopub.execute_input":"2023-07-12T10:39:26.867337Z","iopub.status.busy":"2023-07-12T10:39:26.866955Z","iopub.status.idle":"2023-07-12T10:39:26.873742Z","shell.execute_reply":"2023-07-12T10:39:26.872856Z","shell.execute_reply.started":"2023-07-12T10:39:26.867304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code first creates a dictionary of strings to represent the category names and their corresponding ids.\n-   It then creates a data frame from this dictionary, renaming the columns as needed.\n-   The first column in the data frame is \"Category\" and it contains the category names.\n-   The second column is \"Id\".\n-   Next, the code uses map() to convert each string in Category into an integer.\n-   This integer corresponds to the id of that category in the dictionary.\n-   Finally, head() prints out the first row of the data frame, which is just \"Category\" with an id of 1.\n-   The code will create a DataFrame named \"df_to_process\" with the following columns: Category Id","metadata":{}},{"cell_type":"code","source":"ans_dict = dict(zip(submids, subm_preds.astype(str)))\n\ndf_to_process = (\n    pd.DataFrame\n    .from_dict(ans_dict, orient='index', columns=['Category'])\n    .reset_index()\n    .rename({'index':'Id'}, axis=1)    \n)\ndf_to_process['Id'] = df_to_process['Id'].map(lambda x: str(x)[:-4])\ndf_to_process.head()","metadata":{"execution":{"iopub.execute_input":"2023-07-12T10:39:26.998140Z","iopub.status.busy":"2023-07-12T10:39:26.997769Z","iopub.status.idle":"2023-07-12T10:39:27.073783Z","shell.execute_reply":"2023-07-12T10:39:27.072716Z","shell.execute_reply.started":"2023-07-12T10:39:26.998107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def process_one_id(id_classes_str):\n    if id_classes_str:\n        return REVERSE_CLASSMAP[int(id_classes_str)]\n    else:\n        return id_classes_str","metadata":{"execution":{"iopub.execute_input":"2023-07-12T10:39:27.076081Z","iopub.status.busy":"2023-07-12T10:39:27.075223Z","iopub.status.idle":"2023-07-12T10:39:27.081373Z","shell.execute_reply":"2023-07-12T10:39:27.080322Z","shell.execute_reply.started":"2023-07-12T10:39:27.076042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_to_process['Category'] = df_to_process['Category'].apply(process_one_id)\ndf_to_process.head()","metadata":{"execution":{"iopub.execute_input":"2023-07-12T10:39:27.083687Z","iopub.status.busy":"2023-07-12T10:39:27.083280Z","iopub.status.idle":"2023-07-12T10:39:27.426221Z","shell.execute_reply":"2023-07-12T10:39:27.424783Z","shell.execute_reply.started":"2023-07-12T10:39:27.083652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_to_process.to_csv('submission_1.csv', index=False)","metadata":{"execution":{"iopub.execute_input":"2023-07-12T10:39:27.428782Z","iopub.status.busy":"2023-07-12T10:39:27.428297Z","iopub.status.idle":"2023-07-12T10:39:27.673822Z","shell.execute_reply":"2023-07-12T10:39:27.672853Z","shell.execute_reply.started":"2023-07-12T10:39:27.428704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Second variant of solving the problem","metadata":{}},{"cell_type":"code","source":"# !pip install tensorflow-gpu==1.14.0 -q\n# !pip install keras==2.2.4 -q\n# !pip install git+https://github.com/qubvel/efficientnet -q\n\n!pip install tensorflow-gpu -q\n!pip install keras -q\n!pip install git+https://github.com/qubvel/efficientnet -q\n\nfrom PIL import Image, ImageDraw\nimport collections\nimport glob \nfrom datetime import datetime as dt\nimport gc\nimport json\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\n\nimport cv2\nfrom copy import deepcopy\nimport efficientnet.keras as efn \nimport glob\nfrom IPython.display import Image\nimport json\nimport keras\nimport keras.backend as K\nfrom keras.optimizers import Adam\nfrom keras.applications.densenet import DenseNet201\nfrom keras.applications.resnet_v2 import ResNet50V2\nfrom keras.layers import Dense, Flatten, Activation, Dropout, GlobalAveragePooling2D\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers, applications\nfrom keras.models import Model, load_model\nfrom keras.callbacks import Callback, ModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping\nfrom keras.utils import Sequence\nimport matplotlib.pyplot as plt\nimport multiprocessing\nimport numpy as np\nfrom numpy.random import seed\nimport os\nimport random\nfrom sklearn.metrics import precision_recall_curve, auc\nfrom sklearn.model_selection import train_test_split\nfrom tqdm import tqdm_notebook as tqdm\n\nseed(10)\n\n\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfig = plt.figure(figsize=(20, 12))\nim = Image.open('../input/iwildcam-2020-fgvc7/train/939e25fc-21bc-11ea-a13a-137349068a90.jpg')\nplt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:18:38.196013Z","iopub.execute_input":"2023-07-17T10:18:38.196452Z","iopub.status.idle":"2023-07-17T10:19:19.149844Z","shell.execute_reply.started":"2023-07-17T10:18:38.196419Z","shell.execute_reply":"2023-07-17T10:19:19.148871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <div class=\"h2\">Data Overview</div>","metadata":{}},{"cell_type":"code","source":"pd.read_csv(\"../input/iwildcam-2020-fgvc7/sample_submission.csv\").head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:19.151864Z","iopub.execute_input":"2023-07-17T10:19:19.153149Z","iopub.status.idle":"2023-07-17T10:19:19.250701Z","shell.execute_reply.started":"2023-07-17T10:19:19.153110Z","shell.execute_reply":"2023-07-17T10:19:19.248677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Overview of train & test data</u>\n\nThere are color data and gray data.  There seems to be photos taken while it was bright and photos taken at night.","metadata":{}},{"cell_type":"code","source":"train_jpeg = glob.glob('../input/iwildcam-2020-fgvc7/train/*')\ntest_jpeg = glob.glob('../input/iwildcam-2020-fgvc7/test/*')\n\nprint(\"number of train jpeg data:\", len(train_jpeg))\nprint(\"number of test jpeg data:\", len(test_jpeg))","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:19.252996Z","iopub.execute_input":"2023-07-17T10:19:19.253588Z","iopub.status.idle":"2023-07-17T10:19:23.773629Z","shell.execute_reply.started":"2023-07-17T10:19:19.253470Z","shell.execute_reply":"2023-07-17T10:19:23.772675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train data","metadata":{}},{"cell_type":"code","source":"from PIL import Image, ImageDraw\n\nfig = plt.figure(figsize=(25, 16))\nfor i,im_path in enumerate(train_jpeg[:16]):\n    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])\n    im = Image.open(im_path)\n    im = im.resize((480,270))\n    plt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:23.775988Z","iopub.execute_input":"2023-07-17T10:19:23.777073Z","iopub.status.idle":"2023-07-17T10:19:26.436637Z","shell.execute_reply.started":"2023-07-17T10:19:23.777041Z","shell.execute_reply":"2023-07-17T10:19:26.435667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\nfor i,im_path in enumerate(train_jpeg[16:32]):\n    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])\n    im = Image.open(im_path)\n    im = im.resize((480,270))\n    plt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:26.438470Z","iopub.execute_input":"2023-07-17T10:19:26.439235Z","iopub.status.idle":"2023-07-17T10:19:28.938104Z","shell.execute_reply.started":"2023-07-17T10:19:26.439173Z","shell.execute_reply":"2023-07-17T10:19:28.936828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Test data","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\nfor i,im_path in enumerate(test_jpeg[:16]):\n    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])\n    im = Image.open(im_path)\n    im = im.resize((480,270))\n    plt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:28.940377Z","iopub.execute_input":"2023-07-17T10:19:28.940823Z","iopub.status.idle":"2023-07-17T10:19:31.428921Z","shell.execute_reply.started":"2023-07-17T10:19:28.940789Z","shell.execute_reply":"2023-07-17T10:19:31.427458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Checking iwildcam2020_megadetector_results.json</u>\n\nThis json contains the detection result of the training data by megadetector.\n\nMegadetector is the pre-trained model to detect animals, people, and vehicles in camera trap images.\n\nhttps://github.com/microsoft/CameraTraps/blob/master/megadetector.md#our-ask-to-megadetector-users","metadata":{}},{"cell_type":"code","source":"with open('../input/iwildcam-2020-fgvc7/iwildcam2020_megadetector_results.json', encoding='utf-8') as json_file:\n    megadetector_results =json.load(json_file)\n    \nmegadetector_results.keys()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:31.429945Z","iopub.execute_input":"2023-07-17T10:19:31.430862Z","iopub.status.idle":"2023-07-17T10:19:34.595734Z","shell.execute_reply.started":"2023-07-17T10:19:31.430802Z","shell.execute_reply":"2023-07-17T10:19:34.594830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"megadetector_results_df = pd.DataFrame(megadetector_results[\"images\"])\nmegadetector_results_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:34.596716Z","iopub.execute_input":"2023-07-17T10:19:34.597542Z","iopub.status.idle":"2023-07-17T10:19:34.872399Z","shell.execute_reply.started":"2023-07-17T10:19:34.597482Z","shell.execute_reply":"2023-07-17T10:19:34.871076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   Next, it creates a list of detection objects.\n-   For each detection object in the list, the code calculates its bbox (bounding box) values.\n-   The x1, y1, w_box, and h_box values represent the leftmost corner of the detection's bounding box at (x1, y1), (w_box, h_box), and (xmax-xmin+w_box, ymax-ymin+h_box).\n-   Next, the code draws a red line between these four points using ImageDraw.Line().\n-   The width parameter specifies how wide the line should be; in this case it is set to 4 pixels.\n-   The fill parameter specifies what color to use for the line; in this case it is set to 'Red'.\n-   Finally, the code sets imageWidth and imageHeight to their respective size values and prints them out onscreen.\n-   The code will create a rectangular bounding box around each detected object in the input image.\n-   The code then uses the line() function to draw a red line connecting the four corners of the box.","metadata":{}},{"cell_type":"code","source":"#Refered: https://www.kaggle.com/qinhui1999/how-to-use-bbox-for-iwildcam-2020 \n\ndef draw_bboxs(detections_list, im):\n    \"\"\"\n    detections_list: list of set includes bbox.\n    im: image read by Pillow.\n    \"\"\"\n    \n    for detection in detections_list:\n        x1, y1,w_box, h_box = detection[\"bbox\"]\n        ymin,xmin,ymax, xmax=y1, x1, y1 + h_box, x1 + w_box\n        draw = ImageDraw.Draw(im)\n        \n        imageWidth=im.size[0]\n        imageHeight= im.size[1]\n        (left, right, top, bottom) = (xmin * imageWidth, xmax * imageWidth,\n                                      ymin * imageHeight, ymax * imageHeight)\n        \n        draw.line([(left, top), (left, bottom), (right, bottom),\n               (right, top), (left, top)], width=4, fill='Red')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:34.873830Z","iopub.execute_input":"2023-07-17T10:19:34.874834Z","iopub.status.idle":"2023-07-17T10:19:34.883917Z","shell.execute_reply.started":"2023-07-17T10:19:34.874799Z","shell.execute_reply":"2023-07-17T10:19:34.882118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_num = 8857\nim = Image.open(\"../input/iwildcam-2020-fgvc7/train/\" + megadetector_results_df.loc[data_num]['id'] + \".jpg\")\nim = im.resize((480,270))\ndraw_bboxs(megadetector_results_df.loc[data_num]['detections'], im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:34.888951Z","iopub.execute_input":"2023-07-17T10:19:34.889284Z","iopub.status.idle":"2023-07-17T10:19:34.931403Z","shell.execute_reply.started":"2023-07-17T10:19:34.889240Z","shell.execute_reply":"2023-07-17T10:19:34.930312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:34.932498Z","iopub.execute_input":"2023-07-17T10:19:34.932795Z","iopub.status.idle":"2023-07-17T10:19:35.196187Z","shell.execute_reply.started":"2023-07-17T10:19:34.932771Z","shell.execute_reply":"2023-07-17T10:19:35.194933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can also know how many aminals detected by megadetector in each pictures. ","metadata":{}},{"cell_type":"code","source":"def get_data(x):\n    if x == []:\n        return 0\n    return len(x)\n\nmegadetector_results_df[\"detected_num\"] = megadetector_results_df.loc[:, \"detections\"].map(get_data)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:35.197643Z","iopub.execute_input":"2023-07-17T10:19:35.198321Z","iopub.status.idle":"2023-07-17T10:19:35.321590Z","shell.execute_reply.started":"2023-07-17T10:19:35.198285Z","shell.execute_reply":"2023-07-17T10:19:35.320271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 4))\nax = sns.countplot(x=\"detected_num\", data=megadetector_results_df)\nax.set(ylabel='count')\n#ax.set(ylim=(0,80000))\nplt.title('distribution of count per animals each data of train')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:35.323470Z","iopub.execute_input":"2023-07-17T10:19:35.323968Z","iopub.status.idle":"2023-07-17T10:19:35.791434Z","shell.execute_reply.started":"2023-07-17T10:19:35.323935Z","shell.execute_reply":"2023-07-17T10:19:35.790126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can select training data depending on the number of animals in the picture.","metadata":{}},{"cell_type":"code","source":"megadetector_results_df = megadetector_results_df[megadetector_results_df['detected_num'] < 2]\nmegadetector_results_df = megadetector_results_df.rename(columns={'id': 'image_id'})\nmegadetector_results_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:35.792707Z","iopub.execute_input":"2023-07-17T10:19:35.793032Z","iopub.status.idle":"2023-07-17T10:19:35.838936Z","shell.execute_reply.started":"2023-07-17T10:19:35.793005Z","shell.execute_reply":"2023-07-17T10:19:35.837751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train data","metadata":{}},{"cell_type":"code","source":"with open('/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_train_annotations.json') as json_file:\n    train_annotations_json = json.load(json_file)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:35.840447Z","iopub.execute_input":"2023-07-17T10:19:35.840815Z","iopub.status.idle":"2023-07-17T10:19:37.341200Z","shell.execute_reply.started":"2023-07-17T10:19:35.840780Z","shell.execute_reply":"2023-07-17T10:19:37.340350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_annotations_json.keys()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:37.342276Z","iopub.execute_input":"2023-07-17T10:19:37.343082Z","iopub.status.idle":"2023-07-17T10:19:37.352058Z","shell.execute_reply.started":"2023-07-17T10:19:37.343051Z","shell.execute_reply":"2023-07-17T10:19:37.350207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annotations = pd.DataFrame(train_annotations_json[\"annotations\"])\ndf_annotations.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:37.354569Z","iopub.execute_input":"2023-07-17T10:19:37.355204Z","iopub.status.idle":"2023-07-17T10:19:37.572119Z","shell.execute_reply.started":"2023-07-17T10:19:37.355161Z","shell.execute_reply":"2023-07-17T10:19:37.571167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_images = pd.DataFrame(train_annotations_json[\"images\"])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:37.585173Z","iopub.execute_input":"2023-07-17T10:19:37.585719Z","iopub.status.idle":"2023-07-17T10:19:38.025997Z","shell.execute_reply.started":"2023-07-17T10:19:37.585693Z","shell.execute_reply":"2023-07-17T10:19:38.024755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_categories = pd.DataFrame(train_annotations_json[\"categories\"])\ndf_images.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:38.046090Z","iopub.execute_input":"2023-07-17T10:19:38.047029Z","iopub.status.idle":"2023-07-17T10:19:38.061898Z","shell.execute_reply.started":"2023-07-17T10:19:38.046996Z","shell.execute_reply":"2023-07-17T10:19:38.060149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_categories.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:38.064115Z","iopub.execute_input":"2023-07-17T10:19:38.064634Z","iopub.status.idle":"2023-07-17T10:19:38.082151Z","shell.execute_reply.started":"2023-07-17T10:19:38.064589Z","shell.execute_reply":"2023-07-17T10:19:38.081411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"There are {len(df_categories) - 1} species\")\n\n# I export DataFrame as CSV for convenience. \ndf_annotations.to_csv(\"iwildcam2020_train_annotations_annotations.csv\", index=False)\ndf_images.to_csv(\"iwildcam2020_train_annotations_images.csv\", index=False)\ndf_categories.to_csv(\"iwildcam2020_train_annotations_categories.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:38.100412Z","iopub.execute_input":"2023-07-17T10:19:38.100786Z","iopub.status.idle":"2023-07-17T10:19:39.533905Z","shell.execute_reply.started":"2023-07-17T10:19:38.100758Z","shell.execute_reply":"2023-07-17T10:19:39.532046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Test data","metadata":{}},{"cell_type":"code","source":"with open('/kaggle/input/iwildcam-2020-fgvc7/iwildcam2020_test_information.json') as json_file:\n    test_information_json = json.load(json_file)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:39.536066Z","iopub.execute_input":"2023-07-17T10:19:39.537353Z","iopub.status.idle":"2023-07-17T10:19:39.828461Z","shell.execute_reply.started":"2023-07-17T10:19:39.537305Z","shell.execute_reply":"2023-07-17T10:19:39.827460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_information_json.keys()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:39.829417Z","iopub.execute_input":"2023-07-17T10:19:39.829800Z","iopub.status.idle":"2023-07-17T10:19:39.834189Z","shell.execute_reply.started":"2023-07-17T10:19:39.829775Z","shell.execute_reply":"2023-07-17T10:19:39.833285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_images_test = pd.DataFrame(test_information_json[\"images\"])\ndf_images_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:39.835592Z","iopub.execute_input":"2023-07-17T10:19:39.835845Z","iopub.status.idle":"2023-07-17T10:19:39.983228Z","shell.execute_reply.started":"2023-07-17T10:19:39.835822Z","shell.execute_reply":"2023-07-17T10:19:39.982317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_categories_test = pd.DataFrame(test_information_json[\"categories\"])\ndf_categories_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:39.990620Z","iopub.execute_input":"2023-07-17T10:19:39.990977Z","iopub.status.idle":"2023-07-17T10:19:40.004283Z","shell.execute_reply.started":"2023-07-17T10:19:39.990951Z","shell.execute_reply":"2023-07-17T10:19:40.002441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# I export DataFrame as CSV for convenience. \ndf_images_test.to_csv(\"iwildcam2020_train_annotations_images_test.csv\", index=False)\ndf_categories_test.to_csv(\"iwildcam2020_train_annotations_categories_test.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:40.006936Z","iopub.execute_input":"2023-07-17T10:19:40.008177Z","iopub.status.idle":"2023-07-17T10:19:40.296758Z","shell.execute_reply.started":"2023-07-17T10:19:40.008132Z","shell.execute_reply":"2023-07-17T10:19:40.295986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <u>Data distributions</u>\n\nI plot train and test data in following perspective:\n\n* Time point\n\n* Category ID\n\n* Location","metadata":{}},{"cell_type":"markdown","source":"### When did data taken?\n\nBecause animals can change their activity from time to time, we want to understand how data is distributed over time.","metadata":{}},{"cell_type":"markdown","source":"**Monthly perspective**","metadata":{}},{"cell_type":"code","source":"month_year = df_images['datetime'].map(lambda str: str[2:7])\nlabels_month_year = sorted(list(set(month_year)))\n\nmonth_year_test = df_images_test['datetime'].map(lambda str: str[2:7])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:40.297870Z","iopub.execute_input":"2023-07-17T10:19:40.299205Z","iopub.status.idle":"2023-07-17T10:19:40.400618Z","shell.execute_reply.started":"2023-07-17T10:19:40.299166Z","shell.execute_reply":"2023-07-17T10:19:40.399136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Data starts 2013-01 but there seems be some lacks. For example, train data between 2013-11 to 2014-02 are missing. \n\nAlso we can find that train data in between 2013-01 to 2013-07 are rich than other time point.\n\nTrain data covers test data in perspective of time point.","metadata":{}},{"cell_type":"code","source":"labels_month = sorted(list(set(df_images['datetime'].map(lambda str: str[5:7]))))\nlabels_month","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:40.402020Z","iopub.execute_input":"2023-07-17T10:19:40.403249Z","iopub.status.idle":"2023-07-17T10:19:40.495939Z","shell.execute_reply.started":"2023-07-17T10:19:40.403198Z","shell.execute_reply":"2023-07-17T10:19:40.493972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Train data are bias. In February, March, June and July, data are rich than other months. \n\nTrain data covers test data in perspective of month.\n\nData for November and December are missing. Do animals hibernate?","metadata":{}},{"cell_type":"markdown","source":"**Hourly perspective**","metadata":{}},{"cell_type":"code","source":"train_taken_hour = df_images['datetime'].map(lambda x: dt.strptime(x, '%Y-%m-%d %H:%M:%S.%f').hour)\ntest_taken_hour = df_images_test['datetime'].map(lambda x: dt.strptime(x, '%Y-%m-%d %H:%M:%S.%f').hour)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:40.497791Z","iopub.execute_input":"2023-07-17T10:19:40.498350Z","iopub.status.idle":"2023-07-17T10:19:43.292160Z","shell.execute_reply.started":"2023-07-17T10:19:40.498301Z","shell.execute_reply":"2023-07-17T10:19:43.291176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1,2, figsize=(20,7))\nax = plt.subplot(1,2,1)\nplt.title('Count of train data per hour')\nax = sns.countplot(train_taken_hour)\nax.set(xlabel='hour', ylabel='count')\nax.set(ylim=(0,20000))\n\nax = plt.subplot(1,2,2)\nplt.title('Count of test data per hour')\nax = sns.countplot(test_taken_hour)\nax.set(xlabel='hour', ylabel='count')\nax.set(ylim=(0,20000))","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:43.293306Z","iopub.execute_input":"2023-07-17T10:19:43.293623Z","iopub.status.idle":"2023-07-17T10:19:43.681699Z","shell.execute_reply.started":"2023-07-17T10:19:43.293593Z","shell.execute_reply":"2023-07-17T10:19:43.680408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"If we decide arbitrarily during daytime and at night, we can also calculate diurnal and nocturnal data counts.\n\nFor example, we define \"during daytime\" is \"6~17 O'clock\" and \"at night\" is \"18~5 O'clock\",","metadata":{}},{"cell_type":"code","source":"train_taken_phase = train_taken_hour.map(lambda x: \"daytime\" if x >= 6 and x < 18 else \"night\")\ntest_taken_phase = test_taken_hour.map(lambda x: \"daytime\" if x >= 6 and x < 18 else \"night\")","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:43.683989Z","iopub.execute_input":"2023-07-17T10:19:43.684421Z","iopub.status.idle":"2023-07-17T10:19:43.745541Z","shell.execute_reply.started":"2023-07-17T10:19:43.684390Z","shell.execute_reply":"2023-07-17T10:19:43.744460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Memory savings\ndel train_taken_phase\ndel test_taken_phase\ndel train_taken_hour\ndel test_taken_hour\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:43.746779Z","iopub.execute_input":"2023-07-17T10:19:43.747092Z","iopub.status.idle":"2023-07-17T10:19:44.417128Z","shell.execute_reply.started":"2023-07-17T10:19:43.747065Z","shell.execute_reply":"2023-07-17T10:19:44.415437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### How many data are there per animal category Id?\n\nThere are a lot of categories in dataset. To confirme how many data are there in each categories, I plot barplot.  ","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(30, 4))\nlabels_id = sorted(list(set(df_categories[\"id\"])))\nax = sns.barplot(x=\"id\", y=\"count\",data=df_categories, order=labels_id)\nax.set(ylabel='count')\nax.set(ylim=(0,80000))\nplt.title('distribution of count per id in train')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:44.418481Z","iopub.execute_input":"2023-07-17T10:19:44.418896Z","iopub.status.idle":"2023-07-17T10:19:46.730610Z","shell.execute_reply.started":"2023-07-17T10:19:44.418869Z","shell.execute_reply":"2023-07-17T10:19:46.729512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(30, 4))\nlabels_id = sorted(list(set(df_categories[\"id\"])))\nax = sns.barplot(x=\"id\", y=\"count\",data=df_categories_test, order=labels_id)\nax.set(ylabel='count')\nax.set(ylim=(0,80000))\nplt.title('distribution of count per id in test')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:46.731985Z","iopub.execute_input":"2023-07-17T10:19:46.732288Z","iopub.status.idle":"2023-07-17T10:19:49.060202Z","shell.execute_reply.started":"2023-07-17T10:19:46.732237Z","shell.execute_reply":"2023-07-17T10:19:49.057988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Frequency of data in each id is similar for train and test data.","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 9))\nax = sns.distplot(df_categories['count'][1:])\nax.set(ylim=(0,0.00005))\nax.set(xlabel='count')\nplt.title('distribution of number of data per id zoomed')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:49.061976Z","iopub.execute_input":"2023-07-17T10:19:49.062357Z","iopub.status.idle":"2023-07-17T10:19:49.488728Z","shell.execute_reply.started":"2023-07-17T10:19:49.062319Z","shell.execute_reply":"2023-07-17T10:19:49.487632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Almost data is less than 5000 pictures. \n\nBut we can find that the number of specific IDs is very large and the data is biased.","metadata":{}},{"cell_type":"markdown","source":"### How many data per location?\n\nWe are required to detect photographs taken at different locations, but how distribute are data  in perspect of  location?","metadata":{}},{"cell_type":"code","source":"labels_location_train = sorted(list(set(df_images['location'])))\nlabels_location_test = sorted(list(set(df_images_test['location'])))\nlabels_location = labels_location_train + labels_location_test","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:49.489889Z","iopub.execute_input":"2023-07-17T10:19:49.490158Z","iopub.status.idle":"2023-07-17T10:19:49.526347Z","shell.execute_reply.started":"2023-07-17T10:19:49.490132Z","shell.execute_reply":"2023-07-17T10:19:49.524280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Are different animal kinds photographed in different places?\n\nWe have location data and animal category data, so we can investigate wheathrer different animal kinds are photographed in different places.","metadata":{}},{"cell_type":"code","source":"loc_cat_df_test = pd.merge(df_images, df_annotations, left_on='id', right_on='image_id', how = \"inner\").loc[:,[\"location\", \"category_id\", \"image_id\"]]\nloc_cat_df_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:49.529926Z","iopub.execute_input":"2023-07-17T10:19:49.530466Z","iopub.status.idle":"2023-07-17T10:19:49.869431Z","shell.execute_reply.started":"2023-07-17T10:19:49.530423Z","shell.execute_reply":"2023-07-17T10:19:49.867998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loc_cat_dict = {}\nfor loc in set(loc_cat_df_test[\"location\"]):\n    loc_cat_dict[loc] = list(set(loc_cat_df_test[loc_cat_df_test[\"location\"] == loc][\"category_id\"]))   \nloc_cat_matrix = np.zeros([loc_cat_df_test[\"location\"].max()+1, loc_cat_df_test[\"category_id\"].max()+1])\nloc_cat_matrix.shape","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:49.871012Z","iopub.execute_input":"2023-07-17T10:19:49.871367Z","iopub.status.idle":"2023-07-17T10:19:50.076978Z","shell.execute_reply.started":"2023-07-17T10:19:49.871341Z","shell.execute_reply":"2023-07-17T10:19:50.075809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for loc in loc_cat_dict.keys():\n    for cat in loc_cat_dict[loc]:\n        loc_cat_matrix[loc, cat] = 1","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:50.078085Z","iopub.execute_input":"2023-07-17T10:19:50.080687Z","iopub.status.idle":"2023-07-17T10:19:50.086760Z","shell.execute_reply.started":"2023-07-17T10:19:50.080649Z","shell.execute_reply":"2023-07-17T10:19:50.085621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(15, 15))\nax = sns.heatmap(loc_cat_matrix)\nax.set(xlabel='category', ylabel='location')\nplt.title('Relation between animal categories and locations')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:50.087934Z","iopub.execute_input":"2023-07-17T10:19:50.088200Z","iopub.status.idle":"2023-07-17T10:19:51.889449Z","shell.execute_reply.started":"2023-07-17T10:19:50.088176Z","shell.execute_reply":"2023-07-17T10:19:51.888527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It's a bit hard to see, but columns are the categories of animals and rows are the locations. Since similar patterns appear in the vertical direction, it seems that similar species may appear even in different places.","metadata":{}},{"cell_type":"markdown","source":"### How many animals in each photograph sequence?\n\nWe can know how many animals each photograph sequence (continuous frame of camera trap from startup to taking) by annotations value of train_annotations_json. Count key seems represent number of animals appear in each photograph sequence. \n\nThree Pan troglodytes appear in folloing frames.","metadata":{}},{"cell_type":"code","source":"df_annotations[2429:2440]","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:51.890826Z","iopub.execute_input":"2023-07-17T10:19:51.891913Z","iopub.status.idle":"2023-07-17T10:19:51.903745Z","shell.execute_reply.started":"2023-07-17T10:19:51.891855Z","shell.execute_reply":"2023-07-17T10:19:51.902204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\n#for i,im_path in enumerate(df_annotations[df_annotations.loc[:,\"count\"] == 3].loc[:,\"image_id\"][2429:2440]):\nfor i,im_path in enumerate(df_annotations.loc[:,\"image_id\"][2429:2440]):\n    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])\n    im = Image.open(\"../input/iwildcam-2020-fgvc7/train/\" + im_path + \".jpg\")\n    im = im.resize((480,270))\n    plt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:51.905383Z","iopub.execute_input":"2023-07-17T10:19:51.905788Z","iopub.status.idle":"2023-07-17T10:19:53.734718Z","shell.execute_reply.started":"2023-07-17T10:19:51.905752Z","shell.execute_reply":"2023-07-17T10:19:53.732961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Does the number of individuals that appear at one time vary depending on the animal species?","metadata":{}},{"cell_type":"code","source":"c = collections.Counter(df_annotations.loc[:,\"count\"])\nanimals_in_pict = list(c.keys())\nfreq = list(c.values())\nk = zip(animals_in_pict,freq)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.736610Z","iopub.execute_input":"2023-07-17T10:19:53.736988Z","iopub.status.idle":"2023-07-17T10:19:53.772532Z","shell.execute_reply.started":"2023-07-17T10:19:53.736955Z","shell.execute_reply":"2023-07-17T10:19:53.770908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animals_in_pict_df = pd.DataFrame(sorted(k),columns=['num_of_animals','freq'])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.774119Z","iopub.execute_input":"2023-07-17T10:19:53.774560Z","iopub.status.idle":"2023-07-17T10:19:53.787569Z","shell.execute_reply.started":"2023-07-17T10:19:53.774520Z","shell.execute_reply":"2023-07-17T10:19:53.786065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animals_in_pict_df","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.789282Z","iopub.execute_input":"2023-07-17T10:19:53.789635Z","iopub.status.idle":"2023-07-17T10:19:53.816778Z","shell.execute_reply.started":"2023-07-17T10:19:53.789606Z","shell.execute_reply":"2023-07-17T10:19:53.813984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Only a limited number of animals are grouped together. 266 species are taken in train set, but only 14 species were photographed, with more than 10 animals at a time. It turns out that there is a relationship between the animal species and the number of individuals reflected.　","metadata":{}},{"cell_type":"code","source":"species_morethan_10 = list(set(df_annotations[df_annotations.loc[:,\"count\"] >= 10].loc[:,\"category_id\"]))\ndf_categories[df_categories.loc[:,\"id\"].isin(species_morethan_10)].loc[:,[\"id\", \"name\"]]","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.818086Z","iopub.execute_input":"2023-07-17T10:19:53.818498Z","iopub.status.idle":"2023-07-17T10:19:53.841238Z","shell.execute_reply.started":"2023-07-17T10:19:53.818467Z","shell.execute_reply":"2023-07-17T10:19:53.839884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Species that shows more than 30 individuals at a time in a photo is  only a cow and a boar.","metadata":{}},{"cell_type":"code","source":"species_morethan_30 = list(set(df_annotations[df_annotations.loc[:,\"count\"] >= 30].loc[:,\"category_id\"]))\ndf_categories[df_categories.loc[:,\"id\"].isin(species_morethan_30)].loc[:,[\"id\", \"name\"]]","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.842854Z","iopub.execute_input":"2023-07-17T10:19:53.843341Z","iopub.status.idle":"2023-07-17T10:19:53.857702Z","shell.execute_reply.started":"2023-07-17T10:19:53.843300Z","shell.execute_reply":"2023-07-17T10:19:53.856232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annotations[(df_annotations.loc[:,\"category_id\"] == 2) & (df_annotations.loc[:,\"count\"] >= 30)].head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.859105Z","iopub.execute_input":"2023-07-17T10:19:53.859445Z","iopub.status.idle":"2023-07-17T10:19:53.879187Z","shell.execute_reply.started":"2023-07-17T10:19:53.859416Z","shell.execute_reply":"2023-07-17T10:19:53.878325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\n#for i,im_path in enumerate(df_annotations[df_annotations.loc[:,\"count\"] == 3].loc[:,\"image_id\"][2429:2440]):\nfor i,im_path in enumerate(df_annotations.loc[:,\"image_id\"][149674:149678]):\n    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])\n    im = Image.open(\"../input/iwildcam-2020-fgvc7/train/\" + im_path + \".jpg\")\n    im = im.resize((480,270))\n    plt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:53.880681Z","iopub.execute_input":"2023-07-17T10:19:53.881078Z","iopub.status.idle":"2023-07-17T10:19:54.559562Z","shell.execute_reply.started":"2023-07-17T10:19:53.881050Z","shell.execute_reply":"2023-07-17T10:19:54.558338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annotations[(df_annotations.loc[:,\"category_id\"] == 71) & (df_annotations.loc[:,\"count\"] >= 30)].head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:54.561000Z","iopub.execute_input":"2023-07-17T10:19:54.561350Z","iopub.status.idle":"2023-07-17T10:19:54.575451Z","shell.execute_reply.started":"2023-07-17T10:19:54.561320Z","shell.execute_reply":"2023-07-17T10:19:54.574352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"jpeg ='../input/iwildcam-2020-fgvc7/train/8897a9f8-21bc-11ea-a13a-137349068a90.jpg'\nim = Image.open(jpeg)\nim = im.resize((480,270))\nplt.imshow(im)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:54.576962Z","iopub.execute_input":"2023-07-17T10:19:54.577586Z","iopub.status.idle":"2023-07-17T10:19:54.892819Z","shell.execute_reply.started":"2023-07-17T10:19:54.577556Z","shell.execute_reply":"2023-07-17T10:19:54.891331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model example","metadata":{}},{"cell_type":"markdown","source":"I prepare EfficientNet example. The point of this model is that I choose photos which one or less　animal is taken for training.\n\nI refered following kernels.\n\nhttps://www.kaggle.com/ateplyuk/inat2019-starter-keras-efficientnet/data\n\nhttps://www.kaggle.com/mobassir/keras-efficientnetb2-for-classifying-cloud","metadata":{}},{"cell_type":"code","source":"train_anns_df = df_annotations[['image_id','category_id']]\ntrain_img_df = df_images[['id', 'file_name']].rename(columns={'id':'image_id'})\ndf_train_file_cat = pd.merge(train_img_df, train_anns_df, on='image_id')\ndf_train_file_cat['category_id']=df_train_file_cat['category_id'].astype(str)\ndf_train_file_cat.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:54.894306Z","iopub.execute_input":"2023-07-17T10:19:54.894616Z","iopub.status.idle":"2023-07-17T10:19:55.246083Z","shell.execute_reply.started":"2023-07-17T10:19:54.894590Z","shell.execute_reply":"2023-07-17T10:19:55.244582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_file_cat = pd.merge(megadetector_results_df, df_train_file_cat, on='image_id', how='inner')\n\nfig = plt.figure(figsize=(15, 4))\nax = sns.countplot(x=\"detected_num\", data=megadetector_results_df)\nax.set(ylabel='count')\nplt.title('distribution of count per animals each data of train')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:55.247401Z","iopub.execute_input":"2023-07-17T10:19:55.247734Z","iopub.status.idle":"2023-07-17T10:19:55.807185Z","shell.execute_reply.started":"2023-07-17T10:19:55.247706Z","shell.execute_reply":"2023-07-17T10:19:55.806440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prepare data and model","metadata":{}},{"cell_type":"markdown","source":"### Parameters\n","metadata":{}},{"cell_type":"code","source":"batch_size = 128\nimg_size = 96\nlr = 0.001 \nnb_classes = 267\nnb_epochs = 70","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:55.808473Z","iopub.execute_input":"2023-07-17T10:19:55.808762Z","iopub.status.idle":"2023-07-17T10:19:55.814131Z","shell.execute_reply.started":"2023-07-17T10:19:55.808738Z","shell.execute_reply":"2023-07-17T10:19:55.813042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code starts by creating two ImageDataGenerator objects.\n-   The first, train_datagen, will be used to generate images of the training data.\n-   The second, valid_generator, will be used to generate images of the validation data.\n-   Next, the code sets up some parameters for the ImageDataGenerator objects.\n-   First, it sets the scale parameter to 1/255 so that the generated images will have a resolution of 256x256 pixels.\n-   Next, it sets the validation_split parameter to 0.25 so that 25% of the images in each dataset will be used for validation purposes.\n-   Finally, it sets the horizontal_flip flag to True so that all image files will be flipped horizontally (so that they are displayed right-to-left).\n-   The next section of code defines how many images should be generated per batch and how many batches should be generated total.\n-   The batch size is set to 5000 and the shuffle flag is set to True so that all training data items will be randomly shuffled before being processed by train_datagen.\n-   Finally, classes is set to an empty list which means that all training data items will be processed as individual instances rather than being grouped into categories like in a traditional classifier system\n-   The code will generate two data sets, one for training and the other for testing.\n-   The train_datagen data set will contain images of files with a file name that starts with \"train\" and has an associated category_id value of 1.\n-   The test_datagen data set will contain images of files with a file name that starts with \"test\" and has an associated category_id value of 2.\n-   The code also specifies the dimensions of the generated data sets, as well as how they should be resized.\n-   It also specifies whether the images should be flipped horizontally (true) and zoomed in or out (0.3 and 0.3, respectively).\n-   Finally, it specifies how much space to shift each image's width","metadata":{}},{"cell_type":"code","source":"%%time\n\ntrain_datagen=ImageDataGenerator(rescale=1./255, \n    validation_split=0.25,\n    horizontal_flip = True,    \n    vertical_flip=True,\n    zoom_range = 0.5,\n    width_shift_range = 0.5,\n    height_shift_range=0.5\n    )\n\ntrain_generator=train_datagen.flow_from_dataframe(    \n    dataframe=df_train_file_cat[:50000],    \n    directory=\"../input/iwildcam-2020-fgvc7/train\",\n    x_col=\"file_name\",\n    y_col=\"category_id\",\n    batch_size=batch_size,\n    shuffle=True,\n    classes = [ str(i) for i in range(nb_classes)],\n    class_mode=\"categorical\",    \n    target_size=(img_size,img_size))\n\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\nvalid_generator=test_datagen.flow_from_dataframe(    \n    dataframe=df_train_file_cat[50000:],    \n    directory=\"../input/iwildcam-2020-fgvc7/train\",\n    x_col=\"file_name\",\n    y_col=\"category_id\",\n    batch_size=batch_size,\n    shuffle=True,\n    classes = [ str(i) for i in range(nb_classes)],\n    class_mode=\"categorical\",  \n    target_size=(img_size,img_size))","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:19:55.815284Z","iopub.execute_input":"2023-07-17T10:19:55.815643Z","iopub.status.idle":"2023-07-17T10:22:56.159537Z","shell.execute_reply.started":"2023-07-17T10:19:55.815610Z","shell.execute_reply":"2023-07-17T10:22:56.158437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"-   The code first creates an instance of the EfficientNetB3 class.\n-   This class is used to create a model that predicts the probability of each class in an image.\n-   The weights parameter specifies which features should be used in the model, and include_top determines whether top-level features (such as those at the level of classes) should be included in the prediction.\n-   The pooling parameter controls how features are combined when predicting probabilities; by default, they are averaged together.\n-   Next, the code sets up a variable called x to store the input data for training and predictions.\n-   The output from the EfficientNetB3 class will be stored in x .\n-   The next section of code creates a Dense object called predictions .\n-   This object will contain all of the predicted probabilities for each image.\n-   It is initialized with a size equal to 3 , meaning that it will hold 30 values (one for each pixel in an image).\n-   Finally, the get_model() function returns a Model object containing both inputs and predictions .\n-   The code first creates an instance of the EfficientNetB3 model.\n-   This model is designed to predict the probability of a given class (in this case, images of cats) from a set of training images.\n-   Next, the code creates a variable called x which will store the predictions made by the EfficientNetB3 model.\n-   Finally, the code uses the Model() function to create a prediction model that can be used to make predictions on new data.","metadata":{}},{"cell_type":"code","source":"def get_model():\n    K.clear_session()\n    base_model =  efn.EfficientNetB3(weights='imagenet', include_top=False, pooling='avg', input_shape=(img_size, img_size, 3))\n    x = base_model.output\n    predictions = Dense(nb_classes, activation=\"softmax\")(x)\n    return Model(inputs=base_model.input, outputs=predictions)\n\nmodel = get_model()\nmodel.compile(optimizers.Adam(lr=lr, decay=1e-6),loss='categorical_crossentropy',metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:22:56.160667Z","iopub.execute_input":"2023-07-17T10:22:56.160940Z","iopub.status.idle":"2023-07-17T10:23:01.290048Z","shell.execute_reply.started":"2023-07-17T10:22:56.160915Z","shell.execute_reply":"2023-07-17T10:23:01.289081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"early = EarlyStopping(monitor='val_loss', min_delta=0, patience=7, verbose=1, mode='auto')","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.291509Z","iopub.execute_input":"2023-07-17T10:23:01.291769Z","iopub.status.idle":"2023-07-17T10:23:01.295964Z","shell.execute_reply.started":"2023-07-17T10:23:01.291745Z","shell.execute_reply":"2023-07-17T10:23:01.295071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Training","metadata":{}},{"cell_type":"markdown","source":"-   The code starts by importing the necessary libraries.\n-   It then creates a model object and sets some properties of that object.\n-   The most important property is \"steps_per_epoch\", which specifies the number of steps per epoch in the training process.\n-   The code also sets the \"validation_data\" and \"validation_steps\" properties to be equal to the values of \"generator\" and \"2\", respectively.\n-   Next, the code creates four worker threads and assigns them to the \"workers\" variable.\n-   Finally, it sets up two callbacks: one for early termination (called \"early\"), and another for reporting progress (called \"verbose\").\n-   The next section of code defines what data will be used during training.\n-   First, it imports the validation data set into memory using the Python library pandas.\n-   Then, it uses pandas' Series objects to create a dataset that contains all valid predictions made by each model during training.\n-   Next, the code calculates how many iterations were completed for each model on each epoch using Pandas' Series objects.\n-   This information is stored in an array called \"epochs\".\n-   Finally, it prints out this information to screen so that you can see how well each model is performing overall.\n-   The code will run the model on a training set of data and a validation set of data.\n-   The model is fit using the generator function, which takes as input a train_generator object and an epochs argument.\n-   The steps_per_epoch argument sets the number of steps per epoch, while the validation_steps argument sets the number of validation steps.\n-   Finally, the epochs argument specifies how many batches of data to use for training and validation.\n-   The callbacks argument defines two callbacks: early and late.\n-   The early callback is called when the first batch of data has been processed, while the late callback is called when all batches have been processed.\n-   The verbose flag determines whether or not output information about each step in processing will","metadata":{}},{"cell_type":"code","source":"%%time\nhistory = model.fit_generator(generator=train_generator,  \n                                    steps_per_epoch=70,\n                                    validation_data=valid_generator, \n                                    validation_steps=2,\n                                    epochs=nb_epochs,\n                                    callbacks = [early],\n                                    verbose=2,\n                                    workers=4,\n                                    use_multiprocessing=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.296858Z","iopub.execute_input":"2023-07-17T10:23:01.297119Z","iopub.status.idle":"2023-07-17T10:23:01.469111Z","shell.execute_reply.started":"2023-07-17T10:23:01.297088Z","shell.execute_reply":"2023-07-17T10:23:01.467595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history_df = pd.DataFrame(history.history)\nhistory_df[['loss', 'val_loss']].plot()\nhistory_df[['accuracy', 'val_accuracy']].plot()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.470857Z","iopub.execute_input":"2023-07-17T10:23:01.471188Z","iopub.status.idle":"2023-07-17T10:23:01.518953Z","shell.execute_reply.started":"2023-07-17T10:23:01.471163Z","shell.execute_reply":"2023-07-17T10:23:01.516933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This code is training a deep learning model using the TensorFlow library. Let's go through the code step by step:\n\n1. The `scheduler` function is defined. This function takes two arguments: `epoch` and `lr` (learning rate). It is used as a callback function to adjust the learning rate during training. If the epoch is less than 10, it returns the current learning rate unchanged. Otherwise, it returns the current learning rate multiplied by the exponential function `tf.math.exp(-0.1)`.\n\n2. The `get_model` function is defined. This function creates a ResNet50V2 model with pre-trained weights from the ImageNet dataset. The model is configured to exclude the top layer, use average pooling, and take input images of size `(img_size, img_size, 3)`. The output of the base model is then passed through a Dense layer with `nb_classes` units and softmax activation. The function returns the complete model.\n\n3. The `model` variable is assigned the result of calling the `get_model` function. This creates the model that will be trained.\n\n4. The `model` is compiled using the Adam optimizer with a learning rate of `lr` and a decay rate of `1e-6`. The loss function is set to `'categorical_crossentropy'` and the metric to track during training is `'accuracy'`.\n\n5. An `EarlyStopping` callback is created. This callback monitors the validation loss and stops training if the loss does not improve for `patience` number of epochs (in this case, 7). The `min_delta` parameter is set to 0, meaning any improvement in the loss will be considered as an improvement.\n\n6. A `LearningRateScheduler` callback is created using the `scheduler` function defined earlier. This callback adjusts the learning rate during training based on the current epoch.\n\n7. The `model.fit_generator` function is called to start the training process. This function takes several arguments:\n   - `generator`: The training data generator.\n   - `steps_per_epoch`: The number of steps (batches) to take per epoch.\n   - `validation_data`: The validation data generator.\n   - `validation_steps`: The number of steps (batches) to take for validation.\n   - `epochs`: The number of epochs to train for.\n   - `callbacks`: A list of callbacks to use during training (in this case, `early` and `callback`).\n   - `verbose`: The verbosity mode (0 = silent, 1 = progress bar, 2 = one line per epoch).\n   - `workers`: The number of worker processes to use for data loading.\n   - `use_multiprocessing`: Whether to use multiprocessing for data loading.\n\n8. The `history` variable is assigned the result of the `model.fit_generator` function. This contains information about the training process, such as the loss and accuracy values at each epoch.\n\nOverall, this code sets up a deep learning model, compiles it with the specified optimizer and loss function, and trains it using the provided data generators and callbacks. The learning rate is adjusted during training using the `LearningRateScheduler` callback, and early stopping is used to prevent overfitting.","metadata":{}},{"cell_type":"code","source":"%%time\nimport tensorflow as tf\ndef scheduler(epoch, lr):\n    if epoch < 10:\n        return lr\n    else:\n        return lr * tf.math.exp(-0.1)\n\ndef get_model():\n    K.clear_session()\n    base_model =  ResNet50V2(weights='imagenet', include_top=False, pooling='avg', input_shape=(img_size, img_size, 3))\n    x = base_model.output\n    predictions = Dense(nb_classes, activation=\"softmax\")(x)\n    return Model(inputs=base_model.input, outputs=predictions)\n\nmodel = get_model()\nmodel.compile(optimizers.Adam(lr=lr, decay=1e-6),loss='categorical_crossentropy',metrics=['accuracy'])\n\nearly = EarlyStopping(monitor='val_loss', min_delta=0, patience=7, verbose=1, mode='auto')\ncallback = tf.keras.callbacks.LearningRateScheduler(scheduler)\n\nhistory = model.fit_generator(generator=train_generator,  \n                                    steps_per_epoch=70,\n                                    validation_data=valid_generator, \n                                    validation_steps=2,\n                                    epochs=nb_epochs,\n                                    callbacks = [early,callback],\n                                    verbose=2,\n                                    workers=4,\n                                    use_multiprocessing=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.520221Z","iopub.status.idle":"2023-07-17T10:23:01.520737Z","shell.execute_reply.started":"2023-07-17T10:23:01.520496Z","shell.execute_reply":"2023-07-17T10:23:01.520518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history_df = pd.DataFrame(history.history)\nhistory_df[['loss', 'val_loss']].plot()\nhistory_df[['accuracy', 'val_accuracy']].plot()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\ndel train_datagen, train_generator\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.523160Z","iopub.status.idle":"2023-07-17T10:23:01.523704Z","shell.execute_reply.started":"2023-07-17T10:23:01.523472Z","shell.execute_reply":"2023-07-17T10:23:01.523494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Prediction","metadata":{}},{"cell_type":"code","source":"sam_sub_df = pd.read_csv('../input/iwildcam-2020-fgvc7/sample_submission.csv')\nsam_sub_df[\"file_name\"] = sam_sub_df[\"Id\"].map(lambda str : str + \".jpg\")\nsam_sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.525206Z","iopub.status.idle":"2023-07-17T10:23:01.525640Z","shell.execute_reply.started":"2023-07-17T10:23:01.525462Z","shell.execute_reply":"2023-07-17T10:23:01.525480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\ntest_generator = test_datagen.flow_from_dataframe(      \n    \n        dataframe=sam_sub_df,    \n    \n        directory = \"../input/iwildcam-2020-fgvc7/test\",    \n        x_col=\"file_name\",\n        target_size = (img_size,img_size),\n        batch_size = 1,\n        classes = [ str(i) for i in range(nb_classes)],\n        shuffle = False,\n        class_mode = None\n        )","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.527037Z","iopub.status.idle":"2023-07-17T10:23:01.527418Z","shell.execute_reply.started":"2023-07-17T10:23:01.527222Z","shell.execute_reply":"2023-07-17T10:23:01.527238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ntest_generator.reset()\npredict=model.predict_generator(test_generator, steps = len(test_generator.filenames))\npredicted_class_indices=np.argmax(predict,axis=1)\nsam_sub_df[\"Category\"] = predicted_class_indices\nsam_sub_df = sam_sub_df.loc[:,[\"Id\", \"Category\"]]\nsam_sub_df.to_csv(\"submission_2.csv\",index=False)","metadata":{"execution":{"iopub.status.busy":"2023-07-17T10:23:01.528547Z","iopub.status.idle":"2023-07-17T10:23:01.528868Z","shell.execute_reply.started":"2023-07-17T10:23:01.528717Z","shell.execute_reply":"2023-07-17T10:23:01.528732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The orginal training set contains pictures of many animals at one time. I thought they have a bad impact to learning. By eliminating these, it seems that learning has converged well. Instead, the predictions are not very good. As one of the improvement plans I think, it may be effective to cut out the part of data where the animal is reflected.","metadata":{}}]}