{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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"}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport os\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.680836Z","iopub.execute_input":"2025-04-30T09:56:56.681560Z","iopub.status.idle":"2025-04-30T09:56:56.695674Z","shell.execute_reply.started":"2025-04-30T09:56:56.681509Z","shell.execute_reply":"2025-04-30T09:56:56.695012Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torchvision\nfrom torch.utils.data import DataLoader,random_split\nimport torch.nn.functional as F\nimport torch.nn as nn\nimport torch.optim as optim\nfrom PIL import Image\nfrom torchvision.transforms import ToTensor\nimport torchvision.transforms as T\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.696986Z","iopub.execute_input":"2025-04-30T09:56:56.697212Z","iopub.status.idle":"2025-04-30T09:56:56.715013Z","shell.execute_reply.started":"2025-04-30T09:56:56.697196Z","shell.execute_reply":"2025-04-30T09:56:56.714252Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_dir='/kaggle/input/cassava-leaf-disease-classification/train_images'\nlabel_dir='/kaggle/input/cassava-leaf-disease-classification/train.csv'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.719868Z","iopub.execute_input":"2025-04-30T09:56:56.720360Z","iopub.status.idle":"2025-04-30T09:56:56.736197Z","shell.execute_reply.started":"2025-04-30T09:56:56.720343Z","shell.execute_reply":"2025-04-30T09:56:56.735505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import dataset\nimport os\n\nfiles=os.listdir(data_dir)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.737322Z","iopub.execute_input":"2025-04-30T09:56:56.737557Z","iopub.status.idle":"2025-04-30T09:56:56.760090Z","shell.execute_reply.started":"2025-04-30T09:56:56.737536Z","shell.execute_reply":"2025-04-30T09:56:56.759291Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(files)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.761020Z","iopub.execute_input":"2025-04-30T09:56:56.761239Z","iopub.status.idle":"2025-04-30T09:56:56.766086Z","shell.execute_reply.started":"2025-04-30T09:56:56.761224Z","shell.execute_reply":"2025-04-30T09:56:56.765435Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"files[1]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.792684Z","iopub.execute_input":"2025-04-30T09:56:56.792879Z","iopub.status.idle":"2025-04-30T09:56:56.797208Z","shell.execute_reply.started":"2025-04-30T09:56:56.792864Z","shell.execute_reply":"2025-04-30T09:56:56.796667Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df=pd.read_csv(label_dir)\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.841376Z","iopub.execute_input":"2025-04-30T09:56:56.841654Z","iopub.status.idle":"2025-04-30T09:56:56.869641Z","shell.execute_reply.started":"2025-04-30T09:56:56.841636Z","shell.execute_reply":"2025-04-30T09:56:56.868751Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def open_image(path):\n    with open(path,'rb') as f:\n        img=Image.open(f)\n        return img.convert('RGB')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.870876Z","iopub.execute_input":"2025-04-30T09:56:56.871437Z","iopub.status.idle":"2025-04-30T09:56:56.875361Z","shell.execute_reply.started":"2025-04-30T09:56:56.871417Z","shell.execute_reply":"2025-04-30T09:56:56.874569Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import Dataset\nclass CassavaLeaf(Dataset):\n    def __init__(self,root,transform):\n        super().__init__()\n        self.root=root\n        self.files=[fname for fname in os.listdir(root) if fname.endswith('jpg')]\n        self.classes=df.iloc[:,1]\n        self.transform=transform\n\n    def __len__(self):\n        return len(self.files)\n\n    def __getitem__(self,i):\n        fname=self.files[i]\n        fpath=os.path.join(self.root,fname)\n        img=self.transform(open_image(fpath))\n        class_idx=self.classes[i]\n        return img,class_idx","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.883874Z","iopub.execute_input":"2025-04-30T09:56:56.884090Z","iopub.status.idle":"2025-04-30T09:56:56.895035Z","shell.execute_reply.started":"2025-04-30T09:56:56.884075Z","shell.execute_reply":"2025-04-30T09:56:56.894458Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"imagenet_stats=([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n\nimage_size=120\ndataset=CassavaLeaf(data_dir,T.Compose([T.Resize(image_size),\n                                       T.Pad(8,padding_mode='reflect'),\n                                       T.RandomCrop(image_size),\n                                       T.ToTensor(),\n                                       T.Normalize(*imagenet_stats)]))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.895882Z","iopub.execute_input":"2025-04-30T09:56:56.896155Z","iopub.status.idle":"2025-04-30T09:56:56.925420Z","shell.execute_reply.started":"2025-04-30T09:56:56.896133Z","shell.execute_reply":"2025-04-30T09:56:56.924829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(dataset)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.926514Z","iopub.execute_input":"2025-04-30T09:56:56.926719Z","iopub.status.idle":"2025-04-30T09:56:56.933409Z","shell.execute_reply.started":"2025-04-30T09:56:56.926705Z","shell.execute_reply":"2025-04-30T09:56:56.932721Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_ds,val_ds=random_split(dataset,[20000,1397])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.947768Z","iopub.execute_input":"2025-04-30T09:56:56.948263Z","iopub.status.idle":"2025-04-30T09:56:56.952252Z","shell.execute_reply.started":"2025-04-30T09:56:56.948246Z","shell.execute_reply":"2025-04-30T09:56:56.951579Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dl=DataLoader(train_ds,batch_size=20,shuffle=True,num_workers=3,pin_memory=True)\nval_dl=DataLoader(val_ds,batch_size=20,num_workers=3,pin_memory=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.976696Z","iopub.execute_input":"2025-04-30T09:56:56.976869Z","iopub.status.idle":"2025-04-30T09:56:56.980758Z","shell.execute_reply.started":"2025-04-30T09:56:56.976856Z","shell.execute_reply":"2025-04-30T09:56:56.979998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json\n\njson_file = open('/kaggle/input/cassava-leaf-disease-classification/label_num_to_disease_map.json')\nclasses_name = json.load(json_file)\nclasses_name","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:56.998964Z","iopub.execute_input":"2025-04-30T09:56:56.999150Z","iopub.status.idle":"2025-04-30T09:56:57.005703Z","shell.execute_reply.started":"2025-04-30T09:56:56.999136Z","shell.execute_reply":"2025-04-30T09:56:57.004940Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib\n%matplotlib inline\n\ndef denormalize(image,mean,std):\n    # if len(image.shape)==3:\n        image=image.unsqueeze(0)\n        mean=torch.tensor(mean).reshape(1,3,1,1)\n        std=torch.tensor(std).reshape(1,3,1,1)\n        return image *std+mean\n\ndef show_image(img_tensor,label):\n  print('label : ',classes_name[str(label)],'('+str(label)+')')\n  img_tensor=denormalize(img_tensor,*imagenet_stats)[0].permute((1,2,0))\n  plt.imshow(img_tensor)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:57.021150Z","iopub.execute_input":"2025-04-30T09:56:57.021616Z","iopub.status.idle":"2025-04-30T09:56:57.032909Z","shell.execute_reply.started":"2025-04-30T09:56:57.021596Z","shell.execute_reply":"2025-04-30T09:56:57.032327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_image(*dataset[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:57.049286Z","iopub.execute_input":"2025-04-30T09:56:57.049828Z","iopub.status.idle":"2025-04-30T09:56:57.207205Z","shell.execute_reply.started":"2025-04-30T09:56:57.049810Z","shell.execute_reply":"2025-04-30T09:56:57.206505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.utils import make_grid\n\ndef show_batch(dl):\n  for image,label in dl:\n    print(image.shape)\n      \n    fig,ax=plt.subplots(figsize=(16,16))\n    ax.set_xticks([]);ax.set_yticks([])\n    image=denormalize(image[:64],*imagenet_stats)\n    # print(image[0].shape)\n    ax.imshow(make_grid(image[0],nrow=8).permute(1,2,0))\n    break\n\nshow_batch(train_dl)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:57.364477Z","iopub.execute_input":"2025-04-30T09:56:57.364981Z","iopub.status.idle":"2025-04-30T09:56:58.567831Z","shell.execute_reply.started":"2025-04-30T09:56:57.364961Z","shell.execute_reply":"2025-04-30T09:56:58.566838Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def accuracy(output,label):\n    _,pred=torch.max(output,dim=1)\n    return torch.tensor(torch.sum(pred==label).item()/len(pred))\n\nclass ImageClassifierBase(nn.Module):\n    def training_step(self,batch):\n        image,label=batch\n        out=self(image)\n        loss=F.cross_entropy(out,label)\n        return loss\n\n    def validation_step(self,batch):\n        image,label=batch\n        out=self(image)\n        val_loss=F.cross_entropy(out,label)\n        val_acc=accuracy(out,label)\n        return {'val_loss':val_loss,'val_acc':val_acc}\n\n    def validation_epoch_end(self,output):\n         batch_loss=[x['val_loss'] for x in output]\n         epoch_loss=torch.stack(batch_loss).mean()\n         batch_acc=[x['val_acc'] for x in output]\n         epoch_acc=torch.stack(batch_acc).mean()\n         return {'val_loss':epoch_loss.item(),'val_acc':epoch_acc.item()}\n\n    def epoch_end(self,epoch,result):\n        print(\"Epoch [{}],{} train_loss: {:.4f}, val_loss: {:.4f}, val_acc: {:.4f}\".format(\n            epoch, \"last_lr: {:.5f},\".format(result['lrs'][-1]) if 'lrs' in result else '',\n            result['train_loss'], result['val_loss'], result['val_acc']))\n\n    \n    @torch.no_grad()\n    def evaluate(self,val_loader):\n         self.eval()\n         output=[self.validation_step(batch) for batch in val_loader]\n         return self.validation_epoch_end(output)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:11.348615Z","iopub.execute_input":"2025-04-30T10:00:11.349201Z","iopub.status.idle":"2025-04-30T10:00:11.358412Z","shell.execute_reply.started":"2025-04-30T10:00:11.349173Z","shell.execute_reply":"2025-04-30T10:00:11.357586Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision import models\n\n#models.list_models()\n\nclass CassavaModel(ImageClassifierBase):\n    def __init__(self,num_classes,pretrained=True):\n        super().__init__()\n        self.network=models.resnet50(pretrained=pretrained)\n        self.network.fc=nn.Linear(self.network.fc.in_features,num_classes)\n\n    def forward(self,xb):\n        return self.network(xb)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:13.853728Z","iopub.execute_input":"2025-04-30T10:00:13.854408Z","iopub.status.idle":"2025-04-30T10:00:13.858718Z","shell.execute_reply.started":"2025-04-30T10:00:13.854385Z","shell.execute_reply":"2025-04-30T10:00:13.858035Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_default_device():\n    if torch.cuda.is_available():\n        return torch.device('cuda')\n    else:\n        return torch.device('cpu')\n\ndef to_device(data,device):\n    if isinstance(data,(list,tuple)):\n        return [to_device(x,device) for x in data]\n    return data.to(device,non_blocking=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:58.615966Z","iopub.execute_input":"2025-04-30T09:56:58.616156Z","iopub.status.idle":"2025-04-30T09:56:58.634059Z","shell.execute_reply.started":"2025-04-30T09:56:58.616142Z","shell.execute_reply":"2025-04-30T09:56:58.633363Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DeviceDataLoader():\n    def __init__(self,dl,device):\n        self.dl=dl\n        self.device=device\n\n    def __iter__(self):\n        for b in self.dl:\n            yield to_device(b,self.device)\n\n    def __len__(self):\n        return len(self.dl)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:58.634818Z","iopub.execute_input":"2025-04-30T09:56:58.635053Z","iopub.status.idle":"2025-04-30T09:56:58.658378Z","shell.execute_reply.started":"2025-04-30T09:56:58.635032Z","shell.execute_reply":"2025-04-30T09:56:58.657689Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm.notebook import tqdm\n\ndef fit(epochs,lr,model,train_dl,val_dl,opt_fn=torch.optim.SGD):\n    history=[]\n    opt=opt_fn(model.parameter(),lr)\n\n    for epoch in range(epochs):\n        model.train()\n        train_losses=[]\n\n        for batch in tqdm(train_dl):\n            loss=model.training_step(batch)\n            train_losses.append(loss)\n            loss.backward()\n            opt.step()\n            opt.zero_grad()\n        result=model.evaluate(val_dl)\n        result['train_loss']=torch.stack(train_losses).mean().item()\n        model.epoch(epoch,result)\n        history.append(result)\n    return history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T09:56:58.659143Z","iopub.execute_input":"2025-04-30T09:56:58.659368Z","iopub.status.idle":"2025-04-30T09:56:58.676038Z","shell.execute_reply.started":"2025-04-30T09:56:58.659349Z","shell.execute_reply":"2025-04-30T09:56:58.675374Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_lr(optimizer):\n    for param_group in optimizer.param_groups:\n        return param_group['lr']\n\ndef fit_one_cycle(epochs,mox_lr,model,train_dl,val_dl,weight_decay=0,\n                  grad_clip=None, opt_func=torch.optim.SGD):\n    torch.cuda.empty_cache()\n    history=[]\n    optimizer=opt_func(model.parameters(),max_lr,weight_decay=weight_decay)\n\n    sched=torch.optim.lr_scheduler.OneCycleLR(optimizer,max_lr,epochs=epochs,\n                                             steps_per_epoch=len(train_dl))\n\n    for epoch in range(epochs):\n        model.train()\n        train_losses=[]\n        lrs=[]\n        for batch in tqdm(train_dl):\n            loss=model.training_step(batch)\n            train_losses.append(loss)\n            loss.backward()\n\n            if grad_clip:\n                nn.utils.clip_grad_value_(model.parameters(),grad_clip)\n\n            optimizer.step()\n            optimizer.zero_grad()\n            lrs.append(get_lr(optimizer))\n            sched.step()\n        result=model.evaluate(val_dl)\n        result['train_loss']=torch.stack(train_losses).mean().item()\n        result['lrs']=lrs\n        model.epoch_end(epoch,result)\n        history.append(result)\n    return history\n            ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:19.663026Z","iopub.execute_input":"2025-04-30T10:00:19.663744Z","iopub.status.idle":"2025-04-30T10:00:19.670105Z","shell.execute_reply.started":"2025-04-30T10:00:19.663719Z","shell.execute_reply":"2025-04-30T10:00:19.669369Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device=get_default_device()\ndevice","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:21.044963Z","iopub.execute_input":"2025-04-30T10:00:21.045569Z","iopub.status.idle":"2025-04-30T10:00:21.050446Z","shell.execute_reply.started":"2025-04-30T10:00:21.045544Z","shell.execute_reply":"2025-04-30T10:00:21.049732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dl=DeviceDataLoader(train_dl,device)\nval_dl=DeviceDataLoader(val_dl,device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:21.950613Z","iopub.execute_input":"2025-04-30T10:00:21.951054Z","iopub.status.idle":"2025-04-30T10:00:21.954347Z","shell.execute_reply.started":"2025-04-30T10:00:21.951035Z","shell.execute_reply":"2025-04-30T10:00:21.953802Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model=CassavaModel(len(dataset.classes))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:23.799014Z","iopub.execute_input":"2025-04-30T10:00:23.799713Z","iopub.status.idle":"2025-04-30T10:00:24.609361Z","shell.execute_reply.started":"2025-04-30T10:00:23.799691Z","shell.execute_reply":"2025-04-30T10:00:24.608564Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"to_device(model, device);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:24.640053Z","iopub.execute_input":"2025-04-30T10:00:24.640462Z","iopub.status.idle":"2025-04-30T10:00:24.731652Z","shell.execute_reply.started":"2025-04-30T10:00:24.640443Z","shell.execute_reply":"2025-04-30T10:00:24.731122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history=[model.evaluate(val_dl)]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:25.625766Z","iopub.execute_input":"2025-04-30T10:00:25.625994Z","iopub.status.idle":"2025-04-30T10:00:31.497273Z","shell.execute_reply.started":"2025-04-30T10:00:25.625978Z","shell.execute_reply":"2025-04-30T10:00:31.496009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:31.499328Z","iopub.execute_input":"2025-04-30T10:00:31.499649Z","iopub.status.idle":"2025-04-30T10:00:31.506294Z","shell.execute_reply.started":"2025-04-30T10:00:31.499620Z","shell.execute_reply":"2025-04-30T10:00:31.505475Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 6\nmax_lr = 0.01\ngrad_clip = 0.1\nweight_decay = 1e-4\nopt_func = torch.optim.Adam","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:33.365112Z","iopub.execute_input":"2025-04-30T10:00:33.365875Z","iopub.status.idle":"2025-04-30T10:00:33.369723Z","shell.execute_reply.started":"2025-04-30T10:00:33.365834Z","shell.execute_reply":"2025-04-30T10:00:33.368999Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history += fit_one_cycle(epochs, max_lr, model, train_dl, val_dl,\n                         grad_clip=grad_clip,\n                         weight_decay=weight_decay,\n                         opt_func=opt_func)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T10:00:35.084573Z","iopub.execute_input":"2025-04-30T10:00:35.084832Z","iopub.status.idle":"2025-04-30T10:02:32.577186Z","shell.execute_reply.started":"2025-04-30T10:00:35.084815Z","shell.execute_reply":"2025-04-30T10:02:32.576072Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}