{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import f1_score\nimport gensim as gn\nfrom tqdm import tqdm_notebook\n\nfrom keras.layers import LSTM,Bidirectional,TimeDistributed, Embedding,Dense,Input,GlobalMaxPool1D,Flatten,Dropout\nfrom keras.layers import CuDNNLSTM,CuDNNGRU,GlobalAveragePooling1D,GlobalMaxPooling1D,concatenate\nfrom keras.models import Sequential,Model\nfrom keras.preprocessing.text import Tokenizer\nfrom keras.preprocessing.sequence import pad_sequences\nfrom keras.callbacks import ModelCheckpoint\nfrom keras import backend as K\nfrom keras.optimizers import Adam\nfrom keras.engine.topology import Layer\nfrom keras import initializers, regularizers, constraints\nimport gc\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# build attention layer \n\nclass Attention(Layer):\n    def __init__(self, step_dim,\n                 W_regularizer=None, b_regularizer=None,\n                 W_constraint=None, b_constraint=None,\n                 bias=True, **kwargs):\n        self.supports_masking = True\n        self.init = initializers.get('glorot_uniform')\n\n        self.W_regularizer = regularizers.get(W_regularizer)\n        self.b_regularizer = regularizers.get(b_regularizer)\n\n        self.W_constraint = constraints.get(W_constraint)\n        self.b_constraint = constraints.get(b_constraint)\n\n        self.bias = bias\n        self.step_dim = step_dim\n        self.features_dim = 0\n        super(Attention, self).__init__(**kwargs)\n        \n    def build(self, input_shape):\n        assert len(input_shape) == 3\n\n        self.W = self.add_weight((input_shape[-1],),\n                                 initializer=self.init,\n                                 name='{}_W'.format(self.name),\n                                 regularizer=self.W_regularizer,\n                                 constraint=self.W_constraint)\n        self.features_dim = input_shape[-1]\n\n        if self.bias:\n            self.b = self.add_weight((input_shape[1],),\n                                     initializer='zero',\n                                     name='{}_b'.format(self.name),\n                                     regularizer=self.b_regularizer,\n                                     constraint=self.b_constraint)\n        else:\n            self.b = None\n\n        self.built = True\n        \n    def compute_mask(self, input, input_mask=None):\n        return None\n\n    def call(self, x, mask=None):\n        \n        features_dim = self.features_dim\n        step_dim = self.step_dim\n\n        eij = K.reshape(K.dot(K.reshape(x, (-1, features_dim)),\n                        K.reshape(self.W, (features_dim, 1))), (-1, step_dim))\n\n        if self.bias:\n            eij += self.b\n\n        eij = K.tanh(eij)\n\n        a = K.exp(eij)\n\n        if mask is not None:\n            a *= K.cast(mask, K.floatx())\n\n        a /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx())\n\n        a = K.expand_dims(a)\n        weighted_input = x * a\n        return K.sum(weighted_input, axis=1)\n    def compute_output_shape(self, input_shape):\n        return input_shape[0], self.features_dim","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(\"../input/train.csv\")\ndf_test = pd.read_csv(\"../input/test.csv\")\ndf = pd.concat([df_train ,df_test])\n\nprint(\"Unsincere avg: \", df_train.target.mean())\nprint(\"total: \", df_train.target.count())\nprint('Test samples: ', df_test.qid.count())\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def add_lower(embedding, vocab):\n    count = 0\n    for word in vocab:\n        if word in embedding and word.lower() not in embedding:  \n            embedding[word.lower()] = embedding[word]\n            count += 1\n    print(f\"Added {count} words to embedding\")\n    \ndef build_vocab(texts):\n    sentences = texts.apply(lambda x: x.split()).values\n    vocab = {}\n    for sentence in sentences:\n        for word in sentence:\n            try:\n                vocab[word] += 1\n            except KeyError:\n                vocab[word] = 1\n    return vocab\nvocab = build_vocab(df['question_text'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"contraction_mapping = {\"ain't\": \"is not\", \"aren't\": \"are not\",\"can't\": \"cannot\", \"'cause\": \"because\", \"could've\": \"could have\",\n                       \"couldn't\": \"could not\", \"didn't\": \"did not\",  \"doesn't\": \"does not\", \"don't\": \"do not\", \"hadn't\": \"had not\", \n                       \"hasn't\": \"has not\", \"haven't\": \"have not\", \"he'd\": \"he would\",\"he'll\": \"he will\", \"he's\": \"he is\", \"how'd\": \"how did\",\n                       \"how'd'y\": \"how do you\", \"how'll\": \"how will\", \"how's\": \"how is\",  \"I'd\": \"I would\", \"I'd've\": \"I would have\", \"I'll\": \"I will\", \n                       \"I'll've\": \"I will have\",\"I'm\": \"I am\", \"I've\": \"I have\", \"i'd\": \"i would\", \"i'd've\": \"i would have\", \"i'll\": \"i will\", \n                       \"i'll've\": \"i will have\",\"i'm\": \"i am\", \"i've\": \"i have\", \"isn't\": \"is not\", \"it'd\": \"it would\", \"it'd've\": \"it would have\", \n                       \"it'll\": \"it will\", \"it'll've\": \"it will have\",\"it's\": \"it is\", \"let's\": \"let us\", \"ma'am\": \"madam\", \"mayn't\": \"may not\", \n                       \"might've\": \"might have\",\"mightn't\": \"might not\",\"mightn't've\": \"might not have\", \"must've\": \"must have\", \"mustn't\": \"must not\",\n                       \"mustn't've\": \"must not have\", \"needn't\": \"need not\", \"needn't've\": \"need not have\",\"o'clock\": \"of the clock\", \"oughtn't\": \"ought not\", \n                       \"oughtn't've\": \"ought not have\", \"shan't\": \"shall not\", \"sha'n't\": \"shall not\", \"shan't've\": \"shall not have\", \"she'd\": \"she would\",\n                       \"she'd've\": \"she would have\", \"she'll\": \"she will\", \"she'll've\": \"she will have\", \"she's\": \"she is\", \"should've\": \"should have\",\n                       \"shouldn't\": \"should not\", \"shouldn't've\": \"should not have\", \"so've\": \"so have\",\"so's\": \"so as\", \"this's\": \"this is\",\"that'd\": \"that would\",\n                       \"that'd've\": \"that would have\", \"that's\": \"that is\", \"there'd\": \"there would\", \"there'd've\": \"there would have\", \"there's\": \"there is\",\n                       \"here's\": \"here is\",\"they'd\": \"they would\", \"they'd've\": \"they would have\", \"they'll\": \"they will\", \"they'll've\": \"they will have\",\n                       \"they're\": \"they are\", \"they've\": \"they have\", \"to've\": \"to have\", \"wasn't\": \"was not\", \"we'd\": \"we would\", \"we'd've\": \"we would have\",\n                       \"we'll\": \"we will\", \"we'll've\": \"we will have\", \"we're\": \"we are\", \"we've\": \"we have\", \"weren't\": \"were not\", \"what'll\": \"what will\", \n                       \"what'll've\": \"what will have\", \"what're\": \"what are\",  \"what's\": \"what is\", \"what've\": \"what have\", \"when's\": \"when is\",\n                       \"when've\": \"when have\", \"where'd\": \"where did\", \"where's\": \"where is\", \"where've\": \"where have\", \"who'll\": \"who will\",\n                       \"who'll've\": \"who will have\", \"who's\": \"who is\", \"who've\": \"who have\", \"why's\": \"why is\", \"why've\": \"why have\", \"will've\": \"will have\",\n                       \"won't\": \"will not\", \"won't've\": \"will not have\", \"would've\": \"would have\", \"wouldn't\": \"would not\", \"wouldn't've\": \"would not have\", \n                       \"y'all\": \"you all\", \"y'all'd\": \"you all would\",\"y'all'd've\": \"you all would have\",\"y'all're\": \"you all are\",\"y'all've\": \"you all have\",\n                       \"you'd\": \"you would\", \"you'd've\": \"you would have\", \"you'll\": \"you will\", \"you'll've\": \"you will have\", \"you're\": \"you are\",\n                       \"you've\": \"you have\" }","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def clean_contractions(text, mapping):\n    specials = [\"’\", \"‘\", \"´\", \"`\"]\n    for s in specials:\n        text = text.replace(s, \"'\")\n    text = ' '.join([mapping[t] if t in mapping else t for t in text.split(\" \")])\n    return text","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"punct = \"/-'?!.,#$%\\'()*+-/:;<=>@[\\\\]^_`{|}~\" + '\"\"“”’' + '∞θ÷α•à−β∅³π‘₹´°£€\\×™√²—–&'\npunct_mapping = {\"‘\": \"'\", \"₹\": \"e\", \"´\": \"'\", \"°\": \"\", \"€\": \"e\", \"™\": \"tm\", \"√\": \" sqrt \", \"×\": \"x\", \"²\": \"2\", \"—\": \"-\",\n                 \"–\": \"-\", \"’\": \"'\", \"_\": \"-\", \"`\": \"'\", '“': '\"', '”': '\"', '“': '\"', \"£\": \"e\", '∞': 'infinity',\n                 'θ': 'theta', '÷': '/', 'α': 'alpha', '•': '.', 'à': 'a', '−': '-', 'β': 'beta', '∅': '', '³': '3',\n                 'π': 'pi', }","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def clean_special_chars(text, punct, mapping):\n    for p in mapping:\n        text = text.replace(p, mapping[p])\n    \n    for p in punct:\n        text = text.replace(p, f' {p} ')\n    \n    specials = {'\\u200b': ' ', '…': ' ... ', '\\ufeff': '', 'करना': '', 'है': ''}  # Other special characters that I have to deal with in last\n    for s in specials:\n        text = text.replace(s, specials[s])\n    \n    return text","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mispell_dict = {'colour': 'color', 'centre': 'center', 'favourite': 'favorite', 'travelling': 'traveling',\n                'counselling': 'counseling', 'theatre': 'theater', 'cancelled': 'canceled', 'labour': 'labor',\n                'organisation': 'organization', 'wwii': 'world war 2', 'citicise': 'criticize', 'youtu ': 'youtube ', \n                'Qoura': 'Quora', 'sallary': 'salary', 'Whta': 'What', 'narcisist': 'narcissist', 'howdo': 'how do',\n                'whatare': 'what are', 'howcan': 'how can', 'howmuch': 'how much', 'howmany': 'how many', 'whydo': 'why do',\n                'doI': 'do I', 'theBest': 'the best', 'howdoes': 'how does', 'mastrubation': 'masturbation', 'mastrubate': 'masturbate',\n                \"mastrubating\": 'masturbating', 'pennis': 'penis', 'Etherium': 'Ethereum', 'narcissit': 'narcissist',\n                'bigdata': 'big data', '2k17': '2017', '2k18': '2018', 'qouta': 'quota', 'exboyfriend': 'ex boyfriend', \n                'airhostess': 'air hostess', \"whst\": 'what', 'watsapp': 'whatsapp', 'demonitisation': 'demonetization', \n                'demonitization': 'demonetization', 'demonetisation': 'demonetization', 'pokémon': 'pokemon'}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def correct_spelling(x, dic):\n    for word in dic.keys():\n        x = x.replace(word, dic[word])\n    return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Lowering\ndf_train['treated_question'] = df_train['question_text'].apply(lambda x: x.lower())\ndf_test['treated_question'] = df_test['question_text'].apply(lambda x: x.lower())\n# Contractions\ndf_train['treated_question'] = df_train['treated_question'].apply(lambda x: clean_contractions(x, contraction_mapping))\ndf_test['treated_question'] = df_test['treated_question'].apply(lambda x: clean_contractions(x, contraction_mapping))\n\n# Special characters\ndf_train['treated_question'] = df_train['treated_question'].apply(lambda x: clean_special_chars(x, punct, punct_mapping))\ndf_test['treated_question'] = df_test['treated_question'].apply(lambda x: clean_special_chars(x, punct, punct_mapping))\n\n# Spelling mistakes\ndf_train['treated_question'] = df_train['treated_question'].apply(lambda x: correct_spelling(x, mispell_dict))\ndf_test['treated_question'] = df_test['treated_question'].apply(lambda x: correct_spelling(x, mispell_dict))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train, val = train_test_split(df_train, test_size=0.1, random_state=42)\n\nn_words = 50000\ntokenizer = Tokenizer(num_words=n_words)\ntokenizer.fit_on_texts(list(train.treated_question))\n\nq_train = tokenizer.texts_to_sequences(train.treated_question)\nq_val = tokenizer.texts_to_sequences(val.treated_question)\nq_test = tokenizer.texts_to_sequences(df_test.treated_question)\n\nmax_len = 100\nq_train = pad_sequences(q_train,maxlen=max_len)\nq_val = pad_sequences(q_val,maxlen=max_len)\nq_test = pad_sequences(q_test,maxlen=max_len)\n\ny_train = train.target\ny_val = val.target\n\ndel train,val,df_train,df\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def f1(y_true, y_pred):\n    def recall(y_true, y_pred):\n        \"\"\"Recall metric.\n\n        Only computes a batch-wise average of recall.\n\n        Computes the recall, a metric for multi-label classification of\n        how many relevant items are selected.\n        \"\"\"\n        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))\n        recall = true_positives / (possible_positives + K.epsilon())\n        return recall\n\n    def precision(y_true, y_pred):\n        \"\"\"Precision metric.\n\n        Only computes a batch-wise average of precision.\n\n        Computes the precision, a metric for multi-label classification of\n        how many selected items are relevant.\n        \"\"\"\n        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))\n        precision = true_positives / (predicted_positives + K.epsilon())\n        return precision\n    precision = precision(y_true, y_pred)\n    recall = recall(y_true, y_pred)\n    return 2*((precision*recall)/(precision+recall+K.epsilon()))\n\n#find the best threshold\ndef optim_thres(y_val,y_pred):\n    score = 0\n    thresholds = np.arange(0.1,0.501,0.01)\n    for thres in thresholds:\n        thres = np.round(thres,2)\n        temp_pred = (y_pred > thres).astype(int)\n        temp_score = f1_score(y_val,temp_pred)\n        print(\"Thres: {} --------- F1: {}\".format(thres,temp_score))\n        if temp_score > score:\n            score = temp_score\n            final_thres = thres\n    return final_thres","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# try to mix all embeddings \n# first read & fit a model with all of them \n\nemb_file = \"../input/embeddings/glove.840B.300d/glove.840B.300d.txt\"\nglove_dic = {}\nfor line in tqdm_notebook(open(emb_file)):\n    temp = line.split(\" \")\n    glove_dic[temp[0]] = np.asarray(temp[1:],dtype='float32')\nadd_lower(glove_dic, vocab)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"word_index = tokenizer.word_index\nemb_size = glove_dic['.'].shape[0]\nemb_matrix = np.zeros((n_words,emb_size))\nfor w,index in word_index.items():\n    if index >= n_words:\n        continue\n    vec = glove_dic.get(w)\n    if vec is not None:\n        emb_matrix[index,:] = vec\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"inp = Input(shape=(max_len,))\nx = Embedding(input_dim=n_words,output_dim=emb_size, weights=[emb_matrix],trainable=False)(inp)\nx1 = Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)\nx2 = Bidirectional(CuDNNGRU(128, return_sequences=True))(x)\nx1 = GlobalAveragePooling1D()(x1)\nx2 = GlobalAveragePooling1D()(x2)\nconcat = concatenate([x1, x2])\nx = Dense(64, activation=\"relu\")(concat)\ndrop = Dropout(0.1)(x)\nx = Dense(1, activation='sigmoid')(x)\nmodel = Model(inputs=inp,output=x)\nmodel.summary()\nmodel_name = 'lstm_glove_emb'\ncheckpoint = ModelCheckpoint(filepath='./{}.hdf5'.format(model_name),\n                             monitor='val_loss',mode='min',verbose=1,\n                            save_best_only=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc',f1])\nhistory  = model.fit(q_train,y_train,batch_size=1500,epochs=5,\n                     validation_data=(q_val,y_val),verbose=1,callbacks=[checkpoint])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del glove_dic\ngc.collect()\nmodel.load_weights('./{}.hdf5'.format(model_name))\ny_pred_glove = model.predict(q_val,batch_size=1064,verbose=1)\npred_glove = model.predict(q_test,batch_size=1064,verbose=1)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"emb_file = \"../input/embeddings/paragram_300_sl999/paragram_300_sl999.txt\"\nemb_dic = {}\nfor line in tqdm_notebook(open(emb_file,encoding='utf-8',errors='ignore')):\n    temp = line.split(\" \")\n    emb_dic[temp[0]] = np.asarray(temp[1:],dtype='float32')\n    \nemb_matrix = np.zeros((n_words,emb_size))\nfor w,index in word_index.items():\n    if index >= n_words:\n        continue\n    vec = emb_dic.get(w)\n    if vec is not None:\n        emb_matrix[index,:] = vec","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"inp = Input(shape=(max_len,))\nx = Embedding(input_dim=n_words,output_dim=emb_size, weights=[emb_matrix],trainable=False)(inp)\nx1 = Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)\nx2 = Bidirectional(CuDNNGRU(128, return_sequences=True))(x)\nx1 = GlobalAveragePooling1D()(x1)\nx2 = GlobalAveragePooling1D()(x2)\nconcat = concatenate([x1, x2])\nx = Dense(64, activation=\"relu\")(concat)\ndrop = Dropout(0.1)(x)\nx = Dense(1, activation='sigmoid')(x)\nmodel = Model(inputs=inp,output=x)\nmodel.summary()\nmodel_name = 'lstm_paragram_emb'\ncheckpoint = ModelCheckpoint(filepath='./{}.hdf5'.format(model_name),\n                             monitor='val_loss',mode='min',verbose=1,\n                            save_best_only=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nmodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc',f1])\nhistory  = model.fit(q_train,y_train,batch_size=1500,epochs=5,\n                     validation_data=(q_val,y_val),verbose=1,callbacks=[checkpoint])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del emb_dic\ngc.collect()\nmodel.load_weights('./{}.hdf5'.format(model_name))\ny_pred_paragram = model.predict(q_val,batch_size=1064,verbose=1)\npred_paragram = model.predict(q_test,batch_size=1064,verbose=1)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"emb_file = '../input/embeddings/wiki-news-300d-1M/wiki-news-300d-1M.vec'\nemb_dic = {}\nfor line in tqdm_notebook(open(emb_file,encoding='utf-8',errors='ignore')):\n    temp = line.split(\" \")\n    emb_dic[temp[0]] = np.asarray(temp[1:],dtype='float32')\n    \nemb_matrix = np.zeros((n_words,emb_size))\nfor w,index in word_index.items():\n    if index >= n_words:\n        continue\n    vec = emb_dic.get(w)\n    if vec is not None:\n        emb_matrix[index,:] = vec","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"inp = Input(shape=(max_len,))\nx = Embedding(input_dim=n_words,output_dim=emb_size, weights=[emb_matrix])(inp)\nx1 = Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)\nx2 = Bidirectional(CuDNNGRU(128, return_sequences=True))(x)\nx1 = GlobalAveragePooling1D()(x1)\nx2 = GlobalAveragePooling1D()(x2)\nconcat = concatenate([x1, x2])\nx = Dense(64, activation=\"relu\")(concat)\ndrop = Dropout(0.1)(x)\nx = Dense(1, activation='sigmoid')(x)\nmodel = Model(inputs=inp,output=x)\nmodel.summary()\nmodel_name = 'lstm_wiki_emb'\ncheckpoint = ModelCheckpoint(filepath='./{}.hdf5'.format(model_name),\n                             monitor='val_loss',mode='min',verbose=1,\n                            save_best_only=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nmodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc',f1])\nhistory  = model.fit(q_train,y_train,batch_size=1500,epochs=5,\n                     validation_data=(q_val,y_val),verbose=1,callbacks=[checkpoint])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del emb_dic\ngc.collect()\nmodel.load_weights('./{}.hdf5'.format(model_name))\ny_pred_wiki = model.predict(q_val,batch_size=1064,verbose=1)\npred_wiki = model.predict(q_test,batch_size=1064,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_pred_all = np.mean(np.array([y_pred_glove,y_pred_paragram,y_pred_wiki]),axis=0)\nprint(y_pred_all.shape)\nfinal_thresh = optim_thres(y_val,y_pred_all)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"final_pred = np.mean(np.array([pred_glove,pred_paragram,pred_wiki]),axis=0)\nsub_pred = (final_pred > final_thresh).astype(int)\nsub = pd.DataFrame({\"qid\":df_test[\"qid\"].values})\nsub['prediction'] = sub_pred\nsub.to_csv(\"submission.csv\", index=False)","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}