{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":89850,"databundleVersionId":11256103,"sourceType":"competition"},{"sourceId":228079357,"sourceType":"kernelVersion"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# PlantCLEF ResNet18 Infer 5x5","metadata":{}},{"cell_type":"markdown","source":"https://www.kaggle.com/code/stpeteishii/plantclef-resnet18-train","metadata":{}},{"cell_type":"code","source":"!pip install lightning ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:15.132278Z","iopub.execute_input":"2025-03-14T11:10:15.132676Z","iopub.status.idle":"2025-03-14T11:10:22.485411Z","shell.execute_reply.started":"2025-03-14T11:10:15.132634Z","shell.execute_reply":"2025-03-14T11:10:22.484094Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport random\nimport numpy as np\nimport pandas as pd\nimport csv\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import DataLoader, Dataset, Subset, random_split, SubsetRandomSampler\nfrom torchvision import datasets, transforms, models\nfrom torchvision.datasets import ImageFolder\nfrom torchvision.transforms import ToTensor\nfrom torchvision.utils import make_grid\n\nimport cv2\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\n\n# PyTorch Lightning\nimport lightning.pytorch as L\nfrom lightning.pytorch import LightningModule, Trainer, LightningDataModule\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:22.48661Z","iopub.execute_input":"2025-03-14T11:10:22.487011Z","iopub.status.idle":"2025-03-14T11:10:36.589438Z","shell.execute_reply.started":"2025-03-14T11:10:22.486968Z","shell.execute_reply":"2025-03-14T11:10:36.588198Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"    \n    # Load a pre-trained model (EfficientNet)\n    def load_model():\n        model = models.efficientnet_b0(pretrained=True)\n        model.eval()  # Set to evaluation mode\n        return model\n","metadata":{}},{"cell_type":"code","source":"import timm\n\nclass ConvolutionalNetwork(LightningModule):\n    def __init__(self, num_classes=None):\n        super().__init__()\n        if num_classes is None:\n            raise ValueError(\"num_classes must be specified.\")\n        self.base_model = timm.create_model('resnet18', \n                                            pretrained=True, \n                                            num_classes=num_classes)\n\n    def forward(self, x):\n        return self.base_model(x)\n\n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=0.001)\n        return optimizer\n\n    def training_step(self, train_batch, batch_idx):\n        X, y = train_batch\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"train_loss\", loss)\n        self.log(\"train_acc\", acc)\n        return loss\n\n    def validation_step(self, val_batch, batch_idx):\n        X, y = val_batch\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"val_loss\", loss)\n        self.log(\"val_acc\", acc)\n\n    def test_step(self, test_batch, batch_idx):\n        X, y = test_batch\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"test_loss\", loss)\n        self.log(\"test_acc\", acc)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:36.590771Z","iopub.execute_input":"2025-03-14T11:10:36.591332Z","iopub.status.idle":"2025-03-14T11:10:40.481146Z","shell.execute_reply.started":"2025-03-14T11:10:36.591286Z","shell.execute_reply":"2025-03-14T11:10:40.479614Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load the image\ndef load_image(image_path):\n    image = cv2.imread(image_path)\n    image = cv2.resize(image, None, fx=0.5, fy=0.5)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    return image\n\n# Split the image into 25 equal parts (5x5 grid)\ndef split_image(image):\n    h, w, _ = image.shape\n    h_fourth, w_fourth = h // 5, w // 5\n    \n    patches = [\n        image[i*h_fourth:(i+1)*h_fourth, j*w_fourth:(j+1)*w_fourth]\n        for i in range(5) for j in range(5)\n    ]\n    return patches\n\n\n# Preprocess the image for the model\ndef preprocess_image(image):\n    transform = transforms.Compose([\n        transforms.ToPILImage(),\n        transforms.Resize((224, 224)),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n    ])\n    return transform(image).unsqueeze(0)  # Add batch dimension\n\n# Classify the patches and retrieve labels\ndef classify_patches(model, patches, class_labels):\n    results = []\n    for patch in patches:\n        input_tensor = preprocess_image(patch)\n        with torch.no_grad():\n            output = model(input_tensor)\n        _, predicted = torch.max(output, 1)\n        results.append(class_labels[predicted.item()])\n    return results\n\n\n# Main function\ndef main(image_path):\n    num_classes = len(class_names)\n    image = load_image(image_path)\n    patches = split_image(image)\n    #model = load_model()\n    model = ConvolutionalNetwork.load_from_checkpoint(\"/kaggle/input/plant-lightning-resnet18/model_checkpoint.ckpt\", num_classes=num_classes)\n    predictions = classify_patches(model, patches, class_names)\n    #display_results(image, patches, predictions)\n    return predictions","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:40.483799Z","iopub.execute_input":"2025-03-14T11:10:40.484287Z","iopub.status.idle":"2025-03-14T11:10:40.496033Z","shell.execute_reply.started":"2025-03-14T11:10:40.484223Z","shell.execute_reply":"2025-03-14T11:10:40.494717Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"\n    # Display the results\n    def display_results(image, patches, predictions):\n        fig, axes = plt.subplots(3, 3, figsize=(12, 12))\n        for i, ax in enumerate(axes.flatten()):\n            ax.imshow(patches[i])\n            ax.set_title(f\"Predicted: {predictions[i]}\")\n            ax.axis(\"off\")\n        plt.tight_layout()\n        plt.show()","metadata":{}},{"cell_type":"code","source":"class_df=pd.read_csv('/kaggle/input/plant-lightning-resnet18/class_names.csv')\nclass_names=class_df.iloc[:,0].tolist()\nprint(class_names[0:3])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:12:06.133603Z","iopub.execute_input":"2025-03-14T11:12:06.134073Z","iopub.status.idle":"2025-03-14T11:12:06.144252Z","shell.execute_reply.started":"2025-03-14T11:12:06.13404Z","shell.execute_reply":"2025-03-14T11:12:06.143015Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test=pd.read_csv('/kaggle/input/plantclef-2025/PlantCLEF2025_test.csv',sep=';')\nprint(len(test))\ndir0='/kaggle/input/plantclef-2025/PlantCLEF2025_test_images/PlantCLEF2025_test_images'\ntest['path']=test['quadrat_id'].apply(lambda x:os.path.join(dir0,x+'.jpg'))\ntest[\"species_ids\"]=''","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:40.585433Z","iopub.status.idle":"2025-03-14T11:10:40.585988Z","shell.execute_reply":"2025-03-14T11:10:40.585693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def display_results(image, patches, predictions):\n\n    plt.figure(figsize=(11, 11))\n    plt.imshow(image)\n    plt.title(\"Original Image\")\n    plt.axis(\"off\")\n    plt.show()\n\n    fig, axes = plt.subplots(5, 5, figsize=(9, 9))\n    for i, ax in enumerate(axes.flatten()):\n        ax.imshow(patches[i])\n        ax.set_title(f\"{predictions[i]}\", fontsize=9)\n        ax.axis(\"off\")\n    fig.suptitle(\"Grid Image\", fontsize=16)  \n    plt.tight_layout()\n    plt.show()\n\n\nfor i in range(1):\n    path=test.iloc[i,4]\n    preds=main(path)\n    print(preds)\n    image = load_image(path)\n    patches = split_image(image)\n    display_results(image, patches, preds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:40.585433Z","iopub.status.idle":"2025-03-14T11:10:40.585988Z","shell.execute_reply":"2025-03-14T11:10:40.585693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i in range(len(test)):\n    path=test.iloc[i,4]\n    preds=main(path)\n    test.loc[i,'species_ids']=str(list(set(preds)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:40.587134Z","iopub.status.idle":"2025-03-14T11:10:40.587594Z","shell.execute_reply":"2025-03-14T11:10:40.587396Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submit=test[[\"quadrat_id\",\"species_ids\"]]\nsubmit.to_csv(\"my_run.csv\", sep=',', index=False, quoting=csv.QUOTE_ALL)\ndisplay(submit)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-14T11:10:40.588632Z","iopub.status.idle":"2025-03-14T11:10:40.5891Z","shell.execute_reply":"2025-03-14T11:10:40.5889Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}