{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import random\nimport os\nimport pandas as pd\nimport numpy as np\nimport torch\nimport cv2\nfrom torch.utils.data import Dataset,DataLoader\nfrom torch.utils.data.sampler import SequentialSampler, RandomSampler\nfrom torch.cuda.amp import autocast, GradScaler\nfrom torch.nn.modules.loss import _WeightedLoss\nimport torch.nn.functional as F\nfrom torch import nn\nimport torchvision.models as models\n\n\nfrom sklearn.model_selection import GroupKFold, StratifiedKFold\n\nfrom albumentations import (\n    HorizontalFlip, VerticalFlip, IAAPerspective, ShiftScaleRotate, CLAHE, RandomRotate90,\n    Transpose, ShiftScaleRotate, Blur, OpticalDistortion, GridDistortion, HueSaturationValue,\n    IAAAdditiveGaussianNoise, GaussNoise, MotionBlur, MedianBlur, IAAPiecewiseAffine, RandomResizedCrop,\n    IAASharpen, IAAEmboss, RandomBrightnessContrast, Flip, OneOf, Compose, Normalize, Cutout, CoarseDropout, ShiftScaleRotate, CenterCrop, Resize\n)\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations import ImageOnlyTransform\nfrom tqdm import tqdm\nimport time\nfrom sklearn.metrics import log_loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_PATH = '../input/cassava-leaf-disease-classification/train_images'\nTEST_PATH = '../input/cassava-leaf-disease-classification/test_images'\n\n\n\ntrain = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ntrain.head()\n\nCFG = {\n    'fold_num': 5,\n    'seed': 719,\n    'model_arch': 'tf_efficientnet_b4_ns',\n    'img_size': 128,\n    'epochs': 1,\n    'train_bs': 16,\n    'valid_bs': 32,\n    'size': 256,\n    'T_0': 10,\n    'lr': 1e-4,\n    'min_lr': 1e-6,\n    'weight_decay':1e-6,\n    'num_workers': 4,\n    'accum_iter': 2,\n    'verbose_step': 1,\n    'device': 'cuda:0'\n}\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"def seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n    \n\n    \ndef get_transforms(*, data):\n    \n    if data == 'train':\n        return Compose([\n            #Resize(CFG.size, CFG.size),\n            RandomResizedCrop(CFG['size'], CFG['size']),\n            Transpose(p=0.5),\n            HorizontalFlip(p=0.5),\n            VerticalFlip(p=0.5),\n            ShiftScaleRotate(p=0.5),\n            Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225],\n            ),\n            ToTensorV2(),\n            ])\n\n    elif data == 'valid':\n        return Compose([\n            Resize(CFG['size'], CFG['size']),\n            Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225],\n            ),\n            ToTensorV2(),\n        ])\n\n\n\n    \n    \nclass TrainDataset(Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.file_names = df['image_id'].values\n        self.labels = df['label'].values\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        file_name = self.file_names[idx]\n        file_path = f'{TRAIN_PATH}/{file_name}'\n        image = cv2.imread(file_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        if self.transform:\n            augmented = self.transform(image=image)\n            image = augmented['image']\n        label = torch.tensor(self.labels[idx]).long()\n        return image, label\n    \n\nclass TestDataset(Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.file_names = df['image_id'].values\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        file_name = self.file_names[idx]\n        file_path = f'{TEST_PATH}/{file_name}'\n        image = cv2.imread(file_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        if self.transform:\n            augmented = self.transform(image=image)\n            image = augmented['image']\n        return image\n\n\ndef prepare_dataloader(df, trn_idx, val_idx, data_root):\n    train_ = df.loc[trn_idx,:].reset_index(drop=True)\n    valid_ = df.loc[val_idx,:].reset_index(drop=True)\n        \n    train_ds = TrainDataset(train_, transform=get_transforms(data='train'))\n    valid_ds = TrainDataset(valid_, transform=get_transforms(data='valid'))\n    \n    train_loader = torch.utils.data.DataLoader(\n        train_ds,\n        batch_size=CFG['train_bs'],\n        pin_memory=False,\n        drop_last=False,\n        shuffle=True,        \n        num_workers=CFG['num_workers'],\n    )\n    val_loader = torch.utils.data.DataLoader(\n        valid_ds, \n        batch_size=CFG['valid_bs'],\n        num_workers=CFG['num_workers'],\n        shuffle=False,\n        pin_memory=False,\n    )\n    return train_loader, val_loader\n\n\nclass CassvaImgClassifier(nn.Module):\n    def __init__(self, n_class, pretrained=False):\n        super().__init__()\n        self.model = models.resnext50_32x4d(pretrained=pretrained)\n        n_features = self.model.fc.in_features\n        self.model.fc = nn.Identity()\n        self.pooling = nn.AdaptiveAvgPool2d(1)\n        self.model.classifier = nn.Linear(n_features, n_class)\n        \n    def forward(self, x):\n        x = self.model(x)\n        return x\n\n\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_one_epoch(epoch, model, optimizer,criterion, train_loader, device, train_data):\n    print('Training')\n    model.train()\n    train_running_loss = 0.0\n    train_running_correct = 0\n    for i, data in tqdm(enumerate(train_loader), total=int(len(train_data)/train_loader.batch_size)):\n        data, target = data[0].to(device), data[1].to(device)\n        optimizer.zero_grad()\n        outputs = model(data)\n        loss = criterion(outputs, target)\n        train_running_loss += loss.item()\n        _, preds = torch.max(outputs.data, 1)\n        train_running_correct += (preds == target).sum().item()\n        loss.backward()\n        optimizer.step()\n        \n    train_loss = train_running_loss/len(train_loader.dataset)\n    train_accuracy = 100. * train_running_correct/len(train_loader.dataset)    \n    return train_loss, train_accuracy\n\n        \ndef valid_one_epoch(epoch, model, criterion, val_loader, device, val_data):\n    t = time.time()\n    print('Validating')\n    model.eval()\n    val_running_loss = 0.0\n    val_running_correct = 0\n    with torch.no_grad():\n        for i, data in tqdm(enumerate(val_loader), total=int(len(val_data)/val_loader.batch_size)):\n            data, target = data[0].to(device).float(), data[1].to(device).long()\n            outputs = model(data)\n            loss = criterion(outputs, target)\n            \n            val_running_loss += loss.item()\n            _, preds = torch.max(outputs.data, 1)\n            val_running_correct += (preds == target).sum().item()\n        \n        val_loss = val_running_loss/len(val_loader.dataset)\n        val_accuracy = 100. * val_running_correct/len(val_loader.dataset)        \n        return val_loss, val_accuracy\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if __name__ == '__main__':\n        \n    seed_everything(CFG['seed'])\n    \n    folds = StratifiedKFold(n_splits=CFG['fold_num'], shuffle=True, random_state=CFG['seed']).split(np.arange(train.shape[0]), train.label.values)\n    \n    validation_auc = 0\n    \n    for fold, (trn_idx, val_idx) in enumerate(folds):\n        if fold>0:\n            break\n        print('Training with {} started'.format(fold))\n\n        print(len(trn_idx), len(val_idx))\n        train_loader, val_loader = prepare_dataloader(train, trn_idx, val_idx, data_root=TRAIN_PATH)\n        device = torch.device(CFG['device'])\n        model = CassvaImgClassifier(train.label.nunique(), pretrained=False).to(device)\n        scaler = GradScaler()   \n        optimizer = torch.optim.Adam(model.parameters(), lr=CFG['lr'], weight_decay=CFG['weight_decay'])\n        #scheduler = torch.optim.lr_scheduler.StepLR(optimizer, gamma=0.1, step_size=CFG['epochs']-1)\n        scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0=CFG['T_0'], T_mult=1, eta_min=CFG['min_lr'], last_epoch=-1)\n        #scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer=optimizer, pct_start=0.1, div_factor=25, \n        #                                                max_lr=CFG['lr'], epochs=CFG['epochs'], steps_per_epoch=len(train_loader))\n        \n        criterion = torch.nn.CrossEntropyLoss()#MyCrossEntropyLoss().to(device)\n        \n        for epoch in range(CFG['epochs']):\n            \n            train_loss , train_auc = train_one_epoch(epoch, model, optimizer, criterion, train_loader, device,trn_idx)\n            \n            val_loss, val_auc = valid_one_epoch(epoch, model, criterion, val_loader, device, val_idx)\n            print(f\"=========Epoch: {epoch}/{CFG['epochs']}============\")\n            print(f\"Train Loss: {train_loss:.4f}, Train Acc: {train_auc:.2f}\")\n            print(f'Val Loss: {val_loss:.4f}, Val Acc: {val_auc:.2f}')\n            if val_auc>validation_auc:\n                print(\"saving the best model\")\n                torch.save(model.state_dict(),'{}_test'.format(CFG['model_arch']))\n                validation_auc = val_auc\n            ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nfolds = StratifiedKFold(n_splits=CFG['fold_num'], shuffle=True, random_state=CFG['seed']).split(np.arange(train.shape[0]), train.label.values)\n    \nvalidation_loss = 99999\n\nfor fold, (trn_idx, val_idx) in enumerate(folds):\n    if fold>0:\n        break\n    print('Training with {} started'.format(fold))\n\n    print(len(trn_idx), len(val_idx))\n    train_loader, val_loader = prepare_dataloader(train, trn_idx, val_idx, data_root=TRAIN_PATH)\n\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n#loading Test Data\ntest = pd.DataFrame()\ntest['image_id'] = list(os.listdir('../input/cassava-leaf-disease-classification/test_images'))\ntest_ds = TestDataset(test, transform=get_transforms(data='valid'))\n\n#loading the model\n\nmodel = CassvaImgClassifier(train.label.nunique(), pretrained=False)\nmodel.load_state_dict(torch.load('../input/pre-trained-model/tf_efficientnet_b4_ns_test'))\nif torch.cuda.is_available():\n    model.cuda()\n\n\ntst_loader = torch.utils.data.DataLoader(\n    test_ds,\n    num_workers=CFG['num_workers'],\n    shuffle=False,\n    pin_memory=True,\n)\n\nmodel.eval()\ntk0 = tqdm(enumerate(tst_loader), total=len(tst_loader))\npred_label = [] \nfor i, (image) in tk0:\n    imgs = image.to(device)\n    image_preds = model(imgs) \n    ps = torch.exp(image_preds)\n    probab = list(ps.cpu()[0])\n    pred_label.append(probab.index(max(probab)))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test['label'] = pred_label\n\ntest[['image_id', 'label']].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}