{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8f22b80585064e28665a7f01bd619e479d388fa0"},"cell_type":"code","source":"WEIGHT_FILE = '../input/embeddings/glove.840B.300d/glove.840B.300d.txt'\nTRAIN_FILE = '../input/train.csv'\nTEST_FILE = '../input/test.csv'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"840fc236b521dd52ee9c9bcc548a71f0dcf9efa3"},"cell_type":"code","source":"import re\nimport unicodedata\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom nltk.tokenize import wordpunct_tokenize\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence\n\nfrom sklearn.metrics import f1_score\nfrom matplotlib import pyplot as plt\nimport torch","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5d685bfdde1bdb76660023c40e79391be4af8c0e"},"cell_type":"markdown","source":"# Dataset Reader"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"class Dataset:\n\n    def __init__(self,\n                 train_df,\n                 test_df,\n                 input_field='question_text',\n                 target_filed='target',\n                 validation_size=0.1,\n                 clean_function=None,\n                 verbose=False):\n\n        self.input_field = input_field\n        self.target_filed = target_filed\n        self.validation_size = validation_size\n        self.verbose = verbose\n\n        self.train = None\n        self.validation = None\n        self.test = None\n\n        self.test_qid = []\n\n        self.clean_function = clean_function if clean_function is not None else lambda x: x\n        self.words = set()\n\n        self.init_data(train_df, test_df)\n\n    def init_data(self, train_df, test_df, validation_size=None):\n\n        validation_size = validation_size if validation_size is not None else self.validation_size\n\n        train_df, validation_df = train_test_split(train_df,\n                                                   test_size=validation_size,\n                                                   stratify=train_df[self.target_filed])\n\n        self.train = self._form_data_field(df=train_df, title='Collect train')\n        self.validation = self._form_data_field(df=validation_df, title='Collect validation')\n        self.test = self._form_data_field(df=test_df, title='Collect test')\n        self.test_qid = test_df.qid\n\n    def _form_data_field(self, df, title=''):\n\n        data = []\n\n        indexes = tqdm(df.index, desc=title) if self.verbose else df.index\n\n        for index in indexes:\n\n            if len(df.loc[index, self.input_field]) <= 3:\n                continue\n\n            text = wordpunct_tokenize(self.clean_function(df.loc[index, self.input_field]))\n\n            for word in text:\n                self.words.add(word)\n\n            target = df.loc[index, self.target_filed] if self.target_filed in df else False\n\n            if not text:\n                continue\n\n            sample = {\n                self.input_field: text,\n                self.target_filed: target\n            }\n\n            data.append(sample)\n\n        return data\n\n    def batch_generator(self, data_type, batch_size=32, sequence_max_length=None):\n\n        data = self.__dict__[data_type]\n\n        for n_batch in range(len(data) // batch_size):\n\n            batch = data[n_batch * batch_size:(n_batch + 1) * batch_size]\n\n            sequence_max_length = sequence_max_length if sequence_max_length is not None else -1\n\n            x = [sample[self.input_field][:sequence_max_length] for sample in batch]\n\n            y = [sample[self.target_filed] for sample in batch]\n\n            yield x, y","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3974387d32c392937eaef86b75b1f38ba73239e0"},"cell_type":"markdown","source":"# Simple Text Cleaner"},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true,"_uuid":"dfb34cf4036da6e39b081288229e40415a2ac97a"},"cell_type":"code","source":"class Cleaner:\n\n    def __init__(self):\n\n        pass\n\n    @staticmethod\n    def unicode_to_ascii(x):\n\n        return ''.join(\n            c for c in unicodedata.normalize('NFD', x)\n            if unicodedata.category(c) != 'Mn'\n        )\n\n    @staticmethod\n    def normalize_string(x):\n\n        x = re.sub(r\"([.!?])\", r\" .\", x)\n        x = re.sub('[0-9]{5,}', '#####', x)\n        x = re.sub('[0-9]{4}', '####', x)\n        x = re.sub('[0-9]{3}', '###', x)\n        x = re.sub('[0-9]{2}', '##', x)\n        s = re.sub(r\"[^a-zA-Z.#]+\", r\" \", x)\n\n        return s\n\n    def clean(self, sentence):\n\n        x = sentence.strip().lower()\n        x = self.unicode_to_ascii(x)\n        x = self.normalize_string(x)\n\n        return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c85871377daf572ed6078046c334a352450d3838"},"cell_type":"markdown","source":"# Model Wrapper"},{"metadata":{"trusted":true,"_uuid":"1df7210efb27cc04d4bc7afa14d615bd65a5fecc","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"class Wrapper:\n\n    def __init__(self, dataset, model, model_name, criterion, optimizer, sequence_max_length=32):\n\n        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n        self.dataset = dataset\n\n        self.model = model.to(self.device)\n        self.model_name = model_name\n        self.criterion = criterion\n        self.optimizer = optimizer\n\n        self.sequence_max_length = sequence_max_length\n\n        self.losses = []\n        self.batch_mean_losses = []\n\n        self.f1 = []\n        self.best_f1 = 0\n        self.best_threshold = 0\n        self.best_epoch = 0\n\n        self.batch_size = 0\n        self.epochs = 0\n\n    @staticmethod\n    def search_best_threshold_for_f1_score(y_prediction, y_true):\n\n        y_prediction = y_prediction.cpu().detach().numpy()\n        y_true = y_true.cpu().detach().numpy().astype(int)\n\n        best_f1, best_thresh = 0, 0\n\n        for thresh in np.arange(0.1, 0.501, 0.01):\n\n            thresh = np.round(thresh, 2)\n\n            pred = (y_prediction > thresh).astype(int)\n\n            if len(pd.Series(pred).value_counts()) > 1:\n\n                f1 = f1_score(y_true, pred)\n\n                if f1 > best_f1:\n                    best_thresh = thresh\n                    best_f1 = f1\n\n        return best_f1, best_thresh\n\n    def train(self, epochs=5, batch_size=32, verbose=False, save=False):\n\n        self.epochs = epochs\n        self.batch_size = batch_size\n\n        self.losses = []\n        self.batch_mean_losses = []\n\n        for n_epoch in range(1, self.epochs+1):\n\n            if verbose:\n                pbar = tqdm(total=len(self.dataset.train) // self.batch_size, desc='Train Epoch {}'.format(n_epoch))\n\n            batch_losses = []\n\n            for x, y in self.dataset.batch_generator(data_type='train',\n                                                     batch_size=self.batch_size):\n\n                y_prediction, y = self.model(x, y)\n\n                loss = self.criterion(y_prediction, y)\n\n                self.losses.append(loss.item())\n                batch_losses.append(loss.item())\n\n                self.optimizer.zero_grad()\n                loss.backward()\n                self.optimizer.step()\n\n                if verbose:\n                    pbar.update(1)\n\n            batch_mean_loss = np.mean(batch_losses)\n\n            self.batch_mean_losses.append(batch_mean_loss)\n\n            if verbose:\n                pbar.close()\n\n            with torch.no_grad():\n\n                y_validation_prediction = torch.Tensor().to(self.device)\n                y_validation = torch.Tensor().to(self.device)\n\n                if verbose:\n                    pbar = tqdm(total=len(self.dataset.validation) // self.batch_size,\n                                desc='Validation Epoch {}'.format(n_epoch))\n\n                for x, y in self.dataset.batch_generator(data_type='validation', batch_size=self.batch_size):\n\n                    y_prediction, y = self.model(x, y)\n\n                    y_validation_prediction = torch.cat((y_validation_prediction, y_prediction))\n                    y_validation = torch.cat((y_validation, y))\n\n                    if verbose:\n                        pbar.update(1)\n\n            if verbose:\n                pbar.close()\n\n            f1, threshold = self.search_best_threshold_for_f1_score(y_validation_prediction, y_validation)\n\n            if f1 > self.best_f1:\n                self.best_f1 = f1\n                self.best_threshold = threshold\n                self.best_epoch = n_epoch\n                \n                if save:\n                    self.save_model()\n\n            self.f1.append(f1)\n\n            message = 'Epoch: [{}/{}] | Loss: {:.5f} | F1 Score: {:3f} | Threshold: {}'.format(\n                n_epoch,\n                self.epochs,\n                batch_mean_loss,\n                f1,\n                threshold,\n            )\n\n            if verbose:\n                print(message)\n\n    def save_model(self):\n\n        state_dict = {\n            'epoch': self.best_epoch,\n            'f1': self.best_f1,\n            'threshold': self.best_threshold,\n            'model_state_dict': self.model.state_dict(),\n            'optimizer_state_dict': self.optimizer.state_dict(),\n            'losses': self.batch_mean_losses,\n        }\n\n        directory = 'models_checkpoints/{}/'.format(self.model_name)\n\n        try:\n            os.mkdir(directory)\n        except FileExistsError:\n            pass\n\n        torch.save(state_dict, directory + 'best.pt')\n\n    def load_model(self, file=None):\n\n        file = file if file is not None else 'models_checkpoints/{}/best.pt'.format(self.model_name)\n\n        checkpoint = torch.load(file)\n\n        self.model.load_state_dict(checkpoint['model_state_dict'])\n        self.optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n\n        self.best_epoch = checkpoint['epoch']\n        self.best_f1 = checkpoint['f1']\n        self.best_threshold = checkpoint['threshold']\n\n        self.losses = checkpoint['losses']\n\n    def plot_losses(self, losses_type='batch_mean_losses', figsize=(16, 14), xlabel='Epoch'):\n\n        losses = self.__dict__[losses_type]\n\n        plt.figure(figsize=figsize)\n\n        plt.plot([0] + losses)\n\n        plt.title('Losses')\n        plt.xlabel(xlabel)\n        plt.ylabel('Loss')\n\n        plt.grid()\n\n        plt.ylim(0, np.max(losses) * 1.2)\n        plt.xlim(1, len(losses))\n\n    def submission(self, verbose=False):\n\n        with torch.no_grad():\n\n            y_test_prediction = torch.Tensor().to(self.device)\n\n            if verbose:\n                pbar = tqdm(total=len(self.dataset.test),\n                            desc='Test')\n\n            for x, y in self.dataset.batch_generator(data_type='test', batch_size=1):\n\n                y_prediction, _ = self.model(x, y)\n\n                y_test_prediction = torch.cat((y_test_prediction, y_prediction))\n\n                if verbose:\n                    pbar.update(1)\n\n        if verbose:\n            pbar.close()\n\n        y_test_prediction = y_test_prediction.cpu().detach().numpy()\n\n        submission = pd.DataFrame(data={\n            'qid': self.dataset.test_qid,\n            'prediction': (y_test_prediction > self.best_threshold).astype(int)\n        })\n\n        return submission","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"911ff9bb5c48ba8a3c8907af8f002c0d47fad07f"},"cell_type":"markdown","source":"# Pretrained Embedding Layer"},{"metadata":{"trusted":true,"_uuid":"32def44ef11c31378fbd95a481527538bb86cefd","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"class EmbeddingFromPretrained(nn.Module):\n\n    def __init__(self,\n                 weight_file,\n                 vector_size,\n                 sequence_max_length=64,\n                 pad_token='PAD',\n                 pad_after=True,\n                 existing_words=None,\n                 verbose=False):\n\n        super(EmbeddingFromPretrained, self).__init__()\n\n        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n        self.weight_file = weight_file\n        self.vector_size = vector_size\n        self.sequence_max_length = sequence_max_length\n\n        self.pad_token = pad_token\n        self.pad_index = 0\n\n        self.pad_after = pad_after\n\n        self.existing_words = existing_words if existing_words is not None else []\n\n        self.word2index = {\n            self.pad_token: self.pad_index\n        }\n\n        self.index2word = {\n            self.pad_index: self.pad_token\n        }\n\n        self.embedding_layer = self.__collect_embeddings__(verbose=verbose)\n\n    def __collect_embeddings__(self, verbose=False):\n\n        embedding_matrix = [np.zeros(shape=(self.vector_size, ))]\n\n        with open(file=self.weight_file, mode='r', encoding='utf-8', errors='ignore') as file:\n\n            index = len(self.word2index)\n\n            lines = tqdm(file.readlines(), desc='Collect embeddings') if verbose else file.readlines()\n\n            for line in lines:\n\n                line = line.split()\n\n                word = ' '.join(line[:-self.vector_size])\n                embeddings = np.asarray(line[-self.vector_size:], dtype='float32')\n\n                if not word or embeddings.shape[0] != self.vector_size or word not in self.existing_words:\n                    continue\n\n                self.word2index[word] = index\n                self.index2word[index] = word\n\n                embedding_matrix.append(embeddings)\n\n                index += 1\n\n        return torch.nn.Embedding.from_pretrained(torch.Tensor(embedding_matrix)).to(self.device)\n\n    def forward(self, input_batch, targets_batch):\n\n        sequence_max_length = self.sequence_max_length if self.sequence_max_length is not None \\\n            else max([len(sample) for sample in input_batch])\n\n        sequence_lengths = []\n\n        embedded_batch = torch.Tensor(size=(len(input_batch), sequence_max_length, self.vector_size)).to(self.device)\n\n        for n_sample in range(len(input_batch)):\n\n            tokens = [self.word2index[token] for token in input_batch[n_sample] if token in self.word2index]\n            tokens = tokens[:sequence_max_length]\n\n            if not tokens:\n                targets_batch.pop(n_sample)\n                continue\n\n            sequence_lengths.append(len(tokens))\n\n            if len(tokens) < sequence_max_length:\n\n                pads = [self.pad_index] * (sequence_max_length - len(tokens))\n\n                if self.pad_after:\n                    tokens = tokens + pads\n                else:\n                    tokens = pads + tokens\n\n            tokens = torch.LongTensor(tokens).to(self.device)\n\n            embedded_batch[n_sample] = self.embedding_layer(tokens).to(self.device)\n\n        targets_batch = torch.Tensor(targets_batch).to(self.device)\n\n        if embedded_batch.sum() == 0:\n            return None, None, None\n\n        sequence_lengths = torch.Tensor(sequence_lengths)\n\n        sequence_lengths, permutation_idx = sequence_lengths.sort(descending=True)\n\n        embedded_batch = embedded_batch[permutation_idx]\n        sequence_lengths = sequence_lengths.to(self.device)\n        targets_batch = targets_batch[permutation_idx]\n\n        return embedded_batch, sequence_lengths, targets_batch","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b1286ccd3ce369578ef105cafef26e8ff2bbe37c"},"cell_type":"markdown","source":"# Fully connected Neural Network"},{"metadata":{"trusted":true,"_uuid":"c20d6019062fcff0a2cb5eb2426874d418037d64","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"class NeuralNetwork(nn.Module):\n\n    def __init__(self,\n                 sizes,\n                 activation_function=F.relu,\n                 sigmoid_output=False):\n\n        super(NeuralNetwork, self).__init__()\n\n        self.sizes = list(sizes)\n        self.activation_function = activation_function\n        self.sigmoid_output = sigmoid_output\n\n        if self.sizes[-1] != 1 and self.sigmoid_output:\n            self.sizes.append(1)\n\n        self.input_size = self.sizes[0]\n        self.output_size = self.sizes[-1]\n\n        self.linear_1 = nn.Linear(in_features=self.sizes[0], out_features=self.sizes[1])\n\n        if len(self.sizes) > 3:\n            self.linear_2 = nn.Linear(in_features=self.sizes[1], out_features=self.sizes[2])\n\n        if len(self.sizes) > 4:\n            self.linear_3 = nn.Linear(in_features=self.sizes[2], out_features=self.sizes[3])\n\n        if len(self.sizes) > 5:\n            self.linear_4 = nn.Linear(in_features=self.sizes[3], out_features=self.sizes[4])\n\n        self.linear_last = nn.Linear(in_features=self.sizes[-2], out_features=self.sizes[-1])\n\n        # its not work\n        #\n        # self.layers = []\n        # for n in range(len(self.sizes[:-1])):\n        #     self.__dict__['linear_layer_{}'.format(n)] = nn.Linear(in_features=self.sizes[n],\n        #                                                            out_features=self.sizes[n+1])\n        #     self.layers.append(self.__dict__['linear_layer_{}'.format(n)])\n\n    def forward(self, x, x_lengths=None):\n\n        # for n, layer in enumerate(self.layers):\n        #\n        #     x = layer.forward(x)\n        #\n        #     if n == len(self.sizes) and self.sigmoid_output:\n        #         x = torch.sigmoid(x)\n        #         return x[:, 0]\n        #\n        #     else:\n        #         x = self.activation_function(x)\n\n        x = self.linear_1(x)\n        x = self.activation_function(x)\n\n        if len(self.sizes) > 3:\n            x = self.linear_2(x)\n            x = self.activation_function(x)\n\n        if len(self.sizes) > 4:\n            x = self.linear_3(x)\n            x = self.activation_function(x)\n\n        if len(self.sizes) > 5:\n            x = self.linear_4(x)\n            x = self.activation_function(x)\n\n        x = self.linear_last(x)\n        x = torch.sigmoid(x)\n\n        return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"1968829e97e3dd1ae79b1a53030d0317b6a32b01"},"cell_type":"markdown","source":"# Deep Average Network\n\nhttp://www.aclweb.org/anthology/P15-1162"},{"metadata":{"trusted":true,"_uuid":"ae4fb5a9f6f8a0a800fed0f5f2b640d848a23871","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"class DAN(nn.Module):\n\n    def __init__(self,\n                 embedding_layer=None,\n                 weight_file=None,\n                 embedding_size=300,\n                 sizes=(300, 128, 64),\n                 activation_function=F.relu,\n                 sigmoid_output=True):\n\n        super(DAN, self).__init__()\n\n        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n        if embedding_layer is not None:\n            self.embedding_layer = embedding_layer\n        elif weight_file is not None:\n            self.embedding_layer = EmbeddingFromPretrained(weight_file=weight_file, vector_size=embedding_size)\n        else:\n            raise ValueError('Need embedding layer or weight file')\n\n        self.embedding_layer = self.embedding_layer.to(self.device)\n\n        self.neural_network = NeuralNetwork(sizes=sizes,\n                                            activation_function=activation_function,\n                                            sigmoid_output=sigmoid_output).to(self.device)\n\n    def forward(self, tokens, target):\n\n        x, _, y = self.embedding_layer(tokens, target)\n\n        x = x.mean(dim=1)\n\n        x = self.neural_network(x)\n\n        return x[:, 0], y","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"97fc28dc1444179bec92970f1d273f16ca21a521"},"cell_type":"markdown","source":"# Import Data"},{"metadata":{"trusted":true,"_uuid":"78fe1525657cc7f80ecb32cd2979c42da0af27ee"},"cell_type":"code","source":"train_df = pd.read_csv(TRAIN_FILE)\ntest_df = pd.read_csv(TEST_FILE)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2fde990e0a5fda95c0c68770e0b6feb692721a54"},"cell_type":"markdown","source":"# Prepare Dataset"},{"metadata":{"trusted":true,"_uuid":"e287af7210cef8f4781de6e4a21bf5d0143714ed"},"cell_type":"code","source":"cleaner = Cleaner()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"881f094d69a7a880ff3af983e66bf791f71ea934"},"cell_type":"code","source":"dataset = Dataset(train_df=train_df, test_df=test_df, verbose=True, validation_size=0.1, clean_function=cleaner.clean)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8b1cccfe9866d597181bc72b7ae51cef9650018b"},"cell_type":"markdown","source":"# Load Embeddings"},{"metadata":{"trusted":true,"_uuid":"b206e87091c1ef5594f91f2bb46aa8b963bba2de","scrolled":false},"cell_type":"code","source":"embedding_layer = EmbeddingFromPretrained(weight_file=WEIGHT_FILE, vector_size=300, existing_words=dataset.words, verbose=True)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"007c3ef8c314ac875585f71d63661823d8297e3a"},"cell_type":"markdown","source":"# Model settings"},{"metadata":{"trusted":true,"_uuid":"f5272fc232480427f74916c8d88ab2d84a0bb8f5"},"cell_type":"code","source":"dan = DAN(\n    sizes=[embedding_layer.vector_size, 256, 128, 64, 32],\n    embedding_layer=embedding_layer\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4de9bdb2253b589719a93564db0ab5b711303729"},"cell_type":"code","source":"criterion = torch.nn.modules.loss.BCELoss()\noptimizer = torch.optim.Adam(dan.parameters())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"492eede0533437c4ec4efdb1ef452ec8f65e5b03"},"cell_type":"code","source":"EPOCHS = 7\nBATCH_SIZE = 32","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8ca996da13862c114aa23460a318b1a7b1a4e815"},"cell_type":"markdown","source":"# Wrap model"},{"metadata":{"trusted":true,"_uuid":"bfaf5b22e2dee3433e15748233419a10b49b2b82"},"cell_type":"code","source":"dan_wrapper = Wrapper(dataset=dataset,\n                      model=dan, \n                      model_name='DAN',\n                      criterion=criterion, \n                      optimizer=optimizer)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3962934a1632404f6a2a66c577459406c537385b"},"cell_type":"markdown","source":"# Check model architecture"},{"metadata":{"trusted":true,"_uuid":"a1dce624cf448e7202a0e835e572dcd8c21023b9"},"cell_type":"code","source":"dan_wrapper.model","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ccac24b6e25e89d4553e35dcc337a8eefe2c546e"},"cell_type":"markdown","source":"# Train"},{"metadata":{"trusted":true,"_uuid":"ca890f9abf5613984d12cf8eaf1b8b3b8b69a46b"},"cell_type":"code","source":"dan_wrapper.train(epochs=EPOCHS, batch_size=BATCH_SIZE, verbose=True, save=False)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0a2a6f831c17399b7a2171a77f256e04fc613285"},"cell_type":"markdown","source":"# Plot batch mean loss"},{"metadata":{"trusted":true,"_uuid":"bff17ed1c13fd22d88dee275c00191fb5a9ae32b"},"cell_type":"code","source":"dan_wrapper.plot_losses()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"126574509150188947399373728aabdcb134e10d"},"cell_type":"code","source":"submission = dan_wrapper.submission(verbose=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0a350dfcbac2e11b2850890ef30cf8aeab938234"},"cell_type":"code","source":"submission.prediction.value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"03f46d9f09383117156c0cb684bb2b3fd4193363"},"cell_type":"code","source":"submission.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"94767c1c296511c4d1ce6207fb80ffe4966f710d"},"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}