{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"%config Completer.use_jedi = False\n# !pip install timm\n!pip install torchsummary\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport cv2\nfrom matplotlib.image import imread\nimport matplotlib.pyplot as plt\nimport torch\nfrom torch import nn\nfrom torch.utils.data import Dataset,DataLoader\nimport torchvision.transforms as transforms\nfrom torchsummary import summary\n# import timm\nfrom tqdm import tqdm\nimport os, sys, gc\nimport time\n\n############\ndata_path = '../input/cassava-leaf-disease-classification/train_images/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Check GPU is available or not\nis_cuda = torch.cuda.is_available()\nif is_cuda:\n    device = torch.device(\"cuda\")\n    print(\"GPU is available\")\nelse:\n    device = torch.device(\"cpu\")\n    print(\"GPU not available, CPU used\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"total_csv = pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ntotal_csv.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.read_csv('../input/cassava-leaf-disease-classification/sample_submission.csv')\nsubmission.head()","execution_count":null,"outputs":[]},{"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\nimg = get_img('../input/cassava-leaf-disease-classification/train_images/1000015157.jpg')\nplt.imshow(img)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_dataset(path, df):\n    \"\"\"path:`../---/--/`\"\"\"\n    img_array = []\n    for img_name in tqdm(df['image_id']):\n        full_path = path + img_name\n        img = get_img(full_path).copy()\n        img = torch.tensor(img).permute(2,0,1)  # convert to torch format color\n        img_array.append(img)\n    img_array = torch.stack(img_array)\n    return img_array\n\nimm = cv2.imread('../input/cassava-leaf-disease-classification/train_images/1000015157.jpg')\nprint(imm.shape)\n# data_raw = read_dataset(data_path, train_csv)\n# print(data_raw.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class HDD_Dataset(Dataset):\n    def __init__(self, df, data_root, device, transforms=None):\n        super().__init__()\n        self.df = df.reset_index(drop=True).copy()\n        self.transforms = transforms\n        self.data_root = data_root\n        self.device = device\n    \n    def __len__(self):\n        return self.df.shape[0]\n    \n    def __getitem__(self, index: int):\n        target = torch.tensor(self.df.iloc[index]['label'], device=device)\n        path = \"{}/{}\".format(self.data_root, self.df.iloc[index]['image_id'])\n        img = torch.tensor(get_img(path).copy()).float().to(device)/255  # normalize to 1\n        img = img.permute(2,0,1)\n        if self.transforms:\n            img = self.transforms(img)\n        return {'image':img, 'label':target}\n\n\nclass RAM_Dataset(Dataset):\n    def __init__(self, df, imgs, device, transforms=None):\n        super().__init__()\n        self.df = df.reset_index(drop=True).copy()\n        self.transforms = transforms\n        self.imgs = imgs\n        self.device = device\n    \n    def __len__(self):\n        return self.df.shape[0]\n    \n    def __getitem__(self, index: int):\n        target = self.df.iloc[index]['label']\n        img  = self.imgs[index].float().to(device)/255  # normalize to 1\n        if self.transforms:\n            img = self.transforms(img)\n        return {'image':img, 'label':target}","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## split data to train, val section"},{"metadata":{"trusted":true},"cell_type":"code","source":"def frac_train_val(N:int, val_frac:float):\n    \"\"\"N: dataset length e.g. 2100\n        val_frac: validation fraction of total e.g. 0.2 \n        return indices of train, validation\"\"\"\n    perm = np.random.permutation(N)\n    thrshld = int(N*val_frac)\n    return perm[thrshld:].tolist(), perm[:thrshld].tolist()\n\n\ntransform_train = transforms.Compose([\n    transforms.RandomResizedCrop(500),\n    transforms.ColorJitter(hue=.07, saturation=.08),\n    transforms.RandomAffine(25, (0.1, 0.1), (0.9, 1.1)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.RandomCrop(400)])\n\ntransform_val = transforms.Compose([transforms.RandomResizedCrop(400)])  # ??\n########### split indices\ninds_train, inds_val = frac_train_val(total_csv.shape[0], 0.2)\n# val_imgs = read_dataset(data_path, train_csv.loc[inds_val])  # store in `int` to reduce memory usage\ntrain_csv = total_csv.loc[inds_train]\nval_csv = total_csv.loc[inds_val]\n#create datasets\ntrain_dataset = HDD_Dataset(train_csv, data_path, device, transform_train)\n\nval_dataset = HDD_Dataset(val_csv, data_path, device, transform_val)\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class print_layer(nn.Module):\n    def __init__(self):\n        super(print_layer, self).__init__()\n    def forward(self, x):\n        print(x.shape)\n        return x\n\n\nclass miniResNet(nn.Module):\n    def __init__(self, C_in, C_mid):\n        super(miniResNet, self).__init__()\n        self.model = nn.Sequential(\n            nn.Conv2d(C_in, C_mid, kernel_size=1), nn.ReLU(),\n            nn.Conv2d(C_mid, C_mid, kernel_size=3, stride=1, padding=1), nn.ReLU(),\n            nn.Conv2d(C_mid, C_in, kernel_size=1), nn.ReLU()\n        )\n    \n    def forward(self, x):\n        return self.model(x) + x\n\n\nclass myClassifier(nn.Module):\n    def __init__(self,):\n        super(myClassifier, self).__init__()\n        self.seq = nn.Sequential(\n        nn.Conv2d(3, 32, kernel_size=5, stride=2, padding=2), nn.ReLU(),  #200\n        nn.Conv2d(32, 64, kernel_size=5, stride=1, padding=2), nn.ReLU(),\n        nn.Dropout2d(0.8),\n        nn.Conv2d(64, 64, kernel_size=5, stride=1, padding=2), nn.ReLU(),\n        nn.MaxPool2d(2, 2),  # 100\n        nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),\n        nn.BatchNorm2d(128), nn.ReLU(),\n        nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1), nn.ReLU(),\n        nn.Dropout2d(),\n        nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1), nn.ReLU(),\n        nn.MaxPool2d(2, 2), # 50\n        miniResNet(128, 50),miniResNet(128, 50),miniResNet(128, 50),miniResNet(128, 50),\n        miniResNet(128, 50),miniResNet(128, 50),# print_layer(),\n        nn.AvgPool2d(50),# print_layer()\n        )\n        self.Lin = nn.Sequential(\n        nn.Linear(128, 30), nn.ReLU(),\n        nn.Linear(30, 5), nn.ReLU()#, print_layer()\n        )\n        \n    def forward(self, x):\n        N = x.shape[0]\n        x_conv = self.seq(x).reshape(N, 128)\n        x_lin = self.Lin(x_conv)\n        return x_lin","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x = torch.randn(2, 3,400,400)\nm = myClassifier()\ny = m(x)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## prequisites of optimizing"},{"metadata":{"trusted":true},"cell_type":"code","source":"@torch.no_grad()\ndef Evaluation(model, test_dataset, path, batch_size, device, criterion):\n    model.eval()\n    test_dataloader = DataLoader(test_dataset, batch_size, shuffle=False)\n    acc = 0\n    loss = 0  # torch.tensor(0)\n    for data_batch in tqdm(test_dataloader):\n        score_pred = model(data_batch['image'])\n        y_pred = torch.max(score_pred, dim=1)[1]\n        acc = acc + torch.sum(y_pred == data_batch['label'])\n        loss += criterion(score_pred, data_batch['label']).data\n    acc = acc / (len(test_dataloader)*batch_size)\n    loss = loss / len(test_dataloader)\n    model.train()\n    return acc, loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"# Create model instance\nmodel = myClassifier()\nmodel = model.to(device, non_blocking=True)  # to GPU or CPU\nsummary(model, input_size=(3,400,400))\n# Define hyperparameters\nlr = torch.tensor(0.0001).to(device)\nlr_decay = torch.tensor(0.95).to(device)  # per epoch\nlr_floor = torch.tensor(0.00001).to(device)\n# Define Loss, Optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=lr)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Hyper parameters\nbatch_size = 64\nn_epochs = 5\n# dataloader\ntrain_dataloader = DataLoader(train_dataset,batch_size=batch_size, shuffle=True)\ntot_batch = len(train_dataloader)\n# loss\ntrain_loss, train_acc = [], []\nval_loss, val_acc = [], []\n# Training RNN\nfor epoch in range(1, n_epochs + 1):\n    epoch_start = time.time()\n    for num_batch, data_batch in enumerate(train_dataloader):\n        batch_start = time.time()\n        \n        optimizer.zero_grad()\n        output = model(data_batch['image'])\n        loss = criterion(output, data_batch['label'])\n        loss.backward()\n        optimizer.step()\n        acc = torch.sum(torch.max(output, dim=1)[1] == data_batch['label']) / batch_size\n        \n        batch_stop = time.time()\n        print(f\"*****Epoch {epoch}, minibatch: {num_batch+1}/{tot_batch} elapsed {batch_stop-batch_start:0.1f}s, loss:{loss:0.4f}*****\")  # write in replace\n    train_loss.append(loss)\n    train_acc.append(acc)\n    tmp_acc, tmp_loss = Evaluation(model, val_dataset, data_path, batch_size, device, criterion)\n    val_loss.append(tmp_loss)\n    val_acc.append(tmp_acc)\n    epoch_stop = time.time()\n    print(f\"Epoch {epoch}/{n_epochs} has finished in {epoch_stop-epoch_start:0.1f}s, train loss: {loss:0.4f}, train acc: {acc*100:0.2f}, val loss: {tmp_loss:0.4f},  val acc:{tmp_acc*100:0.2f}\")\n    lr *= lr_decay\n    if lr < lr_floor:\n        lr = lr_floor\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.save(model.state_dict(),'./model_1.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.save(model,'./model_t_1.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1,2)\n####\nax[0].plot(range(1,len(train_loss)+1), train_loss)\nax[0].plot(range(1,len(val_loss)+1), val_loss)\nax[0].set(xlabel='epoch')\nax[0].set_title('loss')\nax[0].legend(('train','val'))\n\nax[1].plot(range(1,len(train_loss)+1), train_acc)\nax[1].plot(range(1,len(val_loss)+1), val_acc)\nax[1].set(xlabel='epoch')\nax[1].set_title('accuracy')\nax[1].legend(('train','val'))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}