{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":37852,"databundleVersionId":4070249,"sourceType":"competition"}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport random\nimport os\nimport sys\nimport numpy as np\nimport timm\nfrom tqdm import tqdm\n\nimport torch\nimport torch.nn as nn\nimport torchvision.models as models\nimport torch.nn.functional as F\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.optim import Adam, AdamW\nfrom torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, CosineAnnealingLR, ReduceLROnPlateau\nfrom torch.amp import GradScaler\nimport torch.multiprocessing as multiprocessing\nfrom torch.utils.tensorboard import SummaryWriter\nimport datetime\nimport json\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\nimport torchvision.transforms\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import StratifiedKFold\nfrom PIL import Image","metadata":{"jupyter":{"is_executing":true},"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:30:00.180019Z","iopub.execute_input":"2024-12-02T03:30:00.180742Z","iopub.status.idle":"2024-12-02T03:30:00.187233Z","shell.execute_reply.started":"2024-12-02T03:30:00.180705Z","shell.execute_reply":"2024-12-02T03:30:00.186211Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Tensorboard","metadata":{}},{"cell_type":"code","source":"# def gen_Log():\n#     current_time = datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\n#     log_dir = os.path.join(\"runs\", f\"experiment_{current_time}\")\n#     writer = SummaryWriter(log_dir=log_dir)\n#     return writer\n\n# writer = gen_Log()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:38.634415Z","iopub.execute_input":"2024-12-02T03:08:38.634777Z","iopub.status.idle":"2024-12-02T03:08:38.638786Z","shell.execute_reply.started":"2024-12-02T03:08:38.634744Z","shell.execute_reply":"2024-12-02T03:08:38.637922Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# CFG","metadata":{}},{"cell_type":"code","source":"class CFG:\n    # model\n    model_name = 'tf_efficientnet_b2'\n    # criterion\n    criterion_name = 'CrossEntropyLoss'\n    \n    # optimizer\n    optimizer_name = 'AdamW'\n    max_grad_norm = 1000\n    gradient_accumulation_steps = 1\n    # CosineAnnealingLR\n    T_max = 5\n    \n    # scheduler\n    scheduler_name = 'CosineAnnealingLR'\n    \n    # global settings\n    apex = True\n    seed = 42\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')    \n    n_folds = 5\n    used_folds = 5\n    epochs = 1\n    batch_size = 64\n    num_classes = 44\n    print_freq = 200\n    # image settings\n    width_map= {\n        'tf_efficientnet_b2' :260,\n        'convnext_base': 224,\n        'convnext_small': 224\n    }\n    height_map ={\n        'tf_efficientnet_b2' :260,\n        'convnext_base': 224,\n        'convnext_small': 224\n    }\n    width = width_map[model_name]\n    height = height_map[model_name]\n\n    # learning settings\n    lr = 3e-4\n    min_lr = 1e-6\n    weight_decay = 1e-6\n    \ndef set_seed(seed=42):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\nset_seed(seed=CFG.seed)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:40.213336Z","iopub.execute_input":"2024-12-02T03:08:40.214054Z","iopub.status.idle":"2024-12-02T03:08:40.257561Z","shell.execute_reply.started":"2024-12-02T03:08:40.214019Z","shell.execute_reply":"2024-12-02T03:08:40.256583Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 训练数据读入","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/boolart-image-classification/train.csv\")\nFold = StratifiedKFold(n_splits=CFG.n_folds, shuffle=True, random_state=CFG.seed)\n\ntrain['fold'] = int(-1)\nfor fold, (train_index, val_index) in enumerate(Fold.split(train, train['target'])):\n    train.loc[val_index, 'fold'] = fold","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:43.107379Z","iopub.execute_input":"2024-12-02T03:08:43.107732Z","iopub.status.idle":"2024-12-02T03:08:43.150319Z","shell.execute_reply.started":"2024-12-02T03:08:43.107702Z","shell.execute_reply":"2024-12-02T03:08:43.149463Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 计算训练集各通道的mean和std值 ","metadata":{}},{"cell_type":"code","source":"# def calculate_mean_std(data):\n#     means = []\n#     stds = []\n#     for id in tqdm(data['id']):\n#         train_img_path =f\"/kaggle/input/boolart-image-classification/train_image/{id}.jpg\"\n#         image = Image.open(train_img_path).convert(\"RGB\")\n#         image = np.array(image.resize((CFG.width, CFG.height)))\n#         means.append(np.mean(image,axis=(0,1)))\n#         stds.append(np.std(image, axis=(0,1)))\n#     mean = np.mean(means, axis=0)\n#     std = np.mean(stds,axis=0)\n#     return mean / 255, std / 255\n# mean, std = calculate_mean_std(train)\n# %store mean\n# %store std\nmean, std = ([0.8536320017130206, 0.8362727931350286, 0.8301507008641884],\n             [0.23491626922733028, 0.24977155061784578, 0.25436414956228226])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:45.039968Z","iopub.execute_input":"2024-12-02T03:08:45.040778Z","iopub.status.idle":"2024-12-02T03:08:45.045019Z","shell.execute_reply.started":"2024-12-02T03:08:45.040746Z","shell.execute_reply":"2024-12-02T03:08:45.044116Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 数据增强","metadata":{}},{"cell_type":"code","source":"def get_transform(isTransform):\n    if isTransform:\n        return A.Compose([\n            A.Resize(CFG.width, CFG.height),\n            # 翻转\n            A.VerticalFlip(p=0.5),\n            A.HorizontalFlip(p=0.5),\n            # 高斯噪声\n            A.GaussNoise(p=0.2),\n            # 模糊\n            A.OneOf([\n                A.Blur(blur_limit=3, p=0.1),\n                A.MedianBlur(blur_limit=3, p=0.1),\n            ], p=0.2),\n            # 归一化\n            A.Normalize(),\n            # 遮挡\n            A.CoarseDropout(max_holes=8,\n                            max_height=int(CFG.height * 0.1),\n                            max_width=int(CFG.width * 0.1),\n                            p=0.5),\n            ToTensorV2()\n        ])\n    else:\n        return A.Compose([\n            A.Resize(CFG.width, CFG.height),\n            A.Normalize(),\n            ToTensorV2()\n        ])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:46.79266Z","iopub.execute_input":"2024-12-02T03:08:46.793003Z","iopub.status.idle":"2024-12-02T03:08:46.80133Z","shell.execute_reply.started":"2024-12-02T03:08:46.792972Z","shell.execute_reply":"2024-12-02T03:08:46.800405Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_transform_images(imgs, rows, cols):\n    _, axes = plt.subplots(rows, cols, figsize=(rows*2, cols*2))\n    axes = axes.flatten()\n    torch_mean = torch.tensor(mean).view(-1, 1, 1).clone().detach()\n    torch_std = torch.tensor(std).view(-1, 1, 1).clone().detach()\n    for i ,(ax, img) in enumerate(zip(axes, imgs)):\n        img = img * torch_std + torch_mean\n        img = img.permute(1,2,0).numpy()\n        ax.imshow(img)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:49.042979Z","iopub.execute_input":"2024-12-02T03:08:49.043336Z","iopub.status.idle":"2024-12-02T03:08:49.049479Z","shell.execute_reply.started":"2024-12-02T03:08:49.043306Z","shell.execute_reply":"2024-12-02T03:08:49.04832Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# TrainDataSet","metadata":{}},{"cell_type":"code","source":"class TrainDataset(Dataset):\n    def __init__(self, data, transform):\n        self.data = data\n        self.labels = data['target'].values\n        self.id = data['id'].values\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, index):\n        file_path = f\"/kaggle/input/boolart-image-classification/train_image/{self.id[index]}.jpg\"\n        image = np.array(Image.open(file_path).convert(\"RGB\"))\n        image = self.transform(image=image)['image']\n        \n        label = torch.tensor(self.labels[index]).long()\n        return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:51.070056Z","iopub.execute_input":"2024-12-02T03:08:51.070456Z","iopub.status.idle":"2024-12-02T03:08:51.076772Z","shell.execute_reply.started":"2024-12-02T03:08:51.070418Z","shell.execute_reply":"2024-12-02T03:08:51.075825Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"def get_model(model_name, pretrained=False):\n    model = timm.create_model(model_name,pretrained=pretrained)\n    \n    if 'convnext_base' == model_name:\n        model.head.fc = nn.Linear(in_features=1024, out_features=CFG.num_classes, bias=True)\n    if 'convnext_small' == model_name:\n        model.head.fc = nn.Linear(in_features=1024, out_features=CFG.num_classes, bias=True)\n    if 'tf_efficientnet_b2' == model_name:\n        model.classifier = nn.Linear(in_features=model.classifier.in_features, out_features=CFG.num_classes,bias=True)\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:53.045291Z","iopub.execute_input":"2024-12-02T03:08:53.045664Z","iopub.status.idle":"2024-12-02T03:08:53.051199Z","shell.execute_reply.started":"2024-12-02T03:08:53.045635Z","shell.execute_reply":"2024-12-02T03:08:53.050204Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Criterion","metadata":{}},{"cell_type":"code","source":"def get_criterion(criterion_name):\n    if criterion_name == \"CrossEntropyLoss\":\n        return nn.CrossEntropyLoss()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:54.702282Z","iopub.execute_input":"2024-12-02T03:08:54.703083Z","iopub.status.idle":"2024-12-02T03:08:54.706699Z","shell.execute_reply.started":"2024-12-02T03:08:54.703049Z","shell.execute_reply":"2024-12-02T03:08:54.705861Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Scheduler & Optimizer","metadata":{}},{"cell_type":"code","source":"def get_optimizer_scheduler(model, optimizer_name, scheduler_name):\n    optimizer = None\n    scheduler = None\n    \n    if optimizer_name == \"Adam\":\n        optimizer = Adam(model.parameters(), lr=CFG.lr, weight_decay=CFG.weight_decay)\n    if optimizer_name == \"AdamW\":\n        optimizer = AdamW(model.parameters(), lr=CFG.lr, weight_decay=CFG.weight_decay)\n\n    if scheduler_name == \"CosineAnnealingLR\":\n        scheduler = CosineAnnealingLR(optimizer, T_max=CFG.T_max, eta_min=CFG.min_lr)\n    return optimizer, scheduler","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:56.903706Z","iopub.execute_input":"2024-12-02T03:08:56.904038Z","iopub.status.idle":"2024-12-02T03:08:56.909139Z","shell.execute_reply.started":"2024-12-02T03:08:56.904009Z","shell.execute_reply":"2024-12-02T03:08:56.908325Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train_fn","metadata":{}},{"cell_type":"code","source":"def train_fn(train_loader, model, criterion, optimizer, epoch, device):\n    if CFG.apex:\n        scaler = GradScaler()\n    model.train()\n    \n    for step,(images, labels) in enumerate(train_loader):\n        images = images.to(device)\n        labels = labels.to(device)\n        y_pres = model(images)\n        loss = criterion(y_pres, labels)\n\n        if CFG.gradient_accumulation_steps > 1:\n            loss = loss /gradient_accumulation_steps\n        if CFG.apex:\n            scaler.scale(loss).backward()\n        else:\n            loss.backward()\n        grad_norm = torch.nn.utils.clip_grad_norm_(model.parameters(), CFG.max_grad_norm)\n        if (step + 1) % CFG.gradient_accumulation_steps == 0:\n            if CFG.apex:\n                scaler.step(optimizer)\n                scaler.update()\n            else:\n                optimizer.step()\n            optimizer.zero_grad()\n        if step % CFG.print_freq == 0 or step == (len(train_loader)-1):\n            print('Epoch: [{0}][{1}/{2}] '\n                  'Loss: {loss:.4f}'\n                  .format(\n                   epoch+1, step, len(train_loader),loss=loss.item(),\n                   )) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:08:58.901746Z","iopub.execute_input":"2024-12-02T03:08:58.902378Z","iopub.status.idle":"2024-12-02T03:08:58.909031Z","shell.execute_reply.started":"2024-12-02T03:08:58.902346Z","shell.execute_reply":"2024-12-02T03:08:58.90811Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Valid_fn","metadata":{}},{"cell_type":"code","source":"def valid_fn(valid_loader, model, criterion, device):\n    model.eval()\n    preds = []\n    acc = 0.0\n    total_loss = 0.0  # 累积总损失\n    num_batches = len(valid_loader)  # 计算有多少个批次\n\n    for step, (images, labels) in enumerate(valid_loader):\n        images = images.to(device)\n        labels = labels.to(device)\n        batch_size = labels.size(0)\n        \n        # TTA\n        with torch.no_grad():\n            outputs1 = model(images)\n            outputs2 = model(images.flip(-1))\n            outputs3 = model(images.flip(-2))\n            outputs4 = model(images.flip([-2, -1]))\n            outputs5 = model(images.flip(-1).flip([-2, -1]))\n            outputs6 = model(images.flip(-2).flip([-2, -1]))\n            outputs = (outputs1 + outputs2 + outputs3 + outputs4 + outputs5 + outputs6) / 6\n\n            loss = criterion(outputs, labels.long())\n            total_loss += loss.item()  # 累积每个 batch 的损失\n\n            _, predict_y = torch.max(outputs, dim=1)\n            acc += (predict_y.to(device) == labels.to(device)).sum().item()\n\n        # measure elapsed time\n        if step % CFG.print_freq == 0 or step == (len(valid_loader)-1):\n            print('EVAL: [{0}/{1}] '\n                  'Loss: {loss:.4f}'\n                  .format(step, len(valid_loader), loss=loss.item(),\n                   ))\n\n    avg_loss = total_loss / num_batches  # 计算整个验证集的平均损失\n    return avg_loss, acc\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:09:01.093052Z","iopub.execute_input":"2024-12-02T03:09:01.093977Z","iopub.status.idle":"2024-12-02T03:09:01.105008Z","shell.execute_reply.started":"2024-12-02T03:09:01.09393Z","shell.execute_reply":"2024-12-02T03:09:01.103964Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"def train_pipeline(model, criterion, optimizer, scheduler, device):\n    model.to(device)\n    best_score = 0.\n    best_loss = np.inf\n    for fold_id in range(CFG.used_folds):\n        train_index = train[train['fold'] != fold_id].index\n        valid_index = train[train['fold'] == fold_id].index\n\n        train_folds = train.loc[train_index].reset_index(drop=True)\n        valid_folds = train.loc[valid_index].reset_index(drop=True)\n\n        valid_labels = valid_folds['target'].values\n\n        train_dataset = TrainDataset(train_folds,\n                                     transform=get_transform(isTransform=True))\n        valid_dataset = TrainDataset(valid_folds,\n                                     transform=get_transform(isTransform=False))\n\n        train_loader = DataLoader(train_dataset,\n                                  batch_size=CFG.batch_size,\n                                  shuffle=True,\n                                  num_workers=4, pin_memory=True, drop_last=False)\n        valid_loader = DataLoader(valid_dataset,\n                                  batch_size=CFG.batch_size * 2,\n                                  shuffle=False,\n                                  num_workers=4, pin_memory=True, drop_last=False)\n\n        print(f\"FOLD_ID:{fold_id + 1}\")\n        best_score=0.\n        best_loss=np.inf\n        for epoch in range(CFG.epochs):\n            best_score = 0.\n            best_loss = np.inf\n            # train\n            train_fn(train_loader=train_loader,\n                     model=model,\n                     criterion=criterion,\n                     optimizer=optimizer,\n                     epoch=epoch,\n                     device=device)\n            # eval\n            avg_val_loss, acc = valid_fn(valid_loader=valid_loader,\n                                         model=model,\n                                         criterion=criterion,\n                                         device=device)\n            acc = acc / len(valid_dataset)\n            if isinstance(scheduler, ReduceLROnPlateau):\n                scheduler.step(avg_val_loss)\n            elif isinstance(scheduler, CosineAnnealingLR):\n                scheduler.step()\n            elif isinstance(scheduler, CosineAnnealingWarmRestarts):\n                scheduler.step()\n            print(f\"epoch:{epoch + 1}，acc:{acc}\")\n\n            if acc > best_score:\n                best_score = acc\n                torch.save({'model': model.state_dict(),\n                            'preds': acc},\n                           '/kaggle/working/model' + f'{CFG.model_name}_fold{fold_id + 1}_best_score.pth')\n\n            if avg_val_loss < best_loss:\n                best_loss = avg_val_loss\n                torch.save({'model': model.state_dict(),\n                            'preds': acc},\n                           '/kaggle/working/model' + f'{CFG.model_name}_fold{fold_id + 1}_best_loss.pth')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:09:02.960488Z","iopub.execute_input":"2024-12-02T03:09:02.961281Z","iopub.status.idle":"2024-12-02T03:09:02.970917Z","shell.execute_reply.started":"2024-12-02T03:09:02.961248Z","shell.execute_reply":"2024-12-02T03:09:02.970001Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = get_model(CFG.model_name, pretrained=True)\ncriterion = get_criterion(CFG.criterion_name)\noptimizer ,scheduler = get_optimizer_scheduler(model=model, optimizer_name=CFG.optimizer_name, scheduler_name=CFG.scheduler_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:09:15.120758Z","iopub.execute_input":"2024-12-02T03:09:15.121408Z","iopub.status.idle":"2024-12-02T03:09:15.885922Z","shell.execute_reply.started":"2024-12-02T03:09:15.121377Z","shell.execute_reply":"2024-12-02T03:09:15.885142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_pipeline(model, criterion, optimizer, scheduler, CFG.device)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"test_data = pd.read_csv('/kaggle/input/boolart-image-classification/sample_submission.csv')\n\nclass TestDataset(Dataset):\n    def __init__(self, data, transform):\n        self.data = data['id'].values\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        self.file_path = f\"/kaggle/input/boolart-image-classification/test_image/{self.data[idx]}.jpg\"\n        image = np.array(Image.open(self.file_path).convert(\"RGB\"))\n        image = self.transform(image=image)['image']\n        return image,self.data[idx]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:09:22.184617Z","iopub.execute_input":"2024-12-02T03:09:22.185266Z","iopub.status.idle":"2024-12-02T03:09:22.193651Z","shell.execute_reply.started":"2024-12-02T03:09:22.185231Z","shell.execute_reply":"2024-12-02T03:09:22.192796Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def inference(model, models_path, test_loader, device):\n    pre = []\n    image_id = []\n    for i, (images,img_ids) in enumerate(test_loader):\n        image_id += list(img_ids.numpy())\n        images = images.to(device)\n        for model_path in models_path:\n            model.load_state_dict(torch.load(model_path)['model'])\n            model.to(device)\n            model.eval()\n            with torch.no_grad():\n                y_preds1 = F.softmax(model(images))\n                y_preds2 = F.softmax(model(images.flip(-1)))\n                y_preds3 = F.softmax(model(images.flip(-2)))\n                y_preds4 = F.softmax(model(images.flip([-2, -1])))\n                y_preds5 = F.softmax(model(images.flip(-1).flip([-2, -1])))\n                y_preds6 = F.softmax(model(images.flip(-2).flip([-2, -1])))\n            y_preds = (y_preds1.to('cpu').numpy() + y_preds2.to('cpu').numpy() +\n                       y_preds3.to('cpu').numpy() + y_preds4.to('cpu').numpy() + y_preds5.to(\n                        'cpu').numpy() + y_preds6.to('cpu').numpy()) / 6\n        avg_preds = F.softmax(torch.from_numpy(y_preds),dim=1)\n        _,predict_y = torch.max(avg_preds,dim = 1)\n        predict_y = np.array(predict_y).tolist()\n        pre += predict_y\n    return pre,image_id","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:32:24.607886Z","iopub.execute_input":"2024-12-02T03:32:24.608686Z","iopub.status.idle":"2024-12-02T03:32:24.617031Z","shell.execute_reply.started":"2024-12-02T03:32:24.608652Z","shell.execute_reply":"2024-12-02T03:32:24.616123Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dataset = TestDataset(test_data, transform=get_transform(isTransform=False))\ntest_loader = DataLoader(test_dataset, batch_size=CFG.batch_size, shuffle=False,\n                         num_workers=4, pin_memory=True)\ndef get_best_model(model_name):\n    best_acc = 0.\n    best_model_pth = \"\"\n    for fold_id in range(CFG.used_folds):\n        checkpoint = torch.load('/kaggle/working/model' + f'{model_name}_fold{fold_id + 1}_best_score.pth')\n        if(checkpoint['preds'] > best_acc):\n            best_acc = checkpoint['preds']\n            best_model_pth = '/kaggle/working/model' + f'{model_name}_fold{fold_id + 1}_best_score.pth'\n    return best_model_pth\n        \nbest_model_pth = get_best_model(CFG.model_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:32:27.200213Z","iopub.execute_input":"2024-12-02T03:32:27.201022Z","iopub.status.idle":"2024-12-02T03:32:27.393411Z","shell.execute_reply.started":"2024-12-02T03:32:27.200989Z","shell.execute_reply":"2024-12-02T03:32:27.392497Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_model_pth","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:32:29.751702Z","iopub.execute_input":"2024-12-02T03:32:29.752561Z","iopub.status.idle":"2024-12-02T03:32:29.758064Z","shell.execute_reply.started":"2024-12-02T03:32:29.752524Z","shell.execute_reply":"2024-12-02T03:32:29.757205Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions,img_id = inference(model, [best_model_pth], test_loader, CFG.device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:32:31.649459Z","iopub.execute_input":"2024-12-02T03:32:31.650078Z","iopub.status.idle":"2024-12-02T03:34:12.488584Z","shell.execute_reply.started":"2024-12-02T03:32:31.650045Z","shell.execute_reply":"2024-12-02T03:34:12.487541Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Submission\n","metadata":{}},{"cell_type":"code","source":"df = pd.DataFrame({\n    \"id\": img_id,\n    \"predict\": predictions\n})\ndf.to_csv(\"./submission.csv\", index=False)\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T03:34:15.538078Z","iopub.execute_input":"2024-12-02T03:34:15.538506Z","iopub.status.idle":"2024-12-02T03:34:15.581318Z","shell.execute_reply.started":"2024-12-02T03:34:15.538471Z","shell.execute_reply":"2024-12-02T03:34:15.580445Z"}},"outputs":[],"execution_count":null}]}