{"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":30716,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Seed fixed","metadata":{}},{"cell_type":"code","source":"import torch\nimport random\nimport numpy as np\nimport os\n\nseed=50\nos.environ['PYTHONHASHSEED']=str(seed)\nrandom.seed(seed)\nnp.random.seed(seed)\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ntorch.cuda.manual_seed_all(seed)\ntorch.backends.cudnn.deterministic=True\ntorch.backends.cudnn.benchmark=False\ntorch.backends.cudnn.enabled=False","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:04:26.008922Z","iopub.execute_input":"2024-06-04T02:04:26.009739Z","iopub.status.idle":"2024-06-04T02:04:29.090455Z","shell.execute_reply.started":"2024-06-04T02:04:26.009702Z","shell.execute_reply":"2024-06-04T02:04:29.089032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Device","metadata":{}},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:04:32.055798Z","iopub.execute_input":"2024-06-04T02:04:32.056691Z","iopub.status.idle":"2024-06-04T02:04:32.081404Z","shell.execute_reply.started":"2024-06-04T02:04:32.056656Z","shell.execute_reply":"2024-06-04T02:04:32.080504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train/Valid split","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\ndata_path='/kaggle/input/cassava-leaf-disease-classification/'\n\ntrain=pd.read_csv(data_path+'train.csv')\nsubmission=pd.read_csv(data_path+'sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:04:33.992847Z","iopub.execute_input":"2024-06-04T02:04:33.993364Z","iopub.status.idle":"2024-06-04T02:04:34.434639Z","shell.execute_reply.started":"2024-06-04T02:04:33.993332Z","shell.execute_reply":"2024-06-04T02:04:34.433510Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain,valid=train_test_split(train,test_size=0.1,stratify=train['label'],random_state=50)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:04:35.840630Z","iopub.execute_input":"2024-06-04T02:04:35.841035Z","iopub.status.idle":"2024-06-04T02:04:36.434881Z","shell.execute_reply.started":"2024-06-04T02:04:35.841000Z","shell.execute_reply":"2024-06-04T02:04:36.434013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.reset_index(drop=True)\nvalid.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:04:37.541824Z","iopub.execute_input":"2024-06-04T02:04:37.542530Z","iopub.status.idle":"2024-06-04T02:04:37.558702Z","shell.execute_reply.started":"2024-06-04T02:04:37.542497Z","shell.execute_reply":"2024-06-04T02:04:37.557940Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset\n","metadata":{}},{"cell_type":"code","source":"import cv2\nfrom torch.utils.data import Dataset\nimport numpy as np\n\nclass LeafDataset(Dataset):\n    def __init__(self,df,img_dir='./',transform=None,is_test=False):\n        super().__init__()\n        self.df = df\n        self.img_dir = img_dir\n        self.transform = transform\n        self.is_test = is_test\n    \n    def __len__(self):\n        \n        return len(self.df)\n    \n    def __getitem__(self,idx):\n        img_id = self.df.iloc[idx, 0]\n        img_path = self.img_dir + img_id\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)\n        \n        if self.transform is not None:\n            image=self.transform(image=image)['image']\n            \n        if self.is_test:\n            return image\n        else:\n            label = self.df.iloc[idx, 1]\n            return image, label\n    \n    def image_size(self, idx):\n        img_id = self.df.iloc[idx, 0]\n        img_path = self.img_dir + img_i|d\n        image = cv2.imread(img_path)\n        height, width, _= image.shape\n        return height, width","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:04:39.786658Z","iopub.execute_input":"2024-06-04T02:04:39.787025Z","iopub.status.idle":"2024-06-04T02:04:39.970419Z","shell.execute_reply.started":"2024-06-04T02:04:39.786995Z","shell.execute_reply":"2024-06-04T02:04:39.969449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport cv2\nimport os","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:07:13.319809Z","iopub.execute_input":"2024-06-04T02:07:13.320430Z","iopub.status.idle":"2024-06-04T02:07:13.324409Z","shell.execute_reply.started":"2024-06-04T02:07:13.320398Z","shell.execute_reply":"2024-06-04T02:07:13.323396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calc_avg_mean_std(img_names, img_root, size):\n    mean_sum = np.array([0., 0., 0.])\n    std_sum = np.array([0., 0., 0.])\n    n_images = len(img_names)\n    for img_name in img_names:\n        img = cv2.imread(img_root + img_name)\n        img = cv2.resize(img, size)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        mean, std = cv2.meanStdDev(img)\n        mean_sum += np.squeeze(mean)\n        std_sum += np.squeeze(std)\n    return (mean_sum / n_images, std_sum / n_images)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:07:13.887585Z","iopub.execute_input":"2024-06-04T02:07:13.888253Z","iopub.status.idle":"2024-06-04T02:07:13.894446Z","shell.execute_reply.started":"2024-06-04T02:07:13.888223Z","shell.execute_reply":"2024-06-04T02:07:13.893486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_img_root = '../input/cassava-leaf-disease-classification/train_images/'\ntrain_img_names = os.listdir(train_img_root)\ntrain_mean, train_std = calc_avg_mean_std(train_img_names, train_img_root, (512,512))\ntrain_mean, train_std","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:07:17.278234Z","iopub.execute_input":"2024-06-04T02:07:17.278591Z","iopub.status.idle":"2024-06-04T02:12:42.357956Z","shell.execute_reply.started":"2024-06-04T02:07:17.278565Z","shell.execute_reply":"2024-06-04T02:12:42.357038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_mean/255.0, train_std/255.0)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:13:02.932644Z","iopub.execute_input":"2024-06-04T02:13:02.933220Z","iopub.status.idle":"2024-06-04T02:13:02.938883Z","shell.execute_reply.started":"2024-06-04T02:13:02.933188Z","shell.execute_reply":"2024-06-04T02:13:02.937783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Transform","metadata":{}},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch import ToTensorV2","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:06:16.463874Z","iopub.execute_input":"2024-06-04T02:06:16.464837Z","iopub.status.idle":"2024-06-04T02:06:16.469528Z","shell.execute_reply.started":"2024-06-04T02:06:16.464798Z","shell.execute_reply":"2024-06-04T02:06:16.468548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform_train=A.Compose([A.Resize(512,512),A.HorizontalFlip(p=0.3),A.VerticalFlip(p=0.3), A.RandomBrightnessContrast(p=0.3),\n                           A.CLAHE(p=0.5, clip_limit=(1, 14), tile_grid_size=(8, 8)),\n                           A.OneOf([A.NoOp(), A.MultiplicativeNoise(), A.GaussNoise(), A.ISONoise()]),\n          A.Normalize(mean=[0.42984136, 0.49624753, 0.3129598], std=[0.21417203, 0.21910103, 0.19542212]),ToTensorV2()])","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:14:17.896206Z","iopub.execute_input":"2024-06-04T02:14:17.896781Z","iopub.status.idle":"2024-06-04T02:14:17.902868Z","shell.execute_reply.started":"2024-06-04T02:14:17.896751Z","shell.execute_reply":"2024-06-04T02:14:17.901932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform_test=A.Compose([ A.Resize(512,512),A.Normalize(mean=[0.42984136, 0.49624753, 0.3129598], std=[0.21417203, 0.21910103, 0.19542212]),ToTensorV2()]) # training_data 분포로 수정","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:14:18.278661Z","iopub.execute_input":"2024-06-04T02:14:18.279572Z","iopub.status.idle":"2024-06-04T02:14:18.284350Z","shell.execute_reply.started":"2024-06-04T02:14:18.279539Z","shell.execute_reply":"2024-06-04T02:14:18.283403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_dir='/kaggle/input/cassava-leaf-disease-classification/train_images/'\n\ndataset_train=LeafDataset(df=train,img_dir=img_dir,transform=transform_train)\ndataset_valid=LeafDataset(df=valid,img_dir=img_dir,transform=transform_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:14:22.208061Z","iopub.execute_input":"2024-06-04T02:14:22.208395Z","iopub.status.idle":"2024-06-04T02:14:22.212953Z","shell.execute_reply.started":"2024-06-04T02:14:22.208370Z","shell.execute_reply":"2024-06-04T02:14:22.212018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## DataLoader","metadata":{}},{"cell_type":"code","source":"def seed_worker(worker_id):\n    worker_seed=torch.initial_seed()% 2**32\n    np.random.seed(worker_seed)\n    random.seed(worker_seed)\ng=torch.Generator()\ng.manual_seed(0)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:14:25.424659Z","iopub.execute_input":"2024-06-04T02:14:25.425263Z","iopub.status.idle":"2024-06-04T02:14:25.432412Z","shell.execute_reply.started":"2024-06-04T02:14:25.425224Z","shell.execute_reply":"2024-06-04T02:14:25.431539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\nbatch_size=12\n\nloader_train=DataLoader(dataset_train,batch_size=batch_size,shuffle=True,worker_init_fn=seed_worker,generator=g,num_workers=4)\nloader_valid=DataLoader(dataset_valid,batch_size=batch_size,shuffle=False,worker_init_fn=seed_worker,generator=g,num_workers=4)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:15:52.260595Z","iopub.execute_input":"2024-06-04T02:15:52.260997Z","iopub.status.idle":"2024-06-04T02:15:52.267426Z","shell.execute_reply.started":"2024-06-04T02:15:52.260955Z","shell.execute_reply":"2024-06-04T02:15:52.266325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{}},{"cell_type":"code","source":"!pip install efficientnet-pytorch","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:14:38.889629Z","iopub.execute_input":"2024-06-04T02:14:38.889947Z","iopub.status.idle":"2024-06-04T02:14:54.668115Z","shell.execute_reply.started":"2024-06-04T02:14:38.889918Z","shell.execute_reply":"2024-06-04T02:14:54.667167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from efficientnet_pytorch import EfficientNet","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:14:57.286822Z","iopub.execute_input":"2024-06-04T02:14:57.287533Z","iopub.status.idle":"2024-06-04T02:14:57.298627Z","shell.execute_reply.started":"2024-06-04T02:14:57.287493Z","shell.execute_reply":"2024-06-04T02:14:57.297698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch import nn\nclass CNN_Model(nn.Module):\n    def __init__(self, class_n, rate=0.2):\n        super(CNN_Model, self).__init__()\n        self.model = EfficientNet.from_pretrained('efficientnet-b6')\n        self.dropout = nn.Dropout(rate)\n        self.output_layer = nn.Linear(in_features=1000, out_features=class_n, bias=True)\n\n    def forward(self, inputs):\n        output = self.output_layer(self.dropout(self.model(inputs)))\n        return output\nmodel=CNN_Model(class_n = 5)\n\nmodel=model.to(device)\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:16:09.563820Z","iopub.execute_input":"2024-06-04T02:16:09.564669Z","iopub.status.idle":"2024-06-04T02:16:10.271251Z","shell.execute_reply.started":"2024-06-04T02:16:09.564634Z","shell.execute_reply":"2024-06-04T02:16:10.270341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Loss","metadata":{}},{"cell_type":"code","source":"import torch.nn as nn\n\ncriterion=nn.CrossEntropyLoss()","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:16:18.050466Z","iopub.execute_input":"2024-06-04T02:16:18.051339Z","iopub.status.idle":"2024-06-04T02:16:18.055926Z","shell.execute_reply.started":"2024-06-04T02:16:18.051308Z","shell.execute_reply":"2024-06-04T02:16:18.054928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Optimizer","metadata":{}},{"cell_type":"code","source":"optimizer=torch.optim.RAdam(model.parameters(),lr=0.001,weight_decay=0.0001)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:16:21.260334Z","iopub.execute_input":"2024-06-04T02:16:21.261006Z","iopub.status.idle":"2024-06-04T02:16:21.269464Z","shell.execute_reply.started":"2024-06-04T02:16:21.260959Z","shell.execute_reply":"2024-06-04T02:16:21.268366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Scheduler","metadata":{}},{"cell_type":"code","source":"from transformers import get_cosine_schedule_with_warmup\nepochs=16\n\nscheduler=get_cosine_schedule_with_warmup(optimizer,num_warmup_steps=len(loader_train)*2,num_training_steps=len(loader_train)*epochs)","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:16:23.090451Z","iopub.execute_input":"2024-06-04T02:16:23.090834Z","iopub.status.idle":"2024-06-04T02:16:23.098292Z","shell.execute_reply.started":"2024-06-04T02:16:23.090805Z","shell.execute_reply":"2024-06-04T02:16:23.097286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\ngc.collect()\ntorch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:16:23.597799Z","iopub.execute_input":"2024-06-04T02:16:23.598637Z","iopub.status.idle":"2024-06-04T02:16:23.807074Z","shell.execute_reply.started":"2024-06-04T02:16:23.598600Z","shell.execute_reply":"2024-06-04T02:16:23.806123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train","metadata":{}},{"cell_type":"code","source":"from tqdm import tqdm\nimport torch\nimport torch.cuda.amp as amp\nimport gc\nfrom torchvision.transforms import v2\n\nscaler = amp.GradScaler()\ncutmix = v2.CutMix(num_classes=5)\n\ntrain_loss = []\nvalid_acc = []\nfor epoch in range(epochs):\n    ##Train\n    model.train()\n    epoch_train_loss=0\n    for images,labels in tqdm(loader_train):\n        if np.random.random() <= 0.5:\n            images, labels = cutmix(images, labels) ## cutmix\n        images=images.to(device)\n        labels=labels.to(device)\n        \n        optimizer.zero_grad()\n        with amp.autocast(): # amp\n            outputs=model(images)\n            loss=criterion(outputs,labels)\n            epoch_train_loss+=loss.item()\n            train_loss.append(loss.item())\n            \n        scaler.scale(loss).backward()\n        scaler.step(optimizer)\n        scaler.update()\n        \n        scheduler.step()\n    print(f'에폭 [{epoch+1}/{epochs}] - 훈련 데이터 손실값 : {epoch_train_loss/len(loader_train):.4f}')\n    torch.save(model.state_dict(), f'epoch_{epoch}.pth') #Save\n    \n    ##Valid\n    model.eval()\n    epoch_valid_loss=0\n    counts = 0 \n    with torch.no_grad():\n        for images,labels in loader_valid:\n            images=images.to(device)\n            labels=labels.to(device)\n            \n            outputs=model(images)\n            loss=criterion(outputs,labels)\n            epoch_valid_loss+=loss.item()\n            preds=torch.max(outputs.cpu(),dim=1)[1].numpy()\n            true_labels=labels.cpu().numpy()\n            count = np.sum(preds==true_labels)\n            counts += count\n    print(f'에폭 [{epoch+1}/{epochs}] - 검증 데이터 손실값 : {epoch_valid_loss/len(loader_valid):.4f} / 검증 데이터 정확도 : {counts/len(dataset_valid):.4f}')\n    valid_acc.append(counts/len(dataset_valid))","metadata":{"execution":{"iopub.status.busy":"2024-06-04T02:16:25.442191Z","iopub.execute_input":"2024-06-04T02:16:25.443125Z","iopub.status.idle":"2024-06-04T02:16:56.093931Z","shell.execute_reply.started":"2024-06-04T02:16:25.443093Z","shell.execute_reply":"2024-06-04T02:16:56.092532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Analysis","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}