{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport pickle\nimport pandas as pd \nimport numpy as np\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.metrics import accuracy_score, f1_score\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as T\nfrom torchvision import models","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(18, 10))\ndf.breed.value_counts().plot(kind ='bar');\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.drop_duplicates(inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mapping_label = {}\ninv_mapping_label = {}\ni = 0\nfor breed in df.breed.unique():\n    mapping_label[breed] = i\n    inv_mapping_label[i] = breed\n    i += 1\n\nprint(mapping_label)\nprint(inv_mapping_label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['breed'] = df.breed.map(mapping_label)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train, df_val = train_test_split(df, test_size=0.1, shuffle=True, random_state = 42)\nprint('Train data shape ', df_train.shape)\nprint('Validation data shape ', df_val.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DogIdentificationDataset(Dataset):\n    def __init__(self, df, root, transform=None):\n        self.root = root\n        self.transform = transform\n        self.ids = df.id.values\n        self.breed = df.breed.values\n        \n    def __len__(self):\n        return len(self.ids)\n    \n    def __getitem__(self, index):\n        ids = self.ids[index]\n        target = self.breed[index]\n        \n        imagePath = os.path.join(self.root, ids + '.jpg')\n        image = Image.open(imagePath).convert('RGB')\n        \n        if self.transform is not None:\n            image = self.transform(image)\n        \n        target = torch.tensor(target, dtype=torch.long)\n        \n        return image, target\n        \n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def MetricScore(y_true, out):\n    prob = F.softmax(out, dim=1)\n    pred = torch.argmax(prob, dim=1)\n    pred = pred.detach().cpu().numpy()\n    y_true = y_true.detach().cpu().numpy()\n    score = accuracy_score(y_true, pred)\n    return score","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Net(nn.Module):\n    def __init__(self, n_classes, pretrained = True, model ='resnext'):\n        super(Net, self).__init__()\n        if model == 'resnext':\n            self.net = models.resnext50_32x4d(pretrained=pretrained)\n            self.net.fc = nn.Linear(2048, n_classes)\n        elif model == 'vgg19':\n            self.net = models.vgg19(pretrained=pretrained)\n            self.net.classifier[6] = nn.Linear(4096, n_classes)\n    \n    def forward(self, x):\n        x = self.net(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"root = '/kaggle/input/dog-breed-identification/train'\n\ntrainTransform = T.Compose([\n    T.Resize((256, 256)),\n    T.RandomCrop((224, 224)),\n    T.RandomHorizontalFlip(),\n    T.RandomVerticalFlip(),\n    T.RandomPerspective(),\n    T.ToTensor(),\n    T.Normalize(\n        (0.4766, 0.4524, 0.3928),\n        (0.2272, 0.2225, 0.2208))\n])\n\nvalTransform = T.Compose([\n    T.Resize((224, 224)),\n    T.ToTensor(),\n    T.Normalize(\n        (0.4766, 0.4524, 0.3928),\n        (0.2272, 0.2225, 0.2208))\n])\n\ntrainDataset = DogIdentificationDataset(df_train, root, transform=trainTransform)\nvalDataset = DogIdentificationDataset(df_val, root, transform=valTransform)\ntrainLoader = DataLoader(trainDataset, batch_size=64, shuffle=True, num_workers=0)\nvalLoader = DataLoader(valDataset, batch_size=16, shuffle=False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n_classes = df.breed.nunique()\nDEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = Net(n_classes, pretrained=True).to(DEVICE)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"optimizer = optim.SGD(model.parameters(), lr=1e-3)\ncriterion = nn.CrossEntropyLoss()\nnum_epochs = 100\n\nmin_val_loss = np.inf\nmax_val_score = 0\n\nearly_stop = False\nn_epochs_stop = 5\nepochs_no_improve = 0\nlast_epoch = 0\n\ntrain_scores = []\nval_scores = []\n\ntrain_losses = []\nval_losses = []\n\nif os.path.exists('./checkpoint.pth'):\n    print('Load checkpoint')\n    checkpoint = torch.load('./checkpoint.pth')\n    model.load_state_dict(checkpoint['state_dict'])\n    optimizer.load_state_dict(checkpoint['optimizer'])\n    min_val_loss = checkpoint['min_val_loss']\n    max_val_score = checkpoint['max_val_score']\n    last_epoch = checkpoint['epoch']\n\n\nlr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=40, gamma=0.1)\n\nfor epoch in range(last_epoch,num_epochs):\n        \n    train_loss = 0\n    val_loss = 0\n    \n    train_score = 0\n    val_score = 0\n    \n    model.train()\n    pbar = tqdm(trainLoader, total = len(trainLoader))\n    for image, target in pbar:\n        image = image.to(DEVICE)\n        target = target.to(DEVICE)\n        \n        out = model(image)\n        loss = criterion(out, target)\n        \n        loss.backward()\n        optimizer.step()\n        optimizer.zero_grad()\n        \n        score = MetricScore(target, out)\n        \n        train_loss += loss.item()*image.size(0)        \n        train_score += score * image.size(0)\n        \n        pbar.set_postfix({'Train Loss': loss.item(),\n                         'Train Score': score})\n    with torch.no_grad():\n        model.eval()\n        pbar = tqdm(valLoader, total=len(valLoader))\n        for image, target in pbar:\n            image = image.to(DEVICE)\n            target = target.to(DEVICE)\n            \n            out = model(image)\n            loss = criterion(out, target)\n            \n            score = MetricScore(target, out)\n            \n            val_loss += loss.item()*image.size(0)\n            val_score += score*image.size(0)\n            \n            pbar.set_postfix({'Val Loss': loss.item(),\n                             'Val Score': score})\n            \n    lr_scheduler.step()\n    \n    train_loss = train_loss/len(trainLoader.dataset)\n    val_loss = val_loss/len(valLoader.dataset)\n    \n    train_score = train_score/len(trainLoader.dataset)\n    val_score = val_score/len(valLoader.dataset)\n    \n    train_losses.append(train_loss)\n    val_losses.append(val_loss)\n    \n    train_scores.append(train_score)\n    val_scores.append(val_score)\n    \n    print(f'Epoch [{epoch+1}/{num_epochs}] -- Train Loss: {train_loss:.3f} Val Loss: {val_loss:.3f} || Train Score: {train_score*100:.2f}  Val Score: {val_score*100:.2f}')\n    \n    if min_val_loss > val_loss and max_val_score < val_score:\n        min_val_loss = val_loss\n        max_val_score = val_score\n        checkpoint = {'state_dict': model.state_dict(),\n                     'optimizer': optimizer.state_dict(),\n                     'min_val_loss': min_val_loss,\n                     'max_val_score': max_val_score,\n                     'epoch': epoch,\n                     'n_classes': n_classes,\n                     'mapping_label': mapping_label,\n                     'inv_mapping_label':inv_mapping_label}\n        \n        epochs_no_improve = 0\n        torch.save(checkpoint, './checkpoint.pth')\n        \n    else:\n        epochs_no_improve += 1\n        \n    if epoch > 5 and epochs_no_improve == n_epochs_stop:\n        print('Early Stop !!!')\n        print('Stopped')\n        break\n    else:\n        continue\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nfig, ax = plt.subplots(1, 2, figsize=(16, 7))\nfig.suptitle('Training Plot Dog Identification', fontsize=18)\n\nax[0].plot(train_losses)\nax[0].plot(val_losses)\nax[0].set_title('Plot Losses', fontsize=14)\n\nax[1].plot(train_scores)\nax[1].plot(val_scores)\nax[1].set_title('Plot Accuracy Score', fontsize=14)\n\nplt.show()\n\nplt.savefig('./plot.png')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"allDataset = DogIdentificationDataset(df, root, transform=valTransform)\nallLoader = DataLoader(allDataset, batch_size=16, shuffle=True, num_workers=0)\n\ncheckpoint = torch.load('./checkpoint.pth')\nmodel.load_state_dict(checkpoint['state_dict'])\nmodel.eval()\n\nscores = 0\nlosses = 0\n\npbar = tqdm(allLoader, total=len(allLoader))\nfor image, target in pbar:\n    image = image.to(DEVICE)\n    target = target.to(DEVICE)\n    \n    out = model(image)\n    loss = criterion(out, target)\n    \n    score = MetricScore(target, out)\n    \n    losses += loss.item()*image.size(0)\n    scores += score *image.size(0)\n    \n    pbar.set_postfix({'Loss':loss.item(),\n                     'Score':score})\n\nlosses = losses / len(allLoader.dataset)\nscores = scores / len(allLoader.dataset)\n\nprint(f'Loss:{losses:.3f} -- Score:{scores:.3f}')\n    ","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}