├── README.md ├── activation_function.ipynb ├── cnn_mnist.ipynb ├── colab_pro_nov.png ├── elmo_embedding_tfhub.ipynb ├── image_classifier_pytorch.ipynb ├── mnist.py ├── pdf_to_markdown.ipynb ├── pytesseract_img_str.ipynb ├── sarcasm_classifier ├── Sarcasm_Headlines_Dataset_v2.json ├── albert_tfhub │ ├── albert_en_base │ │ └── 1 │ │ │ ├── assets │ │ │ └── 30k-clean.model │ │ │ ├── saved_model.pb │ │ │ └── variables │ │ │ ├── variables.data-00000-of-00001 │ │ │ └── variables.index │ └── albert_vectorizer.ipynb ├── fasttext.ipynb ├── fasttext_input_sarcastic_comments.txt ├── fasttext_sarcasm.ftz ├── fasttext_test_script.py ├── sarcasm_test.bin └── sarcasm_train.bin ├── start_pytorch.ipynb └── tensorflow_hub_useT.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # Deep-Learning 2 | Implementations of Deep Learning techniques in fields of NLP, Computer Vision etc. 3 | -------------------------------------------------------------------------------- /cnn_mnist.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 13, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "from __future__ import print_function\n", 12 | "import keras\n", 13 | "from keras.datasets import mnist\n", 14 | "from keras.models import Sequential\n", 15 | "from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D\n", 16 | "from keras import backend as k\n", 17 | "import matplotlib.pyplot as plt\n", 18 | "import numpy as np" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 2, 24 | "metadata": { 25 | "collapsed": true 26 | }, 27 | "outputs": [], 28 | "source": [ 29 | "#load mnist dataset\n", 30 | "(X_train, y_train), (X_test, y_test) = mnist.load_data() #everytime loading data won't be so easy :)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 5, 36 | "metadata": { 37 | "collapsed": false 38 | }, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "image/png": "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\nXOBz2M432WQTn8NLPOfPn+/z8uXLc273Jz/5ic9jxozxeebMmY0tu8nY4wUAICI6XgAAIqqqoeae\nPXv6fN5552VdZsaMGT737du31vc+/vjjdAoD6jjxxBN9vvXWW33efPPNfQ6H3V566SWfw1l7brzx\nxqzbrzsrW7jdk08+uREVA7m1a9fO51/+8pc+h+08nIkql/fff9/no446yueNN9641nLh3/Hw9yFs\n5ww1AwBQJeh4AQCIqOKHmsOzN8eOHetzOPQRuummm3yeM2dOeoUBkjbaaP2v4D777OPzPffc43Pr\n1q19Dm/OMWrUKJ9feeUVn8Oz9B977DGfe/XqlbOOqVOnNqRsoEH69+/v85lnnpl1mfDwR3hm/r//\n/W+fwzY8b948n3fYYYdmqTMW9ngBAIiIjhcAgIgqfqh58ODBPm+11VZZl3nxxRd9fuCBB9IuCfAG\nDRrk87333pt1meeee87nAQMG+Lxs2bKsy4dnih555JE+h8N3CxYsqLUO7R5pOv74433ONaT84Ycf\n+vzmm2/6/L//+78+h8PLoa5duzZLnbGwxwsAQER0vAAARFSRQ83hRdKnn366z2vXrvV56dKlPo8e\nPTpOYYCkq6++2udLLrnE53DY7Ve/+pXPl19+uc+5hpdD4TZzDeuF8+JK0pIlS/JuF2isIUOG+Pw/\n//M/Pj/77LM+z5o1y+fFixc3aPsdO3ZsQnXxsccLAEBEdLwAAERUMUPNNTU1Pj/++ON5l7/jjjt8\nnjRpUholAd4VV1zhczgUvHr1ap8nTJjgc3gm58qVK7NuM5woI5xYYNttt826fHhIZfz48YWUDTSL\n8Cz6q666qtm3v//++zf7NtPEHi8AABHR8QIAEFHFDDWHt4jafffdsy7zwgsv+Hz77benXhOqW/v2\n7X0+++yzfQ7PLg6Hl8P5bHMJ56R96KGHfN57772zLh8edsl1i0Cg1AwdOtTnNm3a5F3++9//fq2v\nw9+xKVOm+Pzaa681Q3VNxx4vAAAR0fECABBRWQ81//jHP/b5uuuuy7pMeLu00047zefPP/88tboA\nSdp44419Did1CYUTWXzve9/zOWyr/fr187lbt24+b7rppj6HQ2thfvjhh31esWJFoaUDqQlvc7nr\nrrv6HJ7536dPn6zrbrDB+n3FcEKkuhYuXOjzGWec4fM333zTsGJTwh4vAAAR0fECABBR2Q01N3Si\njA8++MDnjz/+OI2SgKzCyTH+85//+LzFFlv4HLbPcIg4l48++sjn5cuX+9ypU6esz/WnP/2pARUD\nzadFixY+77XXXj6Hf7e33HJLn8OJYsKh4vBM5PDqlXDIuu7vzkYbre/awqsFbrvtNp+//vrrAn6K\ndLDHCwBARHS8AABEVHZDzSNGjPA519Bc+Pj111+fek1ANuGtJ8PhrnD497vf/a7P//73v31+8skn\nfb7//vt9/uyzz3x+5JFHfA6Hmh999NEmVA00Xngmfzgs/MQTT2RdPrxF5sSJE31+9dVXfe7QoYPP\n4SRI4Rn+4e0vpdqHc6699lqf586d6/O4ceN8Dg8LxcAeLwAAEdHxAgAQUVkMNe+5554+h7c/C4XD\ny+Etz2bOnJleYUCBwjMzw2GwhjrkkEOy5nAygfBMaSBt4dnL4S3/Lr744qzLP/300z6Ht2cND82E\nvyNPPfWUz+Hwcjg8XHce8nC5Y4891udwQpnnnnvO5xtuuMHn8HBO6J133sn6eGOwxwsAQER0vAAA\nRFQWQ83hrdPCs0DD4eVwKO/000+PUxgQ2SabbOJzrvmZH3vssag1ofpsuOGGPodnJg8fPtzncG7w\nX/ziFz6HZ92Hw8v77LOPz+EQdDj5xvvvv+/zOeec4/OkSZNq1de2bVufDzzwQJ9PPvlkn/v27etz\nOOwcCs+C3n777bMu0xjs8QIAEBEdLwAAEZXFUHN4AXWu4bUxY8b4/MUXX8QpDIjs2Wef9bmQCWSA\nNJx11lk+h8PLX375pc8/+9nPfA7b7Q9/+EOfw9tf/uhHP/I5PKRyzTXX+Hzffff5PG/evJz1LVu2\nzOfwLOown3TSST6HQ9Dh789FF12U8zmagj1eAAAiouMFACAiOl4AACKyQo4HmVl3SVPTL2e9sWPH\n+hweBwhn6AmFp3rPmTMntbpSsrdzblqxi6h2xWjnDdW7d2+fwxl9wt/j8B6n4b15SwDtvAQ0RzsP\n75cbzjK1atUqn9977z2f27Rp4/MOO+yQd/sjR470+brrrvP5m2++aXix8eVt5+zxAgAQER0vAAAR\nldTlROHNEHr27OlzOLwcTox91113+fzxxx+nXB1QfF26dCl2CUCtv7ff+973fG7ZsqXPe+yxR9Z1\nw0t6Xn75ZZ/D++POnj3b5zIZXm4Q9ngBAIiIjhcAgIhKaqi5ffv2Pnfq1CnrMgsWLPA51/0egUr1\nyiuv+LzBBus/N+c62x9IQ48ePXwO73fbvXt3nxcvXuxzeJVKeL/b8NBhNWGPFwCAiOh4AQCIqKSG\nmkNmVuyn1QZVAAAOf0lEQVQSgJLz7rvv+jxr1iyft9tuO5/DyWRKbAINVIjwJgQPPvhg1ozc2OMF\nACAiOl4AACIqqaHmcG7PKVOm+HzggQcWoxyg5IRzModz2N5zzz0+jxo1yufzzz/f5xkzZqRcHYBC\nsMcLAEBEdLwAAERUUkPNixYt8jm8QBvAtz3xxBM+n3jiiT4fccQRPl955ZU+n3HGGT5/+eWXKVcH\nIBf2eAEAiIiOFwCAiEpqqBlA4cJJDMKh5vCs5iFDhvg8cuRInznDGSge9ngBAIiIjhcAgIgsvCA/\n50Jm3SVNTb+cqrW3c25asYuodrTz1NHOSwDtPHV52zl7vAAARFRox9sq1SrA61saeB/SxetbGngf\n0pX39S20461pWh3Io6bYBUAS70PaaopdACTxPqStJt8ChR7j7SCpt6TZkr5qalXwWil5kyY45z4p\nci1Vj3aeGtp5CaGdp6bgdl5QxwsAAJoHJ1cBABARHS8AABHR8QIAEBEdLwAAEdHxAgAQER0vAAAR\n0fECABARHS8AABHR8QIAEBEdLwAAEdHxAgAQER0vAAAR0fECABBRSXa8ZnaVma1t5LqnmdlaM9u2\nuesCmhPtHNWAdv5tqXe8ZjY488Kt+7fSzBaY2TNmNtTMNs2ympPUqDcqs26tex2a2dlmNriR2wu3\nc6mZjTezRZmf5YqmbhOVoVLauZltaWYPmdl7ZrbMzD4zs9fN7NSmbBeVoVLaeWY7Rft7nvr9eDMv\n0FhJlyu58XILSZ0kHSqpl6S5kvo556YH62wgaSPn3OpGPJ9JahGua2bTJS1xzh3e+J9Eynxq+0jS\nO0puJD3SOXd1U7aJylAp7dzMvi/pNkmvZmpuIelIScdKutY5d1ljt43yVyntPLOdov093yjGk2Q8\n45ybFnx9vZkdKukpSePNrKtzbpUkOefWSmrwm5RZ1zV23QLUOOfmmlkHSUtSeg6Ut7Ju55k/mHX/\noP3KzJ6UdL6ZXe7S/rSOclDW7TyjaH/Pi3qM1zn3oqRrJHWWNGjd49mOCZhZKzO73cyWZIbAxpnZ\nVnWHCOoeEzCzDyXtJunQYHhkYrB8FzPrUmC9c5vy86I6lVs7z2GOpNaSNm7CNlDByq2dF/PveSmc\n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\nM9QMlKNw4pdCJnsJlwlzOGlMruWPOeYYn4866qhayz3zzDP5iwWKrG/fvsUuoVmwxwsAQER0vAAA\nRFQxQ82FzNV8yCGH+HzXXXfFKQyo49133/X5sMMO8zmce3nChAk+FzKhRdjOzzjjDJ+HDh3qM2f+\no1xMmjTJ53Cu5kqZe589XgAAIqLjBQAgoooZai5kGK1///4+d+3a1ecZM2akUhOQz+zZs30ePXp0\ns2xz5MiRPodDzUC5mDt3btbHw9tchhPO5Fq+VLHHCwBARHS8AABEVDFDzXfffbfPQ4YMybpMeEbc\nWWed5fOFF16YXmFAZL169Sp2CUCTrFmzJuvj4d/wli1bxiqn2bHHCwBARHS8AABEVDFDze+9916x\nSwBqCc/APPLII32eOHGiz4VMjlGI008/3edbb721WbYJFMuTTz7p88yZM33eeeedfb7gggt8Pu+8\n8+IU1kzY4wUAICI6XgAAIqqYoeY777zT53DSgC5duvgczud8/vnn+3zHHXf4/MEHH6RVIircQQcd\nVOvrSy65xOeePXv6HLbJ+fPnN+g5NttsM5/79Onj88033+xz69atfQ4nllm5cqXPzTXEDaQhbLfP\nPvusz1tttZXPw4cPj1pTc2KPFwCAiOh4AQCIqGKGmsOhiX/84x8+h8N63BYNaQoPWUhSt27dsi43\nYsQIn5cvX96g5wjPju7evbvPudr2iy++6HM4yUz4OFAuwna+evXqIlbSNOzxAgAQER0vAAAR0fEC\nABBRxRzjDd17770+9+3bt4iVoJqEE7hn+3qds88+u9mfe/HixT7/6U9/8nnYsGE+cwkRyl3btm19\n7tevn8/jxo0rRjmNxh4vAAAR0fECABBRRQ41h5cTzZgxw+euXbsWoxxUifBGBVLtidsHDx7sc64h\n6FB42UQ4m9qKFSt8fuWVV3y+5557fH733XcLrBgofSeccILPq1at8rmcb4zDHi8AABHR8QIAEFFF\nDjXPmTPH5+9///tFrATV5K233qr19TnnnOPzm2++6fM111zjc/v27X0eP368z88991zWxxctWtQ8\nxQJlYvLkyT7vsssuPn/55ZfFKKdZsMcLAEBEdLwAAERkhdw4wMy6S5qafjlVa2/n3LRiF1HtaOep\no52XANp56vK2c/Z4AQCIiI4XAICI6HgBAIiIjhcAgIjoeAEAiIiOFwCAiOh4AQCIqNCOt1WqVYDX\ntzTwPqSL17c08D6kK+/rW2jHW9O0OpBHTbELgCTeh7TVFLsASOJ9SFtNvgUKnbmqg6TekmZL+qqp\nVcFrpeRNmuCc+6TItVQ92nlqaOclhHaemoLbeUEdLwAAaB6cXAUAQER0vAAARETHCwBARHS8AABE\nRMcLAEBEdLwAAERExwsAQET/H95sGVnigCAGAAAAAElFTkSuQmCC\n", 43 | "text/plain": [ 44 | "" 45 | ] 46 | }, 47 | "execution_count": 5, 48 | "metadata": {}, 49 | "output_type": "execute_result" 50 | } 51 | ], 52 | "source": [ 53 | "#visualising first 9 data from training dataset\n", 54 | "fig = plt.figure()\n", 55 | "for i in range(9):\n", 56 | " plt.subplot(3,3,i+1)\n", 57 | " plt.tight_layout()\n", 58 | " plt.imshow(X_train[i], cmap='gray', interpolation='none')\n", 59 | " plt.title(\"Digit: {}\".format(y_train[i]))\n", 60 | " plt.xticks([])\n", 61 | " plt.yticks([])\n", 62 | "fig" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 7, 68 | "metadata": { 69 | "collapsed": false 70 | }, 71 | "outputs": [ 72 | { 73 | "name": "stdout", 74 | "output_type": "stream", 75 | "text": [ 76 | "X_train shape (60000, 28, 28)\n", 77 | "y_train shape (60000,)\n", 78 | "X_test shape (10000, 28, 28)\n", 79 | "y_test shape (10000,)\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "# let's print the actual data shape before we reshape and normalize\n", 85 | "print(\"X_train shape\", X_train.shape)\n", 86 | "print(\"y_train shape\", y_train.shape)\n", 87 | "print(\"X_test shape\", X_test.shape)\n", 88 | "print(\"y_test shape\", y_test.shape)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 8, 94 | "metadata": { 95 | "collapsed": true 96 | }, 97 | "outputs": [], 98 | "source": [ 99 | "#input image size 28*28\n", 100 | "img_rows , img_cols = 28, 28" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 9, 106 | "metadata": { 107 | "collapsed": false 108 | }, 109 | "outputs": [ 110 | { 111 | "name": "stdout", 112 | "output_type": "stream", 113 | "text": [ 114 | "X_train shape: (60000, 28, 28, 1)\n", 115 | "60000 train samples\n", 116 | "10000 test samples\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "#reshaping\n", 122 | "#this assumes our data format\n", 123 | "#For 3D data, \"channels_last\" assumes (conv_dim1, conv_dim2, conv_dim3, channels) while \n", 124 | "#\"channels_first\" assumes (channels, conv_dim1, conv_dim2, conv_dim3).\n", 125 | "if k.image_data_format() == 'channels_first':\n", 126 | " X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)\n", 127 | " X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)\n", 128 | " input_shape = (1, img_rows, img_cols)\n", 129 | "else:\n", 130 | " X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)\n", 131 | " X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)\n", 132 | " input_shape = (img_rows, img_cols, 1)\n", 133 | "#more reshaping\n", 134 | "X_train = X_train.astype('float32')\n", 135 | "X_test = X_test.astype('float32')\n", 136 | "X_train /= 255\n", 137 | "X_test /= 255\n", 138 | "print('X_train shape:', X_train.shape)\n", 139 | "print(X_train.shape[0], 'train samples')\n", 140 | "print(X_test.shape[0], 'test samples')" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 16, 146 | "metadata": { 147 | "collapsed": false 148 | }, 149 | "outputs": [ 150 | { 151 | "name": "stdout", 152 | "output_type": "stream", 153 | "text": [ 154 | "(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8), array([5923, 6742, 5958, 6131, 5842, 5421, 5918, 6265, 5851, 5949], dtype=int64))\n" 155 | ] 156 | } 157 | ], 158 | "source": [ 159 | "print(np.unique(y_train, return_counts=True))" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 17, 165 | "metadata": { 166 | "collapsed": true 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "#set number of categories\n", 171 | "num_category = 10" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 19, 177 | "metadata": { 178 | "collapsed": false 179 | }, 180 | "outputs": [ 181 | { 182 | "data": { 183 | "text/plain": [ 184 | "array([ 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.])" 185 | ] 186 | }, 187 | "execution_count": 19, 188 | "metadata": {}, 189 | "output_type": "execute_result" 190 | } 191 | ], 192 | "source": [ 193 | "# convert class vectors to binary class matrices\n", 194 | "y_train = keras.utils.to_categorical(y_train, num_category)\n", 195 | "y_test = keras.utils.to_categorical(y_test, num_category)\n", 196 | "y_train[0]" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 20, 202 | "metadata": { 203 | "collapsed": true 204 | }, 205 | "outputs": [], 206 | "source": [ 207 | "##model building\n", 208 | "model = Sequential()\n", 209 | "#convolutional layer with rectified linear unit activation\n", 210 | "model.add(Conv2D(32, kernel_size=(3, 3),\n", 211 | " activation='relu',\n", 212 | " input_shape=input_shape))\n", 213 | "#32 convolution filters used each of size 3x3\n", 214 | "#again\n", 215 | "model.add(Conv2D(64, (3, 3), activation='relu'))\n", 216 | "#64 convolution filters used each of size 3x3\n", 217 | "#choose the best features via pooling\n", 218 | "model.add(MaxPooling2D(pool_size=(2, 2)))\n", 219 | "#randomly turn neurons on and off to improve convergence\n", 220 | "model.add(Dropout(0.25))\n", 221 | "#flatten since too many dimensions, we only want a classification output\n", 222 | "model.add(Flatten())\n", 223 | "#fully connected to get all relevant data\n", 224 | "model.add(Dense(128, activation='relu'))\n", 225 | "#one more dropout for convergence' sake :) \n", 226 | "model.add(Dropout(0.5))\n", 227 | "#output a softmax to squash the matrix into output probabilities\n", 228 | "model.add(Dense(num_category, activation='softmax'))\n", 229 | "#Adaptive learning rate (adaDelta) is a popular form of gradient descent rivaled only by adam and adagrad\n", 230 | "#categorical ce since we have multiple classes (10) \n", 231 | "model.compile(loss=keras.losses.categorical_crossentropy,\n", 232 | " optimizer=keras.optimizers.Adadelta(),\n", 233 | " metrics=['accuracy'])" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": 22, 239 | "metadata": { 240 | "collapsed": false 241 | }, 242 | "outputs": [ 243 | { 244 | "name": "stdout", 245 | "output_type": "stream", 246 | "text": [ 247 | "Train on 60000 samples, validate on 10000 samples\n", 248 | "Epoch 1/10\n", 249 | "60000/60000 [==============================] - 284s 5ms/step - loss: 0.2120 - acc: 0.9354 - val_loss: 0.0610 - val_acc: 0.9801\n", 250 | "Epoch 2/10\n", 251 | "60000/60000 [==============================] - 271s 5ms/step - loss: 0.0894 - acc: 0.9737 - val_loss: 0.0422 - val_acc: 0.9861\n", 252 | "Epoch 3/10\n", 253 | "60000/60000 [==============================] - 270s 4ms/step - loss: 0.0677 - acc: 0.9800 - val_loss: 0.0402 - val_acc: 0.9870\n", 254 | "Epoch 4/10\n", 255 | "60000/60000 [==============================] - 276s 5ms/step - loss: 0.0567 - acc: 0.9834 - val_loss: 0.0332 - val_acc: 0.9891\n", 256 | "Epoch 5/10\n", 257 | "60000/60000 [==============================] - 271s 5ms/step - loss: 0.0472 - acc: 0.9860 - val_loss: 0.0322 - val_acc: 0.9887\n", 258 | "Epoch 6/10\n", 259 | "60000/60000 [==============================] - 274s 5ms/step - loss: 0.0417 - acc: 0.9870 - val_loss: 0.0297 - val_acc: 0.9899\n", 260 | "Epoch 7/10\n", 261 | "60000/60000 [==============================] - 264s 4ms/step - loss: 0.0371 - acc: 0.9887 - val_loss: 0.0312 - val_acc: 0.9906\n", 262 | "Epoch 8/10\n", 263 | "60000/60000 [==============================] - 264s 4ms/step - loss: 0.0355 - acc: 0.9890 - val_loss: 0.0302 - val_acc: 0.9894\n", 264 | "Epoch 9/10\n", 265 | "60000/60000 [==============================] - 270s 4ms/step - loss: 0.0335 - acc: 0.9896 - val_loss: 0.0387 - val_acc: 0.9886\n", 266 | "Epoch 10/10\n", 267 | "60000/60000 [==============================] - 271s 5ms/step - loss: 0.0335 - acc: 0.9897 - val_loss: 0.0296 - val_acc: 0.9904\n" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "batch_size = 128\n", 273 | "num_epoch = 10\n", 274 | "#model training\n", 275 | "model_log = model.fit(X_train, y_train,\n", 276 | " batch_size=batch_size,\n", 277 | " epochs=num_epoch,\n", 278 | " verbose=1,\n", 279 | " validation_data=(X_test, y_test))" 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": 23, 285 | "metadata": { 286 | "collapsed": false 287 | }, 288 | "outputs": [ 289 | { 290 | "name": "stdout", 291 | "output_type": "stream", 292 | "text": [ 293 | "Test loss: 0.0296396646054\n", 294 | "Test accuracy: 0.9904\n" 295 | ] 296 | } 297 | ], 298 | "source": [ 299 | "#how well did it do? \n", 300 | "score = model.evaluate(X_test, y_test, verbose=0)\n", 301 | "print('Test loss:', score[0])\n", 302 | "print('Test accuracy:', score[1])" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 24, 308 | "metadata": { 309 | "collapsed": false 310 | }, 311 | "outputs": [ 312 | { 313 | "data": { 314 | "image/png": "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\n", 315 | "text/plain": [ 316 | "" 317 | ] 318 | }, 319 | "execution_count": 24, 320 | "metadata": {}, 321 | "output_type": "execute_result" 322 | } 323 | ], 324 | "source": [ 325 | "import os\n", 326 | "# plotting the metrics\n", 327 | "fig = plt.figure()\n", 328 | "plt.subplot(2,1,1)\n", 329 | "plt.plot(model_log.history['acc'])\n", 330 | "plt.plot(model_log.history['val_acc'])\n", 331 | "plt.title('model accuracy')\n", 332 | "plt.ylabel('accuracy')\n", 333 | "plt.xlabel('epoch')\n", 334 | "plt.legend(['train', 'test'], loc='lower right')\n", 335 | "\n", 336 | "plt.subplot(2,1,2)\n", 337 | "plt.plot(model_log.history['loss'])\n", 338 | "plt.plot(model_log.history['val_loss'])\n", 339 | "plt.title('model loss')\n", 340 | "plt.ylabel('loss')\n", 341 | "plt.xlabel('epoch')\n", 342 | "plt.legend(['train', 'test'], loc='upper right')\n", 343 | "\n", 344 | "plt.tight_layout()\n", 345 | "\n", 346 | "fig" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": 25, 352 | "metadata": { 353 | "collapsed": false 354 | }, 355 | "outputs": [ 356 | { 357 | "name": "stdout", 358 | "output_type": "stream", 359 | "text": [ 360 | "Saved model to disk\n" 361 | ] 362 | } 363 | ], 364 | "source": [ 365 | "#Save the model\n", 366 | "# serialize model to JSON\n", 367 | "model_digit_json = model.to_json()\n", 368 | "with open(\"model_digit.json\", \"w\") as json_file:\n", 369 | " json_file.write(model_digit_json)\n", 370 | "# serialize weights to HDF5\n", 371 | "model.save_weights(\"model_digit.h5\")\n", 372 | "print(\"Saved model to disk\")" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": null, 378 | "metadata": { 379 | "collapsed": true 380 | }, 381 | "outputs": [], 382 | "source": [] 383 | } 384 | ], 385 | "metadata": { 386 | "anaconda-cloud": {}, 387 | "kernelspec": { 388 | "display_name": "Python [default]", 389 | "language": "python", 390 | "name": "python3" 391 | }, 392 | "language_info": { 393 | "codemirror_mode": { 394 | "name": "ipython", 395 | "version": 3 396 | }, 397 | "file_extension": ".py", 398 | "mimetype": "text/x-python", 399 | "name": "python", 400 | "nbconvert_exporter": "python", 401 | "pygments_lexer": "ipython3", 402 | "version": "3.5.2" 403 | } 404 | }, 405 | "nbformat": 4, 406 | "nbformat_minor": 1 407 | } 408 | -------------------------------------------------------------------------------- /colab_pro_nov.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sambit9238/Deep-Learning/bf2dfc89a288c03458f748e50fa7dfc0d1aca2e2/colab_pro_nov.png -------------------------------------------------------------------------------- /elmo_embedding_tfhub.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import tensorflow as tf\n", 10 | "import tensorflow_hub as hub\n", 11 | "import numpy as np\n", 12 | "import pandas as pd" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "# ELMO Embedding" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 6, 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "name": "stdout", 29 | "output_type": "stream", 30 | "text": [ 31 | "mkdir: cannot create directory ‘module/module_elmo2’: File exists\n", 32 | " % Total % Received % Xferd Average Speed Time Time Time Current\n", 33 | " Dload Upload Total Spent Left Speed\n", 34 | " 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\n", 35 | "tar: module/module_elmo2: Cannot open: No such file or directory\n", 36 | "tar: Error is not recoverable: exiting now\n", 37 | " 0 331M 0 112k 0 0 168k 0 0:33:35 --:--:-- 0:33:35 168k\n", 38 | "curl: (23) Failed writing body (958 != 1389)\n" 39 | ] 40 | } 41 | ], 42 | "source": [ 43 | "#download the model to local so it can be used again and again\n", 44 | "!mkdir module/module_elmo2\n", 45 | "# Download the module, and uncompress it to the destination folder. \n", 46 | "!curl -L \"https://tfhub.dev/google/elmo/2?tf-hub-format=compressed\" | tar -zxvC module/module_elmo2" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "# Passing Strings" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 12, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "name": "stdout", 63 | "output_type": "stream", 64 | "text": [ 65 | "INFO:tensorflow:Saver not created because there are no variables in the graph to restore\n" 66 | ] 67 | } 68 | ], 69 | "source": [ 70 | "elmo = hub.Module(\"module/module_elmo2/\", trainable=False)\n", 71 | "embeddings = elmo(\n", 72 | "[\"the cat is on the mat\", \"what are you doing in evening\"],\n", 73 | "signature=\"default\",\n", 74 | "as_dict=True)[\"elmo\"]" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 13, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "with tf.Session() as session:\n", 84 | " session.run([tf.global_variables_initializer(), tf.tables_initializer()])\n", 85 | " message_embeddings = session.run(embeddings)" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 14, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "(2, 6, 1024)" 97 | ] 98 | }, 99 | "execution_count": 14, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "message_embeddings.shape" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "# Passing tokenized sentences" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 22, 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "name": "stdout", 122 | "output_type": "stream", 123 | "text": [ 124 | "INFO:tensorflow:Saver not created because there are no variables in the graph to restore\n" 125 | ] 126 | } 127 | ], 128 | "source": [ 129 | "elmo = hub.Module(\"module/module_elmo2/\", trainable=False)\n", 130 | "tokens_input = [[\"the\", \"cat\", \"is\", \"on\", \"the\", \"mat\"],\n", 131 | "[\"what\", \"are\", \"you\", \"doing\", \"in\", \"evening\"]]\n", 132 | "tokens_length = [6, 5]\n", 133 | "embeddings = elmo(\n", 134 | "inputs={\n", 135 | "\"tokens\": tokens_input,\n", 136 | "\"sequence_len\": tokens_length\n", 137 | "},\n", 138 | "signature=\"tokens\",\n", 139 | "as_dict=True)[\"elmo\"]" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 23, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "with tf.Session() as session:\n", 149 | " session.run([tf.global_variables_initializer(), tf.tables_initializer()])\n", 150 | " message_embeddings = session.run(embeddings)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 24, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "(2, 6, 1024)" 162 | ] 163 | }, 164 | "execution_count": 24, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "message_embeddings.shape" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "# If want to use for multiple inputs" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 19, 183 | "metadata": {}, 184 | "outputs": [ 185 | { 186 | "name": "stdout", 187 | "output_type": "stream", 188 | "text": [ 189 | "INFO:tensorflow:Saver not created because there are no variables in the graph to restore\n", 190 | "INFO:tensorflow:Graph was finalized.\n", 191 | "INFO:tensorflow:Running local_init_op.\n", 192 | "INFO:tensorflow:Done running local_init_op.\n" 193 | ] 194 | } 195 | ], 196 | "source": [ 197 | "def embed_elmo2(module):\n", 198 | " with tf.Graph().as_default():\n", 199 | " sentences = tf.placeholder(tf.string)\n", 200 | " embed = hub.Module(module)\n", 201 | " embeddings = embed(sentences)\n", 202 | " session = tf.train.MonitoredSession()\n", 203 | " return lambda x: session.run(embeddings, {sentences: x})\n", 204 | "\n", 205 | "embed_fn = embed_elmo2('module/module_elmo2')" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 20, 211 | "metadata": {}, 212 | "outputs": [ 213 | { 214 | "data": { 215 | "text/plain": [ 216 | "(1, 1024)" 217 | ] 218 | }, 219 | "execution_count": 20, 220 | "metadata": {}, 221 | "output_type": "execute_result" 222 | } 223 | ], 224 | "source": [ 225 | "embed_fn([\"i am sambit\"]).shape" 226 | ] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "metadata": {}, 231 | "source": [ 232 | "# Simple Neural network classifier using elmo embedding" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": 2, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [ 241 | "df = pd.read_csv(\"Sentiment.csv\",encoding=\"latin\")\n", 242 | "df = df[df[\"sentiment\"]!=\"Neutral\"]\n", 243 | "df.loc[df[\"sentiment\"]=='Negative',\"sentiment\"]=0\n", 244 | "df.loc[df[\"sentiment\"]=='Positive',\"sentiment\"]=1" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": 3, 250 | "metadata": {}, 251 | "outputs": [], 252 | "source": [ 253 | "def replace_contraction(text):\n", 254 | " contraction_patterns = [ (r'won\\'t', 'will not'), (r'can\\'t', 'can not'), (r'i\\'m', 'i am'), (r'ain\\'t', 'is not'), (r'(\\w+)\\'ll', '\\g<1> will'), (r'(\\w+)n\\'t', '\\g<1> not'),\n", 255 | " (r'(\\w+)\\'ve', '\\g<1> have'), (r'(\\w+)\\'s', '\\g<1> is'), (r'(\\w+)\\'re', '\\g<1> are'), (r'(\\w+)\\'d', '\\g<1> would'), (r'&', 'and'), (r'dammit', 'damn it'), (r'dont', 'do not'), (r'wont', 'will not') ]\n", 256 | " patterns = [(re.compile(regex), repl) for (regex, repl) in contraction_patterns]\n", 257 | " for (pattern, repl) in patterns:\n", 258 | " (text, count) = re.subn(pattern, repl, text)\n", 259 | " return text\n", 260 | "def replace_links(text, filler=' '):\n", 261 | " text = re.sub(r'((http|https)\\:\\/\\/)?[a-zA-Z0-9\\.\\/\\?\\:@\\-_=#]+\\.([a-zA-Z]){2,6}([a-zA-Z0-9\\.\\&\\/\\?\\:@\\-_=#])*',\n", 262 | " filler, text).strip()\n", 263 | " return text\n", 264 | "def remove_numbers(text):\n", 265 | " text = ''.join([i for i in text if not i.isdigit()])\n", 266 | " return text" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 4, 272 | "metadata": {}, 273 | "outputs": [], 274 | "source": [ 275 | "import re\n", 276 | "def cleanText(text):\n", 277 | " text = text.strip().replace(\"\\n\", \" \").replace(\"\\r\", \" \")\n", 278 | " text = replace_contraction(text)\n", 279 | " text = replace_links(text, \"link\")\n", 280 | " text = remove_numbers(text)\n", 281 | " text = re.sub(r'[,!@#$%^&*)(|/><\";:.?\\'\\\\}{]',\"\",text)\n", 282 | " text = text.lower()\n", 283 | " return text" 284 | ] 285 | }, 286 | { 287 | "cell_type": "code", 288 | "execution_count": 5, 289 | "metadata": {}, 290 | "outputs": [], 291 | "source": [ 292 | "X = np.array(df[\"text\"].apply(cleanText))\n", 293 | "y = np.array(df[\"sentiment\"])" 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 6, 299 | "metadata": {}, 300 | "outputs": [ 301 | { 302 | "data": { 303 | "text/plain": [ 304 | "Counter({1: 2236, 0: 8493})" 305 | ] 306 | }, 307 | "execution_count": 6, 308 | "metadata": {}, 309 | "output_type": "execute_result" 310 | } 311 | ], 312 | "source": [ 313 | "from collections import Counter\n", 314 | "Counter(y)" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 7, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [ 323 | "embed = hub.Module(\"module/module_elmo2\")\n", 324 | "def ELMoEmbedding(x):\n", 325 | " return embed(tf.squeeze(tf.cast(x, tf.string)), signature=\"default\", as_dict=True)[\"default\"]" 326 | ] 327 | }, 328 | { 329 | "cell_type": "code", 330 | "execution_count": 8, 331 | "metadata": {}, 332 | "outputs": [ 333 | { 334 | "name": "stderr", 335 | "output_type": "stream", 336 | "text": [ 337 | "Using TensorFlow backend.\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "import tensorflow.keras as keras \n", 343 | "from keras.layers import Input, Lambda, Dense\n", 344 | "from keras.models import Model\n", 345 | "import keras.backend as K" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": 13, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "def build_model(): \n", 355 | " input_text = Input(shape=(1,), dtype=\"string\")\n", 356 | " embedding = Lambda(ELMoEmbedding, output_shape=(1024, ))(input_text)\n", 357 | " dense = Dense(256, activation='relu', kernel_regularizer=keras.regularizers.l2(0.001))(embedding)\n", 358 | " pred = Dense(1, activation='sigmoid')(dense)\n", 359 | " model = Model(inputs=[input_text], outputs=pred)\n", 360 | " model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])\n", 361 | " return model" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": 14, 367 | "metadata": {}, 368 | "outputs": [ 369 | { 370 | "name": "stdout", 371 | "output_type": "stream", 372 | "text": [ 373 | "INFO:tensorflow:Saver not created because there are no variables in the graph to restore\n" 374 | ] 375 | } 376 | ], 377 | "source": [ 378 | "model_elmo = build_model()" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": 15, 384 | "metadata": {}, 385 | "outputs": [ 386 | { 387 | "name": "stdout", 388 | "output_type": "stream", 389 | "text": [ 390 | "_________________________________________________________________\n", 391 | "Layer (type) Output Shape Param # \n", 392 | "=================================================================\n", 393 | "input_2 (InputLayer) (None, 1) 0 \n", 394 | "_________________________________________________________________\n", 395 | "lambda_2 (Lambda) (None, 1024) 0 \n", 396 | "_________________________________________________________________\n", 397 | "dense_3 (Dense) (None, 256) 262400 \n", 398 | "_________________________________________________________________\n", 399 | "dense_4 (Dense) (None, 1) 257 \n", 400 | "=================================================================\n", 401 | "Total params: 262,657\n", 402 | "Trainable params: 262,657\n", 403 | "Non-trainable params: 0\n", 404 | "_________________________________________________________________\n" 405 | ] 406 | } 407 | ], 408 | "source": [ 409 | "model_elmo.summary()" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": 16, 415 | "metadata": {}, 416 | "outputs": [ 417 | { 418 | "name": "stdout", 419 | "output_type": "stream", 420 | "text": [ 421 | "Train on 8583 samples, validate on 2146 samples\n", 422 | "Epoch 1/5\n", 423 | "8583/8583 [==============================] - 63s 7ms/step - loss: 0.8087 - acc: 0.7853 - val_loss: 0.6919 - val_acc: 0.7819\n", 424 | "Epoch 2/5\n", 425 | "8583/8583 [==============================] - 62s 7ms/step - loss: 0.6015 - acc: 0.8265 - val_loss: 0.6359 - val_acc: 0.7651\n", 426 | "Epoch 3/5\n", 427 | "8583/8583 [==============================] - 62s 7ms/step - loss: 0.5377 - acc: 0.8371 - val_loss: 0.5407 - val_acc: 0.8169\n", 428 | "Epoch 4/5\n", 429 | "8583/8583 [==============================] - 62s 7ms/step - loss: 0.4946 - acc: 0.8401 - val_loss: 0.5016 - val_acc: 0.8071\n", 430 | "Epoch 5/5\n", 431 | "8583/8583 [==============================] - 63s 7ms/step - loss: 0.4836 - acc: 0.8396 - val_loss: 0.4995 - val_acc: 0.8094\n" 432 | ] 433 | } 434 | ], 435 | "source": [ 436 | "with tf.Session() as session:\n", 437 | " K.set_session(session)\n", 438 | " session.run(tf.global_variables_initializer()) \n", 439 | " session.run(tf.tables_initializer())\n", 440 | " history = model_elmo.fit(X, y, epochs=5, batch_size=256, validation_split = 0.2)\n", 441 | " model_elmo.save_weights('./model_elmo_weights.h5')" 442 | ] 443 | }, 444 | { 445 | "cell_type": "code", 446 | "execution_count": 18, 447 | "metadata": {}, 448 | "outputs": [ 449 | { 450 | "data": { 451 | "image/png": "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J1BCQgLXX389Xbp0yRD76tWrueSSS2jVqhVt27bl999/B+CFF16gRYsWtGrVKtuZcovS0uSlDPtmGPXH1KfzhM5MWzGNAS0G8OONP7L6jtU8cfETliiMySRsShZ33w2/Fu4M5bRuDWNymZ+wevXqtGvXjhkzZtCjRw8SExO59tprERGioqKYMmUKlStXZvv27bRv357u3bvn2GD62muvUb58eZYtW8aiRYsyTDH+zDPPUL16dVJTU+nUqROLFi3izjvvZPTo0cyaNYvo6OgMx1q4cCHvvvsuc+fORVU555xzuOiii6hWrRqrVq0iISGBN998k2uvvZaPP/6YAQMGZIln0qRJfP311yxfvpyxY8dy3XVu9vn+/fszbNgwevXqxaFDh0hLS2PGjBlMnTqVuXPnUr58+WPTmxel5P3JJPyWQHxSPAs3LyRCIujWqBsvXfoSV551pU2hYUwewiZZ+CW9Kio9Wbz99tuA62nz8MMP88MPP1CqVCk2btzI1q1bOeWUU7I9zg8//MCdd94JQMuWLWnZsuWx9yZPnsz48eNJSUlh8+bNLF26NMP7mf3444/06tXrWNXRVVddxezZs+nevTsNGzY8tiBS4BTngRYsWEB0dDT16tUjNjaWm266iZ07dxIZGcnGjRuPzS8VFeVuwN988w033njjseqw9OnNg+1QyiE+X/k58UnxzFg9g5S0FNqe2pYxl46hb/O+1KpYq0jiMKYkCJtkkVsJIJh69OjBPffcw88//8yBAwc4++yzAfjwww9JTk5m4cKFREZG0qBBg2ynJc/LH3/8wahRo5g/fz7VqlVj0KBBJ3ScdOnTm4Ob4jy7aqiEhASWL19OgwYNADdr7scffxwSjd2qypwNc4hPimfSkknsOrSL2pVqc2/7e7m+1fU0r9nc7xCNKZaszSLIKlasSMeOHbnpppvo16/fse27d++mZs2aREZGMmvWLP73v//lepwLL7yQiRMnAvDbb7+xaNEiwN2oK1SoQJUqVdi6dSszZsw49plKlSqxd+/eLMfq0KEDn376KQcOHGD//v1MmTKFDh06ZNkvO2lpaUyePJnFixezdu1a1q5dy9SpU0lISKBSpUrUqVPn2GJIhw8f5sCBA3Tu3Jl33333WM+sYFRDrflzDSP+PYJGYxtx/jvnM2HRBK448wpmDpjJurvX8ULnFyxRGHMS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\n", 452 | "text/plain": [ 453 | "
" 454 | ] 455 | }, 456 | "metadata": { 457 | "needs_background": "light" 458 | }, 459 | "output_type": "display_data" 460 | } 461 | ], 462 | "source": [ 463 | "import matplotlib.pyplot as plt\n", 464 | "%matplotlib inline\n", 465 | "\n", 466 | "acc = history.history['acc']\n", 467 | "val_acc = history.history['val_acc']\n", 468 | "loss = history.history['loss']\n", 469 | "val_loss = history.history['val_loss']\n", 470 | "\n", 471 | "epochs = range(1, len(acc) + 1)\n", 472 | "\n", 473 | "plt.plot(epochs, acc, 'g', label='Training Acc')\n", 474 | "plt.plot(epochs, val_acc, 'b', label='Validation Acc')\n", 475 | "plt.title('Training and validation Acc')\n", 476 | "plt.xlabel('Epochs')\n", 477 | "plt.ylabel('Acc')\n", 478 | "plt.legend()\n", 479 | "\n", 480 | "plt.show()" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": {}, 486 | "source": [ 487 | "# Running prediction on saved models" 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": 46, 493 | "metadata": {}, 494 | "outputs": [], 495 | "source": [ 496 | "new_text = ['RT @FrankLuntz: Before the #GOPDebate, 14 focus groupers said they did not have favorable view of Trump.',\n", 497 | " 'Chris Wallace(D) to be the 2nd worst partisan pontificating asshole \"moderating\" #GOPDebate @megynkelly'\n", 498 | " ]\n", 499 | "new_text_pr = np.array(new_text, dtype=object)[:, np.newaxis]" 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "execution_count": 47, 505 | "metadata": {}, 506 | "outputs": [ 507 | { 508 | "name": "stdout", 509 | "output_type": "stream", 510 | "text": [ 511 | "time: 0.6370120048522949\n", 512 | "[[0.17122008]\n", 513 | " [0.3037635 ]]\n" 514 | ] 515 | } 516 | ], 517 | "source": [ 518 | "with tf.Session() as session:\n", 519 | " K.set_session(session)\n", 520 | " session.run(tf.global_variables_initializer()) \n", 521 | " session.run(tf.tables_initializer())\n", 522 | " model_elmo.load_weights('./model_elmo_weights.h5')\n", 523 | " import time\n", 524 | " t = time.time()\n", 525 | " predicts = model_elmo.predict(new_text_pr)\n", 526 | " print(\"time: \", time.time() - t)\n", 527 | " print(predicts)" 528 | ] 529 | } 530 | ], 531 | "metadata": { 532 | "kernelspec": { 533 | "display_name": "Python 3", 534 | "language": "python", 535 | "name": "python3" 536 | }, 537 | "language_info": { 538 | "codemirror_mode": { 539 | "name": "ipython", 540 | "version": 3 541 | }, 542 | "file_extension": ".py", 543 | "mimetype": "text/x-python", 544 | "name": "python", 545 | "nbconvert_exporter": "python", 546 | "pygments_lexer": "ipython3", 547 | "version": "3.6.5" 548 | } 549 | }, 550 | "nbformat": 4, 551 | "nbformat_minor": 2 552 | } 553 | -------------------------------------------------------------------------------- /mnist.py: -------------------------------------------------------------------------------- 1 | from tensorflow.keras import Model 2 | from tensorflow.keras.layers import Dense, Flatten, Conv2D 3 | import tensorflow as tf 4 | import datetime 5 | 6 | from tensorboard import program 7 | tb = program.TensorBoard() 8 | tb.configure(argv=[None, '--logdir', "."]) 9 | url = tb.launch() 10 | print("tensorboard url: ", url) 11 | 12 | 13 | mnist = tf.keras.datasets.mnist 14 | 15 | (x_train, y_train), (x_test, y_test) = mnist.load_data() 16 | x_train, x_test = x_train / 255.0, x_test / 255.0 17 | print(x_train.shape) 18 | 19 | # Add a channels dimension 20 | x_train = x_train[..., tf.newaxis] 21 | x_test = x_test[..., tf.newaxis] 22 | print(x_train.shape) 23 | 24 | #tf.data to batch and shuffle the dataset 25 | train_ds = tf.data.Dataset.from_tensor_slices( 26 | (x_train, y_train)).shuffle(10000).batch(32) 27 | 28 | test_ds = tf.data.Dataset.from_tensor_slices( 29 | (x_test, y_test)).batch(32) 30 | 31 | print(train_ds.element_spec) 32 | print(train_ds) 33 | 34 | 35 | class MyModel(Model): 36 | def __init__(self): 37 | super(MyModel, self).__init__() 38 | self.conv1 = tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu') 39 | self.pool = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=2, padding='same') 40 | self.flatten = tf.keras.layers.Flatten() 41 | self.d1 = tf.keras.layers.Dense(256, activation='relu') 42 | self.d2 = tf.keras.layers.Dense(128, activation='relu') 43 | self.d3 = tf.keras.layers.Dense(10, activation='softmax') 44 | 45 | def call(self, x): 46 | x = self.conv1(x) 47 | x = self.pool(x) 48 | x = self.flatten(x) 49 | x = self.d1(x) 50 | x = self.d2(x) 51 | x = self.d3(x) 52 | return x 53 | 54 | # optimizer and loss function to train 55 | loss_object = tf.keras.losses.SparseCategoricalCrossentropy() 56 | optimizer = tf.keras.optimizers.Adam() 57 | 58 | 59 | # metrics to measure the loss and the accuracy of the model 60 | train_loss = tf.keras.metrics.Mean(name='train_loss') 61 | train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy( 62 | name='train_accuracy') 63 | 64 | test_loss = tf.keras.metrics.Mean(name='test_loss') 65 | test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy( 66 | name='test_accuracy') 67 | 68 | ''' 69 | With eager execution enabled, Tensorflow will calculate the values of tensors as they occur in your code. This means that it won't precompute a static graph for which inputs are fed in through placeholders. This means to back propagate errors, you have to keep track of the gradients of your computation and then apply these gradients to an optimiser. 70 | 71 | This is very different from running without eager execution, where you would build a graph and then simply use sess.run to evaluate your loss and then pass this into an optimiser directly. 72 | 73 | Fundamentally, because tensors are evaluated immediately, you don't have a graph to calculate gradients and so you need a gradient tape. It is not so much that it is just used for visualisation, but more that you cannot implement a gradient descent in eager mode without it. 74 | 75 | Obviously, Tensorflow could just keep track of every gradient for every computation on every tf.Variable. However, that could be a huge performance bottleneck. They expose a gradient tape so that you can control what areas of your code need the gradient information. Note that in non-eager mode, this will be statically determined based on the computational branches that are descendants of your loss but in eager mode there is no static graph and so no way of knowing. 76 | ''' 77 | 78 | 79 | @tf.function 80 | def train_step(model, optimizer, images, labels): 81 | with tf.GradientTape() as tape: 82 | predictions = model(images) 83 | loss = loss_object(labels, predictions) 84 | gradients = tape.gradient(loss, model.trainable_variables) 85 | optimizer.apply_gradients(zip(gradients, model.trainable_variables)) 86 | 87 | train_loss(loss) 88 | train_accuracy(labels, predictions) 89 | 90 | 91 | @tf.function 92 | def test_step(model, images, labels): 93 | predictions = model(images) 94 | t_loss = loss_object(labels, predictions) 95 | 96 | test_loss(t_loss) 97 | test_accuracy(labels, predictions) 98 | 99 | 100 | current_time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") 101 | train_log_dir = 'logs/gradient_tape/' + current_time + '/train' 102 | test_log_dir = 'logs/gradient_tape/' + current_time + '/test' 103 | train_summary_writer = tf.summary.create_file_writer(train_log_dir) 104 | test_summary_writer = tf.summary.create_file_writer(test_log_dir) 105 | 106 | EPOCHS = 5 107 | 108 | # Create an instance of the model 109 | model = MyModel() 110 | 111 | for epoch in range(EPOCHS): 112 | for images, labels in train_ds: 113 | train_step(model, optimizer, images, labels) 114 | with train_summary_writer.as_default(): 115 | tf.summary.scalar('loss', train_loss.result(), step=epoch) 116 | tf.summary.scalar('accuracy', train_accuracy.result(), step=epoch) 117 | 118 | for test_images, test_labels in test_ds: 119 | test_step(model, test_images, test_labels) 120 | with test_summary_writer.as_default(): 121 | tf.summary.scalar('loss', test_loss.result(), step=epoch) 122 | tf.summary.scalar('accuracy', test_accuracy.result(), step=epoch) 123 | 124 | template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}' 125 | print(template.format(epoch+1, 126 | train_loss.result(), 127 | train_accuracy.result()*100, 128 | test_loss.result(), 129 | test_accuracy.result()*100)) 130 | 131 | # Reset the metrics for the next epoch 132 | train_loss.reset_states() 133 | train_accuracy.reset_states() 134 | test_loss.reset_states() 135 | test_accuracy.reset_states() 136 | -------------------------------------------------------------------------------- /pdf_to_markdown.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "#Write to markdown file\n", 10 | "def write_to_markdown(file_name='sample.md', input=\"\"):\n", 11 | " with open(file_name, 'w') as file:\n", 12 | " file.write(input)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 3, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "source_pdf = \"/Users/sambitmahapatra/Downloads/Merged Cell Table.pdf\"" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 4, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stderr", 31 | "output_type": "stream", 32 | "text": [ 33 | "/Users/sambitmahapatra/Documents/hobglobin_code_folder/haystack-app/devenv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", 34 | " from .autonotebook import tqdm as notebook_tqdm\n", 35 | "Fetching 9 files: 100%|██████████| 9/9 [00:00<00:00, 70295.60it/s]\n" 36 | ] 37 | } 38 | ], 39 | "source": [ 40 | "from docling.document_converter import DocumentConverter\n", 41 | "\n", 42 | "# Create a DocumentConverter instance\n", 43 | "converter = DocumentConverter()\n", 44 | "\n", 45 | "# Convert the PDF to Markdown\n", 46 | "result = converter.convert(source_pdf)\n", 47 | "\n", 48 | "# Export the result to Markdown format\n", 49 | "markdown_output = result.document.export_to_markdown()\n", 50 | "write_to_markdown(file_name='sample_docling.md', input=markdown_output)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 5, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "Processing /Users/sambitmahapatra/Downloads/Merged Cell Table.pdf...\n", 63 | "[ ] (0/1=======================================[========================================] (1/1]\n" 64 | ] 65 | } 66 | ], 67 | "source": [ 68 | "import pymupdf4llm\n", 69 | "\n", 70 | "# Convert the PDF to Markdown format\n", 71 | "markdown_output = pymupdf4llm.to_markdown(source_pdf)\n", 72 | "\n", 73 | "write_to_markdown(file_name='sample_pymupdf4llm.md', input=markdown_output)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 6, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "#Reference: https://dev.to/rishabdugar/pdf-extraction-retrieving-text-and-tables-together-using-python-14c2\n", 83 | "\n", 84 | "import pdfplumber\n", 85 | "import pandas as pd\n", 86 | "from pdfplumber.utils import extract_text, get_bbox_overlap, obj_to_bbox\n", 87 | "def convert_pdf_to_markdown(pdf_path):\n", 88 | " pdf = pdfplumber.open(pdf_path)\n", 89 | " all_text = []\n", 90 | " for page in pdf.pages:\n", 91 | " filtered_page = page\n", 92 | " chars = filtered_page.chars\n", 93 | " for table in page.find_tables():\n", 94 | " first_table_char = page.crop(table.bbox).chars[0]\n", 95 | " filtered_page = filtered_page.filter(lambda obj: \n", 96 | " get_bbox_overlap(obj_to_bbox(obj), table.bbox) is None\n", 97 | " )\n", 98 | " chars = filtered_page.chars\n", 99 | " df = pd.DataFrame(table.extract())\n", 100 | " df.columns = df.iloc[0]\n", 101 | " markdown = df.drop(0).to_markdown(index=False)\n", 102 | " chars.append(first_table_char | {\"text\": markdown})\n", 103 | " page_text = extract_text(chars, layout=True)\n", 104 | " all_text.append(page_text)\n", 105 | " pdf.close()\n", 106 | " return \"\\n\".join(all_text)\n", 107 | "\n", 108 | "markdown_output = convert_pdf_to_markdown(source_pdf)\n", 109 | "\n", 110 | "write_to_markdown(file_name='sample_pdfplumber.md', input=markdown_output)" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [] 119 | } 120 | ], 121 | "metadata": { 122 | "kernelspec": { 123 | "display_name": "devenv", 124 | "language": "python", 125 | "name": "python3" 126 | }, 127 | "language_info": { 128 | "codemirror_mode": { 129 | "name": "ipython", 130 | "version": 3 131 | }, 132 | "file_extension": ".py", 133 | "mimetype": "text/x-python", 134 | "name": "python", 135 | "nbconvert_exporter": "python", 136 | "pygments_lexer": "ipython3", 137 | "version": "3.10.15" 138 | } 139 | }, 140 | "nbformat": 4, 141 | "nbformat_minor": 2 142 | } 143 | -------------------------------------------------------------------------------- /pytesseract_img_str.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "pytesseract_img_str.ipynb", 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyNaBBpAfLGAq3NmnxPez41p", 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "id": "view-in-github", 21 | "colab_type": "text" 22 | }, 23 | "source": [ 24 | "\"Open" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "metadata": { 30 | "colab": { 31 | "base_uri": "https://localhost:8080/" 32 | }, 33 | "id": "SWeDS9V1Vny3", 34 | "outputId": "01620632-18c5-49d9-a1e1-7d5e6d886f27" 35 | }, 36 | "source": [ 37 | "!pip3 install pytesseract\n", 38 | "!pip3 install pillow" 39 | ], 40 | "execution_count": 2, 41 | "outputs": [ 42 | { 43 | "output_type": "stream", 44 | "text": [ 45 | "Collecting pytesseract\n", 46 | " Downloading https://files.pythonhosted.org/packages/a0/e6/a4e9fc8a93c1318540e8de6d8d4beb5749b7960388a7c7f27799fc2dd016/pytesseract-0.3.7.tar.gz\n", 47 | "Requirement already satisfied: Pillow in /usr/local/lib/python3.6/dist-packages (from pytesseract) (7.0.0)\n", 48 | "Building wheels for collected packages: pytesseract\n", 49 | " Building wheel for pytesseract (setup.py) ... \u001b[?25l\u001b[?25hdone\n", 50 | " Created wheel for pytesseract: filename=pytesseract-0.3.7-py2.py3-none-any.whl size=13945 sha256=8eeabcfb5e64aab241a9838933b04532c2b2a194ed69709b0acbef04ba65afa9\n", 51 | " Stored in directory: /root/.cache/pip/wheels/81/20/7e/1dd0daad1575d5260916bb1e9781246430647adaef4b3ca3b3\n", 52 | "Successfully built pytesseract\n", 53 | "Installing collected packages: pytesseract\n", 54 | "Successfully installed pytesseract-0.3.7\n", 55 | "Requirement already satisfied: pillow in /usr/local/lib/python3.6/dist-packages (7.0.0)\n" 56 | ], 57 | "name": "stdout" 58 | } 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "metadata": { 64 | "colab": { 65 | "base_uri": "https://localhost:8080/" 66 | }, 67 | "id": "QFtENmUbzSkx", 68 | "outputId": "49274d85-4449-4bef-9eb0-10b07c093543" 69 | }, 70 | "source": [ 71 | "!sudo apt update\n", 72 | "!sudo apt install tesseract-ocr\n", 73 | "!sudo apt install libtesseract-dev" 74 | ], 75 | "execution_count": 9, 76 | "outputs": [ 77 | { 78 | "output_type": "stream", 79 | "text": [ 80 | "\u001b[33m\r0% [Working]\u001b[0m\r \rIgn:1 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease\n", 81 | "\u001b[33m\r0% [Connecting to archive.ubuntu.com] [Connecting to security.ubuntu.com (91.18\u001b[0m\r \rIgn:2 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 InRelease\n", 82 | "\u001b[33m\r0% [Connecting to archive.ubuntu.com] [Connecting to security.ubuntu.com (91.18\u001b[0m\r \rHit:3 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Release\n", 83 | "\u001b[33m\r0% [Connecting to archive.ubuntu.com] [Connecting to security.ubuntu.com (91.18\u001b[0m\u001b[33m\r0% [Release.gpg gpgv 697 B] [Connecting to archive.ubuntu.com (91.189.88.142)] \u001b[0m\r \rHit:4 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ InRelease\n", 84 | "Hit:5 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 Release\n", 85 | "Hit:7 http://security.ubuntu.com/ubuntu bionic-security InRelease\n", 86 | "Hit:9 http://archive.ubuntu.com/ubuntu bionic InRelease\n", 87 | "Hit:10 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic InRelease\n", 88 | "Hit:11 http://archive.ubuntu.com/ubuntu bionic-updates InRelease\n", 89 | "Hit:12 http://archive.ubuntu.com/ubuntu bionic-backports InRelease\n", 90 | "Hit:13 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic InRelease\n", 91 | "Hit:14 http://ppa.launchpad.net/cran/libgit2/ubuntu bionic InRelease\n", 92 | "Hit:15 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease\n", 93 | "Reading package lists... Done\n", 94 | "Building dependency tree \n", 95 | "Reading state information... Done\n", 96 | "51 packages can be upgraded. Run 'apt list --upgradable' to see them.\n", 97 | "Reading package lists... Done\n", 98 | "Building dependency tree \n", 99 | "Reading state information... Done\n", 100 | "The following additional packages will be installed:\n", 101 | " libtesseract5 tesseract-ocr-eng tesseract-ocr-osd\n", 102 | "The following NEW packages will be installed:\n", 103 | " libtesseract5 tesseract-ocr tesseract-ocr-eng tesseract-ocr-osd\n", 104 | "0 upgraded, 4 newly installed, 0 to remove and 51 not upgraded.\n", 105 | "Need to get 6,291 kB of archives.\n", 106 | "After this operation, 20.4 MB of additional disk space will be used.\n", 107 | "Get:1 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 libtesseract5 amd64 5.0.0~git4989-95b98042-1ppa1~bionic1 [1,283 kB]\n", 108 | "Get:2 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 tesseract-ocr-eng all 1:5.0.0~git39-6572757-2ppa1~bionic1 [1,590 kB]\n", 109 | "Get:3 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 tesseract-ocr-osd all 1:5.0.0~git39-6572757-2ppa1~bionic1 [2,991 kB]\n", 110 | "Get:4 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 tesseract-ocr amd64 5.0.0~git4989-95b98042-1ppa1~bionic1 [428 kB]\n", 111 | "Fetched 6,291 kB in 5s (1,377 kB/s)\n", 112 | "debconf: unable to initialize frontend: Dialog\n", 113 | "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 4.)\n", 114 | "debconf: falling back to frontend: Readline\n", 115 | "debconf: unable to initialize frontend: Readline\n", 116 | "debconf: (This frontend requires a controlling tty.)\n", 117 | "debconf: falling back to frontend: Teletype\n", 118 | "dpkg-preconfigure: unable to re-open stdin: \n", 119 | "Selecting previously unselected package libtesseract5:amd64.\n", 120 | "(Reading database ... 146364 files and directories currently installed.)\n", 121 | "Preparing to unpack .../libtesseract5_5.0.0~git4989-95b98042-1ppa1~bionic1_amd64.deb ...\n", 122 | "Unpacking libtesseract5:amd64 (5.0.0~git4989-95b98042-1ppa1~bionic1) ...\n", 123 | "Selecting previously unselected package tesseract-ocr-eng.\n", 124 | "Preparing to unpack .../tesseract-ocr-eng_1%3a5.0.0~git39-6572757-2ppa1~bionic1_all.deb ...\n", 125 | "Unpacking tesseract-ocr-eng (1:5.0.0~git39-6572757-2ppa1~bionic1) ...\n", 126 | "Selecting previously unselected package tesseract-ocr-osd.\n", 127 | "Preparing to unpack .../tesseract-ocr-osd_1%3a5.0.0~git39-6572757-2ppa1~bionic1_all.deb ...\n", 128 | "Unpacking tesseract-ocr-osd (1:5.0.0~git39-6572757-2ppa1~bionic1) ...\n", 129 | "Selecting previously unselected package tesseract-ocr.\n", 130 | "Preparing to unpack .../tesseract-ocr_5.0.0~git4989-95b98042-1ppa1~bionic1_amd64.deb ...\n", 131 | "Unpacking tesseract-ocr (5.0.0~git4989-95b98042-1ppa1~bionic1) ...\n", 132 | "Setting up tesseract-ocr-osd (1:5.0.0~git39-6572757-2ppa1~bionic1) ...\n", 133 | "Setting up tesseract-ocr-eng (1:5.0.0~git39-6572757-2ppa1~bionic1) ...\n", 134 | "Setting up libtesseract5:amd64 (5.0.0~git4989-95b98042-1ppa1~bionic1) ...\n", 135 | "Setting up tesseract-ocr (5.0.0~git4989-95b98042-1ppa1~bionic1) ...\n", 136 | "Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n", 137 | "Processing triggers for libc-bin (2.27-3ubuntu1.3) ...\n", 138 | "/sbin/ldconfig.real: /usr/local/lib/python3.6/dist-packages/ideep4py/lib/libmkldnn.so.0 is not a symbolic link\n", 139 | "\n", 140 | "Reading package lists... Done\n", 141 | "Building dependency tree \n", 142 | "Reading state information... Done\n", 143 | "The following additional packages will be installed:\n", 144 | " libarchive-dev liblept5 libleptonica-dev\n", 145 | "The following NEW packages will be installed:\n", 146 | " libarchive-dev libleptonica-dev libtesseract-dev\n", 147 | "The following packages will be upgraded:\n", 148 | " liblept5\n", 149 | "1 upgraded, 3 newly installed, 0 to remove and 50 not upgraded.\n", 150 | "Need to get 4,335 kB of archives.\n", 151 | "After this operation, 15.2 MB of additional disk space will be used.\n", 152 | "Get:1 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 liblept5 amd64 1.78.0-1+nmu1ppa1~bionic1 [985 kB]\n", 153 | "Get:2 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libarchive-dev amd64 3.2.2-3.1ubuntu0.6 [470 kB]\n", 154 | "Get:3 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 libleptonica-dev amd64 1.78.0-1+nmu1ppa1~bionic1 [1,375 kB]\n", 155 | "Get:4 http://ppa.launchpad.net/alex-p/tesseract-ocr-devel/ubuntu bionic/main amd64 libtesseract-dev amd64 5.0.0~git4989-95b98042-1ppa1~bionic1 [1,505 kB]\n", 156 | "Fetched 4,335 kB in 3s (1,316 kB/s)\n", 157 | "debconf: unable to initialize frontend: Dialog\n", 158 | "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 4.)\n", 159 | "debconf: falling back to frontend: Readline\n", 160 | "debconf: unable to initialize frontend: Readline\n", 161 | "debconf: (This frontend requires a controlling tty.)\n", 162 | "debconf: falling back to frontend: Teletype\n", 163 | "dpkg-preconfigure: unable to re-open stdin: \n", 164 | "Selecting previously unselected package libarchive-dev:amd64.\n", 165 | "(Reading database ... 146452 files and directories currently installed.)\n", 166 | "Preparing to unpack .../libarchive-dev_3.2.2-3.1ubuntu0.6_amd64.deb ...\n", 167 | "Unpacking libarchive-dev:amd64 (3.2.2-3.1ubuntu0.6) ...\n", 168 | "Preparing to unpack .../liblept5_1.78.0-1+nmu1ppa1~bionic1_amd64.deb ...\n", 169 | "Unpacking liblept5 (1.78.0-1+nmu1ppa1~bionic1) over (1.75.3-3) ...\n", 170 | "Selecting previously unselected package libleptonica-dev.\n", 171 | "Preparing to unpack .../libleptonica-dev_1.78.0-1+nmu1ppa1~bionic1_amd64.deb ...\n", 172 | "Unpacking libleptonica-dev (1.78.0-1+nmu1ppa1~bionic1) ...\n", 173 | "Selecting previously unselected package libtesseract-dev:amd64.\n", 174 | "Preparing to unpack .../libtesseract-dev_5.0.0~git4989-95b98042-1ppa1~bionic1_amd64.deb ...\n", 175 | "Unpacking libtesseract-dev:amd64 (5.0.0~git4989-95b98042-1ppa1~bionic1) ...\n", 176 | "Setting up liblept5 (1.78.0-1+nmu1ppa1~bionic1) ...\n", 177 | "Setting up libarchive-dev:amd64 (3.2.2-3.1ubuntu0.6) ...\n", 178 | "Setting up libleptonica-dev (1.78.0-1+nmu1ppa1~bionic1) ...\n", 179 | "Setting up libtesseract-dev:amd64 (5.0.0~git4989-95b98042-1ppa1~bionic1) ...\n", 180 | "Processing triggers for libc-bin (2.27-3ubuntu1.3) ...\n", 181 | "/sbin/ldconfig.real: /usr/local/lib/python3.6/dist-packages/ideep4py/lib/libmkldnn.so.0 is not a symbolic link\n", 182 | "\n", 183 | "Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n" 184 | ], 185 | "name": "stdout" 186 | } 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "metadata": { 192 | "id": "ZwRmLqmlWE7b" 193 | }, 194 | "source": [ 195 | "try:\n", 196 | " from PIL import Image\n", 197 | "except ImportError:\n", 198 | " import Image\n", 199 | "import pytesseract\n", 200 | "\n", 201 | "def ocr_core(filename):\n", 202 | " \"\"\"\n", 203 | " This function will handle the core OCR processing of images.\n", 204 | " \"\"\"\n", 205 | " text = pytesseract.image_to_string(Image.open(filename)) # We'll use Pillow's Image class to open the image and pytesseract to detect the string in the image\n", 206 | " return text" 207 | ], 208 | "execution_count": 7, 209 | "outputs": [] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "metadata": { 214 | "colab": { 215 | "base_uri": "https://localhost:8080/" 216 | }, 217 | "id": "C_e3txmCyjko", 218 | "outputId": "40af0c55-9b5e-4afe-a3c4-bf7ba4a9bd1b" 219 | }, 220 | "source": [ 221 | "print(ocr_core('colab_pro_nov.png'))" 222 | ], 223 | "execution_count": 10, 224 | "outputs": [ 225 | { 226 | "output_type": "stream", 227 | "text": [ 228 | "Google\n", 229 | "\n", 230 | "Nov 6, 2020, 9:33 PM\n", 231 | "\n", 232 | " \n", 233 | "\n", 234 | "Item Price (USD)\n", 235 | "Colab purchase $9.99\n", 236 | "Colab Pro\n", 237 | "\n", 238 | "Total $9.99\n", 239 | "\n", 240 | "Payment method\n", 241 | "\n", 242 | "Visa:\n", 243 | "\n", 244 | " \n", 245 | "\n", 246 | "0314\n", 247 | "\n", 248 | "Transaction ID\n", 249 | "\n", 250 | "COLSUB.5887-6594-1439-53207.5\n", 251 | "\f\n" 252 | ], 253 | "name": "stdout" 254 | } 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "metadata": { 260 | "id": "kkcWuqs-yxuE" 261 | }, 262 | "source": [ 263 | "" 264 | ], 265 | "execution_count": null, 266 | "outputs": [] 267 | } 268 | ] 269 | } -------------------------------------------------------------------------------- /sarcasm_classifier/albert_tfhub/albert_en_base/1/assets/30k-clean.model: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sambit9238/Deep-Learning/bf2dfc89a288c03458f748e50fa7dfc0d1aca2e2/sarcasm_classifier/albert_tfhub/albert_en_base/1/assets/30k-clean.model -------------------------------------------------------------------------------- /sarcasm_classifier/albert_tfhub/albert_en_base/1/saved_model.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sambit9238/Deep-Learning/bf2dfc89a288c03458f748e50fa7dfc0d1aca2e2/sarcasm_classifier/albert_tfhub/albert_en_base/1/saved_model.pb -------------------------------------------------------------------------------- /sarcasm_classifier/albert_tfhub/albert_en_base/1/variables/variables.data-00000-of-00001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sambit9238/Deep-Learning/bf2dfc89a288c03458f748e50fa7dfc0d1aca2e2/sarcasm_classifier/albert_tfhub/albert_en_base/1/variables/variables.data-00000-of-00001 -------------------------------------------------------------------------------- /sarcasm_classifier/albert_tfhub/albert_en_base/1/variables/variables.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sambit9238/Deep-Learning/bf2dfc89a288c03458f748e50fa7dfc0d1aca2e2/sarcasm_classifier/albert_tfhub/albert_en_base/1/variables/variables.index -------------------------------------------------------------------------------- /sarcasm_classifier/fasttext_sarcasm.ftz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sambit9238/Deep-Learning/bf2dfc89a288c03458f748e50fa7dfc0d1aca2e2/sarcasm_classifier/fasttext_sarcasm.ftz -------------------------------------------------------------------------------- /sarcasm_classifier/fasttext_test_script.py: -------------------------------------------------------------------------------- 1 | import fasttext 2 | 3 | class SarcasmService(object): 4 | model = None 5 | 6 | @classmethod 7 | def load_model(self): 8 | loaded_model = fasttext.load_model('fasttext_sarcasm.ftz') 9 | return loaded_model 10 | 11 | @classmethod 12 | def get_model(self): 13 | if self.model is None: 14 | self.model = self.load_model() 15 | return self.model 16 | 17 | 18 | def predict_is_sarcastic(text): 19 | return SarcasmService.get_model().predict(text, k=2) 20 | 21 | if __name__ == '__main__': 22 | ip = 'Make Indian manufacturing competitive to curb Chinese imports: RC Bhargava' 23 | print(f'Result : {predict_is_sarcastic(ip)}') -------------------------------------------------------------------------------- /start_pytorch.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "start_pytorch.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyM5/sYvZvqKrmwjPlD4fg61", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "metadata": { 31 | "id": "vvbFhocgfKeb", 32 | "outputId": "77de76d8-0fa8-4b60-8375-ab5f4cbb2156", 33 | "colab": { 34 | "base_uri": "https://localhost:8080/", 35 | "height": 105 36 | } 37 | }, 38 | "source": [ 39 | "!pip3 install -U torch torchvision" 40 | ], 41 | "execution_count": 2, 42 | "outputs": [ 43 | { 44 | "output_type": "stream", 45 | "text": [ 46 | "Requirement already up-to-date: torch in /usr/local/lib/python3.6/dist-packages (1.6.0+cu101)\n", 47 | "Requirement already up-to-date: torchvision in /usr/local/lib/python3.6/dist-packages (0.7.0+cu101)\n", 48 | "Requirement already satisfied, skipping upgrade: numpy in /usr/local/lib/python3.6/dist-packages (from torch) (1.18.5)\n", 49 | "Requirement already satisfied, skipping upgrade: future in /usr/local/lib/python3.6/dist-packages (from torch) (0.16.0)\n", 50 | "Requirement already satisfied, skipping upgrade: pillow>=4.1.1 in /usr/local/lib/python3.6/dist-packages (from torchvision) (7.0.0)\n" 51 | ], 52 | "name": "stdout" 53 | } 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "metadata": { 59 | "id": "-4oczuyMfOyg" 60 | }, 61 | "source": [ 62 | "import torch" 63 | ], 64 | "execution_count": 4, 65 | "outputs": [] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "metadata": { 70 | "id": "YapL0UdRfU48", 71 | "outputId": "0dc49256-157f-48cd-de24-cfaf7368b5ce", 72 | "colab": { 73 | "base_uri": "https://localhost:8080/", 74 | "height": 105 75 | } 76 | }, 77 | "source": [ 78 | "x = torch.rand(5, 3)\n", 79 | "print(x)" 80 | ], 81 | "execution_count": 7, 82 | "outputs": [ 83 | { 84 | "output_type": "stream", 85 | "text": [ 86 | "tensor([[0.1081, 0.8520, 0.4269],\n", 87 | " [0.9329, 0.3170, 0.1846],\n", 88 | " [0.2535, 0.5622, 0.6611],\n", 89 | " [0.5403, 0.3821, 0.1359],\n", 90 | " [0.4826, 0.6152, 0.9669]])\n" 91 | ], 92 | "name": "stdout" 93 | } 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "metadata": { 99 | "id": "B1REEsbwfZQP", 100 | "outputId": "b49e033a-a0f6-42c9-8c09-e539d483eab4", 101 | "colab": { 102 | "base_uri": "https://localhost:8080/", 103 | "height": 105 104 | } 105 | }, 106 | "source": [ 107 | "torch.empty(5, 3)" 108 | ], 109 | "execution_count": 8, 110 | "outputs": [ 111 | { 112 | "output_type": "execute_result", 113 | "data": { 114 | "text/plain": [ 115 | "tensor([[5.9212e-36, 0.0000e+00, 2.1019e-44],\n", 116 | " [0.0000e+00, 1.4013e-45, 0.0000e+00],\n", 117 | " [1.2121e+04, 7.1846e+22, 9.2198e-39],\n", 118 | " [7.0374e+22, 5.0948e-14, 7.1846e+22],\n", 119 | " [9.2198e-39, 7.0374e+22, 5.0948e-14]])" 120 | ] 121 | }, 122 | "metadata": { 123 | "tags": [] 124 | }, 125 | "execution_count": 8 126 | } 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "metadata": { 132 | "id": "ezIIpXyLfcJX", 133 | "outputId": "5db6a3ba-a179-48a2-8eb3-3f250fdf3526", 134 | "colab": { 135 | "base_uri": "https://localhost:8080/", 136 | "height": 105 137 | } 138 | }, 139 | "source": [ 140 | "torch.zeros(5, 3)" 141 | ], 142 | "execution_count": 9, 143 | "outputs": [ 144 | { 145 | "output_type": "execute_result", 146 | "data": { 147 | "text/plain": [ 148 | "tensor([[0., 0., 0.],\n", 149 | " [0., 0., 0.],\n", 150 | " [0., 0., 0.],\n", 151 | " [0., 0., 0.],\n", 152 | " [0., 0., 0.]])" 153 | ] 154 | }, 155 | "metadata": { 156 | "tags": [] 157 | }, 158 | "execution_count": 9 159 | } 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "metadata": { 165 | "id": "JvunrdyYgIay", 166 | "outputId": "bcbe9c13-c6f3-47db-af6e-5d3876ce4c75", 167 | "colab": { 168 | "base_uri": "https://localhost:8080/", 169 | "height": 34 170 | } 171 | }, 172 | "source": [ 173 | "x = torch.tensor([5.5, 3])\n", 174 | "print(x)" 175 | ], 176 | "execution_count": 10, 177 | "outputs": [ 178 | { 179 | "output_type": "stream", 180 | "text": [ 181 | "tensor([5.5000, 3.0000])\n" 182 | ], 183 | "name": "stdout" 184 | } 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "metadata": { 190 | "id": "vL_R980OgL0_", 191 | "outputId": "8f9334c7-f47a-466c-8790-8610aaa383c8", 192 | "colab": { 193 | "base_uri": "https://localhost:8080/", 194 | "height": 194 195 | } 196 | }, 197 | "source": [ 198 | "#These methods will reuse properties of the input tensor, e.g. dtype, unless new values are provided by user\n", 199 | "\n", 200 | "x = x.new_ones(5, 3, dtype=torch.double) # new_* methods take in sizes\n", 201 | "print(x)\n", 202 | "\n", 203 | "x = torch.randn_like(x, dtype=torch.float) # override dtype!\n", 204 | "print(x) # result has the same size" 205 | ], 206 | "execution_count": 11, 207 | "outputs": [ 208 | { 209 | "output_type": "stream", 210 | "text": [ 211 | "tensor([[1., 1., 1.],\n", 212 | " [1., 1., 1.],\n", 213 | " [1., 1., 1.],\n", 214 | " [1., 1., 1.],\n", 215 | " [1., 1., 1.]], dtype=torch.float64)\n", 216 | "tensor([[ 1.4040, -0.7761, 0.6523],\n", 217 | " [ 0.2967, 0.9208, 1.9486],\n", 218 | " [-0.6122, -0.0583, -0.6845],\n", 219 | " [ 1.0465, 1.7201, 1.4811],\n", 220 | " [-0.7210, -0.5113, -0.8721]])\n" 221 | ], 222 | "name": "stdout" 223 | } 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "metadata": { 229 | "id": "KLDD-d6-gbBe" 230 | }, 231 | "source": [ 232 | "x = torch.ones(5,3)\n", 233 | "y = torch.ones(5,3)" 234 | ], 235 | "execution_count": 12, 236 | "outputs": [] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "metadata": { 241 | "id": "p7AGrFMsitu0", 242 | "outputId": "9a47d217-70cc-454f-ce81-86726a6966c2", 243 | "colab": { 244 | "base_uri": "https://localhost:8080/", 245 | "height": 141 246 | } 247 | }, 248 | "source": [ 249 | "%time x+y" 250 | ], 251 | "execution_count": 13, 252 | "outputs": [ 253 | { 254 | "output_type": "stream", 255 | "text": [ 256 | "CPU times: user 486 µs, sys: 112 µs, total: 598 µs\n", 257 | "Wall time: 376 µs\n" 258 | ], 259 | "name": "stdout" 260 | }, 261 | { 262 | "output_type": "execute_result", 263 | "data": { 264 | "text/plain": [ 265 | "tensor([[2., 2., 2.],\n", 266 | " [2., 2., 2.],\n", 267 | " [2., 2., 2.],\n", 268 | " [2., 2., 2.],\n", 269 | " [2., 2., 2.]])" 270 | ] 271 | }, 272 | "metadata": { 273 | "tags": [] 274 | }, 275 | "execution_count": 13 276 | } 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "metadata": { 282 | "id": "IKb1sTQ6ivHk", 283 | "outputId": "1edd7b91-7663-42c1-af80-0b9f034ebe02", 284 | "colab": { 285 | "base_uri": "https://localhost:8080/", 286 | "height": 141 287 | } 288 | }, 289 | "source": [ 290 | "%time torch.add(x, y)" 291 | ], 292 | "execution_count": 14, 293 | "outputs": [ 294 | { 295 | "output_type": "stream", 296 | "text": [ 297 | "CPU times: user 0 ns, sys: 232 µs, total: 232 µs\n", 298 | "Wall time: 843 µs\n" 299 | ], 300 | "name": "stdout" 301 | }, 302 | { 303 | "output_type": "execute_result", 304 | "data": { 305 | "text/plain": [ 306 | "tensor([[2., 2., 2.],\n", 307 | " [2., 2., 2.],\n", 308 | " [2., 2., 2.],\n", 309 | " [2., 2., 2.],\n", 310 | " [2., 2., 2.]])" 311 | ] 312 | }, 313 | "metadata": { 314 | "tags": [] 315 | }, 316 | "execution_count": 14 317 | } 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "metadata": { 323 | "id": "UdICnHPYizWm", 324 | "outputId": "26e8db9a-41e0-48e8-8c7d-75b4ce37bb8e", 325 | "colab": { 326 | "base_uri": "https://localhost:8080/", 327 | "height": 105 328 | } 329 | }, 330 | "source": [ 331 | "#Addition: providing an output tensor as argument\n", 332 | "result = torch.empty(5, 3)\n", 333 | "torch.add(x, y, out=result)\n", 334 | "print(result)" 335 | ], 336 | "execution_count": 15, 337 | "outputs": [ 338 | { 339 | "output_type": "stream", 340 | "text": [ 341 | "tensor([[2., 2., 2.],\n", 342 | " [2., 2., 2.],\n", 343 | " [2., 2., 2.],\n", 344 | " [2., 2., 2.],\n", 345 | " [2., 2., 2.]])\n" 346 | ], 347 | "name": "stdout" 348 | } 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "metadata": { 354 | "id": "zxgtArJcjAsW", 355 | "outputId": "fdc1bd03-8276-430b-fa92-ca7970bbbde1", 356 | "colab": { 357 | "base_uri": "https://localhost:8080/", 358 | "height": 105 359 | } 360 | }, 361 | "source": [ 362 | "# adds x to y\n", 363 | "y.add_(x)\n", 364 | "print(y)\n", 365 | "#Any operation that mutates a tensor in-place is post-fixed with an _. For example: x.copy_(y), x.t_(), will change x." 366 | ], 367 | "execution_count": 16, 368 | "outputs": [ 369 | { 370 | "output_type": "stream", 371 | "text": [ 372 | "tensor([[2., 2., 2.],\n", 373 | " [2., 2., 2.],\n", 374 | " [2., 2., 2.],\n", 375 | " [2., 2., 2.],\n", 376 | " [2., 2., 2.]])\n" 377 | ], 378 | "name": "stdout" 379 | } 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "metadata": { 385 | "id": "WM60eo8KjRIK", 386 | "outputId": "6bf19d86-43b0-4b1e-b56e-41c8fcaeb9a2", 387 | "colab": { 388 | "base_uri": "https://localhost:8080/", 389 | "height": 105 390 | } 391 | }, 392 | "source": [ 393 | "x.numpy()" 394 | ], 395 | "execution_count": 17, 396 | "outputs": [ 397 | { 398 | "output_type": "execute_result", 399 | "data": { 400 | "text/plain": [ 401 | "array([[1., 1., 1.],\n", 402 | " [1., 1., 1.],\n", 403 | " [1., 1., 1.],\n", 404 | " [1., 1., 1.],\n", 405 | " [1., 1., 1.]], dtype=float32)" 406 | ] 407 | }, 408 | "metadata": { 409 | "tags": [] 410 | }, 411 | "execution_count": 17 412 | } 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "metadata": { 418 | "id": "gTkN6s9bjaNb", 419 | "outputId": "7f82a8bb-f42c-48f1-c9d5-b43f477fc52c", 420 | "colab": { 421 | "base_uri": "https://localhost:8080/", 422 | "height": 52 423 | } 424 | }, 425 | "source": [ 426 | "#Converting NumPy Array to Torch Tensor\n", 427 | "import numpy as np\n", 428 | "a = np.ones(5)\n", 429 | "b = torch.from_numpy(a)\n", 430 | "np.add(a, 1, out=a)\n", 431 | "print(a)\n", 432 | "print(b)" 433 | ], 434 | "execution_count": 18, 435 | "outputs": [ 436 | { 437 | "output_type": "stream", 438 | "text": [ 439 | "[2. 2. 2. 2. 2.]\n", 440 | "tensor([2., 2., 2., 2., 2.], dtype=torch.float64)\n" 441 | ], 442 | "name": "stdout" 443 | } 444 | ] 445 | } 446 | ] 447 | } -------------------------------------------------------------------------------- /tensorflow_hub_useT.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 6, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import tensorflow as tf\n", 10 | "import tensorflow_hub as hub\n", 11 | "import numpy as np" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "# universal sentence encoder using Transformer ARCHITECTURE" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 2, 24 | "metadata": {}, 25 | "outputs": [ 26 | { 27 | "name": "stdout", 28 | "output_type": "stream", 29 | "text": [ 30 | "mkdir: cannot create directory ‘../sentence_wise_email/module/module_useT’: File exists\n", 31 | " % Total % Received % Xferd Average Speed Time Time Time Current\n", 32 | " Dload Upload Total Spent Left Speed\n", 33 | " 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\n", 34 | "./\n", 35 | "./tfhub_module.pb\n", 36 | "./variables/\n", 37 | "./variables/variables.data-00000-of-00001\n", 38 | " 99 745M 99 739M 0 0 20.1M 0 0:00:36 0:00:36 --:--:-- 22.8M./variables/variables.index\n", 39 | "./assets/\n", 40 | "./saved_model.pb\n", 41 | "100 745M 100 745M 0 0 19.6M 0 0:00:37 0:00:37 --:--:-- 16.8M\n" 42 | ] 43 | } 44 | ], 45 | "source": [ 46 | "#download the model to local so it can be used again and again\n", 47 | "!mkdir ../sentence_wise_email/module/module_useT\n", 48 | "# Download the module, and uncompress it to the destination folder. \n", 49 | "!curl -L \"https://tfhub.dev/google/universal-sentence-encoder-large/3?tf-hub-format=compressed\" | tar -zxvC ../sentence_wise_email/module/module_useT" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 7, 55 | "metadata": {}, 56 | "outputs": [ 57 | { 58 | "name": "stdout", 59 | "output_type": "stream", 60 | "text": [ 61 | "Message: Elephant\n", 62 | "Embedding size: 512\n", 63 | "Embedding: [0.04498474299907684, -0.05743394419550896, 0.002211471786722541, ...]\n", 64 | "\n", 65 | "Message: I am a sentence for which I would like to get its embedding.\n", 66 | "Embedding size: 512\n", 67 | "Embedding: [0.05568016692996025, -0.009607920423150063, 0.006246279925107956, ...]\n", 68 | "\n", 69 | "Message: Universal Sentence Encoder embeddings also support short paragraphs. There is no hard limit on how long the paragraph is. Roughly, the longer the more 'diluted' the embedding will be.\n", 70 | "Embedding size: 512\n", 71 | "Embedding: [0.03874940797686577, 0.0765201598405838, -0.0007945669931359589, ...]\n", 72 | "\n" 73 | ] 74 | } 75 | ], 76 | "source": [ 77 | "embed = hub.Module(\"../sentence_wise_email/module/module_useT\")\n", 78 | "\n", 79 | "# Compute a representation for each message, showing various lengths supported.\n", 80 | "word = \"Elephant\"\n", 81 | "sentence = \"I am a sentence for which I would like to get its embedding.\"\n", 82 | "paragraph = (\n", 83 | " \"Universal Sentence Encoder embeddings also support short paragraphs. \"\n", 84 | " \"There is no hard limit on how long the paragraph is. Roughly, the longer \"\n", 85 | " \"the more 'diluted' the embedding will be.\")\n", 86 | "messages = [word, sentence, paragraph]\n", 87 | "\n", 88 | "# Reduce logging output.\n", 89 | "tf.logging.set_verbosity(tf.logging.ERROR)\n", 90 | "\n", 91 | "with tf.Session() as session:\n", 92 | " session.run([tf.global_variables_initializer(), tf.tables_initializer()])\n", 93 | " message_embeddings = session.run(embed(messages))\n", 94 | "\n", 95 | " for i, message_embedding in enumerate(np.array(message_embeddings).tolist()):\n", 96 | " print(\"Message: {}\".format(messages[i]))\n", 97 | " print(\"Embedding size: {}\".format(len(message_embedding)))\n", 98 | " message_embedding_snippet = \", \".join((str(x) for x in message_embedding[:3]))\n", 99 | " print(\"Embedding: [{}, ...]\\n\".format(message_embedding_snippet))" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 8, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "#Function so that one session can be called multiple times. \n", 109 | "#Useful while multiple calls need to be done for embedding. \n", 110 | "import tensorflow as tf\n", 111 | "import tensorflow_hub as hub\n", 112 | "def embed_useT(module):\n", 113 | " with tf.Graph().as_default():\n", 114 | " sentences = tf.placeholder(tf.string)\n", 115 | " embed = hub.Module(module)\n", 116 | " embeddings = embed(sentences)\n", 117 | " session = tf.train.MonitoredSession()\n", 118 | " return lambda x: session.run(embeddings, {sentences: x})\n", 119 | "\n", 120 | "embed_fn = embed_useT('../sentence_wise_email/module/module_useT')" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 9, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "messages = [\n", 130 | " \"we are sorry for the inconvenience\",\n", 131 | " \"we are sorry for the delay\",\n", 132 | " \"we regret for your inconvenience\",\n", 133 | " \"we don't deliver to baner region in pune\",\n", 134 | " \"we will get you the best possible rate\"\n", 135 | "]" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 10, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "encoding_matrix = embed_fn(messages) " 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 15, 150 | "metadata": {}, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/plain": [ 155 | "array([[1. , 0.87426376, 0.8004891 , 0.23807861, 0.46469775],\n", 156 | " [0.87426376, 1.0000001 , 0.60501504, 0.2508136 , 0.4493388 ],\n", 157 | " [0.8004891 , 0.60501504, 0.9999998 , 0.1784874 , 0.4195464 ],\n", 158 | " [0.23807861, 0.2508136 , 0.1784874 , 1.0000001 , 0.24955797],\n", 159 | " [0.46469775, 0.4493388 , 0.4195464 , 0.24955797, 1.0000002 ]],\n", 160 | " dtype=float32)" 161 | ] 162 | }, 163 | "execution_count": 15, 164 | "metadata": {}, 165 | "output_type": "execute_result" 166 | } 167 | ], 168 | "source": [ 169 | "np.inner(encoding_matrix, encoding_matrix)" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 12, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "from math import*\n", 179 | "from decimal import Decimal\n", 180 | "\n", 181 | "class Similarity():\n", 182 | " def euclidean_distance(self,x,y):\n", 183 | "\n", 184 | " \"\"\" return euclidean distance between two lists \"\"\"\n", 185 | "\n", 186 | " return sqrt(sum(pow(a-b,2) for a, b in zip(x, y)))\n", 187 | "\n", 188 | " def manhattan_distance(self,x,y):\n", 189 | "\n", 190 | " \"\"\" return manhattan distance between two lists \"\"\"\n", 191 | "\n", 192 | " return sum(abs(a-b) for a,b in zip(x,y))\n", 193 | "\n", 194 | " def minkowski_distance(self,x,y,p_value):\n", 195 | "\n", 196 | " \"\"\" return minkowski distance between two lists \"\"\"\n", 197 | "\n", 198 | " return self.nth_root(sum(pow(abs(a-b),p_value) for a,b in zip(x, y)),\n", 199 | " p_value)\n", 200 | "\n", 201 | " def nth_root(self,value, n_root):\n", 202 | "\n", 203 | " \"\"\" returns the n_root of an value \"\"\"\n", 204 | "\n", 205 | " root_value = 1/float(n_root)\n", 206 | " return round (Decimal(value) ** Decimal(root_value),3)\n", 207 | "\n", 208 | " def cosine_similarity(self,x,y):\n", 209 | "\n", 210 | " \"\"\" return cosine similarity between two lists \"\"\"\n", 211 | "\n", 212 | " numerator = sum(a*b for a,b in zip(x,y))\n", 213 | " denominator = self.square_rooted(x)*self.square_rooted(y)\n", 214 | " return round(numerator/float(denominator),3)\n", 215 | "\n", 216 | " def square_rooted(self,x):\n", 217 | "\n", 218 | " \"\"\" return 3 rounded square rooted value \"\"\"\n", 219 | "\n", 220 | " return round(sqrt(sum([a*a for a in x])),3)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 13, 226 | "metadata": {}, 227 | "outputs": [ 228 | { 229 | "data": { 230 | "text/plain": [ 231 | "0.8" 232 | ] 233 | }, 234 | "execution_count": 13, 235 | "metadata": {}, 236 | "output_type": "execute_result" 237 | } 238 | ], 239 | "source": [ 240 | "measures = Similarity()\n", 241 | "measures.cosine_similarity(encoding_matrix[0],encoding_matrix[2])" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 16, 247 | "metadata": {}, 248 | "outputs": [ 249 | { 250 | "data": { 251 | "image/png": "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\n", 252 | "text/plain": [ 253 | "
" 254 | ] 255 | }, 256 | "metadata": {}, 257 | "output_type": "display_data" 258 | } 259 | ], 260 | "source": [ 261 | "import matplotlib.pyplot as plt\n", 262 | "import seaborn as sns\n", 263 | "%matplotlib inline\n", 264 | "def plot_similarity(labels, features, rotation):\n", 265 | " corr = np.inner(features, features)\n", 266 | " sns.set(font_scale=1.2)\n", 267 | " g = sns.heatmap(\n", 268 | " corr,\n", 269 | " xticklabels=labels,\n", 270 | " yticklabels=labels,\n", 271 | " vmin=0,\n", 272 | " vmax=1,\n", 273 | " cmap=\"YlGnBu\")\n", 274 | " g.set_xticklabels(labels, rotation=rotation)\n", 275 | " g.set_title(\"Semantic Textual Similarity\")\n", 276 | "\n", 277 | "plot_similarity(messages, encoding_matrix, 90)" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 17, 283 | "metadata": {}, 284 | "outputs": [], 285 | "source": [ 286 | "#It takes similarity matrix (generated from sentence encoder) as input and gives index of redundant statements\n", 287 | "def redundant_sent_idx(sim_matrix):\n", 288 | " dup_idx = [] \n", 289 | " for i in range(sim_matrix.shape[0]):\n", 290 | " if i not in dup_idx:\n", 291 | " tmp = [t+i+1 for t in list(np.where( sim_matrix[i][i+1:] > 0.8 )[0])]\n", 292 | " dup_idx.extend(tmp)\n", 293 | " return dup_idx" 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 18, 299 | "metadata": {}, 300 | "outputs": [], 301 | "source": [ 302 | "dup_indexes = redundant_sent_idx(np.inner(encoding_matrix,encoding_matrix))" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 19, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "data": { 312 | "text/plain": [ 313 | "[1, 2]" 314 | ] 315 | }, 316 | "execution_count": 19, 317 | "metadata": {}, 318 | "output_type": "execute_result" 319 | } 320 | ], 321 | "source": [ 322 | "dup_indexes" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": 20, 328 | "metadata": {}, 329 | "outputs": [ 330 | { 331 | "data": { 332 | "text/plain": [ 333 | "array(['we are sorry for the inconvenience',\n", 334 | " \"we don't deliver to baner region in pune\",\n", 335 | " 'we will get you the best possible rate'], dtype=' 0.8:\n", 594 | " print(\"it is a greetings\")\n", 595 | "else:\n", 596 | " print(\"it is not a greetings\")" 597 | ] 598 | }, 599 | { 600 | "cell_type": "code", 601 | "execution_count": null, 602 | "metadata": {}, 603 | "outputs": [], 604 | "source": [] 605 | } 606 | ], 607 | "metadata": { 608 | "kernelspec": { 609 | "display_name": "Python 3", 610 | "language": "python", 611 | "name": "python3" 612 | }, 613 | "language_info": { 614 | "codemirror_mode": { 615 | "name": "ipython", 616 | "version": 3 617 | }, 618 | "file_extension": ".py", 619 | "mimetype": "text/x-python", 620 | "name": "python", 621 | "nbconvert_exporter": "python", 622 | "pygments_lexer": "ipython3", 623 | "version": "3.6.5" 624 | } 625 | }, 626 | "nbformat": 4, 627 | "nbformat_minor": 2 628 | } --------------------------------------------------------------------------------