{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# importing the libraries\nimport torch\nfrom torch.utils.data import Dataset, DataLoader, Subset\nimport os \nfrom pathlib import Path\nimport json\nfrom torchvision import transforms\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport torch.nn as nn \nimport torch.nn.functional as F\nimport numpy as np \nfrom tqdm import tqdm\nimport pandas as pd \nimport torchvision\nimport time\nimport wandb","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:10.275233Z","iopub.execute_input":"2022-12-17T05:29:10.276514Z","iopub.status.idle":"2022-12-17T05:29:13.292832Z","shell.execute_reply.started":"2022-12-17T05:29:10.276398Z","shell.execute_reply":"2022-12-17T05:29:13.291063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Directory Setup","metadata":{}},{"cell_type":"code","source":"# All given filess\npath = Path(\"../input/cassava-leaf-disease-classification\")\nos.listdir(path)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:13.296154Z","iopub.execute_input":"2022-12-17T05:29:13.297107Z","iopub.status.idle":"2022-12-17T05:29:13.307918Z","shell.execute_reply.started":"2022-12-17T05:29:13.297068Z","shell.execute_reply":"2022-12-17T05:29:13.306768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Labeled Class File\n\nfile = open(os.path.join(path, 'label_num_to_disease_map.json'))\nclass_map = json.load(file)\nclass_map","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:13.309775Z","iopub.execute_input":"2022-12-17T05:29:13.310396Z","iopub.status.idle":"2022-12-17T05:29:13.322698Z","shell.execute_reply.started":"2022-12-17T05:29:13.310358Z","shell.execute_reply":"2022-12-17T05:29:13.320171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# dataset\n\ndf = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:13.326799Z","iopub.execute_input":"2022-12-17T05:29:13.327149Z","iopub.status.idle":"2022-12-17T05:29:13.375875Z","shell.execute_reply.started":"2022-12-17T05:29:13.327115Z","shell.execute_reply":"2022-12-17T05:29:13.375061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Count of Each Class \n\ndf['label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:13.379424Z","iopub.execute_input":"2022-12-17T05:29:13.379998Z","iopub.status.idle":"2022-12-17T05:29:13.393512Z","shell.execute_reply.started":"2022-12-17T05:29:13.379962Z","shell.execute_reply":"2022-12-17T05:29:13.392462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Config","metadata":{}},{"cell_type":"code","source":"config = {\n    'lr': 0.01, \n    'bs': 32,\n    'device' : 'cuda' if torch.cuda.is_available() else 'cpu',\n    'epochs' : 3\n}","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:13.395033Z","iopub.execute_input":"2022-12-17T05:29:13.396059Z","iopub.status.idle":"2022-12-17T05:29:13.465892Z","shell.execute_reply.started":"2022-12-17T05:29:13.396019Z","shell.execute_reply":"2022-12-17T05:29:13.464858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Start W&B logging\n# W&B Login\nfrom kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"wandb-key\")\n\nwandb.login(key=secret_value_0)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:13.470009Z","iopub.execute_input":"2022-12-17T05:29:13.470652Z","iopub.status.idle":"2022-12-17T05:29:14.940550Z","shell.execute_reply.started":"2022-12-17T05:29:13.470602Z","shell.execute_reply":"2022-12-17T05:29:14.939551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Kfold \n\nSince dataset is imbalance therefore we will use StratifiedKFold","metadata":{}},{"cell_type":"code","source":"# K fold\n\nfrom sklearn.model_selection import StratifiedKFold\n\ndf['kfold'] = -1\n\ndf = df.sample(frac=1).reset_index(drop=True)\n\ny = df['label'].values\n\nkf = StratifiedKFold(n_splits=5)\n\nfor f, (t_, v_) in enumerate(kf.split(X = df, y = y)):\n    df.loc[v_, 'kfold'] = f\n    \ndf.to_csv('train_folds.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:14.942172Z","iopub.execute_input":"2022-12-17T05:29:14.942531Z","iopub.status.idle":"2022-12-17T05:29:15.555243Z","shell.execute_reply.started":"2022-12-17T05:29:14.942493Z","shell.execute_reply":"2022-12-17T05:29:15.554304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv('train_folds.csv')\nprint(train_df.shape)\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:15.556677Z","iopub.execute_input":"2022-12-17T05:29:15.558989Z","iopub.status.idle":"2022-12-17T05:29:15.582910Z","shell.execute_reply.started":"2022-12-17T05:29:15.558951Z","shell.execute_reply":"2022-12-17T05:29:15.581978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lets look at one fold and number of all Classes\n\ndf.loc[df.kfold==0]['label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:15.586965Z","iopub.execute_input":"2022-12-17T05:29:15.587239Z","iopub.status.idle":"2022-12-17T05:29:15.598839Z","shell.execute_reply.started":"2022-12-17T05:29:15.587213Z","shell.execute_reply":"2022-12-17T05:29:15.597794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Transform","metadata":{}},{"cell_type":"code","source":"train_tfms = transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor(),\n                           transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\nvalid_tfms = transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor(),])","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:15.601709Z","iopub.execute_input":"2022-12-17T05:29:15.601965Z","iopub.status.idle":"2022-12-17T05:29:15.616370Z","shell.execute_reply.started":"2022-12-17T05:29:15.601941Z","shell.execute_reply":"2022-12-17T05:29:15.614836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset and DataLoader","metadata":{}},{"cell_type":"code","source":"# Dataset and Dataloader\n\nclass LeafDataset(Dataset):\n    def __init__(self, df, root, transform=None):\n        self.df = df \n        self.root = root\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_name, label, _ = self.df.iloc[int(idx)]\n        img_path = os.path.join(self.root, img_name)\n        img = Image.open(img_path)\n        \n        if self.transform:\n            img = self.transform(img)\n        \n        return img, torch.tensor(label)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:15.618254Z","iopub.execute_input":"2022-12-17T05:29:15.620601Z","iopub.status.idle":"2022-12-17T05:29:15.643210Z","shell.execute_reply.started":"2022-12-17T05:29:15.620561Z","shell.execute_reply":"2022-12-17T05:29:15.634615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = os.path.join(path, \"train_images\")\n\nfold = 0\ndf_train = train_df[train_df.kfold==fold]\nvdf_valid = train_df[train_df.kfold!=fold]\n\n# dataset\ntrain_ds = LeafDataset(train_df, root=train_dir, transform=train_tfms)\ntrain_dl = DataLoader(train_ds, batch_size = config['bs'], shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:15.644500Z","iopub.execute_input":"2022-12-17T05:29:15.645144Z","iopub.status.idle":"2022-12-17T05:29:15.668964Z","shell.execute_reply.started":"2022-12-17T05:29:15.645083Z","shell.execute_reply":"2022-12-17T05:29:15.665835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize Data","metadata":{"execution":{"iopub.status.busy":"2022-07-09T05:27:10.63648Z","iopub.execute_input":"2022-07-09T05:27:10.637551Z","iopub.status.idle":"2022-07-09T05:27:10.667205Z","shell.execute_reply.started":"2022-07-09T05:27:10.637508Z","shell.execute_reply":"2022-07-09T05:27:10.666087Z"}}},{"cell_type":"code","source":"plt.figure(figsize=(20,10))\nfor i in range(8):\n    plt.subplot(2, 4, i+1)\n    img = train_ds[i][0]\n    label = train_ds[i][1]\n    plt.title(class_map[str(label.item())])\n    plt.imshow(img.permute(1,2,0))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:15.673497Z","iopub.execute_input":"2022-12-17T05:29:15.673839Z","iopub.status.idle":"2022-12-17T05:29:17.240948Z","shell.execute_reply.started":"2022-12-17T05:29:15.673806Z","shell.execute_reply":"2022-12-17T05:29:17.237301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{"execution":{"iopub.status.busy":"2022-07-09T05:39:23.830729Z","iopub.execute_input":"2022-07-09T05:39:23.831259Z","iopub.status.idle":"2022-07-09T05:39:23.838473Z","shell.execute_reply.started":"2022-07-09T05:39:23.831212Z","shell.execute_reply":"2022-07-09T05:39:23.837321Z"}}},{"cell_type":"code","source":"model = torchvision.models.resnet34(pretrained=True)\nmodel.fc = nn.Linear(512, 5)\n\nclass ResNet34(nn.Module):\n    def __init__(self, pretrained):\n        super(ResNet34, self).__init__()\n        if pretrained is True:\n            self.model = torchvision.models.resnet34(pretrained=True)\n        else:\n            self.model = torchvision.models.resnet34()\n        # change the classification layer\n        self.l0= nn.Linear(1000, 5)\n        self.dropout = nn.Dropout2d(0.4)\n        \n    def forward(self, x):\n        batch = x.shape[0]\n        x = self.model(x)\n        l0 = self.l0(x)\n        out = nn.Softmax(dim=1)(l0)\n        return out\n\nmodel = ResNet34(pretrained=True).to(config['device'])","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:17.241941Z","iopub.execute_input":"2022-12-17T05:29:17.242350Z","iopub.status.idle":"2022-12-17T05:29:23.261954Z","shell.execute_reply.started":"2022-12-17T05:29:17.242301Z","shell.execute_reply":"2022-12-17T05:29:23.260930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:23.263457Z","iopub.execute_input":"2022-12-17T05:29:23.263923Z","iopub.status.idle":"2022-12-17T05:29:23.274204Z","shell.execute_reply.started":"2022-12-17T05:29:23.263884Z","shell.execute_reply":"2022-12-17T05:29:23.273150Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on one batch","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\n\nxb, yb = next(iter(train_dl))\n\nxb = xb.to(config['device'])\nyb = yb.to(config['device'])\n\noutput = model(xb)\n\nloss_fn = nn.CrossEntropyLoss()\n\nprint('output shape', output.shape)\n\nloss = loss_fn(output, yb)\n\nprint('loss', loss.detach().cpu().numpy())\n\nprediction = torch.argmax(output, dim=1)\n\naccuracy = accuracy_score(yb.cpu().numpy(), prediction.cpu().numpy())\n\nprint('accuracy', accuracy*100)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:23.275787Z","iopub.execute_input":"2022-12-17T05:29:23.276585Z","iopub.status.idle":"2022-12-17T05:29:29.883706Z","shell.execute_reply.started":"2022-12-17T05:29:23.276544Z","shell.execute_reply":"2022-12-17T05:29:29.882694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training Function","metadata":{}},{"cell_type":"code","source":"optimizer = torch.optim.SGD(model.parameters(), lr = config['lr'])","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:29.885027Z","iopub.execute_input":"2022-12-17T05:29:29.885707Z","iopub.status.idle":"2022-12-17T05:29:29.893400Z","shell.execute_reply.started":"2022-12-17T05:29:29.885667Z","shell.execute_reply":"2022-12-17T05:29:29.891906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Validation(dl):\n    losses, accuracy = [], []\n    with torch.no_grad():\n        for data in tqdm(dl):\n            xb, yb = data[0].to(config['device']), data[1].to(config['device'])\n            output = model(xb)\n            loss = loss_fn(output, yb)\n            prediction = torch.argmax(output, dim=1)\n            acc = accuracy_score(yb.cpu().numpy(), prediction.cpu().numpy())\n            losses.append(loss.item())\n            accuracy.append(acc)\n    return sum(losses)/len(losses), sum(accuracy)/len(accuracy)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:29.894821Z","iopub.execute_input":"2022-12-17T05:29:29.895399Z","iopub.status.idle":"2022-12-17T05:29:30.051848Z","shell.execute_reply.started":"2022-12-17T05:29:29.895363Z","shell.execute_reply":"2022-12-17T05:29:30.050617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(model, train_dl,valid_dl, optimizer):\n    \n    train_acc, train_loss = [], []\n    for epoch in range(config['epochs']):\n        running_loss = 0.0\n        for i, data in enumerate(tqdm(train_dl)):\n\n            xb, yb = data[0].to(config['device']), data[1].to(config['device'])\n\n\n            optimizer.zero_grad()\n\n            output = model(xb)\n\n            loss = loss_fn(output, yb)\n            loss.backward()\n            optimizer.step()\n            \n            running_loss += loss.item()\n        val_loss, val_acc = Validation(valid_dl)\n        print('Epoch: %d, Train Loss: %0.3f, Val Loss: %0.3f, Val Acc: %0.3f'% (epoch, running_loss/len(train_dl), val_loss, val_acc))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:30.053297Z","iopub.execute_input":"2022-12-17T05:29:30.053877Z","iopub.status.idle":"2022-12-17T05:29:30.063350Z","shell.execute_reply.started":"2022-12-17T05:29:30.053836Z","shell.execute_reply":"2022-12-17T05:29:30.062255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing ","metadata":{}},{"cell_type":"code","source":"train_dir = os.path.join(path, \"train_images\")\ntrain_df = pd.read_csv('train_folds.csv')\n\nfold = 0\ndf_train = train_df[train_df.kfold!=fold]\ndf_valid = train_df[train_df.kfold==fold]\n\n# dataset\ntrain_ds = LeafDataset(df_train, root=train_dir, transform=train_tfms)\nvalid_ds = LeafDataset(df_valid, root=train_dir,  transform=valid_tfms)\n\n# Subset of Dataset\ntrain_ds = Subset(train_ds, np.arange(len(train_ds)/10))\nvalid_ds = Subset(valid_ds, np.arange(len(train_ds)/10))\n\n# dataloader\ntrain_dl = DataLoader(train_ds, batch_size = config['bs'], shuffle=True)\nvalid_dl = DataLoader(valid_ds, batch_size = config['bs'], shuffle=False)\n\n# Train \nprint('------------Fold: %d-----------------'%(fold))\ntik = time.time()\ntrain(model,train_dl,valid_dl, optimizer)\ntok = time.time()\nprint('total time taken: %0.2f' % ((tok-tik)/60))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:29:30.064847Z","iopub.execute_input":"2022-12-17T05:29:30.065395Z","iopub.status.idle":"2022-12-17T05:31:03.830116Z","shell.execute_reply.started":"2022-12-17T05:29:30.065360Z","shell.execute_reply":"2022-12-17T05:31:03.829098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# First We will Train on a Subset of Dataset","metadata":{}},{"cell_type":"code","source":"# train_dir = os.path.join(path, \"train_images\")\n# train_df = pd.read_csv('train_folds.csv')\n\n# for fold in range(5):\n\n#     df_train = train_df[train_df.kfold==fold]\n#     df_valid = train_df[train_df.kfold!=fold]\n\n#     # dataset\n#     train_ds = LeafDataset(train_df, root=train_dir, transform=tfms)\n#     valid_ds = LeafDataset(df_valid, root=train_dir,  transform=tfms)\n\n#     # Subset of Dataset\n#     train_ds = Subset(train_ds, np.arange(len(train_ds)/4))\n#     valid_ds = Subset(valid_ds, np.arange(len(train_ds)/4))\n\n#     # dataloader\n#     train_dl = DataLoader(train_ds, batch_size = bs, shuffle=True)\n#     valid_dl = DataLoader(valid_ds, batch_size = bs, shuffle=False)\n\n#     # Train \n#     print('------------Fold: %d-----------------'%(fold))\n#     train(model,train_dl,valid_dl, optimizer)","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:31:03.831458Z","iopub.execute_input":"2022-12-17T05:31:03.832424Z","iopub.status.idle":"2022-12-17T05:31:03.837674Z","shell.execute_reply.started":"2022-12-17T05:31:03.832383Z","shell.execute_reply":"2022-12-17T05:31:03.836682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Lets Train On Half of The Dataset","metadata":{}},{"cell_type":"code","source":"# train_dir = os.path.join(path, \"train_images\")\n# train_df = pd.read_csv('train_folds.csv')\n\n# for fold in range(5):\n\n#     df_train = train_df[train_df.kfold!=fold]\n#     df_valid = train_df[train_df.kfold==fold]\n    \n\n#     # dataset\n#     train_ds = LeafDataset(df_train, root=train_dir, transform=train_tfms)\n#     valid_ds = LeafDataset(df_valid, root=train_dir,  transform=valid_tfms)\n\n#     # Subset of Dataset\n#     train_ds = Subset(train_ds, np.arange(len(train_ds)/2))\n#     valid_ds = Subset(valid_ds, np.arange(len(valid_ds)/2))\n\n#     # dataloader\n#     train_dl = DataLoader(train_ds, batch_size = bs, shuffle=True)\n#     valid_dl = DataLoader(valid_ds, batch_size = bs, shuffle=False)\n#     print(len(train_dl), len(valid_dl))\n    \n#     # Train \n#     print('------------Fold: %d-----------------'%(fold))\n#     tik = time.time()\n#     train(model,train_dl,valid_dl, optimizer)\n#     tok = time.time()\n#     print('total time taken: %0.2f' % ((tok-tik)/60))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:31:03.838962Z","iopub.execute_input":"2022-12-17T05:31:03.839846Z","iopub.status.idle":"2022-12-17T05:31:03.848498Z","shell.execute_reply.started":"2022-12-17T05:31:03.839809Z","shell.execute_reply":"2022-12-17T05:31:03.847401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = os.path.join(path, \"train_images\")\ntrain_df = pd.read_csv('train_folds.csv')\n\nfor fold in range(5):\n\n    df_train = train_df[train_df.kfold!=fold]\n    df_valid = train_df[train_df.kfold==fold]\n    \n\n    # dataset\n    train_ds = LeafDataset(df_train, root=train_dir, transform=train_tfms)\n    valid_ds = LeafDataset(df_valid, root=train_dir,  transform=valid_tfms)\n    # Subset of Dataset\n    train_ds = Subset(train_ds, np.arange(len(train_ds)))\n    valid_ds = Subset(valid_ds, np.arange(len(valid_ds)))\n\n    # dataloader\n    train_dl = DataLoader(train_ds, batch_size = config['bs'], shuffle=True)\n    valid_dl = DataLoader(valid_ds, batch_size = config['bs'], shuffle=False)\n    \n    # Train \n    print('------------Fold: %d-----------------'%(fold))\n    tik = time.time()\n    train(model,train_dl,valid_dl, optimizer)\n    tok = time.time()\n    print('total time taken: %0.2f' % ((tok-tik)/60))","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:31:03.849755Z","iopub.execute_input":"2022-12-17T05:31:03.850514Z","iopub.status.idle":"2022-12-17T05:45:13.998814Z","shell.execute_reply.started":"2022-12-17T05:31:03.850477Z","shell.execute_reply":"2022-12-17T05:45:13.997019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# saving the model \ntorch.save(model.state_dict(), 'model.pkl')","metadata":{"execution":{"iopub.status.busy":"2022-12-17T05:45:14.000234Z","iopub.status.idle":"2022-12-17T05:45:14.000735Z","shell.execute_reply.started":"2022-12-17T05:45:14.000467Z","shell.execute_reply":"2022-12-17T05:45:14.000490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To improve this model, we have to experiment with different parameters, and we will use wandb to track all the expeeriment, in the next version.\n\nWe will make a submission from this model","metadata":{}}]}