{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":25563,"databundleVersionId":2094376,"sourceType":"competition"},{"sourceId":2032065,"sourceType":"datasetVersion","datasetId":1216613},{"sourceId":63374,"sourceType":"modelInstanceVersion","modelInstanceId":52841}],"dockerImageVersionId":30699,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\n\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import DataLoader,Dataset\nfrom torchvision import transforms\nfrom torchvision import models as models\nimport torchvision\nfrom torch.utils.data import random_split  \nimport torch\nimport torch.nn as nn\n\nfrom matplotlib import pyplot as plt\nfrom PIL import Image\n\nimport albumentations as A # Image augmentation\nfrom albumentations.pytorch import ToTensorV2 # Image Augmentation\n\nfrom tqdm.notebook import tqdm\nimport seaborn as sns\n\nimport cv2\nprint(\"import done\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-09T23:23:10.526985Z","iopub.execute_input":"2024-06-09T23:23:10.527663Z","iopub.status.idle":"2024-06-09T23:23:10.534869Z","shell.execute_reply.started":"2024-06-09T23:23:10.527632Z","shell.execute_reply":"2024-06-09T23:23:10.533900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = 'cuda' if torch.cuda.is_available() else 'cpu'  \nprint(\"device:\",device)\n\nclass_threshold = 0.4\n\nnum_epochs = 30\nbatch_size = 128\nlr = 0.0001\nimg_size = 256","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:10.917774Z","iopub.execute_input":"2024-06-09T23:23:10.918061Z","iopub.status.idle":"2024-06-09T23:23:10.923693Z","shell.execute_reply.started":"2024-06-09T23:23:10.918032Z","shell.execute_reply":"2024-06-09T23:23:10.922802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 1. Processing the Dataset\nresize_img_file = '../input/resized-plant2021/img_sz_256'\ntrain_img_file=\"../input/plant-pathology-2021-fgvc8/train_images/\"\ntest_img_dir =  '../input/plant-pathology-2021-fgvc8/test_images/'\ntrain_origin = pd.read_csv('../input/plant-pathology-2021-fgvc8/train.csv')\n\ntrain_origin.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:11.391540Z","iopub.execute_input":"2024-06-09T23:23:11.392079Z","iopub.status.idle":"2024-06-09T23:23:11.418432Z","shell.execute_reply.started":"2024-06-09T23:23:11.392054Z","shell.execute_reply":"2024-06-09T23:23:11.417560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#smaller dataset\n# train_origin = train_origin.sample(frac=0.4, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:11.786511Z","iopub.execute_input":"2024-06-09T23:23:11.786808Z","iopub.status.idle":"2024-06-09T23:23:11.790696Z","shell.execute_reply.started":"2024-06-09T23:23:11.786782Z","shell.execute_reply":"2024-06-09T23:23:11.789877Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 2. Initialize multi-label labels using one-hot encoding\nlabels_list = [\"healthy\", \"scab\", \"rust\", \"frog_eye_leaf_spot\", \"powdery_mildew\", \"complex\"]\ntrain_df = train_origin[['image']].copy()\nfor label in labels_list:\n    train_df[label] = 0\n\nfor label in labels_list:\n    train_df.loc[train_origin['labels'].str.contains(label), label] = 1\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:12.192145Z","iopub.execute_input":"2024-06-09T23:23:12.192403Z","iopub.status.idle":"2024-06-09T23:23:12.264191Z","shell.execute_reply.started":"2024-06-09T23:23:12.192382Z","shell.execute_reply":"2024-06-09T23:23:12.263295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_origin['labels'].value_counts()\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:12.645771Z","iopub.execute_input":"2024-06-09T23:23:12.646378Z","iopub.status.idle":"2024-06-09T23:23:12.655492Z","shell.execute_reply.started":"2024-06-09T23:23:12.646344Z","shell.execute_reply":"2024-06-09T23:23:12.654560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_counts=train_origin['labels'].value_counts()\n\nplt.figure(figsize=(20,12))\n\ncolors=np.random.rand(len(label_counts),3)\n\nsns.barplot(x=label_counts.index, y=label_counts.values, palette=colors)\nplt.xticks(rotation=45)\nplt.show()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:13.112963Z","iopub.execute_input":"2024-06-09T23:23:13.113288Z","iopub.status.idle":"2024-06-09T23:23:13.522261Z","shell.execute_reply.started":"2024-06-09T23:23:13.113260Z","shell.execute_reply":"2024-06-09T23:23:13.521393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def visualize_batch(path,image_ids, labels):\n    plt.figure(figsize=(16, 12))\n    \n    for ind, (image_id, label) in enumerate(zip(image_ids, labels)):\n        plt.subplot(3, 3, ind + 1)\n        image = cv2.imread(os.path.join(path, image_id))\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        plt.imshow(image)\n        plt.title(f\"Class: {label}\", fontsize=12)\n        plt.axis(\"off\")\n    plt.show()\n\n\ntmp_df = train_origin.sample(9)\nimage_ids = tmp_df[\"image\"].values\nlabels = tmp_df[\"labels\"].values\nvisualize_batch(train_img_file,image_ids,labels)\n    \n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:13.592832Z","iopub.execute_input":"2024-06-09T23:23:13.593103Z","iopub.status.idle":"2024-06-09T23:23:27.291019Z","shell.execute_reply.started":"2024-06-09T23:23:13.593079Z","shell.execute_reply":"2024-06-09T23:23:27.289085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PathologyPlantsDataset(Dataset): # Load image\n    def __init__(self, image_ids, targets, path, mode, transform=None):\n        self.image_ids = image_ids\n        self.targets = targets\n        self.root_dir = path\n        self.mode = mode\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.image_ids)\n    \n    def __getitem__(self, idx):\n        # Read image\n        image_path = os.path.join(self.root_dir, self.image_ids.iloc[idx])\n        image = Image.open(image_path)\n        img = np.array(image)\n        # Process image\n        if self.transform:\n            image = self.transform(image=img)['image']\n        \n        if self.mode == 'test':\n            target = None\n        else:\n            target = torch.tensor(self.targets[idx], dtype=torch.float32) \n        \n        return (image, target)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:27.292839Z","iopub.execute_input":"2024-06-09T23:23:27.293517Z","iopub.status.idle":"2024-06-09T23:23:27.302848Z","shell.execute_reply.started":"2024-06-09T23:23:27.293482Z","shell.execute_reply":"2024-06-09T23:23:27.301919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transform = A.Compose([\n    A.Rotate(\n        always_apply=False, \n        p=0.1, \n        limit=(-68, 178), \n        interpolation=1, \n        border_mode=0, \n        value=(0, 0, 0), \n        mask_value=None\n    ),\n    A.HorizontalFlip(\n        p=0.2\n    ),\n    \n#     A.RandomShadow(\n#         num_shadows_lower=1, \n#         num_shadows_upper=1, \n#         shadow_dimension=3, \n#         shadow_roi=(0, 0.6, 1, 1), \n#         p=0.4\n#     ),\n#     A.ShiftScaleRotate(\n#         shift_limit=0.05, \n#         scale_limit=0.05, \n#         rotate_limit=15, \n#         p=0.6\n#     ),\n#     A.RandomFog(\n#         fog_coef_lower=0.2, \n#         fog_coef_upper=0.2, \n#         alpha_coef=0.2, \n#         p=0.3\n#     ),\n#     A.RGBShift(\n#         r_shift_limit=15, \n#         g_shift_limit=15, \n#         b_shift_limit=15, \n#         p=0.3\n#     ),\n    A.RandomBrightnessContrast(\n        p=0.3\n    ),\n    A.GaussNoise(\n        var_limit=(50, 70),  \n        always_apply=False, \n        p=0.3\n    ),\n    A.Resize(\n        height=img_size,\n        width=img_size,\n    ),\n#     A.CoarseDropout(\n#         max_holes=5, \n#         max_height=5, \n#         max_width=5, \n#         min_holes=3, \n#         min_height=5, \n#         min_width=5,\n#         always_apply=False, \n#         p=0.2\n#     ),\n#     A.Normalize(                   #bad idea, to delete\n#         mean=(0.485, 0.456, 0.406), \n#         std=(0.229, 0.224, 0.225)\n#     ),\n    ToTensorV2(),\n])\nval_transform = A.Compose([\n    A.Resize(\n        height=img_size,\n        width=img_size,\n    ),\n#     A.Normalize(                 #bad idea, to delete\n#         mean=(0.485, 0.456, 0.406), \n#         std=(0.229, 0.224, 0.225)\n#     ),\n    \n    ToTensorV2(),\n])\n\n\nX_train, X_valid, y_train, y_valid = train_test_split(\n    train_df['image'], \n    train_df[labels_list].values,  \n    test_size=0.2, \n    random_state=42\n)\nprint(\"Training dataset length：\",len(X_train))\nprint(\"Testing dataset length：\",len(X_valid))\n\nfor i in range(2):  # Print the first 2 samples for inspection\n    print(f\"Image path: {X_train.iloc[i]}, Labels: {y_train[i]}\") ","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:23:27.304006Z","iopub.execute_input":"2024-06-09T23:23:27.304267Z","iopub.status.idle":"2024-06-09T23:23:27.322689Z","shell.execute_reply.started":"2024-06-09T23:23:27.304245Z","shell.execute_reply":"2024-06-09T23:23:27.321782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def visualize(image):\n    plt.figure(figsize=(5, 5))\n    plt.axis('off')\n    plt.imshow(image.permute(1,2,0))\n    plt.show()\n\n# Print some example images\nfor i in range(10):  # Adjust the range to print more images\n    image_path = X_train.iloc[i]\n    image = cv2.imread(os.path.join(resize_img_file,image_path))\n    if image is not None:\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        transformed = train_transform(image=image)['image']\n        visualize(transformed)\n        \n    else:\n        print(f\"Warning: Unable to read image at path: {image_path}\")\n        \n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:40:11.395910Z","iopub.execute_input":"2024-06-09T23:40:11.396251Z","iopub.status.idle":"2024-06-09T23:40:13.831617Z","shell.execute_reply.started":"2024-06-09T23:40:11.396222Z","shell.execute_reply":"2024-06-09T23:40:13.830603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_set = PathologyPlantsDataset(X_train, y_train, path=resize_img_file ,mode='train',transform=train_transform)\nval_set = PathologyPlantsDataset(X_valid, y_valid, path=resize_img_file, mode='valid', transform=val_transform)\n# train_set = PathologyPlantsDataset(X_train, y_train, path=train_img_file ,mode='train',transform=train_transform)\n# val_set = PathologyPlantsDataset(X_valid, y_valid, path=train_img_file, mode='valid', transform=val_transform)\n\n# Hyperparameter settings\ntrain_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)\nvalid_loader = DataLoader(val_set, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:40:34.230432Z","iopub.execute_input":"2024-06-09T23:40:34.230786Z","iopub.status.idle":"2024-06-09T23:40:34.239264Z","shell.execute_reply.started":"2024-06-09T23:40:34.230758Z","shell.execute_reply":"2024-06-09T23:40:34.238359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def model_resnet():\n    # Load pre-trained ResNet50 model\n#     model = models.resnet50(weights='ResNet50_Weights.DEFAULT')\n    model = models.resnet50()\n    \n    \n    # Unfreeze the parameters of all layers (if you need to fine-tune the whole model, you can comment out this code below)\n    for param in model.parameters():\n        param.requires_grad = True  #False , before jun 9 22:52\n\n    # Modify the last layer of the model\n    model.fc = nn.Sequential(\n        nn.Linear(model.fc.in_features,512),\n        nn.ReLU(),  # ReLU activation function\n        nn.BatchNorm1d(512),  # approved standardized layer\n        nn.Dropout(0.5),\n        nn.Linear(512, 6),  # The final fully connected layer that maps feature dimensions to category numbers\n        nn.Sigmoid()  # Sigmoid Activation function for multi-label categorization\n    )\n    # Załaduj model bezpośrednio z lokalizacji pliku\n    model_path='/kaggle/input/resnet50/pytorch/base/1/my_resnet_model.pth'\n    model.load_state_dict(torch.load(model_path))\n    \n    return model\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:42:14.735450Z","iopub.execute_input":"2024-06-09T23:42:14.735806Z","iopub.status.idle":"2024-06-09T23:42:14.742782Z","shell.execute_reply.started":"2024-06-09T23:42:14.735781Z","shell.execute_reply":"2024-06-09T23:42:14.741749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def model_resnet():\n#     # Load pre-trained ResNet50 model\n# #     model = models.resnet50(weights='ResNet50_Weights.DEFAULT')\n#     model = models.resnet50()\n    \n    \n#     # Unfreeze the parameters of all layers (if you need to fine-tune the whole model, you can comment out this code below)\n#     for param in model.parameters():\n#         param.requires_grad = True  #False , before jun 9 22:52\n\n#     # Modify the last layer of the model\n#     model.fc = nn.Sequential(\n#         nn.Linear(model.fc.in_features,512),\n#         nn.ReLU(),  # ReLU activation function\n#         nn.BatchNorm1d(512),  # approved standardized layer\n#         nn.Dropout(0.5),\n#         nn.Linear(512, 6),  # The final fully connected layer that maps feature dimensions to category numbers\n#         nn.Sigmoid()  # Sigmoid Activation function for multi-label categorization\n#     )\n#     # Załaduj model bezpośrednio z lokalizacji pliku\n#     model_path='/kaggle/input/resnet50/pytorch/base/1/my_resnet_model.pth'\n#     model.load_state_dict(torch.load(model_path))\n    \n#     return model\n\n#     # Modify the last layer of the model\n#     model.fc = nn.Sequential(\n#         nn.Linear(model.fc.in_features, 512),\n#         nn.ReLU(),  # ReLU activation function\n#         nn.BatchNorm1d(512),  # Batch normalization\n#         nn.Dropout(0.5),\n#         nn.Linear(512, 128),  # New fully connected layer\n#         nn.ReLU(),  # ReLU activation function\n#         nn.BatchNorm1d(128),  # Batch normalization\n#         nn.Dropout(0.5),\n#         nn.Linear(128, 16),  # Another fully connected layer\n#         nn.ReLU(),  # ReLU activation function\n#         nn.BatchNorm1d(16),  # Batch normalization\n#         nn.Dropout(0.5),\n#         nn.Linear(16, 6),  # Final fully connected layer\n#         nn.Softmax(dim=1)  # Softmax activation function for multi-class classification\n#     )\n    \n#     # Load model state directly from the file path\n#     model_path = '/kaggle/input/resnet50/pytorch/base/1/my_resnet_model.pth'\n#     model.load_state_dict(torch.load(model_path))\n    \n#     return model\n\n# # Example of how to use the model\n# device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n# model = model_resnet().to(device)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:42:24.842249Z","iopub.execute_input":"2024-06-09T23:42:24.842618Z","iopub.status.idle":"2024-06-09T23:42:25.472275Z","shell.execute_reply.started":"2024-06-09T23:42:24.842590Z","shell.execute_reply":"2024-06-09T23:42:25.471340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_resnet = model_resnet().to(device)\n# loss_fn = torch.nn.MultiLabelSoftMarginLoss()\nloss_fn = nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(my_resnet.parameters(), lr=lr)\n\n\nmy_resnet = nn.DataParallel(my_resnet)  #use 2x GPU (it's faster)\n# model = model.to(device)\n# Zapisanie modelu na dysku\n# torch.save(my_resnet.state_dict(), model_path)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:42:26.712779Z","iopub.execute_input":"2024-06-09T23:42:26.713584Z","iopub.status.idle":"2024-06-09T23:42:27.346137Z","shell.execute_reply.started":"2024-06-09T23:42:26.713552Z","shell.execute_reply":"2024-06-09T23:42:27.345332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_params = sum(p.numel() for p in my_resnet.parameters())\nprint(\"Liczba wszystkich parametrów w modelu: \", total_params)\n\nfor name, param in my_resnet.named_parameters():\n    print(name, param.size())\n\n\n\n\nprint(my_resnet)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:42:28.522754Z","iopub.execute_input":"2024-06-09T23:42:28.523693Z","iopub.status.idle":"2024-06-09T23:42:28.535217Z","shell.execute_reply.started":"2024-06-09T23:42:28.523658Z","shell.execute_reply":"2024-06-09T23:42:28.534379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import f1_score, accuracy_score\nfrom tqdm import tqdm\n\ndef to_numpy(tensor):\n    return tensor.detach().cpu().numpy()\n\ndef get_metrics(y_pred_proba,y_test,threshold=0.5):\n    y_pred = np.where(y_pred_proba > threshold, 1, 0)\n    y1 = y_pred.round().astype(np.float32)\n    y2 = y_test.round().astype(np.float32)\n    \n    \n    y_pred = (y_pred_proba > threshold).astype(int)  # Direct conversion to integer  \n    f1 = f1_score(y_test, y_pred, average='samples', zero_division=1)\n    acc = accuracy_score(y_test,y_pred, normalize=True)\n\n    return acc, f1 \n\ndef train_or_valid(dataloader, model, device, loss_fn, optimizer=None, is_train=True):\n    torch.cuda.empty_cache()\n    loss_val = 0\n    accuracy = 0\n    f1score = 0\n    num_batches = len(dataloader)\n    \n    if is_train:\n        model.train()\n    else:\n        model.eval()\n    \n    with torch.set_grad_enabled(is_train):\n        stream = tqdm(dataloader)\n        for batch, (X, y) in enumerate(stream, start=1):\n            X, y = X.to(device).float(), y.to(device)\n            \n            pred_prob = model(X)\n            loss = loss_fn(pred_prob, y)\n            \n            if is_train:\n                optimizer.zero_grad()\n                loss.backward()\n                optimizer.step()\n            \n            loss_val += loss.item()\n            acc, f1 = get_metrics(to_numpy(pred_prob), to_numpy(y))\n            \n            accuracy += acc\n            f1score += f1\n            \n            desc = f'Epoch {epoch:3d}/{num_epochs} - {\"train\" if is_train else \"valid\"}_Loss: {loss_val/batch:.4f}, ' + \\\n                   f'{\"train\" if is_train else \"valid\"}_Acc: {accuracy/batch:.4f}, {\"train\" if is_train else \"valid\"}_F1: {f1score/batch:.4f}'\n            stream.set_description(desc)\n    \n    return loss_val / num_batches, accuracy / num_batches, f1score / num_batches\n\ndef train(dataloader, model, device, loss_fn, optimizer, train_loss, train_acc, train_f1, epoch, num_epochs):\n    loss, acc, f1 = train_or_valid(dataloader, model, device, loss_fn, optimizer, is_train=True)\n    train_loss.append(loss)\n    train_acc.append(acc)\n    train_f1.append(f1)\n\ndef valid(dataloader, model, device, loss_fn, valid_loss, valid_acc, valid_f1, epoch, num_epochs):\n    loss, acc, f1 = train_or_valid(dataloader, model, device, loss_fn, optimizer=None, is_train=False)\n    valid_loss.append(loss)\n    valid_acc.append(acc)\n    valid_f1.append(f1)\n    return f1\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T22:14:40.046823Z","iopub.execute_input":"2024-06-09T22:14:40.047228Z","iopub.status.idle":"2024-06-09T22:14:40.066551Z","shell.execute_reply.started":"2024-06-09T22:14:40.047192Z","shell.execute_reply":"2024-06-09T22:14:40.065539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n# training process\n\ntrain_loss, train_acc, train_f1 = [], [], []\nvalid_loss, valid_acc, valid_f1 = [], [], []\n\nbest_f1 = 0\nfor epoch in range(1, num_epochs + 1):\n    train(train_loader, my_resnet, device, loss_fn, optimizer, train_loss, train_acc, train_f1, epoch, num_epochs)\n    vaild_f1 = valid(valid_loader, my_resnet, device, loss_fn, valid_loss, valid_acc, valid_f1, epoch, num_epochs)\n    if vaild_f1 > best_f1:\n        torch.save(my_resnet.state_dict(),'Best_model.pth')\n        best_f1 = vaild_f1","metadata":{"execution":{"iopub.status.busy":"2024-06-09T22:14:40.067697Z","iopub.execute_input":"2024-06-09T22:14:40.068007Z","iopub.status.idle":"2024-06-09T23:04:47.025491Z","shell.execute_reply.started":"2024-06-09T22:14:40.067979Z","shell.execute_reply":"2024-06-09T23:04:47.024533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from matplotlib.ticker import MaxNLocator \n\ndef plot_result(train,valid,mode,file_name):\n    epochs = range(1, len(train) + 1)\n    fig, ax = plt.subplots(figsize=(8, 5)) \n    if mode == 'loss':\n        ax.plot(epochs, train, label='Training loss', marker='o')  \n        ax.plot(epochs, valid, label='Validation loss', marker='o')  \n        ax.legend(frameon=False, fontsize=14)  \n        ax.get_xaxis().set_major_locator(MaxNLocator(integer=True))  \n        ax.set_title('Loss', fontsize=18)  \n        ax.set_xlabel('Epoch', fontsize=14)  \n        ax.set_ylabel('Loss', fontsize=14)  \n        plt.savefig(file_name + '.png')\n#         plt.close(fig)\n    elif mode == 'acc':\n        ax.plot(epochs, train, label='Training Accuracy', marker='o')  \n        ax.plot(epochs, valid, label='Validation accuracy', marker='o')  \n        ax.legend(frameon=False, fontsize=14)  \n        ax.get_xaxis().set_major_locator(MaxNLocator(integer=True))  \n        ax.set_title('Accuracy', fontsize=18)  \n        ax.set_xlabel('Epoch', fontsize=14)  \n        ax.set_ylabel('Accuracy', fontsize=14)  \n        plt.savefig(file_name + '.png')\n#         plt.close(fig)\n    elif mode =='f1':\n        ax.plot(epochs, train, label='Training F1-Score', marker='o')  \n        ax.plot(epochs, valid, label='Validation F1-Score', marker='o')  \n        ax.legend(frameon=False, fontsize=14)  \n        ax.get_xaxis().set_major_locator(MaxNLocator(integer=True))  \n        ax.set_title('F1-Score', fontsize=18)  \n        ax.set_xlabel('Epoch', fontsize=14)  \n        ax.set_ylabel('F1-Score', fontsize=14)  \n        plt.savefig(file_name + '.png')\n#         plt.close(fig)\n                ","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:05:01.024412Z","iopub.execute_input":"2024-06-09T23:05:01.025067Z","iopub.status.idle":"2024-06-09T23:05:01.036637Z","shell.execute_reply.started":"2024-06-09T23:05:01.025035Z","shell.execute_reply":"2024-06-09T23:05:01.035699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_result(train_loss,valid_loss,'loss','res_loss')    \nplot_result(train_acc,valid_acc,'acc','res_acc')  \nplot_result(train_f1,valid_f1,'f1','res_f1')  ","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:05:04.741922Z","iopub.execute_input":"2024-06-09T23:05:04.742276Z","iopub.status.idle":"2024-06-09T23:05:05.799669Z","shell.execute_reply.started":"2024-06-09T23:05:04.742246Z","shell.execute_reply":"2024-06-09T23:05:05.798786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#TEST\n\n# Define test image directory\ntest_img_dir = '../input/plant-pathology-2021-fgvc8/test_images'\n\n# Define transformation for test images\ntest_transform = transforms.Compose([\n    transforms.Resize((img_size, img_size)),  # Assuming the model expects input size of 224x224\n    transforms.ToTensor(),\n])\n\n# Custom dataset class for the test images\nclass TestDataset(Dataset):\n    def __init__(self, img_dir, transform=None):\n        self.img_dir = img_dir\n        self.transform = transform\n        self.img_filenames = os.listdir(img_dir)\n\n    def __len__(self):\n        return len(self.img_filenames)\n\n    def __getitem__(self, idx):\n        img_path = os.path.join(self.img_dir, self.img_filenames[idx])\n        image = Image.open(img_path).convert('RGB')\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        return image, self.img_filenames[idx]\n\n# Create DataLoader for the test dataset\ntest_dataset = TestDataset(test_img_dir, transform=test_transform)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\n# Load the best model\nmodel_path = 'Best_model.pth'\nmy_resnet.load_state_dict(torch.load(model_path))\nmy_resnet.to(device)\n\n#-----------------------------------------------------------------------\n\n# Function to run inference on the test set and generate predictions\ndef test(dataloader, model, device):\n    model.eval()\n    predictions = []\n    filenames = []\n    \n    with torch.no_grad():\n        stream = tqdm(dataloader, desc=\"Testing\")\n        for X, filenames_batch in stream:\n            X = X.to(device)\n            pred_proba = model(X)\n            y_pred = torch.sigmoid(pred_proba)  # Assuming sigmoid for binary/multilabel classification\n            y_pred = (y_pred > 0.5).int()  # Apply threshold\n\n            predictions.extend(y_pred.cpu().numpy())\n            filenames.extend(filenames_batch)\n    \n    return predictions, filenames\n\n# Run the test function with the DataLoader\ntest_predictions, test_filenames = test(test_loader, my_resnet, device)\n\n# Convert predictions to labels\nmapped_predictions = []\nfor pred in test_predictions:\n    classes = [labels_list[i] for i, val in enumerate(pred) if val == 1]\n    mapped_pred = ' '.join(classes)\n    mapped_predictions.append(mapped_pred)\n    \n    \n# Prepare the submission DataFrame\nsubmission_df = pd.DataFrame({\n    'image': test_filenames,\n    'labels': mapped_predictions\n})\n\n# Save the submission file\nsubmission_df.to_csv('submission.csv', index=False)\nprint(\"Submission file saved as 'submission.csv'\")\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:17:55.742885Z","iopub.execute_input":"2024-06-09T23:17:55.743250Z","iopub.status.idle":"2024-06-09T23:17:56.482108Z","shell.execute_reply.started":"2024-06-09T23:17:55.743220Z","shell.execute_reply":"2024-06-09T23:17:56.481227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read the submission CSV file\nsubmission_df = pd.read_csv('submission.csv')\n\n# Print the contents of the submission DataFrame\nprint(\"Submission DataFrame:\")\nprint(submission_df)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T23:17:58.071936Z","iopub.execute_input":"2024-06-09T23:17:58.072296Z","iopub.status.idle":"2024-06-09T23:17:58.082011Z","shell.execute_reply.started":"2024-06-09T23:17:58.072266Z","shell.execute_reply":"2024-06-09T23:17:58.080907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#only one image inference\n\n# import torch\n# from torchvision import transforms\n# from PIL import Image\n\n# # Define test image path\n# test_img_path = '../input/plant-pathology-2021-fgvc8/train_images/800113bb65efe69e.jpg'\n\n# # Define transformation for the test image\n# test_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),  # Assuming the model expects input size of 224x224\n#     transforms.ToTensor(),\n# ])\n\n# # Load the test image\n# test_image = Image.open(test_img_path).convert('RGB')\n# test_image = test_transform(test_image).unsqueeze(0)  # Add batch dimension\n\n# # Load the best model\n# model_path = 'Best_model.pth'\n# my_resnet.load_state_dict(torch.load(model_path))\n# my_resnet.to(device)\n\n# # Put the model in evaluation mode\n# my_resnet.eval()\n\n# # Move the test image to the appropriate device\n# test_image = test_image.to(device)\n\n# # Perform inference\n# with torch.no_grad():\n#     pred_proba = my_resnet(test_image)\n#     pred_label = torch.sigmoid(pred_proba) > 0.5\n\n# # Convert prediction to label\n# labels_list = [\"healthy\", \"scab\", \"rust\", \"frog_eye_leaf_spot\", \"powdery_mildew\", \"complex\"]\n# predicted_labels = [labels_list[i] for i, val in enumerate(pred_label.squeeze().tolist()) if val == 1]\n\n# # Print predicted labels\n# print(\"Predicted labels:\", predicted_labels)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T10:02:40.235551Z","iopub.execute_input":"2024-06-09T10:02:40.236369Z","iopub.status.idle":"2024-06-09T10:02:40.245261Z","shell.execute_reply.started":"2024-06-09T10:02:40.236339Z","shell.execute_reply":"2024-06-09T10:02:40.244439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test_image_path = '../input/plant-pathology-2021-fgvc8/test_images/'\n\n# test_images = os.listdir(test_image_path)\n\n# os.listdir(\"/kaggle/working\")\n# if os.path.exists(\"/kaggle/working/submission.csv\"):\n#     os.remove(\"submission.csv\")\n\n\n\n# sub = pd.DataFrame(test_images, columns=['image'])\n# sub['labels'] = 'frog_eye_leaf_spot'\n# sub['labels'] = 'rust'\n# print(sub)\n# print(len(sub))","metadata":{"execution":{"iopub.status.busy":"2024-06-09T10:29:37.381435Z","iopub.execute_input":"2024-06-09T10:29:37.382099Z","iopub.status.idle":"2024-06-09T10:29:37.393185Z","shell.execute_reply.started":"2024-06-09T10:29:37.382068Z","shell.execute_reply":"2024-06-09T10:29:37.392245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sub.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T10:29:40.688359Z","iopub.execute_input":"2024-06-09T10:29:40.689165Z","iopub.status.idle":"2024-06-09T10:29:40.694310Z","shell.execute_reply.started":"2024-06-09T10:29:40.689136Z","shell.execute_reply":"2024-06-09T10:29:40.693390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}