{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"scrolled":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":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"train_df = pd.read_csv('../input/train.csv')\nX_train = train_df[\"question_text\"].fillna(\"dieter\").values\ntest_df = pd.read_csv('../input/test.csv')\nX_test = test_df[\"question_text\"].fillna(\"dieter\").values\ny = train_df[\"target\"]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d565c03e9b7b2f133e4e8f4eb0ed687c355f1fc4"},"cell_type":"code","source":"from keras.models import Model\nfrom keras.layers import Input, Dense, Embedding, concatenate\nfrom keras.layers import CuDNNGRU, Bidirectional, GlobalAveragePooling1D, GlobalMaxPooling1D, Conv1D\nfrom keras.layers import Add, BatchNormalization, Activation, CuDNNLSTM, Dropout\nfrom keras.layers import *\nfrom keras.models import *\nfrom keras.preprocessing import text, sequence\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nimport gc\nfrom sklearn import metrics","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ca0edbb51d3a75ca4d667c5eca1dcdfb916a7fa7"},"cell_type":"code","source":"maxlen = 70\nmax_features = 50000\nembed_size = 300\n\ntokenizer = text.Tokenizer(num_words=max_features)\ntokenizer.fit_on_texts(list(X_train) + list(X_test))\n\nX_train = tokenizer.texts_to_sequences(X_train)\nX_test = tokenizer.texts_to_sequences(X_test)\n\nx_train = sequence.pad_sequences(X_train, maxlen=maxlen)\nx_test = sequence.pad_sequences(X_test, maxlen=maxlen)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3f5c8eee53cf45ccfd1ce56f4011f1df00186a5e"},"cell_type":"code","source":"def attention_3d_block(inputs):\n    # inputs.shape = (batch_size, time_steps, input_dim)\n    TIME_STEPS = inputs.shape[1].value\n    SINGLE_ATTENTION_VECTOR = False\n    \n    input_dim = int(inputs.shape[2])\n    a = Permute((2, 1))(inputs)\n    a = Reshape((input_dim, TIME_STEPS))(a) # this line is not useful. It's just to know which dimension is what.\n    a = Dense(TIME_STEPS, activation='softmax')(a)\n    if SINGLE_ATTENTION_VECTOR:\n        a = Lambda(lambda x: K.mean(x, axis=1))(a)\n        a = RepeatVector(input_dim)(a)\n    a_probs = Permute((2, 1))(a)\n    output_attention_mul = Multiply()([inputs, a_probs])\n    return output_attention_mul","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"43ba65d695360fe604e235ead98e2bc38ecaeb1b"},"cell_type":"code","source":"from keras import backend as K\nfrom keras.engine.topology import Layer, InputSpec\nfrom keras import initializers\n\nclass AttLayer(Layer):\n    def __init__(self, attention_dim):\n        self.init = initializers.get('normal')\n        self.supports_masking = True\n        self.attention_dim = attention_dim\n        super(AttLayer, self).__init__()\n\n    def build(self, input_shape):\n        assert len(input_shape) == 3\n        self.W = K.variable(self.init((input_shape[-1], self.attention_dim)))\n        self.b = K.variable(self.init((self.attention_dim, )))\n        self.u = K.variable(self.init((self.attention_dim, 1)))\n        self.trainable_weights = [self.W, self.b, self.u]\n        super(AttLayer, self).build(input_shape)\n\n    def compute_mask(self, inputs, mask=None):\n        return mask\n\n    def call(self, x, mask=None):\n        # size of x :[batch_size, sel_len, attention_dim]\n        # size of u :[batch_size, attention_dim]\n        # uit = tanh(xW+b)\n        uit = K.tanh(K.bias_add(K.dot(x, self.W), self.b))\n        ait = K.dot(uit, self.u)\n        ait = K.squeeze(ait, -1)\n\n        ait = K.exp(ait)\n\n        if mask is not None:\n            # Cast the mask to floatX to avoid float64 upcasting in theano\n            ait *= K.cast(mask, K.floatx())\n        ait /= K.cast(K.sum(ait, axis=1, keepdims=True) + K.epsilon(), K.floatx())\n        ait = K.expand_dims(ait)\n        weighted_input = x * ait\n        output = K.sum(weighted_input, axis=1)\n\n        return output\n\n    def compute_output_shape(self, input_shape):\n        return (input_shape[0], input_shape[-1])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"def48377e4113ab78d5b5bafc323f36d3b9232ba"},"cell_type":"code","source":"EMBEDDING_FILE = '../input/embeddings/glove.840B.300d/glove.840B.300d.txt'\ndef get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')\nembeddings_index = dict(get_coefs(*o.split(\" \")) for o in open(EMBEDDING_FILE))\n\nall_embs = np.stack(embeddings_index.values())\nemb_mean,emb_std = all_embs.mean(), all_embs.std()\nembed_size = all_embs.shape[1]\n\nword_index = tokenizer.word_index\nnb_words = min(max_features, len(word_index))\nembedding_matrix_1 = np.random.normal(emb_mean, emb_std, (nb_words, embed_size))\nfor word, i in word_index.items():\n    if i >= max_features: continue\n    embedding_vector = embeddings_index.get(word)\n    if embedding_vector is not None: embedding_matrix_1[i] = embedding_vector\n\ndel embeddings_index; gc.collect() ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"29c446e36dc3e0cfeb86b35828664f739d3b3eae"},"cell_type":"code","source":"EMBEDDING_FILE = '../input/embeddings/wiki-news-300d-1M/wiki-news-300d-1M.vec'\ndef get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')\nembeddings_index = dict(get_coefs(*o.split(\" \")) for o in open(EMBEDDING_FILE) if len(o)>100)\n\nall_embs = np.stack(embeddings_index.values())\nemb_mean,emb_std = all_embs.mean(), all_embs.std()\nembed_size = all_embs.shape[1]\n\nword_index = tokenizer.word_index\nnb_words = min(max_features, len(word_index))\nembedding_matrix_2 = np.random.normal(emb_mean, emb_std, (nb_words, embed_size))\nfor word, i in word_index.items():\n    if i >= max_features: continue\n    embedding_vector = embeddings_index.get(word)\n    if embedding_vector is not None: embedding_matrix_2[i] = embedding_vector\ndel embeddings_index; gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1cf537631d802e0d8434d75e8a3f5f39d1f73477"},"cell_type":"code","source":"EMBEDDING_FILE = '../input/embeddings/paragram_300_sl999/paragram_300_sl999.txt'\ndef get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')\nembeddings_index = dict(get_coefs(*o.split(\" \")) for o in open(EMBEDDING_FILE, encoding=\"utf8\", errors='ignore') if len(o)>100)\n\nall_embs = np.stack(embeddings_index.values())\nemb_mean,emb_std = all_embs.mean(), all_embs.std()\nembed_size = all_embs.shape[1]\n\nword_index = tokenizer.word_index\nnb_words = min(max_features, len(word_index))\nembedding_matrix_3 = np.random.normal(emb_mean, emb_std, (nb_words, embed_size))\nfor word, i in word_index.items():\n    if i >= max_features: continue\n    embedding_vector = embeddings_index.get(word)\n    if embedding_vector is not None: embedding_matrix_3[i] = embedding_vector\n        \ndel embeddings_index; gc.collect()   ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f741d8d29bd523d6dae9f077ea602c00e066b89c"},"cell_type":"code","source":"# https://www.kaggle.com/strideradu/word2vec-and-gensim-go-go-go\nfrom gensim.models import KeyedVectors\n\nEMBEDDING_FILE = '../input/embeddings/GoogleNews-vectors-negative300/GoogleNews-vectors-negative300.bin'\nembeddings_index = KeyedVectors.load_word2vec_format(EMBEDDING_FILE, binary=True)\n\nword_index = tokenizer.word_index\nnb_words = min(max_features, len(word_index))\nembedding_matrix_4 = (np.random.rand(nb_words, embed_size) - 0.5) / 5.0\nfor word, i in word_index.items():\n    if i >= max_features: continue\n    if word in embeddings_index:\n        embedding_vector = embeddings_index.get_vector(word)\n        embedding_matrix_4[i] = embedding_vector\n        \ndel embeddings_index; gc.collect()        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7d891d3452e22c4fa9f7e2781527618041a38f83"},"cell_type":"code","source":"embedding_matrix = np.concatenate((embedding_matrix_1, embedding_matrix_2, embedding_matrix_3, embedding_matrix_4), axis=1)  \ndel embedding_matrix_1, embedding_matrix_2, embedding_matrix_3, embedding_matrix_4\ngc.collect()\nnp.shape(embedding_matrix)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d536ec84108d3044fbf90a5394223848699d9f1d"},"cell_type":"code","source":"\ndef model1(init):\n    x = Reshape((maxlen, embed_size * 4, 1))(init)\n    \n    filter_sizes = [1,2,3]\n    num_filters = 32\n    \n    conv_0 = Conv2D(num_filters, kernel_size=(filter_sizes[0], embed_size), padding='valid', kernel_initializer='normal', activation='relu')(x)\n    conv_1 = Conv2D(num_filters, kernel_size=(filter_sizes[1], embed_size), padding='valid', kernel_initializer='normal', activation='relu')(x)\n    conv_2 = Conv2D(num_filters, kernel_size=(filter_sizes[2], embed_size), padding='valid', kernel_initializer='normal', activation='relu')(x)\n    #conv_3 = Conv2D(num_filters, kernel_size=(filter_sizes[3], embed_size), padding='valid', kernel_initializer='normal', activation='relu')(x)\n\n    maxpool_0 = MaxPool2D(pool_size=(maxlen - filter_sizes[0] + 1, 1), strides=(1,1), padding='valid')(conv_0)\n    maxpool_1 = MaxPool2D(pool_size=(maxlen - filter_sizes[1] + 1, 1), strides=(1,1), padding='valid')(conv_1)\n    maxpool_2 = MaxPool2D(pool_size=(maxlen - filter_sizes[2] + 1, 1), strides=(1,1), padding='valid')(conv_2)\n    #maxpool_3 = MaxPool2D(pool_size=(maxlen - filter_sizes[3] + 1, 1), strides=(1,1), padding='valid')(conv_3)\n\n    concatenated_tensor = Concatenate(axis=1)([maxpool_0, maxpool_1, maxpool_2])\n    \n    gmp = GlobalMaxPooling2D()(concatenated_tensor)\n    gap = GlobalAveragePooling2D()(concatenated_tensor)\n    \n    conc = Concatenate(axis=1)([gmp, gap])\n    \n    #flatten = Flatten()(concatenated_tensor)\n    return conc\n\ndef model2(init):\n    x = init\n    x = Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)\n    x = attention_3d_block(x)\n    x = Bidirectional(CuDNNLSTM(64, return_sequences=True))(x)\n    x = AttLayer(64)(x)\n    return x\n\n\ndef model3(init):\n    filters = 64\n    x = init\n    pool = []\n    \n    x = Conv1D(filters, 1, activation='relu')(init)\n    x = MaxPooling1D(2)(x)\n    x = Dropout(0.1)(x)\n    \n    x = Conv1D(filters, 2, activation='relu')(x)\n    x = MaxPooling1D(2)(x)\n    x = Dropout(0.1)(x)\n    \n    x = Conv1D(filters, 3, activation='relu')(x)\n    x = MaxPooling1D(2)(x)\n    x = Dropout(0.1)(x)\n    \n    x = Conv1D(filters, 5, activation='relu')(x)\n    x = MaxPooling1D(2)(x)\n    x = Dropout(0.1)(x)\n    \n    x = Flatten()(x)\n    return x\n\ndef model4(init):\n    x = init\n    x = Bidirectional(CuDNNGRU(128, return_sequences=True))(x)\n    x = attention_3d_block(x)\n    x = Bidirectional(CuDNNGRU(64, return_sequences=True))(x)\n    x = AttLayer(64)(x)\n    return x\n\ndef all_embed(init):\n    x = init\n    \n    #out1 = model1(x)\n    #out2 = model2(x)    #CuDNNLSTM\n    out3 = model3(x)   #Conv1D\n    #out4 = model4(x)    #CuDNNGRU\n    \n    #conc = concatenate([out1, out2, out3, out4])\n    \n    return out3\n    \ndef get_model():\n    inp = Input(shape=(maxlen, ))\n    embed1 = Embedding(max_features, embed_size * 4, weights=[embedding_matrix], trainable=False)(inp)\n    \n    out = all_embed(embed1)\n    \n    x = Dropout(0.3)(out)\n    x = Dense(128, activation='relu')(x)\n    \n    outp = Dense(1, activation=\"sigmoid\")(x)\n    \n    model = Model(inputs=inp, outputs=outp)\n    model.compile(loss='binary_crossentropy',\n                  optimizer='adam',\n                  metrics=['accuracy'])    \n\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"f07462c499d43887b355f683829862fcc245e817"},"cell_type":"code","source":"model = get_model()\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2f14547280cb1ee50b34dc2d884d878520177073"},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nX_tra, X_val, y_tra, y_val = train_test_split(x_train, y, test_size = 0.1, random_state=42)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7ae9b027caa539ee520f4289b6a338dfdc750f14"},"cell_type":"code","source":"early_stopping = EarlyStopping(patience=3, verbose=1, monitor='val_loss', mode='min')\nmodel_checkpoint = ModelCheckpoint('./quora.model', save_best_only=True, verbose=1, monitor='val_loss', mode='min')\nreduce_lr = ReduceLROnPlateau(factor=0.5, patience=3, min_lr=0.0001, verbose=1)\n\n#model = load_model('./quora.model')\n\nbatch_size = 1536\nepochs = 3\n\nhist = model.fit(X_tra, y_tra, batch_size=batch_size, epochs=epochs, validation_data=(X_val, y_val), verbose=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"620cf2de14879fbd5f653466d9efc8eeb15d8730"},"cell_type":"code","source":"pred_val_y = model.predict([X_val], batch_size=1024, verbose=1)\nthresholds = []\nfor thresh in np.arange(0.1, 0.501, 0.01):\n    thresh = np.round(thresh, 2)\n    res = metrics.f1_score(y_val, (pred_val_y > thresh).astype(int))\n    thresholds.append([thresh, res])\n    print(\"F1 score at threshold {0} is {1}\".format(thresh, res))\n    \nthresholds.sort(key=lambda x: x[1], reverse=True)\nbest_thresh = thresholds[0][0]\nprint(\"Best threshold: \", best_thresh)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"404a671dca09cebb0a014796063bd59d82f98714"},"cell_type":"code","source":"y_pred = model.predict(x_test, batch_size=1024, verbose=True)\ny_te = (y_pred[:,0] > best_thresh).astype(np.int)\n\nsubmit_df = pd.DataFrame({\"qid\": test_df[\"qid\"], \"prediction\": y_te})\nsubmit_df.to_csv(\"submission.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d3c861699e0ae612641cc3eb7d288500c2168cd1"},"cell_type":"code","source":"from IPython.display import HTML\nimport base64  \nimport pandas as pd  \n\ndef create_download_link( df, title = \"Download CSV file\", filename = \"data.csv\"):  \n    csv = df.to_csv(index =False)\n    b64 = base64.b64encode(csv.encode())\n    payload = b64.decode()\n    html = '<a download=\"{filename}\" href=\"data:text/csv;base64,{payload}\" target=\"_blank\">{title}</a>'\n    html = html.format(payload=payload,title=title,filename=filename)\n    return HTML(html)\n\ncreate_download_link(submit_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"48313b5e086fd1dd08d43e51190db353a689cbbc"},"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}