{"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":"This code is based on [Google Landmark 2nd code](https://github.com/WesleyZhang1991/Google_Landmark_Retrieval_2021_2nd_Place_Solution).<br>\nThe cropped dataset comes from [Awsaf](http://https://www.kaggle.com/awsaf49/happywhale-boundingbox-yolov5)<br>\nYou can change backbone and head arbitrarily through config files. if helpful, please upvote :D","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-02-20T02:51:59.467094Z","iopub.execute_input":"2022-02-20T02:51:59.467349Z","iopub.status.idle":"2022-02-20T02:52:05.42642Z","shell.execute_reply.started":"2022-02-20T02:51:59.467319Z","shell.execute_reply":"2022-02-20T02:52:05.425536Z"}}},{"cell_type":"code","source":"!cp -r ../input/traincode/Google_Landmark_Retrieval_2021_2nd_Place_Solution/* ./ ","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:01:53.938064Z","iopub.execute_input":"2022-02-20T09:01:53.938781Z","iopub.status.idle":"2022-02-20T09:01:58.787872Z","shell.execute_reply.started":"2022-02-20T09:01:53.938662Z","shell.execute_reply":"2022-02-20T09:01:58.786993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mv ./logs/GLDv2clean/ResNeSt101_512_all_input512_bs12_lossarcfacescale30margin0.3_optSGD_lr0.0008_wd1e-05_warm0.0_ep100_schecosine_drop0.0_re1.0_smoothoff_samplergld_pad20_necknobias_cache_all_list_color0.0_affine0.0/resnest101_35_best.pth ./logs/GLDv2clean/ResNeSt101_512_all_input512_bs12_lossarcfacescale30margin0.3_optSGD_lr0.0008_wd1e-05_warm0.0_ep100_schecosine_drop0.0_re1.0_smoothoff_samplergld_pad20_necknobias_cache_all_list_color0.0_affine0.0/resnest101_30_best.pth","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:01:58.789963Z","iopub.execute_input":"2022-02-20T09:01:58.790220Z","iopub.status.idle":"2022-02-20T09:01:59.466685Z","shell.execute_reply.started":"2022-02-20T09:01:58.790184Z","shell.execute_reply":"2022-02-20T09:01:59.465801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#if train \n# !python train.py","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:01:59.468212Z","iopub.execute_input":"2022-02-20T09:01:59.468473Z","iopub.status.idle":"2022-02-20T09:01:59.472483Z","shell.execute_reply.started":"2022-02-20T09:01:59.468436Z","shell.execute_reply":"2022-02-20T09:01:59.471760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from utils.logger import setup_logger\nfrom model import make_model\nfrom solver import make_optimizer, WarmupMultiStepLR\nfrom solver.scheduler_factory import create_scheduler\nfrom loss import make_loss\nfrom processor import do_train\nimport random\nimport datetime\nimport torch\nimport numpy as np\nimport os\nimport argparse\nfrom config import cfg\nimport pandas as pd\nfrom sklearn.preprocessing import LabelEncoder\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom torch.utils.data import Dataset, DataLoader\nimport cv2\nfrom tqdm import tqdm\nimport joblib\nfrom sklearn.model_selection import StratifiedKFold","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:01:59.474044Z","iopub.execute_input":"2022-02-20T09:01:59.475865Z","iopub.status.idle":"2022-02-20T09:02:02.901682Z","shell.execute_reply.started":"2022-02-20T09:01:59.475772Z","shell.execute_reply":"2022-02-20T09:02:02.900953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed):\n    # torch.manual_seed(seed)\n    # torch.cuda.manual_seed(seed)\n    # torch.cuda.manual_seed_all(seed)\n    # np.random.seed(seed)\n    # random.seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:02.904341Z","iopub.execute_input":"2022-02-20T09:02:02.904626Z","iopub.status.idle":"2022-02-20T09:02:02.912353Z","shell.execute_reply.started":"2022-02-20T09:02:02.904587Z","shell.execute_reply":"2022-02-20T09:02:02.911555Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"local_rank = 0 # int(os.environ[\"LOCAL_RANK\"])\n\nif True:\n    cfg.merge_from_file(\"./configs/GLDv2/ResNeSt101_512_all.yml\")\n    if len(cfg.BASE) > 0:\n        cfg.merge_from_file(cfg.BASE)\n    cfg.merge_from_file(\"./configs/GLDv2/ResNeSt101_512_all.yml\")\nloss_postfix = f'{cfg.MODEL.ID_LOSS_TYPE}'\nif cfg.MODEL.ID_LOSS_TYPE == 'arcface':\n    loss_postfix += f'scale{cfg.SOLVER.COSINE_SCALE}margin{cfg.SOLVER.COSINE_MARGIN}'\nif cfg.MODEL.NECK_BIAS:\n    neck_bias_postfix = 'neckbias'\nelse:\n    neck_bias_postfix = 'necknobias'\nif len(cfg.DATALOADER.CACHE_LIST) > 0:\n    cache_info = cfg.DATALOADER.CACHE_LIST.split('.pkl')[0]\nelse:\n    cache_info = 'nocache'\naug_info = f'color{cfg.INPUT.COLOR_PROB}_affine{cfg.INPUT.RANDOM_AFFINE_PROB}'\noutput_dir = cfg.OUTPUT_DIR + f'_input{cfg.INPUT.SIZE_TRAIN[0]}_bs{cfg.SOLVER.IMS_PER_BATCH}_loss{loss_postfix}_opt{cfg.SOLVER.OPTIMIZER_NAME}_lr{cfg.SOLVER.BASE_LR}_wd{cfg.SOLVER.WEIGHT_DECAY}_warm{cfg.SOLVER.WARMUP_EPOCHS}_ep{cfg.SOLVER.MAX_EPOCHS}_sche{cfg.SOLVER.WARMUP_METHOD}_drop{cfg.MODEL.CNN_DROPOUT}_re{cfg.INPUT.RE_PROB}_smooth{cfg.MODEL.IF_LABELSMOOTH}_sampler{cfg.DATALOADER.SAMPLER}_pad{cfg.INPUT.PADDING}_{neck_bias_postfix}_{cache_info}_{aug_info}'\nif output_dir and not os.path.exists(output_dir) and args.local_rank == 0:\n    os.makedirs(output_dir)\ncfg.OUTPUT_DIR = output_dir\ncfg.freeze()\n\nset_seed(cfg.SOLVER.SEED)","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:02.913784Z","iopub.execute_input":"2022-02-20T09:02:02.914285Z","iopub.status.idle":"2022-02-20T09:02:02.946138Z","shell.execute_reply.started":"2022-02-20T09:02:02.914243Z","shell.execute_reply":"2022-02-20T09:02:02.945430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if cfg.MODEL.DIST_TRAIN:\n\n    torch.cuda.set_device(0)\n\nlogger = setup_logger(\"reid_baseline\", output_dir, if_train=True)\nlogger.info(\"Saving model in the path :{}\".format(cfg.OUTPUT_DIR))\n\nif True:\n    logger.info(\"Loaded configuration file {}\".format(\"./configs/GLDv2/ResNeSt101_512_all.yml\"))\n    with open(\"./configs/GLDv2/ResNeSt101_512_all.yml\", 'r') as cf:\n        config_str = \"\\n\" + cf.read()\n        # logger.info(config_str)\n# logger.info(\"Running with config:\\n{}\".format(cfg))\n\nif cfg.MODEL.DIST_TRAIN:\n    torch.distributed.init_process_group(backend='nccl',\n                                         init_method='env://',\n                                         timeout=datetime.timedelta(1800))\n\nos.environ['CUDA_VISIBLE_DEVICES'] = cfg.MODEL.DEVICE_ID","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:02.947289Z","iopub.execute_input":"2022-02-20T09:02:02.948733Z","iopub.status.idle":"2022-02-20T09:02:02.973047Z","shell.execute_reply.started":"2022-02-20T09:02:02.948687Z","shell.execute_reply":"2022-02-20T09:02:02.972172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_transforms = {\n    \"train\": A.Compose([\n        A.Resize(cfg['INPUT']['SIZE_TRAIN'][0], cfg['INPUT']['SIZE_TRAIN'][0]),\n        A.HorizontalFlip(p=0.5),\n        A.VerticalFlip(p=0.5),\n        A.Rotate(limit=30, p=0.5),\n        A.Normalize(\n            mean=[0.485, 0.456, 0.406],\n            std=[0.229, 0.224, 0.225],\n            max_pixel_value=255.0,\n            p=1.0\n        ),\n        ToTensorV2()], p=1.),\n\n    \"valid\": A.Compose([\n        A.Resize(cfg['INPUT']['SIZE_TRAIN'][0], cfg['INPUT']['SIZE_TRAIN'][0]),\n        A.Normalize(\n            mean=[0.485, 0.456, 0.406],\n            std=[0.229, 0.224, 0.225],\n            max_pixel_value=255.0,\n            p=1.0\n        ),\n        ToTensorV2()], p=1.)\n}","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:02.974927Z","iopub.execute_input":"2022-02-20T09:02:02.975975Z","iopub.status.idle":"2022-02-20T09:02:02.989536Z","shell.execute_reply.started":"2022-02-20T09:02:02.975934Z","shell.execute_reply":"2022-02-20T09:02:02.988709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class HappyWhaleDataset(Dataset):\n    def __init__(self, df, transforms=None):\n        self.df = df\n        self.file_names = df['file_path'].values\n        self.labels = df['individual_id'].values\n        self.transforms = transforms\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, index):\n        img_path = self.file_names[index]\n        img = cv2.imread(img_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        label = self.labels[index]\n\n        if self.transforms:\n            img = self.transforms(image=img)[\"image\"]\n\n        return  img, torch.tensor(label, dtype=torch.long)","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:02.990949Z","iopub.execute_input":"2022-02-20T09:02:02.991379Z","iopub.status.idle":"2022-02-20T09:02:03.008841Z","shell.execute_reply.started":"2022-02-20T09:02:02.991339Z","shell.execute_reply":"2022-02-20T09:02:03.007904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes = 15587\nmodel = make_model(cfg, num_class=num_classes)\nmodel.load_state_dict(torch.load(\"./logs/GLDv2clean/ResNeSt101_512_all_input512_bs12_lossarcfacescale30margin0.3_optSGD_lr0.0008_wd1e-05_warm0.0_ep100_schecosine_drop0.0_re1.0_smoothoff_samplergld_pad20_necknobias_cache_all_list_color0.0_affine0.0/resnest101_30_best.pth\"))\nloss_func = make_loss(cfg, num_classes=num_classes)","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:03.012518Z","iopub.execute_input":"2022-02-20T09:02:03.016008Z","iopub.status.idle":"2022-02-20T09:02:07.787731Z","shell.execute_reply.started":"2022-02-20T09:02:03.015964Z","shell.execute_reply":"2022-02-20T09:02:07.785683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optimizer = make_optimizer(cfg, model)\nif cfg.SOLVER.WARMUP_METHOD:\n    print('===========using cosine learning rate=======')\n    scheduler = create_scheduler(cfg, optimizer)\nelse:\n    print('===========using normal learning rate=======')\n    scheduler = WarmupMultiStepLR(optimizer, cfg.SOLVER.STEPS, cfg.SOLVER.GAMMA,\n                                  cfg.SOLVER.WARMUP_FACTOR,\n                                  cfg.SOLVER.WARMUP_EPOCHS, cfg.SOLVER.WARMUP_METHOD)\n\ndef get_test_file_path(id):\n    return f\"{TEST_DIR}/{id}\"\n\nROOT_DIR = '../input/happywhalecropped'\nTEST_DIR = '../input/happywhalecropped/test_images/test_images'\nweights_path = \"../input/dummymodel4/Loss13.7021_epoch49.bin\"\n\n\ndf = pd.read_csv(\"../input/happy-whale-and-dolphin/sample_submission.csv\")\ndf['file_path'] = df['image'].apply(get_test_file_path)\n#hardcode dummy label for input in ArcMargin forward function\ndf['individual_id'] = 0\n#save LabelEncoder object during training so we can made the invers transform after the predictions\nencoder = LabelEncoder()\nencoder.classes_ = np.load(r\"./le.pkl\",allow_pickle=True)\n\ndata_transforms = {\n    \"test\": A.Compose([\n        A.Resize(cfg['INPUT']['SIZE_TRAIN'][0], cfg['INPUT']['SIZE_TRAIN'][0]),\n        A.Normalize(\n            mean=[0.485, 0.456, 0.406],\n            std=[0.229, 0.224, 0.225],\n            max_pixel_value=255.0,\n            p=1.0\n        ),\n        ToTensorV2()], p=1.)\n}","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:07.789208Z","iopub.execute_input":"2022-02-20T09:02:07.789457Z","iopub.status.idle":"2022-02-20T09:02:07.962840Z","shell.execute_reply.started":"2022-02-20T09:02:07.789424Z","shell.execute_reply":"2022-02-20T09:02:07.962004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = HappyWhaleDataset(df, transforms=data_transforms[\"test\"])\ntest_loader = DataLoader(test_dataset, batch_size=100,\n                          num_workers=4, shuffle=False, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:07.964103Z","iopub.execute_input":"2022-02-20T09:02:07.964578Z","iopub.status.idle":"2022-02-20T09:02:07.973615Z","shell.execute_reply.started":"2022-02-20T09:02:07.964535Z","shell.execute_reply":"2022-02-20T09:02:07.972572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = \"cuda\"\nmodel.to(device)\nmodel.eval()\nall_pred_list = []\nfor img, target in tqdm(test_loader):\n    with torch.no_grad():\n        img = img.to(device)\n        target = target.to(device)\n        score, feat = model(img, target)\n        _, pred = score.topk(5, 1, True, True)\n        pred = pred.detach().cpu().numpy()\n        all_pred_list.extend(pred)\n\n# conver pred2name\n# for pred in all_pred_list:\n#     encoder.inverse_transform(pred)\n\nname_pred = []\n# conver pred2name\nfor pred in tqdm(all_pred_list):\n    final_pred = \"\"\n    names = encoder.inverse_transform(pred)\n    for idx, name in enumerate(names):\n        if idx < 4:\n            final_pred += name + \" \"\n        else:\n            final_pred += name\n    name_pred.append(final_pred)\n\nsubmission = pd.read_csv(\"../input/happy-whale-and-dolphin/sample_submission.csv\")\nsubmission['predictions'] = name_pred\nsubmission.to_csv(\"submission.csv\", index=None)","metadata":{"execution":{"iopub.status.busy":"2022-02-20T09:02:07.988674Z","iopub.execute_input":"2022-02-20T09:02:07.989308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}