{"cells":[{"metadata":{},"cell_type":"markdown","source":"# My solution in efficientnet\n\n## step1.training efn-b0 in public train set and val in private test set  LB=0.1856\n## steg2.add no landmark filter LB=0.2069\n## step3.finetuen efn-b0 in private train set","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# 1.Clean Test set\n[original notebook](https://www.kaggle.com/rhtsingh/pytorch-landmark-or-non-landmark-identification/)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nfrom tqdm import tqdm\nimport cv2\nimport torch\nfrom torch.autograd import Variable as V\nimport torchvision.models as models\nfrom torchvision import transforms as trn\nfrom torch.nn import functional as F\nimport os\nimport numpy as np\nimport cv2\nfrom PIL import Image\nimport gc\ngc.enable()\nimport matplotlib.pyplot as plt\n\nimport sys\nsys.path.append('../input/landmark-20-clean/')\nimport wideresnet","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Load classes and I/O labels of Places365 Dataset","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_labels():\n    # prepare all the labels\n    # scene category relevant\n    file_name_category = '../input/landmark-20-clean/categories_places365.txt'\n    classes = list()\n    with open(file_name_category) as class_file:\n        for line in class_file:\n            classes.append(line.strip().split(' ')[0][3:])\n    classes = tuple(classes)\n\n    # indoor and outdoor relevant\n    file_name_IO = '../input/landmark-20-clean/IO_places365.txt'\n    with open(file_name_IO) as f:\n        lines = f.readlines()\n        labels_IO = []\n        for line in lines:\n            items = line.rstrip().split()\n            labels_IO.append(int(items[-1]) -1) # 0 is indoor, 1 is outdoor\n    labels_IO = np.array(labels_IO)\n    return classes, labels_IO","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image Transformations","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def returnTF():\n# load the image transformer\n    tf = trn.Compose([\n        trn.ToPILImage(),\n        trn.Resize((224,224)),\n        trn.ToTensor(),\n        trn.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\n    return tf","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Load Pretrained Weights & Create Model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def hook_feature(module, input, output):\n    features_blobs.append(np.squeeze(output.data.cpu().numpy()))\n    \ndef recursion_change_bn(module):\n    if isinstance(module, torch.nn.BatchNorm2d):\n        module.track_running_stats = 1\n    else:\n        for i, (name, module1) in enumerate(module._modules.items()):\n            module1 = recursion_change_bn(module1)\n    return module\n\ndef load_model():\n    # this model has a last conv feature map as 14x14\n    model_file = '../input/landmark-20-clean/wideresnet18_places365.pth.tar'\n\n    model = wideresnet.resnet18(num_classes=365)\n    checkpoint = torch.load(model_file, map_location=lambda storage, loc: storage)\n    state_dict = {str.replace(k,'module.',''): v for k,v in checkpoint['state_dict'].items()}\n    model.load_state_dict(state_dict)\n    \n    # hacky way to deal with the upgraded batchnorm2D and avgpool layers...\n    for i, (name, module) in enumerate(model._modules.items()):\n        module = recursion_change_bn(model)\n    model.avgpool = torch.nn.AvgPool2d(kernel_size=14, stride=1, padding=0)\n\n    model.eval()\n    # hook the feature extractor\n    features_names = ['layer4','avgpool'] # this is the last conv layer of the resnet\n    for name in features_names:\n        model._modules.get(name).register_forward_hook(hook_feature)\n    return model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Config","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"classes, labels_IO = load_labels()\nfeatures_blobs = []\ndevice = torch.device(\"cuda\") if torch.cuda.is_available() else \"cpu\"\nmodel = load_model()\nmodel = model.to(device)\n\ntf = returnTF()\n\nparams = list(model.parameters())\nweight_softmax = params[-2].data.cpu().numpy()\nweight_softmax[weight_softmax<0] = 0","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Prediction Loop","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"test_clean = pd.read_csv('../input/landmark-recognition-2020/sample_submission.csv')\nio_test = []\nfor i, img_id in tqdm(enumerate(test_clean.id), total=len(test_clean)):\n    image_path = f\"../input/landmark-recognition-2020/test/{img_id[0]}/{img_id[1]}/{img_id[2]}/{img_id}.jpg\"\n    img = cv2.imread(image_path, cv2.IMREAD_COLOR)\n    input_img = V(tf(img).unsqueeze(0))\n    logit = model.forward(input_img.to(device))\n    h_x = F.softmax(logit, 1).data.squeeze()\n    probs, idx = h_x.sort(0, True)\n    probs = probs.cpu().numpy()\n    idx = idx.cpu().numpy()\n\n    io_image = np.mean(labels_IO[idx[:10]]) # vote for the indoor or outdoor\n    if io_image < 0.5:\n        io_test.append(0) \n    else:\n        io_test.append(1) \n        \n    del input_img\n    del img\n    del image_path\n    del logit\n    del probs\n    del idx\n    del io_image\n    if i%1000 ==0:\n        gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_clean['io'] = io_test\n# test_clean.to_csv('test_io.csv',index=False)\ntest_clean.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# int(test_clean[test_clean.id=='00084cdf8f600d00'].io)\nio_labels = np.array((test_clean.io))\nprint(io_labels.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### show img landmark or no landmark","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def return_img(img_id):\n    image_path = f\"../input/landmark-recognition-2020/test/{img_id[0]}/{img_id[1]}/{img_id[2]}/{img_id}.jpg\"\n    img = np.array(Image.open(image_path).resize((224, 224), Image.LANCZOS))\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get 'landmark' images\nn = 16\nlandmark_images =  test_clean[test_clean['io'] == 1]['id'][:n]\n\nfig = plt.figure(figsize = (16, 16))\nfor i, img_id in enumerate(landmark_images):\n    image = return_img(img_id)\n    fig.add_subplot(4, 4, i+1)\n    plt.title(img_id)\n    plt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get non 'landmark' images\nn = 16\nlandmark_images =  test_clean[test_clean['io'] == 0]['id'][:n]\n# landmark_indexes = landmark_images[:n].index.values\n\n# Plot image examples\nfig = plt.figure(figsize = (16, 16))\nfor i, img_id in enumerate(landmark_images):\n    image = return_img(img_id)\n    fig.add_subplot(4, 4, i+1)\n    plt.title(img_id)\n    plt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2.[PyTorch Inference Submission] EfficientNet Baseline From [original notebook](https://www.kaggle.com/rhtsingh/pytorch-training-inference-efficientnet-baseline)\n\n*Note: I have exhausted my GPU for this week and so was unable to complete training. When training started I had only 1/30hr left.*\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"### Settup Dependencies","execution_count":null},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# !pip install efficientnet_pytorch\n# !pip install torch_optimizer","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install ../input/efficientnet-pytorch/EfficientNet-PyTorch-master/ > /dev/null # no output","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"import os\nimport gc\ngc.enable()\nimport sys\nimport math\nimport json\nimport time\nimport random\nfrom glob import glob\nfrom datetime import datetime\n\nimport cv2\nimport csv\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport multiprocessing\nfrom sklearn.preprocessing import LabelEncoder\n\nimport torch\nimport torchvision\nfrom torch import Tensor\nfrom torchvision import transforms\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.autograd import Variable\nfrom torch.nn.parameter import Parameter\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nfrom tqdm import tqdm\n\nimport efficientnet_pytorch\n\n# import torch_optimizer as optim\nimport torch.optim as optim\nimport albumentations as A\n\nimport sklearn\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Train Configuration\n\n*Note: Lots of improvement can be done simply here. e.g.*\n\n* MIN SAMPLES PER CLASS - This variable is a threshold for total number of images in a class. If has class has less than this count then it will be discarded from training set.\n* BATCH SIZE            - The number of images in each training batch.\n* EPOCHS                - Total number of epochs.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"> ### Dataset\n\nimage size=(3, 224, 224)","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"class ImageDataset(torch.utils.data.Dataset):\n    def __init__(self, dataframe: pd.DataFrame, image_dir:str, mode: str):\n        self.df = dataframe\n        self.mode = mode\n        self.image_dir = image_dir\n        \n        transforms_list = []\n        if self.mode == 'train':\n            # Increase image size from (64,64) to higher resolution,\n            # Make sure to change in RandomResizedCrop as well.\n            transforms_list = [\n                transforms.Resize((224,224)),\n                transforms.RandomHorizontalFlip(),\n                transforms.RandomChoice([\n                    transforms.RandomResizedCrop(224),\n                    transforms.ColorJitter(0.2, 0.2, 0.2, 0.2),\n                    transforms.RandomAffine(degrees=15, translate=(0.2, 0.2),\n                                            scale=(0.8, 1.2), shear=15,\n                                            resample=Image.BILINEAR)\n                ]),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                      std=[0.229, 0.224, 0.225]),\n            ]\n        else:\n            transforms_list.extend([\n                # Keep this resize same as train\n                transforms.Resize((224,224)),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                      std=[0.229, 0.224, 0.225]),\n            ])\n        self.transforms = transforms.Compose(transforms_list)\n\n    def __getitem__(self, index: int):\n        image_id = self.df.iloc[index].id\n        image_path = f\"{self.image_dir}/{image_id[0]}/{image_id[1]}/{image_id[2]}/{image_id}.jpg\"\n        image = Image.open(image_path)\n        image = self.transforms(image)\n\n        if self.mode == 'test':\n            return {'image':image}\n        else:\n            return {'image':image, \n                    'target':self.df.iloc[index].landmark_id}\n\n    def __len__(self) -> int:\n        return self.df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Load Data","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_data(public_train, train, test, train_dir, test_dir):\n    counts = public_train.landmark_id.value_counts()\n    selected_classes = counts[counts >= MIN_SAMPLES_PER_CLASS].index\n    num_classes = selected_classes.shape[0]\n    print('classes with at least N samples:', num_classes)\n\n#     public_train = public_train.loc[public_train.landmark_id.isin(selected_classes)]\n    print('public train_df', public_train.shape)\n    print('train_df', train.shape)\n    print('test_df', test.shape)\n\n    # filter non-existing test images\n    exists = lambda img: os.path.exists(f'{test_dir}/{img[0]}/{img[1]}/{img[2]}/{img}.jpg')\n    test = test.loc[test.id.apply(exists)]\n    print('test_df after filtering', test.shape)\n\n    label_encoder = LabelEncoder()\n    label_encoder.fit(public_train.landmark_id.values)\n    print('found classes', len(label_encoder.classes_))\n    assert len(label_encoder.classes_) == num_classes\n    \n    print(list(public_train.landmark_id)[:10])\n    print(list(train.landmark_id)[:10])\n\n    train.landmark_id = label_encoder.transform(train.landmark_id)\n\n    train_dataset = ImageDataset(train, train_dir, mode='train')\n    test_dataset = ImageDataset(test, test_dir, mode='test')\n\n    train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE,\n                              shuffle=True, num_workers=4, drop_last=True)\n\n    test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE,\n                             shuffle=False, num_workers=NUM_WORKERS)\n\n    return train_loader, test_loader, label_encoder, num_classes, train.shape[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Model\n\n*Note: Used efficientnet-b0. Experimenting with different archs can yield different results*","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def stop_weight_updata(model):\n#     for layer in list(model.children()):\n#         for i, p in enumerate(layer.parameters()):\n#             print(i, p.requires_grad)\n    print('_______________________________________________________')\n    for layer in list(model.children())[:-1]:\n        for i, p in enumerate(layer.parameters()):\n            p.requires_grad = False\n#     print('_______________________________________________________')\n#     for layer in list(model.children()):\n#         for i, p in enumerate(layer.parameters()):\n#             print(i, p.requires_grad)\n            \n\nclass EfficientNetEncoderHead(nn.Module):\n    def __init__(self, depth, num_classes=81313):\n        super(EfficientNetEncoderHead, self).__init__()\n        self.depth = depth\n        model_name = 'efficientnet-b' + str(self.depth)\n#         self.base = efficientnet_pytorch.EfficientNet.from_pretrained(f'efficientnet-b{self.depth}')\n        self.base = efficientnet_pytorch.EfficientNet.from_name(f'efficientnet-b{self.depth}')\n#         self.base.load_state_dict(torch.load(efn_weights[model_name]))\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.output_filter = self.base._fc.in_features\n        self.classifier = nn.Linear(self.output_filter, num_classes)\n    def forward(self, x):\n        x = self.base.extract_features(x)\n        x = self.avg_pool(x).squeeze(-1).squeeze(-1)\n        x = self.classifier(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Test model\n# model = EfficientNetEncoderHead(depth=0, num_classes=81313)\n# try:\n#     model_path = '../input/efnb0-10-gap05917pth/efn-b0_10_GAP0.5917.pth'\n#     model.load_state_dict(torch.load(model_path, map_location='cpu'))\n#     print('Model found in {}'.format(model_path))\n# except:\n#     print('Random initialize model!')\n\n# model.cuda()\n# stop_weight_updata(model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Inference Function","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def inference(data_loader, model):\n    model.eval()\n\n    activation = nn.Softmax(dim=1)\n    all_predicts, all_confs, all_targets = [], [], []\n\n    with torch.no_grad():\n        for i, data in enumerate(tqdm(data_loader, disable=IN_KERNEL)):\n            if data_loader.dataset.mode != 'test':\n                input_, target = data['image'], data['target']\n            else:\n                input_, target = data['image'], None\n\n            output = model(input_.cuda())\n            output = activation(output)\n\n            confs, predicts = torch.topk(output, NUM_TOP_PREDICTS)\n            all_confs.append(confs)\n            all_predicts.append(predicts)\n\n            if target is not None:\n                all_targets.append(target)\n\n    predicts = torch.cat(all_predicts)\n    confs = torch.cat(all_confs)\n    targets = torch.cat(all_targets) if len(all_targets) else None\n\n    return predicts, confs, targets","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## trainning loop","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class AverageMeter:\n    ''' Computes and stores the average and current value '''\n    def __init__(self) -> None:\n        self.reset()\n\n    def reset(self) -> None:\n        self.val = 0.0\n        self.avg = 0.0\n        self.sum = 0.0\n        self.count = 0\n\n    def update(self, val: float, n: int = 1) -> None:\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count\n\ndef GAP(predicts: torch.Tensor, confs: torch.Tensor, targets: torch.Tensor) -> float:\n    ''' Simplified GAP@1 metric: only one prediction per sample is supported '''\n    assert len(predicts.shape) == 1\n    assert len(confs.shape) == 1\n    assert len(targets.shape) == 1\n    assert predicts.shape == confs.shape and confs.shape == targets.shape\n\n    _, indices = torch.sort(confs, descending=True)\n\n    confs = confs.cpu().numpy()\n    predicts = predicts[indices].cpu().numpy()\n    targets = targets[indices].cpu().numpy()\n\n    res, true_pos = 0.0, 0\n\n    for i, (c, p, t) in enumerate(zip(confs, predicts, targets)):\n        rel = int(p == t)\n        true_pos += rel\n\n        res += true_pos / (i + 1) * rel\n\n    res /= targets.shape[0] # FIXME: incorrect, not all test images depict landmarks\n    return res\n\ndef train_step(train_loader, model, criterion, optimizer, epoch, lr_scheduler):\n    print(f'epoch {epoch}')\n    batch_time = AverageMeter()\n    losses = AverageMeter()\n    avg_score = AverageMeter()\n    acc_score = AverageMeter()\n\n    model.train()\n    num_steps = len(train_loader)\n\n    print(f'total batches: {num_steps}')\n\n    end = time.time()\n    lr = None\n\n    for i, data in enumerate(train_loader):\n        input_ = data['image']\n        target = data['target']\n        batch_size, _, _, _ = input_.shape\n\n        output = model(input_.cuda())\n        loss = criterion(output, target.cuda())\n        confs, predicts = torch.max(output.detach(), dim=1)\n\n        avg_score.update(GAP(predicts, confs, target), input_.size(0))\n        losses.update(loss.data.item(), input_.size(0))\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        lr_scheduler.step()\n        lr = optimizer.param_groups[0]['lr']\n\n        batch_time.update(time.time() - end)\n        end = time.time()\n\n        if i % LOG_FREQ == 0:\n            print(f'{epoch} [{i}/{num_steps}]\\t'\n                  f'time {batch_time.val:.3f} ({batch_time.avg:.3f})\\t'\n                  f'loss {losses.val:.4f} ({losses.avg:.4f})\\t'\n                  f'GAP {avg_score.val:.4f} ({avg_score.avg:.4f})\\t'\n                  f'lr {lr:.8f}')\n\n    print(f' * average GAP on train {avg_score.avg:.4f}')\n    return avg_score.avg","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Generate Submission","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def softmax(x):\n    \"\"\"Compute softmax values for each sets of scores in x.\"\"\"\n    return np.exp(x) / np.sum(np.exp(x), axis=0)\n\ndef generate_submission(test_loader, model, label_encoder):\n    sample_sub = pd.read_csv('../input/landmark-recognition-2020/sample_submission.csv')\n\n    predicts_gpu, confs_gpu, _ = inference(test_loader, model)\n    predicts, confs = predicts_gpu.cpu().numpy(), confs_gpu.cpu().numpy()\n        \n\n    labels = [label_encoder.inverse_transform(pred) for pred in predicts]\n    print('labels', np.array(labels).shape)\n    print('confs', np.array(confs).shape)\n\n    sub = test_loader.dataset.df\n    \n    def concat(label: np.ndarray, conf: np.ndarray) -> str:\n#         result = ' '.join([f'{L} {c}' for L, c in zip(label, conf)])\n        # softmax conf\n#         conf = softmax(conf)\n#         print(label)\n#         print(conf)\n        result = ''\n        for L, c in zip(label, conf):\n            if L in private_counts:\n                result = f'{L} {c}'\n                break\n        \n        return result\n    \n    landmarks = [concat(label, conf) for label, conf in zip(labels, confs)]\n    for i in range(len(landmarks)):\n        if io_labels[i] == 0:\n            landmarks[i] = ''\n    \n    sub['landmarks'] = landmarks\n#     sub['landmarks'] = [concat(label, conf) if label[0] in private_counts else '' for label, conf in zip(labels, confs)]\n\n    sample_sub = sample_sub.set_index('id')\n    sub = sub.set_index('id')\n    sample_sub.update(sub)\n\n    sample_sub.to_csv('submission.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Process","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"IN_KERNEL = os.environ.get('KAGGLE_WORKING_DIR') is not None\nMIN_SAMPLES_PER_CLASS = 1 \nBATCH_SIZE = 64\nNUM_WORKERS = multiprocessing.cpu_count()\nNUM_EPOCHS = 2\nLOG_FREQ = 10\nNUM_TOP_PREDICTS = 5\nNUM_PUBLIC_TRAIN_IMAGES = 1580470\ntrain_dir = '../input/landmark-recognition-2020/train/'\ntest_dir = '../input/landmark-recognition-2020/test/'\n\nif __name__ == '__main__':\n    # when re-running code, classes_num(num of landmark_ids) of the private train set  is less than the public train set, so we need to reload the original train.csv\n    public_train = pd.read_csv('../input/glr-train-csv/train.csv') # The public train.csv\n    train = pd.read_csv('../input/landmark-recognition-2020/train.csv')  # Treat as the private train.csv when submit to re-run code\n    test = pd.read_csv('../input/landmark-recognition-2020/sample_submission.csv')\n    \n    global_start_time = time.time()\n    private_counts = train.landmark_id.value_counts()\n    print('Private train set landmark_ids lenght:', len(private_counts))\n#     train_loader, test_loader, label_encoder, num_classes, train_len = load_data(train, test, train_dir, test_dir)\n    train_loader, test_loader, label_encoder, num_classes, train_len = load_data(public_train, train, test, train_dir, test_dir)\n#     print(label_encoder.inverse_transform([100]))\n\n    model = EfficientNetEncoderHead(depth=0, num_classes=num_classes)\n    try:\n        model_path = '../input/efnb0-10-gap05917pth/efn-b0_10_GAP0.5917.pth'\n        model.load_state_dict(torch.load(model_path, map_location='cpu'))\n        print('Model found in {}'.format(model_path))\n    except:\n        print('Random initialize model!')\n        \n    model.cuda()\n    \n    is_finetune = False\n    if train_len != 1580470:\n        is_finetune = True\n    # finetune\n    if is_finetune:\n        stop_weight_updata(model)\n        criterion = nn.CrossEntropyLoss()\n\n#         optimizer = optim.Adam(model.parameters(), lr=1e-6, weight_decay=1e-4)\n        optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-6, weight_decay=1e-4)\n        \n        scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=len(train_loader)*NUM_EPOCHS, eta_min=1e-6)\n\n        for epoch in range(1, 2):\n            print('-' * 50)\n            train_step(train_loader, model, criterion, optimizer, epoch, scheduler)\n        \n\n    print('inference mode')\n    generate_submission(test_loader, model, label_encoder)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"*Note: Will be publishing better kernels soon with more advanced techniques for landmark recognition.*\n### More To Come. Stay Tuned. !!","execution_count":null}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}