{"cells":[{"metadata":{},"cell_type":"markdown","source":"iNaturalist Competition 2018 Training Code\n==========================================\n\nI did not write the following code myself. I copied this from [last years baseline](https://github.com/macaodha/inat_comp_2018) and only did some refactorization to make the code run in this kernel. Actually, I was just exploring the dataset and trying to see how past solutions do. All the credit goes to user macaoda.\n\nSo far, I managed to make the pre trained model run and also trained it on a few epochs over the training data. As you can see, the scores do not match this years baseline yet. According to user [zz, scores of at least 0.22 are possible](https://www.kaggle.com/c/inaturalist-2019-fgvc6/discussion/87749) with slight changes. Sadly, I will not be able to spend more time with this competition.\n\nHope, this kernel helps you in some way."},{"metadata":{},"cell_type":"markdown","source":"# Step 0: Import modules"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import os\nimport shutil\nimport time\nimport numpy as np\n\nimport torch\nimport torch.nn as nn\nimport torch.backends.cudnn as cudnn\nimport torch.optim\nimport torch.utils.data\n#import torchvision.models as models\n\nimport urllib.request\n\nimport torch.nn.functional as F\nimport torch.utils.model_zoo as model_zoo\n\nimport torch.utils.data as data\nfrom PIL import Image\nimport os\nimport json\nfrom torchvision import transforms\nimport random\nimport numpy as np","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Step 1: Download pre-trained model and define global variables"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# uncomment this to work with last years baseline model\n# performance will however be bad, with this commented out, we will just work\n# on a pre trained image net model\n# print('Downloading model files...', end=\"\")\n# url = 'http://vision.caltech.edu/~macaodha/inat2018/iNat_2018_InceptionV3.pth.tar'  \n# urllib.request.urlretrieve(url, 'iNat_2018_InceptionV3.pth.tar')\n# print('Done.')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Params:\n    # arch = 'inception_v3'\n    num_classes = 1010\n    workers = 8\n    epochs = 4\n    start_epoch = 0\n    batch_size = 64  # might want to make smaller \n    lr = 0.0045\n    lr_decay = 0.94\n    epoch_decay = 4\n    momentum = 0.9\n    weight_decay = 1e-4\n    print_freq = 100\n\n    resume = 'iNat_2018_InceptionV3.pth.tar'    # path to trained model\n    train_file = '../input/train2019.json'      # path to train file\n    val_file = '../input/test2019.json'         # path to test file\n    data_root_train = '../input/train_val2019/' # path to train images\n    data_root_test = '../input/test2019/'       # path to test images\n    op_file_name = 'submission.csv'             # submission filename\n\n    # set evaluate to True to run the test set\n    evaluate = True\n    save_preds = True","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Step 2: Model initialization\nI simply copied the code from the different modules and did some refactorization to execute it in this kernel. "},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# This code was copied from https://github.com/macaodha/inat_comp_2018/blob/master/inception.py\n\n# Same as the version from the official start_epoch\n# ttps://github.com/pytorch/vision/blob/master/torchvision/models/inception.py\n# Only change being that it can take variable sized inputs\n# See line 122\n\n__all__ = ['Inception3', 'inception_v3']\n\n\nmodel_urls = {\n    # Inception v3 ported from TensorFlow\n    'inception_v3_google': 'https://download.pytorch.org/models/inception_v3_google-1a9a5a14.pth',\n}\n\n\ndef inception_v3(pretrained=False, **kwargs):\n    r\"\"\"Inception v3 model architecture from\n    `\"Rethinking the Inception Architecture for Computer Vision\" <http://arxiv.org/abs/1512.00567>`_.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n    \"\"\"\n    if pretrained:\n        if 'transform_input' not in kwargs:\n            kwargs['transform_input'] = True\n        model = Inception3(**kwargs)\n        model.load_state_dict(model_zoo.load_url(model_urls['inception_v3_google']))\n        return model\n\n    return Inception3(**kwargs)\n\n\nclass Inception3(nn.Module):\n\n    def __init__(self, num_classes=1000, aux_logits=True, transform_input=False):\n        super(Inception3, self).__init__()\n        self.aux_logits = aux_logits\n        self.transform_input = transform_input\n        self.Conv2d_1a_3x3 = BasicConv2d(3, 32, kernel_size=3, stride=2)\n        self.Conv2d_2a_3x3 = BasicConv2d(32, 32, kernel_size=3)\n        self.Conv2d_2b_3x3 = BasicConv2d(32, 64, kernel_size=3, padding=1)\n        self.Conv2d_3b_1x1 = BasicConv2d(64, 80, kernel_size=1)\n        self.Conv2d_4a_3x3 = BasicConv2d(80, 192, kernel_size=3)\n        self.Mixed_5b = InceptionA(192, pool_features=32)\n        self.Mixed_5c = InceptionA(256, pool_features=64)\n        self.Mixed_5d = InceptionA(288, pool_features=64)\n        self.Mixed_6a = InceptionB(288)\n        self.Mixed_6b = InceptionC(768, channels_7x7=128)\n        self.Mixed_6c = InceptionC(768, channels_7x7=160)\n        self.Mixed_6d = InceptionC(768, channels_7x7=160)\n        self.Mixed_6e = InceptionC(768, channels_7x7=192)\n        if aux_logits:\n            self.AuxLogits = InceptionAux(768, num_classes)\n        self.Mixed_7a = InceptionD(768)\n        self.Mixed_7b = InceptionE(1280)\n        self.Mixed_7c = InceptionE(2048)\n        self.fc = nn.Linear(2048, num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):\n                import scipy.stats as stats\n                stddev = m.stddev if hasattr(m, 'stddev') else 0.1\n                X = stats.truncnorm(-2, 2, scale=stddev)\n                values = torch.Tensor(X.rvs(m.weight.data.numel()))\n                values = values.view(m.weight.data.size())\n                m.weight.data.copy_(values)\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()\n\n    def forward(self, x):\n        if self.transform_input:\n            x = x.clone()\n            x[:, 0] = x[:, 0] * (0.229 / 0.5) + (0.485 - 0.5) / 0.5\n            x[:, 1] = x[:, 1] * (0.224 / 0.5) + (0.456 - 0.5) / 0.5\n            x[:, 2] = x[:, 2] * (0.225 / 0.5) + (0.406 - 0.5) / 0.5\n        # 299 x 299 x 3\n        x = self.Conv2d_1a_3x3(x)\n        # 149 x 149 x 32\n        x = self.Conv2d_2a_3x3(x)\n        # 147 x 147 x 32\n        x = self.Conv2d_2b_3x3(x)\n        # 147 x 147 x 64\n        x = F.max_pool2d(x, kernel_size=3, stride=2)\n        # 73 x 73 x 64\n        x = self.Conv2d_3b_1x1(x)\n        # 73 x 73 x 80\n        x = self.Conv2d_4a_3x3(x)\n        # 71 x 71 x 192\n        x = F.max_pool2d(x, kernel_size=3, stride=2)\n        # 35 x 35 x 192\n        x = self.Mixed_5b(x)\n        # 35 x 35 x 256\n        x = self.Mixed_5c(x)\n        # 35 x 35 x 288\n        x = self.Mixed_5d(x)\n        # 35 x 35 x 288\n        x = self.Mixed_6a(x)\n        # 17 x 17 x 768\n        x = self.Mixed_6b(x)\n        # 17 x 17 x 768\n        x = self.Mixed_6c(x)\n        # 17 x 17 x 768\n        x = self.Mixed_6d(x)\n        # 17 x 17 x 768\n        x = self.Mixed_6e(x)\n        # 17 x 17 x 768\n        if self.training and self.aux_logits:\n            aux = self.AuxLogits(x)\n        # 17 x 17 x 768\n        x = self.Mixed_7a(x)\n        # 8 x 8 x 1280\n        x = self.Mixed_7b(x)\n        # 8 x 8 x 2048\n        x = self.Mixed_7c(x)\n        # 8 x 8 x 2048\n        x = F.adaptive_avg_pool2d(x, 1)\n        #x = F.avg_pool2d(x, kernel_size=8)\n        # 1 x 1 x 2048\n        x = F.dropout(x, training=self.training)\n        # 1 x 1 x 2048\n        x = x.view(x.size(0), -1)\n        # 2048\n        x = self.fc(x)\n        # 1000 (num_classes)\n        if self.training and self.aux_logits:\n            return x, aux\n        return x\n\n\nclass InceptionA(nn.Module):\n\n    def __init__(self, in_channels, pool_features):\n        super(InceptionA, self).__init__()\n        self.branch1x1 = BasicConv2d(in_channels, 64, kernel_size=1)\n\n        self.branch5x5_1 = BasicConv2d(in_channels, 48, kernel_size=1)\n        self.branch5x5_2 = BasicConv2d(48, 64, kernel_size=5, padding=2)\n\n        self.branch3x3dbl_1 = BasicConv2d(in_channels, 64, kernel_size=1)\n        self.branch3x3dbl_2 = BasicConv2d(64, 96, kernel_size=3, padding=1)\n        self.branch3x3dbl_3 = BasicConv2d(96, 96, kernel_size=3, padding=1)\n\n        self.branch_pool = BasicConv2d(in_channels, pool_features, kernel_size=1)\n\n    def forward(self, x):\n        branch1x1 = self.branch1x1(x)\n\n        branch5x5 = self.branch5x5_1(x)\n        branch5x5 = self.branch5x5_2(branch5x5)\n\n        branch3x3dbl = self.branch3x3dbl_1(x)\n        branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)\n        branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)\n\n        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)\n        branch_pool = self.branch_pool(branch_pool)\n\n        outputs = [branch1x1, branch5x5, branch3x3dbl, branch_pool]\n        return torch.cat(outputs, 1)\n\n\nclass InceptionB(nn.Module):\n\n    def __init__(self, in_channels):\n        super(InceptionB, self).__init__()\n        self.branch3x3 = BasicConv2d(in_channels, 384, kernel_size=3, stride=2)\n\n        self.branch3x3dbl_1 = BasicConv2d(in_channels, 64, kernel_size=1)\n        self.branch3x3dbl_2 = BasicConv2d(64, 96, kernel_size=3, padding=1)\n        self.branch3x3dbl_3 = BasicConv2d(96, 96, kernel_size=3, stride=2)\n\n    def forward(self, x):\n        branch3x3 = self.branch3x3(x)\n\n        branch3x3dbl = self.branch3x3dbl_1(x)\n        branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)\n        branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)\n\n        branch_pool = F.max_pool2d(x, kernel_size=3, stride=2)\n\n        outputs = [branch3x3, branch3x3dbl, branch_pool]\n        return torch.cat(outputs, 1)\n\n\nclass InceptionC(nn.Module):\n\n    def __init__(self, in_channels, channels_7x7):\n        super(InceptionC, self).__init__()\n        self.branch1x1 = BasicConv2d(in_channels, 192, kernel_size=1)\n\n        c7 = channels_7x7\n        self.branch7x7_1 = BasicConv2d(in_channels, c7, kernel_size=1)\n        self.branch7x7_2 = BasicConv2d(c7, c7, kernel_size=(1, 7), padding=(0, 3))\n        self.branch7x7_3 = BasicConv2d(c7, 192, kernel_size=(7, 1), padding=(3, 0))\n\n        self.branch7x7dbl_1 = BasicConv2d(in_channels, c7, kernel_size=1)\n        self.branch7x7dbl_2 = BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0))\n        self.branch7x7dbl_3 = BasicConv2d(c7, c7, kernel_size=(1, 7), padding=(0, 3))\n        self.branch7x7dbl_4 = BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0))\n        self.branch7x7dbl_5 = BasicConv2d(c7, 192, kernel_size=(1, 7), padding=(0, 3))\n\n        self.branch_pool = BasicConv2d(in_channels, 192, kernel_size=1)\n\n    def forward(self, x):\n        branch1x1 = self.branch1x1(x)\n\n        branch7x7 = self.branch7x7_1(x)\n        branch7x7 = self.branch7x7_2(branch7x7)\n        branch7x7 = self.branch7x7_3(branch7x7)\n\n        branch7x7dbl = self.branch7x7dbl_1(x)\n        branch7x7dbl = self.branch7x7dbl_2(branch7x7dbl)\n        branch7x7dbl = self.branch7x7dbl_3(branch7x7dbl)\n        branch7x7dbl = self.branch7x7dbl_4(branch7x7dbl)\n        branch7x7dbl = self.branch7x7dbl_5(branch7x7dbl)\n\n        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)\n        branch_pool = self.branch_pool(branch_pool)\n\n        outputs = [branch1x1, branch7x7, branch7x7dbl, branch_pool]\n        return torch.cat(outputs, 1)\n\n\nclass InceptionD(nn.Module):\n\n    def __init__(self, in_channels):\n        super(InceptionD, self).__init__()\n        self.branch3x3_1 = BasicConv2d(in_channels, 192, kernel_size=1)\n        self.branch3x3_2 = BasicConv2d(192, 320, kernel_size=3, stride=2)\n\n        self.branch7x7x3_1 = BasicConv2d(in_channels, 192, kernel_size=1)\n        self.branch7x7x3_2 = BasicConv2d(192, 192, kernel_size=(1, 7), padding=(0, 3))\n        self.branch7x7x3_3 = BasicConv2d(192, 192, kernel_size=(7, 1), padding=(3, 0))\n        self.branch7x7x3_4 = BasicConv2d(192, 192, kernel_size=3, stride=2)\n\n    def forward(self, x):\n        branch3x3 = self.branch3x3_1(x)\n        branch3x3 = self.branch3x3_2(branch3x3)\n\n        branch7x7x3 = self.branch7x7x3_1(x)\n        branch7x7x3 = self.branch7x7x3_2(branch7x7x3)\n        branch7x7x3 = self.branch7x7x3_3(branch7x7x3)\n        branch7x7x3 = self.branch7x7x3_4(branch7x7x3)\n\n        branch_pool = F.max_pool2d(x, kernel_size=3, stride=2)\n        outputs = [branch3x3, branch7x7x3, branch_pool]\n        return torch.cat(outputs, 1)\n\n\nclass InceptionE(nn.Module):\n\n    def __init__(self, in_channels):\n        super(InceptionE, self).__init__()\n        self.branch1x1 = BasicConv2d(in_channels, 320, kernel_size=1)\n\n        self.branch3x3_1 = BasicConv2d(in_channels, 384, kernel_size=1)\n        self.branch3x3_2a = BasicConv2d(384, 384, kernel_size=(1, 3), padding=(0, 1))\n        self.branch3x3_2b = BasicConv2d(384, 384, kernel_size=(3, 1), padding=(1, 0))\n\n        self.branch3x3dbl_1 = BasicConv2d(in_channels, 448, kernel_size=1)\n        self.branch3x3dbl_2 = BasicConv2d(448, 384, kernel_size=3, padding=1)\n        self.branch3x3dbl_3a = BasicConv2d(384, 384, kernel_size=(1, 3), padding=(0, 1))\n        self.branch3x3dbl_3b = BasicConv2d(384, 384, kernel_size=(3, 1), padding=(1, 0))\n\n        self.branch_pool = BasicConv2d(in_channels, 192, kernel_size=1)\n\n    def forward(self, x):\n        branch1x1 = self.branch1x1(x)\n\n        branch3x3 = self.branch3x3_1(x)\n        branch3x3 = [\n            self.branch3x3_2a(branch3x3),\n            self.branch3x3_2b(branch3x3),\n        ]\n        branch3x3 = torch.cat(branch3x3, 1)\n\n        branch3x3dbl = self.branch3x3dbl_1(x)\n        branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)\n        branch3x3dbl = [\n            self.branch3x3dbl_3a(branch3x3dbl),\n            self.branch3x3dbl_3b(branch3x3dbl),\n        ]\n        branch3x3dbl = torch.cat(branch3x3dbl, 1)\n\n        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)\n        branch_pool = self.branch_pool(branch_pool)\n\n        outputs = [branch1x1, branch3x3, branch3x3dbl, branch_pool]\n        return torch.cat(outputs, 1)\n\n\nclass InceptionAux(nn.Module):\n\n    def __init__(self, in_channels, num_classes):\n        super(InceptionAux, self).__init__()\n        self.conv0 = BasicConv2d(in_channels, 128, kernel_size=1)\n        self.conv1 = BasicConv2d(128, 768, kernel_size=5)\n        self.conv1.stddev = 0.01\n        self.fc = nn.Linear(768, num_classes)\n        self.fc.stddev = 0.001\n\n    def forward(self, x):\n        # 17 x 17 x 768\n        x = F.avg_pool2d(x, kernel_size=5, stride=3)\n        # 5 x 5 x 768\n        x = self.conv0(x)\n        # 5 x 5 x 128\n        x = self.conv1(x)\n        # 1 x 1 x 768\n        x = x.view(x.size(0), -1)\n        # 768\n        x = self.fc(x)\n        # 1000\n        return x\n\n\nclass BasicConv2d(nn.Module):\n\n    def __init__(self, in_channels, out_channels, **kwargs):\n        super(BasicConv2d, self).__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)\n        self.bn = nn.BatchNorm2d(out_channels, eps=0.001)\n\n    def forward(self, x):\n        x = self.conv(x)\n        x = self.bn(x)\n        return F.relu(x, inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# The following was copied from https://github.com/macaodha/inat_comp_2018/blob/master/train_inat.py\n\n# Adapted from https://github.com/pytorch/examples/blob/master/imagenet/main.py\n\nbest_prec3 = 0.0  # store current best top 3\n\ndef train(train_loader, model, criterion, optimizer, epoch):\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = AverageMeter()\n    top1 = AverageMeter()\n    top3 = AverageMeter()\n\n    # switch to train mode\n    model.train()\n\n    end = time.time()\n    print('Epoch:{0}'.format(epoch))\n    print('Itr\\t\\tTime\\t\\tData\\t\\tPrec@1\\t\\tPrec@3')\n    for i, (input, im_id, target, tax_ids) in enumerate(train_loader):\n        # measure data loading time\n        data_time.update(time.time() - end)\n\n        input = input.cuda()\n        target = target.cuda(async=True)\n        input_var = torch.autograd.Variable(input)\n        target_var = torch.autograd.Variable(target)\n\n        # compute output\n        output = model(input_var)\n        loss = criterion(output, target_var)\n\n        # measure accuracy and record loss\n        prec1, prec3 = accuracy(output.data, target, topk=(1, 3))\n        # losses.update(loss.data[0], input.size(0))\n        top1.update(prec1[0], input.size(0))\n        top3.update(prec3[0], input.size(0))\n\n        # compute gradient and do SGD step\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        # measure elapsed time\n        batch_time.update(time.time() - end)\n        end = time.time()\n\n        if i % args.print_freq == 0:\n            print('[{0}/{1}]\\t'\n                '{batch_time.val:.2f} ({batch_time.avg:.2f})\\t'\n                '{data_time.val:.2f} ({data_time.avg:.2f})\\t'\n                '{top1.val:.2f} ({top1.avg:.2f})\\t'\n                '{top3.val:.2f} ({top3.avg:.2f})'.format(\n                i, len(train_loader), batch_time=batch_time,\n                data_time=data_time, top1=top1, top3=top3))\n\n\ndef validate(val_loader, model, criterion, save_preds=False):\n    batch_time = AverageMeter()\n    losses = AverageMeter()\n    top1 = AverageMeter()\n    top3 = AverageMeter()\n\n    # switch to evaluate mode\n    model.eval()\n\n    end = time.time()\n    pred = []\n    im_ids = []\n\n    print('Validate:\\tTime\\t\\tPrec@1\\t\\tPrec@3')\n    for i, (input, im_id, target, tax_ids) in enumerate(val_loader):\n        input = input.cuda()\n        target = target.cuda(async=True)\n        input_var = torch.autograd.Variable(input, volatile=True)\n        target_var = torch.autograd.Variable(target, volatile=True)\n\n        # compute output\n        output = model(input_var)\n        # loss = criterion(output, target_var)\n\n        if save_preds:\n            # store the top K classes for the prediction\n            im_ids.append(im_id.cpu().numpy().astype(np.int))\n            _, pred_inds = output.data.topk(5,1,True,True)\n            pred.append(pred_inds.cpu().numpy().astype(np.int))\n\n        # measure accuracy and record loss\n        prec1, prec3 = accuracy(output.data, target, topk=(1, 3))\n        # losses.update(loss.data[0], input.size(0))\n\n        top1.update(prec1[0], input.size(0))\n        top3.update(prec3[0], input.size(0))\n\n        # measure elapsed time\n        batch_time.update(time.time() - end)\n        end = time.time()\n        \n        if i % args.print_freq == 0:\n            print('[{0}/{1}]\\t'\n                  '{batch_time.val:.2f} ({batch_time.avg:.2f})\\t'\n                  '{top1.val:.2f} ({top1.avg:.2f})\\t'\n                  '{top3.val:.2f} ({top3.avg:.2f})'.format(\n                   i, len(val_loader), batch_time=batch_time,\n                   top1=top1, top3=top3))\n\n    print(' * Prec@1 {top1.avg:.3f} Prec@3 {top3.avg:.3f}'\n          .format(top1=top1, top3=top3))\n\n    if save_preds:\n        return top3.avg, np.vstack(pred), np.hstack(im_ids)\n    else:\n        return top3.avg\n\n\ndef save_checkpoint(state, is_best, filename='checkpoint.pth.tar'):\n    torch.save(state, filename)\n    if is_best:\n        print(\"\\tSaving new best model\")\n        shutil.copyfile(filename, 'model_best.pth.tar')\n\n\nclass AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count\n\n\ndef adjust_learning_rate(optimizer, epoch):\n    \"\"\"Sets the learning rate to the initial LR decayed by 10 every 30 epochs\"\"\"\n    lr = args.lr * (0.1 ** (epoch // 30))\n    for param_group in optimizer.param_groups:\n        param_group['lr'] = lr\n\n\ndef accuracy(output, target, topk=(1,)):\n    \"\"\"Computes the precision@k for the specified values of k\"\"\"\n    maxk = max(topk)\n    batch_size = target.size(0)\n\n    _, pred = output.topk(maxk, 1, True, True)\n    pred = pred.t()\n    correct = pred.eq(target.view(1, -1).expand_as(pred))\n\n    res = []\n    for k in topk:\n        correct_k = correct[:k].view(-1).float().sum(0, keepdim=True)\n        res.append(correct_k.mul_(100.0 / batch_size))\n    return res","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# The following was copied from https://github.com/macaodha/inat_comp_2018/blob/master/inat2018_loader.py\n\ndef default_loader(path):\n    return Image.open(path).convert('RGB')\n\ndef load_taxonomy(ann_data, tax_levels, classes):\n    # loads the taxonomy data and converts to ints\n    taxonomy = {}\n\n    if 'categories' in ann_data.keys():\n        num_classes = len(ann_data['categories'])\n        for tt in tax_levels:\n            tax_data = [aa[tt] for aa in ann_data['categories']]\n            _, tax_id = np.unique(tax_data, return_inverse=True)\n            taxonomy[tt] = dict(zip(range(num_classes), list(tax_id)))\n    else:\n        # set up dummy data\n        for tt in tax_levels:\n            taxonomy[tt] = dict(zip([0], [0]))\n\n    # create a dictionary of lists containing taxonomic labels\n    classes_taxonomic = {}\n    for cc in np.unique(classes):\n        tax_ids = [0]*len(tax_levels)\n        for ii, tt in enumerate(tax_levels):\n            tax_ids[ii] = taxonomy[tt][cc]\n        classes_taxonomic[cc] = tax_ids\n\n    return taxonomy, classes_taxonomic\n\n\nclass INAT(data.Dataset):\n    def __init__(self, root, ann_file, is_train=True):\n\n        # load annotations\n        print('Loading annotations from: ' + os.path.basename(ann_file))\n        with open(ann_file) as data_file:\n            ann_data = json.load(data_file)\n\n        # set up the filenames and annotations\n        self.imgs = [aa['file_name'] for aa in ann_data['images']]\n        self.ids = [aa['id'] for aa in ann_data['images']]\n\n        # if we dont have class labels set them to '0'\n        if 'annotations' in ann_data.keys():\n            self.classes = [aa['category_id'] for aa in ann_data['annotations']]\n        else:\n            self.classes = [0]*len(self.imgs)\n\n        # load taxonomy\n        self.tax_levels = ['id', 'genus', 'family', 'order', 'class', 'phylum', 'kingdom']\n                           #8142, 4412,    1120,     273,     57,      25,       6\n        self.taxonomy, self.classes_taxonomic = load_taxonomy(ann_data, self.tax_levels, self.classes)\n\n        # print out some stats\n        print('\\t' + str(len(self.imgs)) + ' images')\n        print('\\t' + str(len(set(self.classes))) + ' classes')\n\n        self.root = root\n        self.is_train = is_train\n        self.loader = default_loader\n\n        # augmentation params\n        self.im_size = [299, 299]  # can change this to train on higher res\n        self.mu_data = [0.485, 0.456, 0.406]\n        self.std_data = [0.229, 0.224, 0.225]\n        self.brightness = 0.4\n        self.contrast = 0.4\n        self.saturation = 0.4\n        self.hue = 0.25\n\n        # augmentations\n        self.center_crop = transforms.CenterCrop((self.im_size[0], self.im_size[1]))\n        self.scale_aug = transforms.RandomResizedCrop(size=self.im_size[0])\n        self.flip_aug = transforms.RandomHorizontalFlip()\n        self.color_aug = transforms.ColorJitter(self.brightness, self.contrast, self.saturation, self.hue)\n        self.tensor_aug = transforms.ToTensor()\n        self.norm_aug = transforms.Normalize(mean=self.mu_data, std=self.std_data)\n\n    def __getitem__(self, index):\n        path = self.root + self.imgs[index]\n        im_id = self.ids[index]\n        img = self.loader(path)\n        species_id = self.classes[index]\n        tax_ids = self.classes_taxonomic[species_id]\n\n        if self.is_train:\n            img = self.scale_aug(img)\n            img = self.flip_aug(img)\n            img = self.color_aug(img)\n        else:\n            img = self.center_crop(img)\n\n        img = self.tensor_aug(img)\n        img = self.norm_aug(img)\n\n        return img, im_id, species_id, tax_ids\n\n    def __len__(self):\n        return len(self.imgs)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Step 3: Train and Predict"},{"metadata":{"trusted":true},"cell_type":"code","source":"# The following was copied from https://github.com/macaodha/inat_comp_2018/blob/master/inat2018_loader.py\n\nargs = Params()\n\n# load pretrained model\nprint(\"Using pre-trained inception_v3\")\nmodel = inception_v3(pretrained=True)\nmodel.fc = nn.Linear(2048, args.num_classes)\nmodel.aux_logits = False\nmodel = model.cuda()\n\n# define loss function (criterion) and optimizer\ncriterion = nn.CrossEntropyLoss().cuda()\noptimizer = torch.optim.SGD(model.parameters(), args.lr,\n                            momentum=args.momentum,\n                            weight_decay=args.weight_decay)\n\n# optionally resume from a checkpoint\nif args.resume:\n    if os.path.isfile(args.resume):\n        print(\"=> loading checkpoint '{}'\".format(args.resume))\n        checkpoint = torch.load(args.resume)\n        args.start_epoch = checkpoint['epoch']\n        best_prec3 = checkpoint['best_prec3']\n        model.load_state_dict(checkpoint['state_dict'])\n        optimizer.load_state_dict(checkpoint['optimizer'])\n        print(\"=> loaded checkpoint '{}' (epoch {})\"\n               .format(args.resume, checkpoint['epoch']))\n    else:\n        print(\"=> no checkpoint found at '{}'\".format(args.resume))\n\n    cudnn.benchmark = True\n\n# data loading code\ntrain_dataset = INAT(args.data_root_train, args.train_file,\n                     is_train=True)\nval_dataset = INAT(args.data_root_test, args.val_file,\n                     is_train=False)\n\ntrain_loader = torch.utils.data.DataLoader(train_dataset, batch_size=args.batch_size,\n                   shuffle=True, num_workers=args.workers, pin_memory=True)\nval_loader = torch.utils.data.DataLoader(val_dataset,\n                                         batch_size=args.batch_size, shuffle=False,\n                                         num_workers=args.workers, pin_memory=True)\n\nfor epoch in range(args.start_epoch, args.epochs):\n    adjust_learning_rate(optimizer, epoch)\n\n    # train for one epoch\n    train(train_loader, model, criterion, optimizer, epoch)\n\n    # evaluate on validation set\n    prec3 = validate(val_loader, model, criterion, False)\n\n    # remember best prec@1 and save checkpoint\n    is_best = prec3 > best_prec3\n    best_prec3 = max(prec3, best_prec3)\n    save_checkpoint({\n        'epoch': epoch + 1,\n        #'arch': args.arch,\n        'state_dict': model.state_dict(),\n        'best_prec3': best_prec3,\n        'optimizer' : optimizer.state_dict(),\n    }, is_best)\n\nif args.evaluate:\n    prec3, preds, im_ids = validate(val_loader, model, criterion, True)\n    # write predictions to file\n    if args.save_preds:\n        with open(args.op_file_name, 'w') as opfile:\n            opfile.write('id,predicted\\n')\n            for ii in range(len(im_ids)):\n                opfile.write(str(im_ids[ii]) + ',' + ' '.join([str(j) for j in preds[ii, :]]) + '\\n')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}