{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import torch\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport os\nimport cv2\nimport math\nfrom torch import nn\nfrom torch.nn import functional as F\nimport torchvision\nimport os","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e6b13eca0456d0a159006353dd2ec66e57a346a7"},"cell_type":"code","source":"from torch.autograd import Variable","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"def strokes_to_img(in_strokes):\n    in_strokes = eval(in_strokes)\n    # make an agg figure\n    fig, ax = plt.subplots()\n    for x,y in in_strokes:\n        ax.plot(x, y, linewidth=12.) #  marker='.',\n    ax.axis('off')\n    fig.canvas.draw()\n    \n    # grab the pixel buffer and dump it into a numpy array\n    X = np.array(fig.canvas.renderer._renderer)\n    plt.close(fig)\n    return (cv2.resize(X, (96, 96)) / 255.)[::-1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"082d9d308468b845deb12c58a955dbce0dd0ff2c"},"cell_type":"code","source":"class_files = os.listdir(\"../input/train_simplified/\")\nclasses = {x[:-4]:i for i, x in enumerate(class_files)}\nto_class = {i:x[:-4].replace(\" \", \"_\") for i, x in enumerate(class_files)}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6dfd3f3f5f8441320e26fce6d0dcee5f7359610e"},"cell_type":"code","source":"classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cc2ca31c404c6faa078a96e8ba61aed55b0d56ed"},"cell_type":"code","source":"dfs = [pd.read_csv(\"../input/train_simplified/\" + x, nrows=10000)[[\"word\", \"drawing\"]] for x in class_files]\ndf = pd.concat(dfs)\ndel dfs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c653c50488d535129e1aa8c773a84f6edf5ba61d"},"cell_type":"code","source":"df[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ff11d11fd429d0ccb193a08629db79941f80a44b"},"cell_type":"code","source":"n_samples = df.shape[0]\nbatch_size = 64\n\npick_order = np.arange(n_samples)\npick_per_epoch = n_samples // batch_size\n\ndef train_gen():\n    while True:  # Infinity loop\n        np.random.shuffle(pick_order)\n        for i in range(pick_per_epoch):\n            c_pick = pick_order[i*batch_size: (i+1)*batch_size]\n            dfs = df.iloc[c_pick]\n            out_imgs = list(map(strokes_to_img, dfs[\"drawing\"]))\n            X = np.array(out_imgs)[:, :, :, :3].astype(np.float32)\n            y = np.array([classes[x] for x in dfs[\"word\"]])\n            yield X, y","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ad6b00c84da08f639b0728aaceed5b7003dfcf43","scrolled":true},"cell_type":"code","source":"dataloaders = train_gen()\nx,y = next(iter(dataloaders))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"be684fc5020b7b0038c44875f0c9789b723223a0"},"cell_type":"code","source":"x.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c6b2ee7b92402a9554be5bf6f6f0eda91104a969"},"cell_type":"code","source":"def display_img(n):\n    for i in range(n):\n        plt.subplot(2,n//2,i+1)\n        plt.imshow(x[i])\n        plt.axis('off')\nplt.show()\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ea3cff1e711f5fc3f6464332275650a2f4c9e8ce"},"cell_type":"code","source":"display_img(20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cdabbaf432b2798f0324f0dbb75d522415eb9768"},"cell_type":"code","source":"class CyclicLR(object):\n    def __init__(self, optimizer, base_lr=1e-3, max_lr=6e-3,\n                 step_size=2000, mode='triangular', gamma=1.,\n                 scale_fn=None, scale_mode='cycle', last_batch_iteration=-1):\n\n        \n        self.optimizer = optimizer\n\n        if isinstance(base_lr, list) or isinstance(base_lr, tuple):\n            if len(base_lr) != len(optimizer.param_groups):\n                raise ValueError(\"expected {} base_lr, got {}\".format(\n                    len(optimizer.param_groups), len(base_lr)))\n            self.base_lrs = list(base_lr)\n        else:\n            self.base_lrs = [base_lr] * len(optimizer.param_groups)\n\n        if isinstance(max_lr, list) or isinstance(max_lr, tuple):\n            if len(max_lr) != len(optimizer.param_groups):\n                raise ValueError(\"expected {} max_lr, got {}\".format(\n                    len(optimizer.param_groups), len(max_lr)))\n            self.max_lrs = list(max_lr)\n        else:\n            self.max_lrs = [max_lr] * len(optimizer.param_groups)\n\n        self.step_size = step_size\n\n        if mode not in ['triangular', 'triangular2', 'exp_range'] \\\n                and scale_fn is None:\n            raise ValueError('mode is invalid and scale_fn is None')\n\n        self.mode = mode\n        self.gamma = gamma\n\n        if scale_fn is None:\n            if self.mode == 'triangular':\n                self.scale_fn = self._triangular_scale_fn\n                self.scale_mode = 'cycle'\n            elif self.mode == 'triangular2':\n                self.scale_fn = self._triangular2_scale_fn\n                self.scale_mode = 'cycle'\n            elif self.mode == 'exp_range':\n                self.scale_fn = self._exp_range_scale_fn\n                self.scale_mode = 'iterations'\n        else:\n            self.scale_fn = scale_fn\n            self.scale_mode = scale_mode\n\n        self.batch_step(last_batch_iteration + 1)\n        self.last_batch_iteration = last_batch_iteration\n\n    def batch_step(self, batch_iteration=None):\n        if batch_iteration is None:\n            batch_iteration = self.last_batch_iteration + 1\n        self.last_batch_iteration = batch_iteration\n        for param_group, lr in zip(self.optimizer.param_groups, self.get_lr()):\n            param_group['lr'] = lr\n\n    def _triangular_scale_fn(self, x):\n        return 1.\n\n    def _triangular2_scale_fn(self, x):\n        return 1 / (2. ** (x - 1))\n\n    def _exp_range_scale_fn(self, x):\n        return self.gamma**(x)\n\n    def get_lr(self):\n        step_size = float(self.step_size)\n        cycle = np.floor(1 + self.last_batch_iteration / (2 * step_size))\n        x = np.abs(self.last_batch_iteration / step_size - 2 * cycle + 1)\n\n        lrs = []\n        param_lrs = zip(self.optimizer.param_groups, self.base_lrs, self.max_lrs)\n        for param_group, base_lr, max_lr in param_lrs:\n            base_height = (max_lr - base_lr) * np.maximum(0, (1 - x))\n            if self.scale_mode == 'cycle':\n                lr = base_lr + base_height * self.scale_fn(cycle)\n            else:\n                lr = base_lr + base_height * self.scale_fn(self.last_batch_iteration)\n            lrs.append(lr)\n        return lrs\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"92aa0c940c171ddb770baf091d8576ac03f26163"},"cell_type":"code","source":"device = torch.device('cuda')\n\ncriterion = nn.NLLLoss()\nlr = 0.001\nweight_decay = 5e-4\ngamma=0.1\nstepsize=60\nepochs = 40\nnum_classes=340\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d75118885aa4eef170c0e439a568a495b8a8702d"},"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, pretrained_model):\n        super(Model,self).__init__()\n        self.pretrained_model = pretrained_model\n        self.base = nn.Sequential(*list(pretrained_model.children())[:-1])\n        self.linear = nn.Linear(512,340)\n\n    def forward(self, x):\n        x = self.base(x)\n        x = F.avg_pool2d(x, x.size()[2:])\n        f = x.view(x.size(0), -1)\n        y = self.linear(f)\n        return \n\nft_model = torchvision.models.resnet18(pretrained=True)\nmodel = Model(ft_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"38b4ed146052790116d36cba0dc75ace7ed0fcf1"},"cell_type":"code","source":"opt = torch.optim.SGD(model.parameters(),lr=lr,momentum=0.9,weight_decay=weight_decay)\nscheduler = CyclicLR(opt,gamma=gamma,step_size=stepsize)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3b1a8e3fc3372d3717af7d650400bd72173feffa"},"cell_type":"code","source":"def train_model(model, dataloaders, dataset_sizes, criterion, optimizer, scheduler, use_gpu=True, num_epochs=25, mixup = False, alpha = 0.1):\n    print(\"MIXUP\".format(mixup))\n    since = time.time()\n    best_model_wts = model.state_dict()\n    best_acc = 0.0\n\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n        print('-' * 10)\n\n        # Each epoch has a training and validation phase\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                scheduler.batch_step()\n                model.train(True)  # Set model to training mode\n            else:\n                model.train(False)  # Set model to evaluate mode\n\n            running_loss = 0.0\n            running_corrects = 0\n\n            # Iterate over data.\n            #for data in tqdm(dataloaders):\n            for i, data in enumerate(dataloaders, 0):\n                # get the inputs\n                inputs, labels = data\n                #augementation using mixup\n                #if phase == 'train' and mixup:\n                #    inputs = mixup_batch(inputs, alpha)\n                # wrap them in Variable\n                inputs = torch.from_numpy(inputs)\n                labels = torch.from_numpy(labels)\n                inputs = inputs.permute(0,3,1,2)\n                if use_gpu:\n                    inputs = Variable(inputs.cuda())\n                    labels = Variable(labels.cuda())\n                else:\n                    inputs, labels = Variable(inputs), Variable(labels)\n\n                # zero the parameter gradients\n                optimizer.zero_grad()\n\n                # forward\n                outputs = model(inputs)\n\n                if type(outputs) == tuple:\n                    outputs, _ = outputs\n                _, preds = torch.max(outputs.data, 1)\n                loss = criterion(outputs, labels)\n\n                # backward + optimize only if in training phase\n                if phase == 'train':\n                    loss.backward()\n                    optimizer.step()\n\n                # statistics\n                running_loss += loss.data[0]\n                running_corrects += torch.sum(preds == labels.data)\n\n            epoch_loss = running_loss / dataset_sizes[phase]\n            epoch_acc = running_corrects / dataset_sizes[phase]\n\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(\n                phase, epoch_loss, epoch_acc))\n\n            # deep copy the model\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = model.state_dict()\n\n        print()\n\n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(\n        time_elapsed // 60, time_elapsed % 60))\n    print('Best val Acc: {:4f}'.format(best_acc))\n\n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5fe8742ccd26083828c55365982dadc8b8209737"},"cell_type":"code","source":"import time\nimport tqdm\nuse_cuda=True\nif use_cuda:\n    model.cuda()\n    model = torch.nn.DataParallel(model, device_ids=range(torch.cuda.device_count()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a4f2dd074be99868390e984e722f35265a58fba7"},"cell_type":"code","source":"model_ft = train_model(model=model,dataloaders=dataloaders,scheduler=scheduler,dataset_sizes=3400000,criterion=criterion, optimizer=opt)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b53556bdbda07616c4c2d090dfe820c3e4faa08e"},"cell_type":"code","source":"x,y = next(iter(dataloaders))\nx = torch.from_numpy(x)\nx = x.permute(0,3,1,2)\nk = model(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a4cab58ffd79d394111e41a8922764ddd18c5b29"},"cell_type":"code","source":"x.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6e47b90f77f3bbdb9ee09dede51b01190f8bcecb"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}