{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"},{"sourceId":6853106,"sourceType":"datasetVersion","datasetId":3939159},{"sourceId":7164314,"sourceType":"datasetVersion","datasetId":4138415}],"dockerImageVersionId":30558,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# KKY/MPV semestrální práce na klasifikaci\n# author: jakubrada\n# date: 26.10.2023\n\n# example path:  /kaggle/input/cassava-leaf-disease-classification/sample_submission.csv\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-10T09:14:37.264596Z","iopub.execute_input":"2023-12-10T09:14:37.264841Z","iopub.status.idle":"2023-12-10T09:14:37.269525Z","shell.execute_reply.started":"2023-12-10T09:14:37.264818Z","shell.execute_reply":"2023-12-10T09:14:37.268538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Import knihoven, které budu potřebovat.","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom sklearn.model_selection import train_test_split\nimport numpy as np\nimport os\nfrom PIL import Image\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nimport pandas as pd\nimport cv2","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:37.306754Z","iopub.execute_input":"2023-12-10T09:14:37.307016Z","iopub.status.idle":"2023-12-10T09:14:43.406001Z","shell.execute_reply.started":"2023-12-10T09:14:37.306993Z","shell.execute_reply":"2023-12-10T09:14:43.405236Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vytvoření třídy CassavaDataset, pro načtení datasetu a zpracování augmentací.","metadata":{}},{"cell_type":"code","source":"DATA_DIR = '/kaggle/input/cassava-leaf-disease-classification/train_images/'\nDATA_DIR_test = '/kaggle/input/cassava-leaf-disease-classification/test_images/'\nCSV_DIR = '/kaggle/input/cassava-leaf-disease-classification/train.csv'\n\n\n#  CassavaDataset class for dataset preparation\nclass CassavaDataset(Dataset):\n    def __init__(self, data_dir, csv_file, transform=None):\n        self.data_dir = data_dir\n        self.csv_data = pd.read_csv(csv_file)\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.csv_data)\n\n    def __getitem__(self, idx):\n        image_name = os.path.join(self.data_dir, self.csv_data.iloc[idx, 0])  # 'filename' column\n        image = Image.open(image_name)\n        label = int(self.csv_data.iloc[idx, 1])  # 'label' column\n\n        if self.transform:\n            augmented = self.transform(image=np.array(image))\n            image = augmented['image']\n\n        return image, label\n\n    \n# data augmentations\ntransform = A.Compose([\n    A.Resize(224, 224),\n    A.Blur(blur_limit=(3, 7), p=0.2),   # Apply random Gaussian blur with a probability of 0.2\n    A.RandomContrast(limit=0.2, p=0.5),  # Random contrast adjustment with a probability of 50%\n    A.RandomCrop(width=128, height=128), \n    A.HorizontalFlip(p=0.5),  # Example augmentation: horizontal flip with 50% probability\n    A.RandomRotate90(p=0.5),  # Example augmentation: random 90-degree rotation with 50% probability\n    A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ToTensorV2(),\n])\n\n# augmentation pipeline\ntrain_dataset = CassavaDataset(DATA_DIR, CSV_DIR, transform=transform)\ntrain_size = int(0.9 * len(train_dataset)) # 0.1 should be enaugh for validation\nval_size = len(train_dataset) - train_size\ntrain_dataset, val_dataset = torch.utils.data.random_split(train_dataset, [train_size, val_size])\nprint(train_dataset)\n\nbatch_size = 64\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:43.408035Z","iopub.execute_input":"2023-12-10T09:14:43.409036Z","iopub.status.idle":"2023-12-10T09:14:43.474615Z","shell.execute_reply.started":"2023-12-10T09:14:43.408998Z","shell.execute_reply":"2023-12-10T09:14:43.473798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.efficientnet_v2_s(pretrained=False)\n#model = models.efficientnet_b0(pretrained=True)\nmodel.load_state_dict(torch.load('/kaggle/input/effnet/efficientnet_v2_s-dd5fe13b.pth'))\n\nnum_classes = 5  # Number of cassava disease classes\n#fully connected layer for classification\n#model.fc = nn.Linear(model.fc.in_features, num_classes)\nnum_ftrs = model.classifier[1].in_features\nmodel.classifier[1] = torch.nn.Linear(num_ftrs, 5)\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:43.475548Z","iopub.execute_input":"2023-12-10T09:14:43.475790Z","iopub.status.idle":"2023-12-10T09:14:48.275612Z","shell.execute_reply.started":"2023-12-10T09:14:43.475769Z","shell.execute_reply":"2023-12-10T09:14:48.274805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 20\ntrain_loss_list = []\nval_loss_list = []\n\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    for images, labels in train_loader:\n        images, labels = images.to(torch.float), labels.to(device)\n        images = images.to('cuda')\n        \n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n\n    model.eval()\n    val_loss = 0.0\n    correct = 0\n    total = 0\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.to(torch.float), labels.to(device)\n            images = images.to('cuda')\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            val_loss += loss.item()\n            _, predicted = torch.max(outputs.data, 1)\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n\n    print(f'Epoch {epoch + 1}/{num_epochs}, Training Loss: {running_loss / len(train_loader)}, Validation Loss: {val_loss / len(val_loader)}, Accuracy: {100 * correct / total}%')\n    val_loss_list.append((val_loss / len(val_loader)))\n    train_loss_list.append((running_loss / len(train_loader)))\n\nprint(\"Training finished.\")\n","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:48.276712Z","iopub.execute_input":"2023-12-10T09:14:48.277194Z","iopub.status.idle":"2023-12-10T09:14:56.786597Z","shell.execute_reply.started":"2023-12-10T09:14:48.277157Z","shell.execute_reply":"2023-12-10T09:14:56.784829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\niterations = list(range(1, num_epochs+1))\nprint(train_loss_list)\n# Create the training loss and validation loss plots\nplt.figure(figsize=(10, 5))\nplt.plot(iterations, train_loss_list, label='Training Loss', marker='o', linestyle='-', color='b')\nplt.plot(iterations, val_loss_list, label='Validation Loss', marker='o', linestyle='-', color='r')\n\n# Add labels and title\nplt.xlabel('Iterations')\nplt.ylabel('Loss')\nplt.title('Training and Validation Loss Over Iterations')\n\n# Add a legend\nplt.legend()\n\n# Show the plot\nplt.grid(True)  # Add grid lines\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:56.787662Z","iopub.status.idle":"2023-12-10T09:14:56.788485Z","shell.execute_reply.started":"2023-12-10T09:14:56.788231Z","shell.execute_reply":"2023-12-10T09:14:56.788255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# After training is complete\nOUT_MODEL_DIR = '/kaggle/working/'\nfin_path = OUT_MODEL_DIR + 'cassava_model_001.pth'\ntorch.save(model.state_dict(), fin_path)","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:56.792018Z","iopub.status.idle":"2023-12-10T09:14:56.792565Z","shell.execute_reply.started":"2023-12-10T09:14:56.792327Z","shell.execute_reply":"2023-12-10T09:14:56.792351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nmodel = models.efficientnet_v2_s(pretrained=False)\n#model = models.efficientnet_b0(pretrained=True)\n#model.load_state_dict(torch.load('/kaggle/input/pretrained/resnet18-f37072fd.pth'))\n\nnum_classes = 5  # Number of cassava disease classes\n#fully connected layer for classification\n#model.fc = nn.Linear(model.fc.in_features, num_classes)\nnum_ftrs = model.classifier[1].in_features\nmodel.classifier[1] = torch.nn.Linear(num_ftrs, 5)\n#model = models.resnet50(weights=None)\n#num_classes = 5  # Number of cassava disease classes\n#model.fc = nn.Linear(model.fc.in_features, num_classes)\n\n# Load the trained model's state dictionary\nmodel.load_state_dict(torch.load(fin_path))\nmodel.eval()\ninput_image_path = '/kaggle/input/cassava-leaf-disease-classification/test_images/2216849948.jpg'\n\n\ninput_image = Image.open(input_image_path)\n\npreprocess = transforms.Compose([\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\ninput_tensor = preprocess(input_image)\ninput_tensor = input_tensor.unsqueeze(0)  # Add batch dimension\n\n# Make predictions\nwith torch.no_grad():\n    output = model(input_tensor)\n\n# Process the output to get the predicted class\n_, predicted_class = output.max(1)\n\n# Map the predicted class index to a class label\nclass_names = [\"Cassava Bacterial Blight (CBB)\", \"Cassava Brown Streak Disease (CBSD)\", \"Cassava Green Mottle (CGM)\", \"Cassava Mosaic Disease (CMD)\", \"Healthy\"]\npredicted_class_name = class_names[predicted_class.item()]\n\nprint(f\"Predicted class: {predicted_class_name}\")\n\nplt.imshow(input_image)\nplt.title(f'Predicted class: {predicted_class_name}')\nplt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:56.793765Z","iopub.status.idle":"2023-12-10T09:14:56.794118Z","shell.execute_reply.started":"2023-12-10T09:14:56.793955Z","shell.execute_reply":"2023-12-10T09:14:56.793971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nimport os\nDATA_DIR_test = '/kaggle/input/cassava-leaf-disease-classification/test_images/'\nX_Test = [name for name in (os.listdir(DATA_DIR_test))]\nclass GetData(Dataset):\n    def __init__(self, Dir, FNames, Labels, Transform):\n        self.dir = Dir\n        self.fnames = FNames\n        self.transform = Transform\n        self.lbs = Labels\n        \n    def __len__(self):\n        return len(self.fnames)\n\n    def __getitem__(self, index):\n        x = Image.open(os.path.join(self.dir, self.fnames[index]))\n        if \"train\" in self.dir:            \n            return self.transform(x), self.lbs[index]            \n        elif \"test\" in self.dir:            \n            return self.transform(x), self.fnames[index]\n\nTransform = transforms.Compose(\n    [transforms.ToTensor(),\n     transforms.Resize((224, 224)),\n     #transforms.RandomRotation(90),\n     #transforms.RandomHorizontalFlip(p=0.5),\n     transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))])\n\ntestset = GetData(DATA_DIR_test, X_Test, None, Transform)\ntestloader = DataLoader(testset, batch_size=1, shuffle=False, num_workers=4)\n\ns_ls = []\n\nwith torch.no_grad():\n    model.eval()\n    for image, fname in testloader: \n        image = image.to(torch.float)\n        #image = image.to('cuda')\n        \n        logits = model(image)        \n        ps = torch.exp(logits)        \n        _, top_class = ps.topk(1, dim=1)\n        \n        for pred in top_class:\n            s_ls.append([fname[0], pred.item()])\n            \nsub = pd.DataFrame.from_records(s_ls, columns=['image_id', 'label'])\n\nsub.head()\n\nsub.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-12-10T09:14:56.795548Z","iopub.status.idle":"2023-12-10T09:14:56.796007Z","shell.execute_reply.started":"2023-12-10T09:14:56.795761Z","shell.execute_reply":"2023-12-10T09:14:56.795781Z"},"trusted":true},"execution_count":null,"outputs":[]}]}