{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# separating out the filenames of training, validation and dataset separately in 3 different list variables\n\nimport glob\n\ntrain_files = glob.glob('/kaggle/input/tpu-getting-started/*/train/*.tfrec')\nval_files = glob.glob('/kaggle/input/tpu-getting-started/*/val/*.tfrec')\ntest_files = glob.glob('/kaggle/input/tpu-getting-started/*/test/*.tfrec')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_files","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# now collecting the ids , filenames and images in bytes in three different list variables for train , validation & test files\n\n# importing tensorfow to read .tfrec files\nimport tensorflow as tf\n\nfor i in train_files:\n    train_image_dataset = tf.data.TFRecordDataset(i)\n\n    # Create a dictionary describing the features.\n    train_feature_description = {\n        'class': tf.io.FixedLenFeature([], tf.int64),\n        'id': tf.io.FixedLenFeature([], tf.string),\n        'image': tf.io.FixedLenFeature([], tf.string),\n    }\n\ndef _parse_image_function(example_proto):\n  # Parse the input tf.Example proto using the dictionary above.\n  return tf.io.parse_single_example(example_proto, train_feature_description)\n\ntrain_image_dataset = train_image_dataset.map(_parse_image_function)\n\n\ntrain_ids = [str(image_features['id'].numpy())[2:-1] for image_features in train_image_dataset] # [2:-1] is done to remove b' from 1st and 'from last in train id names\n\ntrain_class = [int(image_features['class'].numpy()) for image_features in train_image_dataset]\n\ntrain_images = [image_features['image'].numpy() for image_features in train_image_dataset]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in val_files:\n    val_image_dataset = tf.data.TFRecordDataset(i)\n\n    # Create a dictionary describing the features.\n    val_feature_description = {\n        'class': tf.io.FixedLenFeature([], tf.int64),\n        'id': tf.io.FixedLenFeature([], tf.string),\n        'image': tf.io.FixedLenFeature([], tf.string),\n    }\n\ndef _parse_image_function(example_proto):\n  # Parse the input tf.Example proto using the dictionary above.\n  return tf.io.parse_single_example(example_proto, val_feature_description)\n\nval_image_dataset = val_image_dataset.map(_parse_image_function)\n\n\nval_ids = [str(image_features['id'].numpy())[2:-1] for image_features in val_image_dataset]\n\nval_class = [int(image_features['class'].numpy()) for image_features in val_image_dataset]\n\nval_images = [image_features['image'].numpy() for image_features in val_image_dataset]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in test_files:\n    test_image_dataset = tf.data.TFRecordDataset(i)\n\n    # Create a dictionary describing the features.\n    test_feature_description = {\n        'id': tf.io.FixedLenFeature([], tf.string),\n        'image': tf.io.FixedLenFeature([], tf.string),\n    }\n\ndef _parse_image_function(example_proto):\n  # Parse the input tf.Example proto using the dictionary above.\n  return tf.io.parse_single_example(example_proto, test_feature_description)\n\ntest_image_dataset = test_image_dataset.map(_parse_image_function)\n\n\ntest_ids = [str(image_features['id'].numpy())[2:-1] for image_features in test_image_dataset]\n\ntest_images = [image_features['image'].numpy() for image_features in test_image_dataset]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# dry run for testing\n\nimport IPython.display as display\n\ndisplay.display(display.Image(data=train_images[200]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# defining dataset\nfrom PIL import Image\nimport cv2\nimport albumentations\nimport torch\nimport numpy as np\nimport io\nfrom torch.utils.data import Dataset\n\nclass FlowerDataset(Dataset):\n    def __init__(self, id , classes , image , img_height , img_width, mean , std , is_valid):\n        self.id = id\n        self.classes = classes\n        self.image = image\n        self.is_valid = is_valid\n        if self.is_valid == 1:\n            self.aug = albumentations.Compose([\n               albumentations.Resize(img_height , img_width, always_apply = True) ,\n               albumentations.Normalize(mean , std , always_apply = True) \n            ])\n        else:\n            self.aug = albumentations.Compose([\n                albumentations.Resize(img_height , img_width, always_apply = True) ,\n                albumentations.Normalize(mean , std , always_apply = True),\n                albumentations.ShiftScaleRotate(shift_limit = 0.0625,\n                                                scale_limit = 0.1 ,\n                                                rotate_limit = 5,\n                                                p = 0.9)\n            ]) \n        \n    def __len__(self):\n        return len(self.id)\n    \n    def __getitem__(self, index):\n        id = self.id[index]\n        img = np.array(Image.open(io.BytesIO(self.image[index]))) \n        img = cv2.resize(img, dsize=(224, 224), interpolation=cv2.INTER_CUBIC)\n        img = self.aug(image = img)['image']\n        img = np.transpose(img , (2,0,1)).astype(np.float32)\n       \n        \n#         return {\n#             'image' : torch.tensor(img, dtype = torch.float),\n#             'class' : torch.tensor(self.classes[index], dtype = torch.long) \n#         }\n\n#         if self.is_valid == 1:\n#             return torch.tensor(img, dtype = torch.float),np.eye(104, dtype='float64')[int(self.classes[index])] # 104 is the no. of classes\n#         else:\n        return torch.tensor(img, dtype = torch.float),torch.tensor(self.classes[index], dtype = torch.long)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# sanity check for FlowerDataset class created\n\ntrain_dataset = FlowerDataset(id = train_ids, classes = train_class, image = train_images, \n                        img_height = 224 , img_width = 224, \n                        mean = (0.485, 0.456, 0.406),\n                        std = (0.229, 0.224, 0.225) , is_valid = 0)\n\nval_dataset = FlowerDataset(id = val_ids, classes = val_class, image = val_images, \n                        img_height = 224 , img_width = 224, \n                        mean = (0.485, 0.456, 0.406),\n                        std = (0.229, 0.224, 0.225) , is_valid = 1)\n\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nidx = 200\nimg = train_dataset[idx][0]\n\nprint(train_dataset[idx][1])\n\nnpimg = img.numpy()\nplt.imshow(np.transpose(npimg, (1,2,0)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting up the dataloader with cutmix data agumentation\n!pip install git+https://github.com/ildoonet/cutmix","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting up the train data loader\n\nfrom cutmix.cutmix import CutMix\n\ntrain_dataloader = CutMix(train_dataset, \n                          num_class=104, \n                          beta=1.0, \n                          prob=0.5, \n                          num_mix=2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting up the validation data loader\n\nfrom torch.utils.data import DataLoader\n\ntraining_dataloader = DataLoader(train_dataset,\n                        shuffle=True,\n                        num_workers=4,\n                        batch_size=1\n                       )\n\nval_dataloader = DataLoader(val_dataset,\n                        shuffle=False,\n                        num_workers=4,\n                        batch_size=1\n                       )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# keeping the train and validation data loaders in one dictionary\ndataloaders = {\n    'train': training_dataloader ,\n    'val': val_dataloader\n}\n\ndataset_sizes = {\n    'train': len(train_dataset) ,\n    'val': len(val_dataset)\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y = next(iter(dataloaders['train']))\ny","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# downloading the pretrained model - efficientnet b7  \n\n!pip install efficientnet_pytorch\n\nimport efficientnet_pytorch\n\nmodel = efficientnet_pytorch.EfficientNet.from_pretrained('efficientnet-b7')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# changing the last layer from 1000 category classifier to 104 flower's catergory classifier \n\nin_features = model._fc.in_features\nmodel._fc = torch.nn.Linear(in_features, 104)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install pretrainedmodels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pretrainedmodels\nmodel_name = 'resnet18' # could be fbresnet152 or inceptionresnetv2\nmodel = pretrainedmodels.__dict__[model_name](num_classes=1000, pretrained='imagenet')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"in_features = model.last_linear.in_features\nmodel.last_linear = torch.nn.Linear(in_features, 104)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Printing out the model to see the changes in made in last layer\n# device = xm.xla_device()\n# model = model.to(device)\nif torch.cuda.is_available():\n    model.cuda()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# installing torchcontrib for Stochastic Weight Averaging in PyTorch \n!pip install torchcontrib","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install torchtoolbox\nfrom torchtoolbox.tools import mixup_data, mixup_criterion","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting up the optimizer , loss func. & scheduler for training\n\n# from cutmix.utils import CutMixCrossEntropyLoss \n\n#for Stochastic Weight Averaging in PyTorch\nfrom torchcontrib.optim import SWA\n\nbase_optimizer = torch.optim.Adam(model._fc.parameters(), lr=1e-4)\n\noptimizer = SWA(base_optimizer, swa_start=5, swa_freq=5, swa_lr=0.05)\n\n# loss_fn = CutMixCrossEntropyLoss(True)\nloss_fn = torch.nn.CrossEntropyLoss()\n\nscheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# setting up the training function\n\nif __name__ == \"__main__\":\n\n    for param in model.parameters():\n        param.requires_grad = False\n        \n    for param in model._fc.parameters():\n        param.requires_grad = True\n\n    epochs = 25\n\n    for epoch in range(epochs):\n        print('Epoch ', epoch,'/',epochs-1)\n        print('-'*15)\n\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # Set model to training mode\n            else:\n                model.eval()   # Set model to evaluate mode\n\n            running_loss = 0.0\n            running_corrects = 0.0\n            \n            alpha = 0.2\n            \n            # Iterate over data.\n            for i,(inputs,labels) in enumerate(dataloaders[phase]):\n                if torch.cuda.is_available():\n                    inputs = inputs.cuda()\n                    labels = labels.cuda()\n                    \n                inputs, labels_a, labels_b, lam = mixup_data(inputs, labels, alpha)\n\n                # zero the parameter gradients\n                optimizer.zero_grad()\n\n                with torch.set_grad_enabled(phase == 'train'):\n                    \n                    outputs = model(inputs)\n                    _, preds = torch.max(outputs, 1)\n                    loss = mixup_criterion(loss_fn, outputs, labels_a, labels_b, lam)\n\n                    # loss = loss_fn(outputs,labels)\n\n                    # we backpropagate to set our learning parameters only in training mode\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data) # (preds == labels.data) as the usage of .data is not recommended, as it might have unwanted side effect.\n\n            # scheduler for weight decay\n            if phase == 'train':\n                scheduler.step()\n\n            epoch_loss = running_loss / float(dataset_sizes[phase])\n            epoch_acc = running_corrects / float(dataset_sizes[phase])\n\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n    optimizer.swap_swa_sgd()       ","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}