{"cells":[{"metadata":{},"cell_type":"markdown","source":"I referred part of the codes & structures from [pytorch-efficientnet-baseline-train-amp-aug]\n\nThis notebook is mainly written for my personal practice.\n\n\n\nIf you have any ideas or questions for this notebook, please feel free to leave a comment :)"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\n\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom matplotlib.pyplot import imread\nimport numpy as np\nimport cv2\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score\nfrom tqdm import tqdm\n\nimport torch\nfrom torch import from_numpy\nimport torch.nn as nn\nimport torchvision\nfrom torchvision import models as tvmodels\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, utils\nfrom torchvision.models import resnet\nimport torch.nn.functional as F\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nfrom torch.cuda.amp import autocast, GradScaler","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#path naming\ndata_path = \"../input/cassava-leaf-disease-classification/\"\ntrain_csv_data_path = data_path+\"train.csv\"\nlabel_json_data_path = data_path+\"label_num_to_disease_map.json\"\ntrain_img_path = data_path+\"train_images/\"\ntest_img_path = data_path+\"test_images/\"\n\ntrain_csv = pd.read_csv(train_csv_data_path)\ntrain_csv['label'] = train_csv['label'].astype('string')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Parameter Setting"},{"metadata":{"trusted":true},"cell_type":"code","source":"num_class=5\n\nlearning_rate = 0.0005\ntraining_epochs = 30\nbt_size = 20\nnum_fold=2\nnum_wk=4\nused_epochs=[5,7,9]\n\n#imagenet mean & std\nimg_mean = [0.485, 0.456, 0.406]\nimg_std = [0.229, 0.224, 0.225]\n\nimg_size = 224 #to use resnet50\n\ndev = 'cuda:0'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Loading & Transforming"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_img(path):\n    im_bgr = cv2.imread(path)\n    im_rgb = im_bgr[:, :, ::-1]\n    #print(im_rgb)\n    return im_rgb\n\ntrain = train_csv","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class GetData(Dataset):\n    def __init__(self, df, dirr, label_out=True, transform=None):\n        super().__init__()\n        self.dirr = dirr\n        self.label_out = label_out\n        self.transform = transform\n        self.df = df.reset_index(drop=True).copy()\n        if self.label_out == True:\n            self.labels = self.df['label'].values\n    \n    def __len__(self):\n        return self.df.shape[0]\n    \n    def __getitem__(self, index:int):\n        img = get_img(\"{}/{}\".format(self.dirr, self.df.loc[index]['image_id']))\n        if self.label_out == True:\n            target = float(self.labels[index])\n        \n        img = self.transform(image=img)['image']\n            \n        if self.label_out:    \n            return img, target\n        if not self.label_out:\n            return img\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_trans = A.Compose([\n    A.RandomResizedCrop(img_size, img_size),\n    A.Transpose(p=0.5),\n    A.HorizontalFlip(p=0.5),\n    A.VerticalFlip(p=0.5),\n    A.ShiftScaleRotate(p=0.5),\n    A.Normalize(img_mean, img_std),\n    ToTensorV2(),\n])\n\nval_trans = A.Compose([\n    A.CenterCrop(img_size, img_size),\n    A.Normalize(img_mean, img_std),\n    ToTensorV2(),\n])\n\ntest_trans = A.Compose([\n    A.CenterCrop(img_size, img_size),\n    A.Normalize(img_mean, img_std),\n    ToTensorV2(),\n])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def split_load_data(df, train_idx, val_idx, data_root=train_img_path):\n    \n    \n    train_ = df.loc[train_idx,:].reset_index(drop=True)\n    valid_ = df.loc[val_idx,:].reset_index(drop=True)\n        \n    train_ds = GetData(train_, data_root, label_out = True, transform = train_trans)\n    valid_ds = GetData(valid_, data_root, label_out = True, transform = val_trans)\n    \n    train_dl = DataLoader(\n        train_ds,\n        batch_size=bt_size,\n        shuffle=True,        \n        num_workers=num_wk,\n    )\n    val_dl = DataLoader(\n        valid_ds, \n        batch_size=bt_size,\n        num_workers=num_wk,\n        shuffle=False\n    )\n    return train_dl, val_dl","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# NN Model Setting"},{"metadata":{"trusted":true},"cell_type":"code","source":"def val_one_epoch(epoch, model, loss, data_loader, device):\n    model.eval()\n    \n    preds_all = []\n    targets_all = []\n    loss_sum = 0\n    sample_num = 0\n    \n    pbar = tqdm(enumerate(data_loader), total=len(data_loader))\n    for step, (imgs, targets) in pbar:\n        imgs = imgs.to(device).float()\n        targets = targets.to(device).long()\n        \n        preds = model(imgs)\n        preds_all += [torch.argmax(preds, 1).detach().cpu().numpy()]\n        targets_all += [targets.detach().cpu().numpy()]\n        \n        cost = loss(preds, targets)\n        \n        loss_sum += cost.item()*targets.shape[0]\n        sample_num += targets.shape[0]\n    \n    preds_all = np.concatenate(preds_all)\n    targets_all = np.concatenate(targets_all)\n    print('accuracy = {:.4f}'.format((preds_all==targets_all).mean()))\n    \n    return (preds_all==targets_all).mean()\n\n\ndef train_one_epoch(model, loss, optim, data_loader, device):\n    model.train()\n    scaler = GradScaler()\n    \n    pbar = tqdm(enumerate(data_loader), total=len(data_loader))\n    for step, (imgs, targets) in pbar:\n        imgs = imgs.to(device).float()\n        targets = targets.to(device).long()\n        optim.zero_grad()\n        \n        with autocast():\n            preds = model(imgs)\n            cost = loss(preds, targets)\n        \n        scaler.scale(cost).backward()\n        scaler.step(optim)\n        scaler.update()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":false,"_kg_hide-output":true},"cell_type":"code","source":"def he_init(m):\n    if type(m) == nn.Linear:\n        nn.init.kaiming_uniform_(m.weight, mode='fan_in', nonlinearity='relu')\n        m.bias.data.fill_(0.01)\n\ncassava_resnet50 = nn.Sequential(\n    resnet.resnet50(pretrained = False),\n    nn.Linear(1000, num_class)\n)\ncassava_resnet50.apply(he_init)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training"},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(dev)\n\nmodel = cassava_resnet50.to(device)\nloss = nn.CrossEntropyLoss().to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n\nacc_cnt = []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"folds = StratifiedKFold(n_splits = num_fold).split(np.arange(train.shape[0]), train.label.values)\n\nfor fld, (train_idx, val_idx) in enumerate(folds):\n    print(len(train_idx), len(val_idx))\n    print('Train fold {} started'.format(fld+1))\n    \n    train_dl, val_dl = split_load_data(train, train_idx, val_idx, data_root=train_img_path)\n    \n    #starting training\n   \n    for epochs in range(training_epochs):\n        train_one_epoch(model, loss, optimizer, train_dl, device)\n    \n        with torch.no_grad():\n            acc = val_one_epoch(epochs+1, model, loss, val_dl, device)\n        acc_cnt.append(acc)\n        torch.save(model.state_dict(),'cassnet_{}'.format(training_epochs*fld + epochs))\n    \n    print('Train finished')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Prediction"},{"metadata":{"trusted":true},"cell_type":"code","source":"#Test Dataset & DataLoader\ntest = pd.DataFrame()\ntest['image_id'] = list(os.listdir(test_img_path))\n\ntest_ds = GetData(test, test_img_path, label_out = False, transform = test_trans)\ntest_dl = DataLoader(dataset = test_ds, batch_size = bt_size, num_workers = num_wk, shuffle = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"acc_cnt = np.array(acc_cnt)\nacc_idx = np.argsort(acc_cnt)\nacc_idx = acc_idx[::-1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"use_num = [acc_idx[0], acc_idx[1], acc_idx[2]]\ndevice = torch.device(dev)\n\nmodel = cassava_resnet50.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def infer_one_epoch(model, data_loader, device):\n    model.eval()\n\n    preds_all = []\n    \n    pbar = tqdm(enumerate(data_loader), total=len(data_loader))\n    for step, (imgs) in pbar:\n        imgs = imgs.to(device).float()\n        \n        preds = model(imgs)\n        preds_all += [torch.softmax(preds, 1).detach().cpu().numpy()]\n        \n    \n    preds_all = np.concatenate(preds_all, axis=0)\n    return preds_all","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(use_num)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_preds = []\n\nfor i in range(3):    \n    model.load_state_dict(torch.load('./cassnet_{}'.format(acc_idx[i])))\n    with torch.no_grad():\n        test_preds += [infer_one_epoch(model, test_dl, device)]   \ntest_preds = np.mean(test_preds, axis=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test['label'] = np.argmax(test_preds, axis=1)\n\ntest.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}