{"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":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport os\n\nimport sklearn\nfrom sklearn.model_selection import train_test_split\nimport torchvision\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nimport multiprocessing\n\nfrom kaggle_secrets import UserSecretsClient\n\n# from skimage.io import imread\nimport cv2\n\nimport imgaug as ia\nimport imgaug.augmenters as iaa\n\nia.seed(1)\n\nfrom skimage.transform import resize\nimport numpy as np\nimport math","metadata":{"_uuid":"bf761bd1-07f1-4d00-9c7c-c352b03ddca3","_cell_guid":"651e9074-0d03-4666-958f-5a5885f10655","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GLOBAL_SEED = 42\n\nnp.random.seed(GLOBAL_SEED)","metadata":{"_uuid":"07b909c2-2e71-48b6-8dfa-ab0443f3d4de","_cell_guid":"19a0b046-3ac0-4d75-9487-48a2c0e76dba","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install faiss-gpu","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_cores = multiprocessing.cpu_count()\nprint(f\"CPU Cores: {num_cores}\")","metadata":{"_uuid":"4d21c1b8-5657-4673-9a00-8e57c5931092","_cell_guid":"da2646ab-8614-44fb-982e-3f33b8fbfe0f","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvcc --version","metadata":{"_uuid":"5bf65e16-7966-4ed5-9531-2b7800a5e8da","_cell_guid":"877eb67e-3137-43fb-8ffd-f790e010881d","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/hotel-id-2021-fgvc8/train.csv\")","metadata":{"_uuid":"57e32d3e-9fc8-4c9b-a4d3-a280785fcfa9","_cell_guid":"3d580ac0-7ff9-473b-8dce-f768bc3651f9","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_classes = len(train_df['hotel_id'].value_counts())\nn_classes","metadata":{"_uuid":"5487fb85-a215-456d-ad40-c1daa39a033c","_cell_guid":"29eb2bbd-6579-405c-9ea0-3a607ed3e1f6","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn import preprocessing\n\nle = preprocessing.LabelEncoder()\nle.fit(train_df['hotel_id'])\n\ntrain_df['label'] = le.transform(train_df['hotel_id'])\n\nkaggle_path = \"/kaggle/input/hotel-id-2021-fgvc8/train_images/\"\ntrain_df['full_filepath'] = kaggle_path + train_df.chain.astype(str) +\"/\"+ train_df.image.astype(str)\n\ntrain_df","metadata":{"_uuid":"cee4b8d0-0c74-48d4-b0dd-4647e7e8e8db","_cell_guid":"82463c5c-b807-45e5-a2ff-768669cabfb9","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_map = dict(sorted(train_df[['label', 'hotel_id']].values.tolist()))","metadata":{"_uuid":"9d3249bd-6bc6-432e-98da-f1600e827727","_cell_guid":"87c05db3-f3c3-473c-a473-92f98fd2deeb","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"min_value = 7\nfor i, v in train_df['label'].value_counts().items():\n    if v > min_value - 1:\n        continue\n    else:\n        for j in range(min_value - v):\n            train_df = train_df.append(train_df[train_df['label'] == i].iloc[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# shuffle\ntrain = train_df.sample(frac=1.0)\n\n# get the first two by group\ntrain = train.groupby(\"label\").head(7)\n\n# sort by Rings\ntrain = train.sort_values(\"label\")\n\nprint(train)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Subsample","metadata":{"_uuid":"f43b772d-c7a5-4992-b04b-7ed95169f3a2","_cell_guid":"65d7a60d-9bb4-4e11-8062-220a3d5e7ef1","trusted":true}},{"cell_type":"code","source":"train['label'].value_counts()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['label'].value_counts()","metadata":{"_uuid":"8bb67a98-7253-440c-aab1-73997aebad29","_cell_guid":"1d54596e-ba6a-47a4-b4ad-0ac7d5b80036","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_val, = train_test_split(train, test_size = 0.30,\n    stratify = train['label'], random_state = GLOBAL_SEED, shuffle = True\n)","metadata":{"_uuid":"9067efec-36c0-4ab5-8126-5baa73d7c133","_cell_guid":"d8d5861b-138d-473d-b046-54bfb286aded","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#n_classes = X_train.label.nunique()\n\nBATCH_SIZE = 64\nSTEPS_PER_EPOCH = len(X_train) // BATCH_SIZE\nEPOCHS = 50\n\nIMG_HEIGHT = 224\nIMG_WIDTH = 224\nIMG_SIZE = (IMG_HEIGHT, IMG_WIDTH)\nn_classes","metadata":{"_uuid":"188c82a6-6183-4cad-8ce4-9f9d9b0f3b1b","_cell_guid":"094f9d06-51d8-45c3-bf1f-714fd191880e","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TF Sequence Class - Faster Approach","metadata":{"_uuid":"c90d3676-c52c-4ebe-bd6f-876438fc7643","_cell_guid":"7d7adc1c-65de-4d15-96e5-09662ec14f32","trusted":true}},{"cell_type":"code","source":"class HotelDataset(torch.utils.data.Dataset):\n    \"\"\"Some Information about CaliforniaDataset\"\"\"\n    def __init__(self, x_set, y_set, training = True, img_size = (224, 224), transform = None):\n        super(HotelDataset, self).__init__()\n\n        self.x_set = x_set\n        self.y_set = (y_set)\n\n        self.aug = iaa.Sequential([\n            iaa.Fliplr(0.5),\n            iaa.Crop(percent=(0, 0.1)),\n            iaa.Sometimes(\n                0.5,\n                iaa.GaussianBlur(sigma=(0, 0.5))\n            ),\n            iaa.LinearContrast((0.75, 1.5)),\n            iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.05*255), per_channel=0.5),\n            iaa.Multiply((0.8, 1.2), per_channel=0.2),\n            iaa.Affine(\n                scale={\"x\": (0.8, 1.2), \"y\": (0.8, 1.2)},\n                translate_percent={\"x\": (-0.2, 0.2), \"y\": (-0.2, 0.2)},\n                rotate=(-25, 25),\n                shear=(-8, 8)\n            )\n        ], random_order=True)\n        \n        self.transform = transform\n        self.training = training\n        self.img_size = img_size\n\n    def __getitem__(self, index):\n        #print(self.x_set[index])\n        x = cv2.resize(cv2.imread(self.x_set[index]), dsize = self.img_size)\n        #print(x.shape)\n        if self.training:\n            x = self.aug(image = x)\n            \n        #x = torchvision.transforms.functional.to_tensor(x)\n        if self.transform is not None:\n            x = self.transform(x)\n        y = self.y_set[index]\n\n        return (x, y)\n\n    def __len__(self):\n        return len(self.x_set)","metadata":{"_uuid":"244cd5a9-f2e8-48e0-a145-468a14ab288f","_cell_guid":"3bc691eb-c55c-424e-a839-40493c4cb814","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install efficientnet_pytorch","metadata":{"_uuid":"ba3c6593-519f-4cba-be1a-d427ec7012a7","_cell_guid":"36bc70fd-4470-41c4-877f-be5afb1bf92b","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfrom efficientnet_pytorch import EfficientNet\nfrom torch import nn\nclass MLP(nn.Module):\n    def __init__(self, layers_size, dropout_rates, final_relu=False, type = \"embedding\"):\n        super(MLP, self).__init__()\n        layers_list = []\n        for i in range(1, len(layers_size) - 1):\n            layers_list.append(nn.Linear(layers_size[i - 1], layers_size[i]))\n            layers_list.append(nn.ReLU())\n            layers_list.append(nn.Dropout(p = dropout_rates[i]))\n        layers_list.append(nn.Linear(layers_size[-2], layers_size[-1]))\n        if final_relu:\n            layers_list.append(nn.ReLU())\n        else:\n            layers_list.append(nn.Softmax(dim = 1))\n        self.net = nn.Sequential(*layers_list)\n    \n    def forward(self, x):\n        return self.net(x)\n        \n    ","metadata":{"_uuid":"3f171b6b-08ee-4259-84ed-9e0c4109b93d","_cell_guid":"ef38a5bb-a62e-4b22-8b29-9810daa1a708","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi --gpu-reset\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Set trunk model and replace the softmax layer with an identity function\ntrunk = EfficientNet.from_pretrained('efficientnet-b0')\ntrunk_output_size = trunk._fc.out_features\n\ntrunk = torch.nn.DataParallel(trunk.to(device))\n\n# Set embedder model. This takes in the output of the trunk and outputs 64 dimensional embeddings\nembedder = torch.nn.DataParallel(MLP([trunk_output_size, 512, 512], dropout_rates = [0, 0.2, 0.2]).to(device))\n\n# Set the classifier. The classifier will take the embeddings and output a 50 dimensional vector.\n# (Our training set will consist of the first 50 classes of the CIFAR100 dataset.)\n# We'll specify the classification loss further down in the code.\nclassifier = torch.nn.DataParallel(MLP([512, 512, n_classes], dropout_rates = [0, 0.2, 0.2])).to(device)\n\n# Set optimizers\ntrunk_optimizer = torch.optim.Adam(trunk.parameters(), lr=0.00001, weight_decay=0.0001)\nembedder_optimizer = torch.optim.Adam(embedder.parameters(), lr=0.005, weight_decay=0.0001)\nclassifier_optimizer = torch.optim.Adam(classifier.parameters(), lr=0.005, weight_decay=0.0001)\n\n# Set the image transforms\ntrain_transform = transforms.Compose([transforms.ToTensor(),\n                                    #transforms.Resize(224, 224),\n                                    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])\n\nval_transform = transforms.Compose([transforms.ToTensor(),\n                                    #transforms.Resize(224, 224),\n                                    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])\n\n\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = HotelDataset(X_train.full_filepath.values, torch.tensor(X_train.label.values), training = True, transform = train_transform)\nval_dataset = HotelDataset(X_val.full_filepath.values, torch.tensor(X_val.label.values), training = False, transform = train_transform)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install pytorch_metric_learning","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pytorch_metric_learning import losses, miners, distances, reducers, testers, samplers\nfrom pytorch_metric_learning.utils.accuracy_calculator import AccuracyCalculator\n### MNIST code originally from https://github.com/pytorch/examples/blob/master/mnist/main.py ### \nfrom torchvision import datasets\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torchvision import datasets, transforms\nimport numpy as np\n\n\nloss = losses.TripletMarginLoss(margin=0.1)\n\nclassification_loss = torch.nn.CrossEntropyLoss()\n\n# Set the mining function\nminer = miners.MultiSimilarityMiner(epsilon=0.1)\n\n# Set the dataloader sampler\nsampler = samplers.MPerClassSampler(train_dataset.y_set, m=4, length_before_new_iter=len(train_dataset))\n\n# Set other training parameters\nbatch_size = 8\nnum_epochs = 4\n\n# Package the above stuff into dictionaries.\nmodels = {\"trunk\": trunk, \"embedder\": embedder, \"classifier\": classifier}\noptimizers = {\"trunk_optimizer\": trunk_optimizer, \"embedder_optimizer\": embedder_optimizer, \"classifier_optimizer\": classifier_optimizer}\nloss_funcs = {\"metric_loss\": loss, \"classifier_loss\": classification_loss}\nmining_funcs = {\"tuple_miner\": miner}\n\n# We can specify loss weights if we want to. This is optional\nloss_weights = {\"metric_loss\": 1, \"classifier_loss\": 0.5}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Remove logs if you want to train with new parameters\n!rm -rf example_logs/ example_saved_models/ example_tensorboard/","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install umap-learn\n!pip install record-keeper","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(device)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%matplotlib inline\nfrom pytorch_metric_learning import losses, miners, samplers, trainers, testers\nfrom pytorch_metric_learning.utils import common_functions\nimport pytorch_metric_learning.utils.logging_presets as logging_presets\nfrom pytorch_metric_learning.utils.accuracy_calculator import AccuracyCalculator\nimport numpy as np\nimport torchvision\nfrom torchvision import datasets, transforms\nimport torch\nimport torch.nn as nn\nfrom PIL import Image\nimport logging\nimport matplotlib.pyplot as plt\nimport umap\nfrom cycler import cycler\nimport record_keeper\nimport pytorch_metric_learning\nlogging.getLogger().setLevel(logging.INFO)\nlogging.info(\"VERSION %s\"%pytorch_metric_learning.__version__)\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"record_keeper, _, _ = logging_presets.get_record_keeper(\"example_logs\", \"example_tensorboard\")\nhooks = logging_presets.get_hook_container(record_keeper)\ndataset_dict = {\"val\": val_dataset}\nmodel_folder = \"example_saved_models\"\n\ndef visualizer_hook(umapper, umap_embeddings, labels, split_name, keyname, *args):\n    logging.info(\"UMAP plot for the {} split and label set {}\".format(split_name, keyname))\n    label_set = np.unique(labels)\n    num_classes = len(label_set)\n    fig = plt.figure(figsize=(20,15))\n    plt.gca().set_prop_cycle(cycler(\"color\", [plt.cm.nipy_spectral(i) for i in np.linspace(0, 0.9, num_classes)]))\n    for i in range(num_classes):\n        idx = labels == label_set[i]\n        plt.plot(umap_embeddings[idx, 0], umap_embeddings[idx, 1], \".\", markersize=1)   \n    plt.show()\n\n# Create the tester\ntester = testers.GlobalEmbeddingSpaceTester(end_of_testing_hook = hooks.end_of_testing_hook, \n                                            visualizer = umap.UMAP(), \n                                            visualizer_hook = visualizer_hook,\n                                            dataloader_num_workers = 2,\n                                            accuracy_calculator=AccuracyCalculator(k=\"max_bin_count\"))\n\nend_of_epoch_hook = hooks.end_of_epoch_hook(tester, \n                                            dataset_dict, \n                                            model_folder, \n                                            test_interval = 1,\n                                            patience = 1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer = trainers.TrainWithClassifier(models,\n                                optimizers,\n                                batch_size,\n                                loss_funcs,\n                                mining_funcs,\n                                train_dataset,\n                                sampler=sampler,\n                                dataloader_num_workers = 2,\n                                loss_weights = loss_weights,\n                                end_of_iteration_hook = hooks.end_of_iteration_hook,\n                                end_of_epoch_hook = end_of_epoch_hook)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%load_ext tensorboard\n%tensorboard --logdir example_tensorboard","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer.train(num_epochs=5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a href=\"./trunk_best3.pth\"> Download File </a>","metadata":{}},{"cell_type":"code","source":"!zip -r saved_model.zip example_saved_models/","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a href=\"./trunk_optimizer_best3.pth\"> Download File </a>","metadata":{}}]}