{"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":"gpu","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# import libraries ","metadata":{}},{"cell_type":"code","source":"# import necessary libraries\nimport pandas as pd\nimport numpy as np \nimport torch\nimport torch.nn as nn\nimport json\n\n# Import torchvision \nimport torchvision\nfrom torchvision import datasets\nfrom PIL import Image\n\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torchvision.transforms import ToTensor\nimport torchvision.transforms as transforms\nimport torch.nn.functional as F\nfrom torch import nn, optim\nfrom torchvision import transforms, models\nimport albumentations\n\nfrom sklearn.model_selection import train_test_split\n\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:03:19.724497Z","iopub.execute_input":"2024-06-16T16:03:19.725178Z","iopub.status.idle":"2024-06-16T16:03:25.955129Z","shell.execute_reply.started":"2024-06-16T16:03:19.725143Z","shell.execute_reply":"2024-06-16T16:03:25.954273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SET UP Device ","metadata":{}},{"cell_type":"code","source":"torch.cuda.empty_cache()\n\n# device dog shit code \ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:20.146028Z","iopub.execute_input":"2024-06-16T16:04:20.146699Z","iopub.status.idle":"2024-06-16T16:04:20.153312Z","shell.execute_reply.started":"2024-06-16T16:04:20.146670Z","shell.execute_reply":"2024-06-16T16:04:20.152310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Loading the DaTa","metadata":{}},{"cell_type":"code","source":"# get data loading in \n\nbase_path = '/kaggle/input/cassava-leaf-disease-classification/'\n\ntrain_path = '/kaggle/input/cassava-leaf-disease-classification/train_images'\n\ntest_path = '/kaggle/input/cassava-leaf-disease-classification/test_images'\n\n\nwith open(base_path+'label_num_to_disease_map.json') as f :\n    mapping = json.loads(f.read())\n    mapping = {int(k): v for k, v in mapping.items()}\nmapping","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:21.982752Z","iopub.execute_input":"2024-06-16T16:04:21.983825Z","iopub.status.idle":"2024-06-16T16:04:21.995165Z","shell.execute_reply.started":"2024-06-16T16:04:21.983789Z","shell.execute_reply":"2024-06-16T16:04:21.993990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\ntrain.tail()","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:23.114555Z","iopub.execute_input":"2024-06-16T16:04:23.115371Z","iopub.status.idle":"2024-06-16T16:04:23.157865Z","shell.execute_reply.started":"2024-06-16T16:04:23.115340Z","shell.execute_reply":"2024-06-16T16:04:23.156944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Dataset responsible for manipulating data for training as well as training tests.\nclass DatasetLeaf(torch.utils.data.Dataset):\n    def __init__(self, data, transform=None):\n        super().__init__()\n        self.data = data.reset_index(drop=True).copy()\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        item = self.data.iloc[index]\n                \n        image = Image.open(f'/kaggle/input/cassava-leaf-disease-classification/train_images/{item[\"image_id\"]}')\n        label = item['label']\n        \n        if self.transform is not None:\n            image = self.transform(image)\n        \n        label = torch.tensor(label, dtype=torch.long)\n            \n        return image, label","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:23.959761Z","iopub.execute_input":"2024-06-16T16:04:23.960636Z","iopub.status.idle":"2024-06-16T16:04:23.967696Z","shell.execute_reply.started":"2024-06-16T16:04:23.960604Z","shell.execute_reply":"2024-06-16T16:04:23.966780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CONFIG ","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 32\nVALID_SIZE = 0.15 # percentage of data for validation .\nDIM = (256, 256)\nWidth, Height = DIM\nepochs = 12\nNUM_Classes = 5\nNUM_Workers = 2","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:26.582954Z","iopub.execute_input":"2024-06-16T16:04:26.583348Z","iopub.status.idle":"2024-06-16T16:04:26.588211Z","shell.execute_reply.started":"2024-06-16T16:04:26.583321Z","shell.execute_reply":"2024-06-16T16:04:26.587126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating Augmntations  ","metadata":{}},{"cell_type":"code","source":"\ntransform_train = transforms.Compose([\n   # transforms.RandomRotation(0, 0.5),\n    transforms.ToTensor(),\n    transforms.Resize(size=DIM),\n    transforms.RandomVerticalFlip(p=0.5),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.Normalize(mean=[0.4303, 0.4967, 0.3134],\n                std=[0.2330, 0.2359, 0.2237]),\n])\n\ntransform_valid = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Resize(size=DIM),\n    transforms.Normalize(mean=[0.4303, 0.4967, 0.3134],\n                std=[0.2330, 0.2359, 0.2237]),\n])\n\n\n# Creating datasets for training and validation\ntrain_data = DatasetLeaf(train, transform_train)\nvalid_data = DatasetLeaf(train, transform_valid)\n\n# Shuffling data and choosing data that will be used for training and validation\nnum_train = len(train_data)\nindices = list(range(num_train))\nnp.random.shuffle(indices)\nsplit = int(np.floor(VALID_SIZE * num_train))\ntrain_idx, valid_idx = indices[split:], indices[:split]\n\ntrain_sampler = SubsetRandomSampler(train_idx)\nvalid_sampler = SubsetRandomSampler(valid_idx)\n\ntrain_loader = torch.utils.data.DataLoader(train_data, batch_size=BATCH_SIZE, num_workers=NUM_Workers, sampler=train_sampler, pin_memory=True)\nvalid_loader = torch.utils.data.DataLoader(valid_data, batch_size=BATCH_SIZE, num_workers=NUM_Workers, sampler=valid_sampler, pin_memory=True)\n\nprint(f\"Length train: {len(train_idx)}\")\nprint(f\"Length valid: {len(valid_idx)}\")","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:28.538238Z","iopub.execute_input":"2024-06-16T16:04:28.538570Z","iopub.status.idle":"2024-06-16T16:04:28.555112Z","shell.execute_reply.started":"2024-06-16T16:04:28.538548Z","shell.execute_reply":"2024-06-16T16:04:28.554221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Some Functions ","metadata":{}},{"cell_type":"code","source":"def train_step(model: torch.nn.Module,\n               data_loader: torch.utils.data.DataLoader,\n               loss_fn: torch.nn.Module,\n               optimizer: torch.optim.Optimizer,\n               accuracy_fn,\n               lrs,\n               scheduler,\n               device: torch.device = device):\n    train_loss, train_acc = 0, 0\n    model.to(device)\n    for batch, (X, y) in enumerate(data_loader):\n        # Send data to GPU\n        X, y = X.to(device), y.to(device)\n\n        # 1. Forward pass\n        y_pred = model(X)\n\n        # 2. Calculate loss\n        loss = loss_fn(y_pred, y)\n        train_loss += loss\n        train_acc += accuracy_fn(y_true=y,\n                                 y_pred=y_pred.argmax(dim=1)) # Go from logits -> pred labels\n\n        # 3. Optimizer zero grad\n        optimizer.zero_grad()\n        lrs.append(get_lr(optimizer))\n        scheduler.step()\n\n        # 4. Loss backward\n        loss.backward()\n\n        # 5. Optimizer step\n        optimizer.step()\n\n    # Calculate loss and accuracy per epoch and print out what's happening\n    train_loss /= len(data_loader)\n    train_acc /= len(data_loader)\n    print(f\"Train loss: {train_loss:.5f} | Train accuracy: {train_acc:.2f}%\")\n    \n    \n    \n    \n    \n\ndef test_step(data_loader: torch.utils.data.DataLoader,\n              model: torch.nn.Module,\n              loss_fn: torch.nn.Module,\n              accuracy_fn,\n              device: torch.device = device):\n    test_loss, test_acc = 0, 0\n    model.to(device)\n    model.eval() # put model in eval mode\n    # Turn on inference context manager\n    with torch.inference_mode(): \n        for X, y in data_loader:\n            # Send data to GPU\n            X, y = X.to(device), y.to(device)\n            \n            # 1. Forward pass\n            test_pred = model(X)\n            \n            # 2. Calculate loss and accuracy\n            test_loss += loss_fn(test_pred, y)\n            test_acc += accuracy_fn(y_true=y,\n                y_pred=test_pred.argmax(dim=1) # Go from logits -> pred labels\n            )\n        \n        # Adjust metrics and print out\n        test_loss /= len(data_loader)\n        test_acc /= len(data_loader)\n        print(f\"Test loss: {test_loss:.5f} | Test accuracy: {test_acc:.2f}%\\n\")","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:30.663798Z","iopub.execute_input":"2024-06-16T16:04:30.664167Z","iopub.status.idle":"2024-06-16T16:04:30.676808Z","shell.execute_reply.started":"2024-06-16T16:04:30.664137Z","shell.execute_reply":"2024-06-16T16:04:30.675767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# pre Trained model ","metadata":{}},{"cell_type":"code","source":"def get_model():\n    net = models.resnet101(weights=True)\n    for param in net.parameters():\n        param.requires_grad = False\n        \n    num_ft = net.fc.in_features\n    net.fc = nn.Sequential(\n                    nn.Linear(num_ft, 256),\n                    nn.ReLU(),\n                    nn.Dropout(0.2),\n                    nn.Linear(256, NUM_Classes),\n                    nn.LogSoftmax(dim=1)\n    )\n    \n    net.to(device)\n    return net ","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:32.509600Z","iopub.execute_input":"2024-06-16T16:04:32.510430Z","iopub.status.idle":"2024-06-16T16:04:32.516285Z","shell.execute_reply.started":"2024-06-16T16:04:32.510392Z","shell.execute_reply":"2024-06-16T16:04:32.515228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = get_model()\n\ntorch.manual_seed(42)\n\n# Setup loss function and optimizer\nloss_fn = nn.CrossEntropyLoss() # this is also called \"criterion\"/\"cost function\" in some places\noptimizer = torch.optim.Adam(params=model.parameters(), lr=0.01)","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:40.000073Z","iopub.execute_input":"2024-06-16T16:04:40.000812Z","iopub.status.idle":"2024-06-16T16:04:42.522964Z","shell.execute_reply.started":"2024-06-16T16:04:40.000782Z","shell.execute_reply":"2024-06-16T16:04:42.521873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"layers = list(range(5))\ni = 0\nfor layer in model.children():\n    if i in layers :\n        for param in layer.parameters():\n            param.requires_grad = False\n    i += 1","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:42.524630Z","iopub.execute_input":"2024-06-16T16:04:42.524963Z","iopub.status.idle":"2024-06-16T16:04:42.530386Z","shell.execute_reply.started":"2024-06-16T16:04:42.524937Z","shell.execute_reply":"2024-06-16T16:04:42.529412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# find total parameters and trainable parameters\ntotal_params = sum(p.numel() for p in model.parameters())\nprint(f'{total_params:,} total parameters')\ntrainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\nprint(f'{trainable_params:,} training parameters')","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:47.386297Z","iopub.execute_input":"2024-06-16T16:04:47.386654Z","iopub.status.idle":"2024-06-16T16:04:47.395799Z","shell.execute_reply.started":"2024-06-16T16:04:47.386625Z","shell.execute_reply":"2024-06-16T16:04:47.394797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import requests\nfrom pathlib import Path \n\n# Download helper functions from Learn PyTorch repo (if not already downloaded)\nif Path(\"helper_functions.py\").is_file():\n  print(\"helper_functions.py already exists, skipping download\")\nelse:\n  print(\"Downloading helper_functions.py\")\n  # Note: you need the \"raw\" GitHub URL for this to work\n  request = requests.get(\"https://raw.githubusercontent.com/mrdbourke/pytorch-deep-learning/main/helper_functions.py\")\n  with open(\"helper_functions.py\", \"wb\") as f:\n        \n    f.write(request.content)\n    \n    \n# Import accuracy metric\nfrom helper_functions import accuracy_fn # Note: could also use torchmetrics.Accuracy(task = 'multiclass', num_classes=len(class_names)).to(device)\n\n# Setup loss function and optimizer\nloss_fn = nn.CrossEntropyLoss() # this is also called \"criterion\"/\"cost function\" in some places\noptimizer = torch.optim.SGD(params=model.parameters(), lr=0.01)\nscheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=0.1, epochs=epochs, steps_per_epoch=len(train_loader))\n\n\ndef get_lr(optimizer):\n    for param_group in optimizer.param_groups:\n        return param_group['lr']\n\n\nfrom timeit import default_timer as timer \ndef print_train_time(start: float, end: float, device: torch.device = None):\n\n    total_time = end - start\n    print(f\"Train time on {device}: {total_time:.3f} seconds\")\n    return total_time","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:48.228029Z","iopub.execute_input":"2024-06-16T16:04:48.228887Z","iopub.status.idle":"2024-06-16T16:04:48.381607Z","shell.execute_reply.started":"2024-06-16T16:04:48.228854Z","shell.execute_reply":"2024-06-16T16:04:48.380708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm.auto import tqdm\n\ntorch.manual_seed(42)\n\n# Measure time\nfrom timeit import default_timer as timer\ntrain_time_start_on_gpu = timer()\n\nepochs = 12\n\nfor epoch in tqdm(range(epochs)):\n    print(f\"Epoch: {epoch}\\n---------\")\n    lrs = []\n    train_step(data_loader=train_loader, \n        model=model, \n        loss_fn=loss_fn,\n        optimizer=optimizer,\n        accuracy_fn=accuracy_fn,\n        lrs=lrs,\n        scheduler=scheduler\n    )\n    test_step(data_loader=valid_loader,\n        model=model,\n        loss_fn=loss_fn,\n        accuracy_fn=accuracy_fn\n    )\n\ntrain_time_end_on_gpu = timer()\ntotal_train_time_model_1 = print_train_time(start=train_time_start_on_gpu,\n                                            end=train_time_end_on_gpu,\n                                            device=device)","metadata":{"execution":{"iopub.status.busy":"2024-06-16T16:04:48.992709Z","iopub.execute_input":"2024-06-16T16:04:48.993115Z","iopub.status.idle":"2024-06-16T16:04:59.605171Z","shell.execute_reply.started":"2024-06-16T16:04:48.993083Z","shell.execute_reply":"2024-06-16T16:04:59.603866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}