{"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 os\nimport gc\nimport cv2\nimport math\nimport copy\nimport pdb\nimport time\nimport random\nfrom glob import glob\nfrom matplotlib import pyplot as plt\n\n# For data manipulation\nimport numpy as np\nimport pandas as pd\n\n# Pytorch Imports\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.cuda import amp\nimport torchvision\n\n# Utils\nimport joblib\nfrom tqdm import tqdm\nfrom collections import defaultdict\n\n# Sklearn Imports\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import StratifiedKFold\n\n# For Image Models\nimport timm\n\n# Albumentations for augmentations\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-19T02:14:10.994342Z","iopub.execute_input":"2023-10-19T02:14:10.995143Z","iopub.status.idle":"2023-10-19T02:14:17.314293Z","shell.execute_reply.started":"2023-10-19T02:14:10.995103Z","shell.execute_reply":"2023-10-19T02:14:17.31328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Why I got “threw exception” erorr while doing multi-img-size ensembel？QAQ","metadata":{}},{"cell_type":"code","source":"\nclass CFG:\n        seed = 42\n        img_size = [[1024,1024],[768,768]]\n        backbone = 'efficientnet_b0'\n        num_classes = 5\n        train_bs = 16\n        validation_bs = 1\n        n_fold = 5\n        n_accumulate = 1\n        device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n        ROOT_DIR = '/kaggle/input/UBC-OCEAN'\n        TEST_DIR = '/kaggle/input/UBC-OCEAN/test_thumbnails' \n        scheduler = 'CosineAnnealingLR'\n        TTA = False\n        ","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.316053Z","iopub.execute_input":"2023-10-19T02:14:17.316445Z","iopub.status.idle":"2023-10-19T02:14:17.346786Z","shell.execute_reply.started":"2023-10-19T02:14:17.316415Z","shell.execute_reply":"2023-10-19T02:14:17.345788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed=42):\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True \n    # Set True :为整个网络的每个卷积层搜索最适合它的卷积实现算法，进而实现网络的加速\n    torch.backends.cudnn.benchmark = False\n    # Set a fixed value for the hash seed\n    os.environ['PYTHONHASHSEED'] = str(seed)\nset_seed(CFG.seed)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.347888Z","iopub.execute_input":"2023-10-19T02:14:17.348171Z","iopub.status.idle":"2023-10-19T02:14:17.381983Z","shell.execute_reply.started":"2023-10-19T02:14:17.348148Z","shell.execute_reply":"2023-10-19T02:14:17.38114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_test_filepath(image_id):\n        return f\"{CFG.TEST_DIR}/{image_id}_thumbnail.png\"","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.384117Z","iopub.execute_input":"2023-10-19T02:14:17.384422Z","iopub.status.idle":"2023-10-19T02:14:17.389196Z","shell.execute_reply.started":"2023-10-19T02:14:17.38439Z","shell.execute_reply":"2023-10-19T02:14:17.388332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f\"{CFG.ROOT_DIR}/test.csv\")\ndf['file_path'] = df['image_id'].apply(get_test_filepath)\ndf['label'] = 0 # dummy\ndf","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.390746Z","iopub.execute_input":"2023-10-19T02:14:17.391073Z","iopub.status.idle":"2023-10-19T02:14:17.424282Z","shell.execute_reply.started":"2023-10-19T02:14:17.391045Z","shell.execute_reply":"2023-10-19T02:14:17.42332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABEL_ENCODER_BIN = '/kaggle/input/label-encoder/label_encoder.pkl'\nencoder = joblib.load( LABEL_ENCODER_BIN )","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.425125Z","iopub.execute_input":"2023-10-19T02:14:17.425346Z","iopub.status.idle":"2023-10-19T02:14:17.434852Z","shell.execute_reply.started":"2023-10-19T02:14:17.425327Z","shell.execute_reply":"2023-10-19T02:14:17.434025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub = pd.read_csv(f\"{CFG.ROOT_DIR}/sample_submission.csv\")\ndf_sub","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.435947Z","iopub.execute_input":"2023-10-19T02:14:17.436237Z","iopub.status.idle":"2023-10-19T02:14:17.458515Z","shell.execute_reply.started":"2023-10-19T02:14:17.436214Z","shell.execute_reply":"2023-10-19T02:14:17.457445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_transforms(CFG):\n    data_transforms_1024 = {     \n        \"valid1024\": A.Compose([\n            A.Resize(*CFG.img_size[0],interpolation=cv2.INTER_NEAREST, p=1.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    }\n    \n    data_transforms_768 = {     \n        \"valid768\": A.Compose([\n            A.Resize(*CFG.img_size[1],interpolation=cv2.INTER_NEAREST, p=1.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    }\n    return data_transforms_1024, data_transforms_768","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.460089Z","iopub.execute_input":"2023-10-19T02:14:17.460408Z","iopub.status.idle":"2023-10-19T02:14:17.468493Z","shell.execute_reply.started":"2023-10-19T02:14:17.46038Z","shell.execute_reply":"2023-10-19T02:14:17.467326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class build_dataset(Dataset):\n    def __init__(self, df, train_mode=True,transforms=None):\n        self.df = df\n        self.train_mode = train_mode\n        self.file_names = df['file_path'].values\n        self.labels = df['label'].values\n        self.transforms = transforms\n        \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.train_mode:\n            if self.transforms:\n                img = self.transforms(image=img)[\"image\"]\n                \n            return {\n                'image': img,\n                'label': torch.tensor(label, dtype=torch.long)\n            }\n        else:\n            if self.transforms:\n                img = self.transforms(image=img)[\"image\"]\n            return {'image': img}","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.470278Z","iopub.execute_input":"2023-10-19T02:14:17.470534Z","iopub.status.idle":"2023-10-19T02:14:17.47971Z","shell.execute_reply.started":"2023-10-19T02:14:17.470503Z","shell.execute_reply":"2023-10-19T02:14:17.478863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_dataloader(df, fold):\n    df_train = df[df.fold != fold].reset_index(drop=True)\n    df_valid = df[df.fold == fold].reset_index(drop=True)\n    # pdb.set_trace()\n    valid_dataset_1024 = build_dataset(df_valid, transforms=build_transforms[\"valid1024\"])\n    valid_dataset_768 = build_dataset(df_valid, transforms=build_transforms[\"valid768\"])\n\n    valid_loader_1024 = DataLoader(valid_dataset_1024, batch_size=CFG.validation_bs, \n                              num_workers=os.cpu_count(), shuffle=False, pin_memory=True)\n    valid_loader_768 = DataLoader(valid_dataset_768, batch_size=CFG.validation_bs, \n                              num_workers=os.cpu_count(), shuffle=False, pin_memory=True)\n    \n    return valid_loader_768, valid_loader_1024","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.483175Z","iopub.execute_input":"2023-10-19T02:14:17.483942Z","iopub.status.idle":"2023-10-19T02:14:17.490965Z","shell.execute_reply.started":"2023-10-19T02:14:17.48392Z","shell.execute_reply":"2023-10-19T02:14:17.49007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class GeM(nn.Module):\n    def __init__(self, p=3, eps=1e-6):\n        super(GeM, self).__init__()\n        self.p = nn.Parameter(torch.ones(1)*p)\n        self.eps = eps\n\n    def forward(self, x):\n        return self.gem(x, p=self.p, eps=self.eps)\n        \n    def gem(self, x, p=3, eps=1e-6):\n        return F.avg_pool2d(x.clamp(min=eps).pow(p), (x.size(-2), x.size(-1))).pow(1./p)\n        \n    def __repr__(self):\n        return self.__class__.__name__ + \\\n                '(' + 'p=' + '{:.4f}'.format(self.p.data.tolist()[0]) + \\\n                ', ' + 'eps=' + str(self.eps) + ')'","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.49254Z","iopub.execute_input":"2023-10-19T02:14:17.492861Z","iopub.status.idle":"2023-10-19T02:14:17.506441Z","shell.execute_reply.started":"2023-10-19T02:14:17.492833Z","shell.execute_reply":"2023-10-19T02:14:17.505655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class build_model(nn.Module):\n    def __init__(self, CFG, num_classes, pretrain_flag=True, checkpoint_path=None):\n        super(build_model, self).__init__()\n        self.model = timm.create_model(CFG.backbone, pretrained=pretrain_flag, checkpoint_path=checkpoint_path)\n\n        in_features = self.model.classifier.in_features\n        self.model.classifier = nn.Identity()\n        self.model.global_pool = nn.Identity()\n        self.pooling = GeM()\n        self.linear = nn.Linear(in_features, num_classes)\n        self.softmax = nn.Softmax(dim=1)\n\n    def forward(self, images):\n        features = self.model(images)\n        pooled_features = self.pooling(features).flatten(1)\n        model = self.linear(pooled_features)\n        return model","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.507505Z","iopub.execute_input":"2023-10-19T02:14:17.507724Z","iopub.status.idle":"2023-10-19T02:14:17.518163Z","shell.execute_reply.started":"2023-10-19T02:14:17.507706Z","shell.execute_reply":"2023-10-19T02:14:17.517238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@torch.no_grad()\ndef test_one_epoch(ckpt_paths_768, ckpt_paths_1024, num_classes, test_loader_768, test_loader_1024, CFG):\n    pred_cls = []\n    multi_img_size_vote = torch.zeros((CFG.validation_bs, CFG.num_classes), device=CFG.device, dtype=torch.float32)\n\n    def process_images(images, model, ckpt_paths, multi_img_size_vote):\n        y_prob_vote_768 = torch.zeros((CFG.validation_bs, CFG.num_classes), device=CFG.device, dtype=torch.float32)\n        y_prob_vote_1024 = torch.zeros((CFG.validation_bs, CFG.num_classes), device=CFG.device, dtype=torch.float32)\n        num_vote = CFG.n_fold\n\n        if CFG.TTA:\n            num_vote *= 3\n\n        for sub_ckpt_path in ckpt_paths:\n            model.load_state_dict(torch.load(sub_ckpt_path))\n            model.to(CFG.device)  # Move the model to the GPU\n            model.eval()\n            images = images.to(CFG.device, dtype=torch.float)  # Ensure the input data type matches the model's device\n            y_preds = model(images)\n\n            if CFG.img_size == [1024, 1024]:\n                y_prob_vote_1024 += F.softmax(y_preds, dim=1)\n            elif CFG.img_size == [768, 768]:\n                y_prob_vote_768 += F.softmax(y_preds, dim=1)\n\n            if CFG.TTA:\n                images_f = [torch.rot90(images, k=i, dims=(-2, -1)) for i in range(1, 4)]\n                for image_f in images_f:\n                    y_preds_f = model(image_f)\n\n                    if CFG.img_size == [1024, 1024]:\n                        y_prob_vote_1024 += F.softmax(y_preds_f, dim=1)\n                    elif CFG.img_size == [768, 768]:\n                        y_prob_vote_768 += F.softmax(y_preds_f, dim=1)\n\n        y_prob_vote_768 /= num_vote\n        y_prob_vote_1024 /= num_vote\n        # You can also calculate the average of both softmax results\n        y_prob_vote = (y_prob_vote_768 + y_prob_vote_1024) / 2\n\n        multi_img_size_vote += y_prob_vote\n\n    pbar_768 = tqdm(enumerate(test_loader_768), total=len(test_loader_768), desc='Test_768: ')\n    pbar_1024 = tqdm(enumerate(test_loader_1024), total=len(test_loader_1024), desc='Test_1024: ')\n\n    for _, (images_768) in pbar_768:\n        images_768 = images_768['image'].to(CFG.device, dtype=torch.float)\n        process_images(images_768, build_model(CFG, num_classes, pretrain_flag=False), ckpt_paths_768, multi_img_size_vote)\n\n    for _, (images_1024) in pbar_1024:\n        images_1024 = images_1024['image'].to(CFG.device, dtype=torch.float)\n        process_images(images_1024, build_model(CFG, num_classes, pretrain_flag=False), ckpt_paths_1024, multi_img_size_vote)\n\n    # Append the class predictions to the list\n    cls_pred = multi_img_size_vote.argmax(1)\n    for pred in cls_pred.data.cpu().numpy():\n        pred_cls.append(pred)\n    # pdb.set_trace()\n    return pred_cls\n","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.519551Z","iopub.execute_input":"2023-10-19T02:14:17.51984Z","iopub.status.idle":"2023-10-19T02:14:17.535841Z","shell.execute_reply.started":"2023-10-19T02:14:17.519813Z","shell.execute_reply":"2023-10-19T02:14:17.534908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def largest_factor(num):\n#     max_factor = 1\n#     i = 2\n    \n#     while i <= num:\n#         if num % i == 0:\n#             max_factor = i\n#             num //= i\n#         else:\n#             i += 1\n            \n#     return max_factor\n\n# files = os.listdir(CFG.TEST_DIR)   # 读入文件夹\n# num_png = len(files)       # 统计文件夹中的文件个数\n# CFG.validation_bs = largest_factor(num_png)\n# CFG.validation_bs","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.536875Z","iopub.execute_input":"2023-10-19T02:14:17.537136Z","iopub.status.idle":"2023-10-19T02:14:17.556054Z","shell.execute_reply.started":"2023-10-19T02:14:17.537117Z","shell.execute_reply":"2023-10-19T02:14:17.555169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_transforms_1024,data_transforms_768 = build_transforms(CFG)\ntest_dataset_768 = build_dataset(df,train_mode=False,transforms=data_transforms_768['valid768'])\ntest_dataset_1024 = build_dataset(df,train_mode=False,transforms=data_transforms_1024['valid1024'])\ntest_loader_768  = DataLoader(test_dataset_768, batch_size=CFG.validation_bs, shuffle=False, pin_memory=True)\ntest_loader_1024  = DataLoader(test_dataset_1024, batch_size=CFG.validation_bs, shuffle=False, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.557329Z","iopub.execute_input":"2023-10-19T02:14:17.557626Z","iopub.status.idle":"2023-10-19T02:14:17.564109Z","shell.execute_reply.started":"2023-10-19T02:14:17.5576Z","shell.execute_reply":"2023-10-19T02:14:17.563237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ckpt_paths_768  = glob('/kaggle/input/v1-1-efficientnet-b0-img768-bs32-fold5-epoch20/V1.1_efficientnet_b0_img768_bs32_fold5_epoch20/*') # pick best ckpt for each fold.\n\nckpt_paths_1024  = glob('/kaggle/input/v4-6-tma-efficientnet-b0-img1024-bs16-fold5-e40/V4.6_tma_efficientnet_b0_img1024_bs16_fold5_epoch40/*') # pick best ckpt for each fold.\n# print(ckpt_paths)\npred_cls = test_one_epoch(ckpt_paths_768,ckpt_paths_1024, CFG.num_classes,test_loader_768,test_loader_1024, CFG)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:17.565155Z","iopub.execute_input":"2023-10-19T02:14:17.565486Z","iopub.status.idle":"2023-10-19T02:14:30.149892Z","shell.execute_reply.started":"2023-10-19T02:14:17.565434Z","shell.execute_reply":"2023-10-19T02:14:30.149049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_labels = encoder.inverse_transform(pred_cls)\n\ndf_sub[\"label\"] = pred_labels\ndf_sub.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:30.150769Z","iopub.execute_input":"2023-10-19T02:14:30.151026Z","iopub.status.idle":"2023-10-19T02:14:30.159031Z","shell.execute_reply.started":"2023-10-19T02:14:30.150968Z","shell.execute_reply":"2023-10-19T02:14:30.15821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub","metadata":{"execution":{"iopub.status.busy":"2023-10-19T02:14:30.16007Z","iopub.execute_input":"2023-10-19T02:14:30.160325Z","iopub.status.idle":"2023-10-19T02:14:30.17112Z","shell.execute_reply.started":"2023-10-19T02:14:30.1603Z","shell.execute_reply":"2023-10-19T02:14:30.170148Z"},"trusted":true},"execution_count":null,"outputs":[]}]}