{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Let's load up the Yelp review dataset, \n",
    "# an array of JSON structures\n",
    "\n",
    "# Grab the data and progress bar\n",
    "# We only need to do this once.\n",
    "!pip install -Iv bokeh==0.13.0\n",
    "import codecs\n",
    "from io import open\n",
    "!wget https://storage.googleapis.com/aai17/yelp_dataset.tar\n",
    "!tar xfvz yelp_dataset.tar\n",
    "!mv dataset/review.json yelp_reviews.json\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bk-root\">\n",
       "        <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
       "        <span id=\"9cd40ca9-0299-434f-b01d-4975b1483b7a\">Loading BokehJS ...</span>\n",
       "    </div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null && id in Bokeh.index) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var id = msg.content.text.trim();\n",
       "            if (id in Bokeh.index) {\n",
       "              Bokeh.index[id].model.document.clear();\n",
       "              delete Bokeh.index[id];\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(\"9cd40ca9-0299-434f-b01d-4975b1483b7a\");\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
       "    }\n",
       "    finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.info(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(js_urls, callback) {\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = js_urls.length;\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var s = document.createElement('script');\n",
       "      s.src = url;\n",
       "      s.async = false;\n",
       "      s.onreadystatechange = s.onload = function() {\n",
       "        root._bokeh_is_loading--;\n",
       "        if (root._bokeh_is_loading === 0) {\n",
       "          console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
       "          run_callbacks()\n",
       "        }\n",
       "      };\n",
       "      s.onerror = function() {\n",
       "        console.warn(\"failed to load library \" + url);\n",
       "      };\n",
       "      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "    }\n",
       "  };var element = document.getElementById(\"9cd40ca9-0299-434f-b01d-4975b1483b7a\");\n",
       "  if (element == null) {\n",
       "    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '9cd40ca9-0299-434f-b01d-4975b1483b7a' but no matching script tag was found. \")\n",
       "    return false;\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.13.0.min.js\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(\"9cd40ca9-0299-434f-b01d-4975b1483b7a\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(js_urls, function() {\n",
       "      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(\"9cd40ca9-0299-434f-b01d-4975b1483b7a\");\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n    }\n    finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.info(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(js_urls, callback) {\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = js_urls.length;\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var s = document.createElement('script');\n      s.src = url;\n      s.async = false;\n      s.onreadystatechange = s.onload = function() {\n        root._bokeh_is_loading--;\n        if (root._bokeh_is_loading === 0) {\n          console.log(\"Bokeh: all BokehJS libraries loaded\");\n          run_callbacks()\n        }\n      };\n      s.onerror = function() {\n        console.warn(\"failed to load library \" + url);\n      };\n      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.getElementsByTagName(\"head\")[0].appendChild(s);\n    }\n  };var element = document.getElementById(\"9cd40ca9-0299-434f-b01d-4975b1483b7a\");\n  if (element == null) {\n    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '9cd40ca9-0299-434f-b01d-4975b1483b7a' but no matching script tag was found. \")\n    return false;\n  }\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.13.0.min.js\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css\");\n    }\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(\"9cd40ca9-0299-434f-b01d-4975b1483b7a\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(js_urls, function() {\n      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.models import ColumnDataSource, LabelSet\n",
    "from bokeh.plotting import figure, show, output_file\n",
    "from bokeh.io import output_notebook\n",
    "output_notebook()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loading...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 5261669/5261669 [00:45<00:00, 116165.09it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded  5261669 reviews in  0:01:22.839652\n",
      "Love the staff, love the meat, love the place. Prepare for a long line around lunch or dinner hours. \n",
      "\n",
      "They ask you how you want you meat, lean or something maybe, I can't remember. Just say you don't want it too fatty. \n",
      "\n",
      "Get a half sour pickle and a hot pepper. Hand cut french fries too. \n",
      "\n",
      "Rating:  5 stars\n"
     ]
    }
   ],
   "source": [
    "from tqdm import tqdm\n",
    "from collections import Counter\n",
    "from datetime import datetime\n",
    "import json\n",
    "\n",
    "t1 = datetime.now()\n",
    "print(\"Loading...\")\n",
    "with open(\"yelp_reviews.json\", \"r\", encoding=\"utf-8\") as f:\n",
    "    reviews = f.read().strip().split(\"\\n\")\n",
    "reviews = [json.loads(review) for review in tqdm(reviews)]\n",
    "print(\"Loaded \", len(reviews), \"reviews in \", datetime.now() - t1)\n",
    "\n",
    "print(reviews[0]['text'], \"\\n\\nRating: \", reviews[0]['stars'],\"stars\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  9%|▊         | 449324/5261669 [00:06<01:09, 69264.96it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selected  100000 positive and 100000 negative reviews\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# choose a random subset of reviews\n",
    "count = 100000\n",
    "import numpy as np\n",
    "import re\n",
    "\n",
    "np.random.seed(1)\n",
    "positive = []\n",
    "negative = []\n",
    "all_reviews = np.array(reviews)\n",
    "np.random.shuffle(all_reviews)\n",
    "notalpha = re.compile('[^a-zA-Z ]')\n",
    "\n",
    "def tokenize(text):\n",
    "    return notalpha.sub('',text).lower().strip()\n",
    "    \n",
    "for review in tqdm(all_reviews):\n",
    "    neg = review['stars'] < 3\n",
    "    pos = review['stars'] > 3\n",
    "    text = tokenize(review['text'])\n",
    "    if neg and len(negative) < count:\n",
    "        negative.append(text)\n",
    "    elif pos and len(positive) < count:\n",
    "        positive.append(text)\n",
    "    if len(negative) >= count and len(positive) >= count:\n",
    "        break\n",
    "\n",
    "print(\"Selected \",len(positive),\"positive and\",len(negative),\"negative reviews\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Please stand by...\n",
      "Memory cleared\n"
     ]
    }
   ],
   "source": [
    "# clean up memory\n",
    "print(\"Please stand by...\")\n",
    "reviews = []\n",
    "all_reviews = []\n",
    "print(\"Memory cleared\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  1%|          | 964/100000 [00:00<00:10, 9635.25it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Gathering positive words\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100000/100000 [00:10<00:00, 9626.41it/s]\n",
      "  1%|          | 672/100000 [00:00<00:14, 6718.00it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Gathering negative words\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100000/100000 [00:15<00:00, 6568.77it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating influence ratios of frequent words\n",
      "Creating training vocabulary\n",
      "Found 9541 words\n"
     ]
    }
   ],
   "source": [
    "from collections import Counter\n",
    "\n",
    "positive_counts = Counter()\n",
    "negative_counts = Counter()\n",
    "total_counts = Counter()\n",
    "pos_neg_ratios = Counter()\n",
    "polarity_cutoff = 0.2\n",
    "min_count = 50\n",
    "\n",
    "print(\"Gathering positive words\")\n",
    "for review in tqdm(positive):\n",
    "    for word in review.split(\" \"):\n",
    "        positive_counts[word] += 1\n",
    "        total_counts[word] += 1\n",
    "\n",
    "print(\"Gathering negative words\")\n",
    "for review in tqdm(negative):\n",
    "    for word in review.split(\" \"):\n",
    "        negative_counts[word] += 1\n",
    "        total_counts[word] += 1\n",
    "        \n",
    "print(\"Creating influence ratios of frequent words\")\n",
    "for term,cnt in list(total_counts.most_common()):\n",
    "    if(cnt >= min_count):\n",
    "        pos_neg_ratio = positive_counts[term] / float(negative_counts[term]+1)\n",
    "        pos_neg_ratios[term] = pos_neg_ratio\n",
    "\n",
    "for word,ratio in pos_neg_ratios.most_common():\n",
    "    if(ratio > 1):\n",
    "        pos_neg_ratios[word] = np.log(ratio)\n",
    "    else:\n",
    "        pos_neg_ratios[word] = -np.log((1 / (ratio + 0.01)))\n",
    "\n",
    "print(\"Creating training vocabulary\")\n",
    "review_vocab = set()\n",
    "for word,p in pos_neg_ratios.most_common():\n",
    "    if (p >= polarity_cutoff or p <= -polarity_cutoff):\n",
    "        review_vocab.add(word)\n",
    "        \n",
    "print(\"Found\",len(review_vocab),\"words\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "  <div class=\"bk-root\" id=\"515dda20-28ec-47e6-93c3-ad781336c903\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"c5082536-8d38-48cc-b93b-0f8c229390dd\":{\"roots\":{\"references\":[{\"attributes\":{},\"id\":\"cf873a76-cb91-448d-b258-19a268066575\",\"type\":\"Selection\"},{\"attributes\":{\"data_source\":{\"id\":\"e03da596-b426-4369-937e-d7b02ab9bcc6\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"8dcc6e4d-2f94-4a7a-8643-1cb4bb4f0e68\",\"type\":\"Quad\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"34075348-babd-410b-b30a-c6d6065dcfc9\",\"type\":\"Quad\"},\"selection_glyph\":null,\"view\":{\"id\":\"f484fdec-95eb-402e-8b3f-ca6ab59b5f2c\",\"type\":\"CDSView\"}},\"id\":\"3b47c96f-3206-49a9-b3f4-98e04dff9b24\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"left\":{\"field\":\"left\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"5d522f84-7d74-45c7-96d6-acb051e71e44\",\"type\":\"Quad\"},{\"attributes\":{},\"id\":\"754b97cd-0033-4f57-ad83-02b3c791442c\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"5287a32b-bd35-42a5-a4be-36da7f490722\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"callback\":null,\"data\":{\"left\":{\"__ndarray__\":\"FlW1u7FrEsDgyMORp8oRwKs80medKRHAdbDgPZOIEMB+SN4nEs8PwBMw+9P9jA7AqBcYgOlKDcA8/zQs1QgMwNHmUdjAxgrAZs5uhKyECcD6tYswmEIIwI+dqNyDAAfAJIXFiG++BcC4bOI0W3wEwE1U/+BGOgPA4TscjTL4AcB2Izk5HrYAwBYWrMoT6P6/PuXlIutj/L9otB97wt/5v5CDWdOZW/e/ulKTK3HX9L/kIc2DSFPyvxjiDbg/nu+/bICBaO6V6r/AHvUYnY3lvxC9aMlLheC/wLa48/T51r/g5j+ppNLJv4CAOax9xaa/QE1GpsvfvD+gVqqIlUjRPwAawyc4Wds/sO5tY+204j9YUPqyPr3nPwiyhgKQxew/3IkJqfDm8D+wus9QGWvzP4jrlfhB7/U/YBxcoGpz+D84TSJIk/f6Pwx+6O+7e/0/5K6ul+T//z/eb7qfBkIBQEiInfMahAJAtKCARy/GA0AguWObQwgFQIrRRu9XSgZA9ukpQ2yMB0BiAg2XgM4IQA==\",\"dtype\":\"float64\",\"shape\":[50]},\"right\":{\"__ndarray__\":\"4MjDkafKEcCrPNJnnSkRwHWw4D2TiBDAfkjeJxLPD8ATMPvT/YwOwKgXGIDpSg3APP80LNUIDMDR5lHYwMYKwGbOboSshAnA+rWLMJhCCMCPnajcgwAHwCSFxYhvvgXAuGziNFt8BMBNVP/gRjoDwOE7HI0y+AHAdiM5OR62AMAWFqzKE+j+vz7l5SLrY/y/aLQfe8Lf+b+Qg1nTmVv3v7pSkytx1/S/5CHNg0hT8r8Y4g24P57vv2yAgWjuleq/wB71GJ2N5b8QvWjJS4Xgv8C2uPP0+da/4OY/qaTSyb+AgDmsfcWmv0BNRqbL37w/oFaqiJVI0T8AGsMnOFnbP7DubWPttOI/WFD6sj695z8IsoYCkMXsP9yJCanw5vA/sLrPUBlr8z+I65X4Qe/1P2AcXKBqc/g/OE0iSJP3+j8Mfujvu3v9P+Surpfk//8/3m+6nwZCAUBIiJ3zGoQCQLSggEcvxgNAILljm0MIBUCK0UbvV0oGQPbpKUNsjAdAYgINl4DOCEDNGvDqlBAKQA==\",\"dtype\":\"float64\",\"shape\":[50]},\"top\":{\"__ndarray__\":\"ERyB9ScHfj8AAAAAAAAAACBV6YX+YGA/gHGMsqjWRT8tVemF/mBwP/aNL99STHs/aKpjJz55hD/2jS/fUkx7P6o4tT0TNIc/mDi1PRM0lz8e1SD4XYWWP9J/plYebZI/9A34bPMnpT8mFQU/LnOjP1Qqm5mdnao/lZH+1ZBNtD/kBuuauNy2P9dNS5iCXr4/SjyENFE1wD/0Dfhs8yfFP4DhChOUv8w/EOZxzvHu0D8R9ZIbRvzUPxzFZ+bpSdc/EWURfDHl2z9Xz/fMUv/gPzroXB4AK+E/cHvQtgH14T9Q4zqc0xtzPwAAAAAAAAAAOs0MfUTD0D+Zb1wpaXrfP3CJWT821No/phnb3krr0z9aIx/jownQP4BxjLKo1sU/WuOpgJJkvz9jivEDVgK2P4S47K9yWK0//k3cs8MVoj+Z8cMkCPubP6y4fcuzD5E/KOOpgJJkjz86VemF/mCAP7D/3ch9kXg/gHGMsqjWZT+jcYyyqNZVP4BxjLKo1kU/gHGMsqjWRT+RcYyyqNZVPw==\",\"dtype\":\"float64\",\"shape\":[50]}},\"selected\":{\"id\":\"cf873a76-cb91-448d-b258-19a268066575\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"eb6eb7c4-e747-4a9e-9a15-11daba4d83ff\",\"type\":\"UnionRenderers\"}},\"id\":\"ff90dea2-b065-4453-97bc-2a1f56de8957\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"7fd3b8aa-0ec4-470c-8e02-672fa401a973\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"background_fill_color\":{\"value\":\"#E8DDCB\"},\"below\":[{\"id\":\"1d0c2611-d305-4e6f-97cc-3b742d313017\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"32ddc11e-d4b4-48fa-9fb8-3185c1217d92\",\"type\":\"LinearAxis\"}],\"plot_height\":400,\"plot_width\":400,\"renderers\":[{\"id\":\"1d0c2611-d305-4e6f-97cc-3b742d313017\",\"type\":\"LinearAxis\"},{\"id\":\"4c8001a1-42cc-4ba4-a039-35d52df12b6e\",\"type\":\"Grid\"},{\"id\":\"32ddc11e-d4b4-48fa-9fb8-3185c1217d92\",\"type\":\"LinearAxis\"},{\"id\":\"c66be886-14aa-43af-8f19-92478d76f176\",\"type\":\"Grid\"},{\"id\":\"e49e36c6-072e-4fda-8b83-622e6b710127\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"75b48d52-40f6-4393-8a9c-c0a9dfb4dcf9\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"f406c684-32a4-43a7-8e77-ae9bcfef600a\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"414a5b30-fa24-4798-b63a-5d41ddac7479\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"737e8201-0961-4793-bf19-9b424e06cead\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"2baf4eb0-f11b-44fe-a1c7-a805a025162b\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"328f0820-d07e-461a-bfbc-58f386adcfc5\",\"type\":\"LinearScale\"}},\"id\":\"fa9f3eec-400b-43da-932b-6bf6175d0d6f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"plot\":{\"id\":\"f91df3cf-a1d3-49e0-ad48-153aaf8f6e9a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"08a723ea-7244-4a6f-916c-bf526af4c477\",\"type\":\"BasicTicker\"}},\"id\":\"7f700055-d2fc-481a-a2b6-2927ee4d696a\",\"type\":\"Grid\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_color\":{\"value\":\"#036564\"},\"left\":{\"field\":\"left\"},\"line_color\":{\"value\":\"#033649\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"8dcc6e4d-2f94-4a7a-8643-1cb4bb4f0e68\",\"type\":\"Quad\"},{\"attributes\":{},\"id\":\"d088c02d-f2d8-4f4f-b577-faf2b737c1d2\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"b96dab66-8473-45de-912b-4452edffcc26\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"callback\":null},\"id\":\"2baf4eb0-f11b-44fe-a1c7-a805a025162b\",\"type\":\"DataRange1d\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"left\":{\"field\":\"left\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"bdc097dd-840e-4488-920c-bdc982ab2407\",\"type\":\"Quad\"},{\"attributes\":{},\"id\":\"dada7d90-8a38-4f64-a716-db6bc49a2090\",\"type\":\"BasicTicker\"},{\"attributes\":{\"source\":{\"id\":\"94a1304b-f1ab-4fa5-bb7c-0943de200fa7\",\"type\":\"ColumnDataSource\"}},\"id\":\"f761a6b5-6a6b-4c01-b5c8-96199d623dfd\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"b87e15d1-b4bb-426f-932d-e7c2832a9a2b\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"79e88870-b456-43a5-b1f9-02df5dcddad3\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data_source\":{\"id\":\"11dc6d38-a529-4f85-9e8b-0a70904ba171\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"15a67c4e-43bd-4c97-9d33-8a0832dac24d\",\"type\":\"Quad\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"e0319fef-9189-414e-835d-328d9e0b2550\",\"type\":\"Quad\"},\"selection_glyph\":null,\"view\":{\"id\":\"f3d464ab-0f7a-41fc-9082-20c2681ea662\",\"type\":\"CDSView\"}},\"id\":\"e49e36c6-072e-4fda-8b83-622e6b710127\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"328f0820-d07e-461a-bfbc-58f386adcfc5\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"e03da596-b426-4369-937e-d7b02ab9bcc6\",\"type\":\"ColumnDataSource\"}},\"id\":\"f484fdec-95eb-402e-8b3f-ca6ab59b5f2c\",\"type\":\"CDSView\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"left\":{\"field\":\"left\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"e0319fef-9189-414e-835d-328d9e0b2550\",\"type\":\"Quad\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_color\":{\"value\":\"#036564\"},\"left\":{\"field\":\"left\"},\"line_color\":{\"value\":\"#033649\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"fbfb19e4-9603-4eb3-a082-375b3dde2f52\",\"type\":\"Quad\"},{\"attributes\":{},\"id\":\"7943d353-b7e9-497c-941c-0cc71a00d1b8\",\"type\":\"Selection\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"f91df3cf-a1d3-49e0-ad48-153aaf8f6e9a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"dada7d90-8a38-4f64-a716-db6bc49a2090\",\"type\":\"BasicTicker\"}},\"id\":\"ce3bd480-60de-424a-a906-715938a9b8f9\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"4a4269e9-fe2e-4e25-8e21-255b8f0febb5\",\"type\":\"SaveTool\"},{\"attributes\":{\"callback\":null,\"data\":{\"left\":{\"__ndarray__\":\"AAAAAACASUApXI/C1bLWQClcj8J1rOZAH4XrUcD/8EApXI/CRan2QDMzMzPLUvxAH4XrUSj+AEGkcD0K69IDQSlcj8KtpwZBrkfhenB8CUEzMzMzM1EMQbgehev1JQ9BH4XrUVz9EEHhehSuvWcSQaRwPQof0hNBZmZmZoA8FUEpXI/C4aYWQexRuB5DERhBrkfheqR7GUFxPQrXBeYaQTMzMzNnUBxB9ihcj8i6HUG4HoXrKSUfQT0K16PFRyBBH4XrUfb8IEEAAAAAJ7IhQeF6FK5XZyJBw/UoXIgcI0GkcD0KudEjQYXrUbjphiRBZmZmZho8JUFI4XoUS/ElQSlcj8J7piZBCtejcKxbJ0HsUbge3RAoQc3MzMwNxihBrkfhej57KUGPwvUobzAqQXE9Ctef5SpBUrgehdCaK0EzMzMzAVAsQRWuR+ExBS1B9ihcj2K6LUHXo3A9k28uQbgehevDJC9BmpmZmfTZL0E9CtejkkcwQa5H4foqojBBH4XrUcP8MEGPwvWoW1cxQQ==\",\"dtype\":\"float64\",\"shape\":[50]},\"right\":{\"__ndarray__\":\"KVyPwtWy1kApXI/CdazmQB+F61HA//BAKVyPwkWp9kAzMzMzy1L8QB+F61Eo/gBBpHA9CuvSA0EpXI/CracGQa5H4XpwfAlBMzMzMzNRDEG4HoXr9SUPQR+F61Fc/RBB4XoUrr1nEkGkcD0KH9ITQWZmZmaAPBVBKVyPwuGmFkHsUbgeQxEYQa5H4XqkexlBcT0K1wXmGkEzMzMzZ1AcQfYoXI/Iuh1BuB6F6yklH0E9CtejxUcgQR+F61H2/CBBAAAAACeyIUHhehSuV2ciQcP1KFyIHCNBpHA9CrnRI0GF61G46YYkQWZmZmYaPCVBSOF6FEvxJUEpXI/Ce6YmQQrXo3CsWydB7FG4Ht0QKEHNzMzMDcYoQa5H4Xo+eylBj8L1KG8wKkFxPQrXn+UqQVK4HoXQmitBMzMzMwFQLEEVrkfhMQUtQfYoXI9iui1B16NwPZNvLkG4HoXrwyQvQZqZmZn02S9BPQrXo5JHMEGuR+H6KqIwQR+F61HD/DBBj8L1qFtXMUEAAAAA9LExQQ==\",\"dtype\":\"float64\",\"shape\":[50]},\"top\":{\"__ndarray__\":\"tLzgUAtXBj9ZgLq9xdGPPjw4cPI34HU+M+i4Ov/lcT5E4EtOVN1XPj/gS05U3Uc+WoC6vcXRPz5agLq9xdFPPlqAur3F0U8+WoC6vcXRLz5agLq9xdEvPk+Aur3F0T8+ZYC6vcXRPz4AAAAAAAAAAGWAur3F0S8+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT4C6vcXRLz4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlgLq9xdEvPgAAAAAAAAAAZYC6vcXRPz4AAAAAAAAAAGWAur3F0S8+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlgLq9xdEvPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4gLq9xdEvPg==\",\"dtype\":\"float64\",\"shape\":[50]}},\"selected\":{\"id\":\"9f99de56-5473-40a9-8793-d7cd664b86db\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"5287a32b-bd35-42a5-a4be-36da7f490722\",\"type\":\"UnionRenderers\"}},\"id\":\"e03da596-b426-4369-937e-d7b02ab9bcc6\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"axis_label\":\"relative count\",\"formatter\":{\"id\":\"c6428b1f-1afe-43aa-b7a2-422fed94ed7f\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"be858f97-d9a9-403b-b66e-fa5cbe46751a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"9c2486d2-eb53-454d-a624-7fdd74c21b85\",\"type\":\"BasicTicker\"}},\"id\":\"5a969e6c-91b3-4b64-9d04-c3b3a5253b79\",\"type\":\"LinearAxis\"},{\"attributes\":{\"background_fill_color\":{\"value\":\"#E8DDCB\"},\"below\":[{\"id\":\"057b5c7c-a9c8-4607-ab9e-e16db67fc933\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"c8e832d8-739d-42fc-a6ad-94257d1e0f4a\",\"type\":\"LinearAxis\"}],\"plot_height\":400,\"plot_width\":400,\"renderers\":[{\"id\":\"057b5c7c-a9c8-4607-ab9e-e16db67fc933\",\"type\":\"LinearAxis\"},{\"id\":\"d242b9d7-28e9-4c22-86e3-1dac9ead99fa\",\"type\":\"Grid\"},{\"id\":\"c8e832d8-739d-42fc-a6ad-94257d1e0f4a\",\"type\":\"LinearAxis\"},{\"id\":\"7472d447-783c-4674-a542-645fa0706ebf\",\"type\":\"Grid\"},{\"id\":\"8f660d45-c1f4-4395-92ea-97c26be4733b\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"69926ff7-926b-43de-ab98-4d31168fd8d9\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"10240fdb-38a5-4c6f-aebf-1dc6b5156437\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"8be02e8f-8d7b-4053-a7f3-bbe7c37cb0cb\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"a9dd7902-7377-422b-8873-721c7053be0a\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"e3320d3a-0087-4cb8-8c21-14b404bcd627\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"6d7cdff1-3287-4122-93f0-8e1fd2d157b0\",\"type\":\"LinearScale\"}},\"id\":\"45e1d527-512c-450e-aa6e-9defda4c7f4f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"callback\":null,\"data\":{\"left\":{\"__ndarray__\":\"AAAAAAAA8D8pXI/ClabWQClcj8J1puZAH4XrUdD88EApXI/CZab2QDMzMzP7T/xAH4XrUcj8AEGkcD0Kk9EDQSlcj8JdpgZBrkfheih7CUEzMzMz808MQbgeheu9JA9BH4XrUcT8EEHhehSuKWcSQaRwPQqP0RNBZmZmZvQ7FUEpXI/CWaYWQexRuB6/EBhBrkfheiR7GUFxPQrXieUaQTMzMzPvTxxB9ihcj1S6HUG4HoXruSQfQT0K16OPRyBBH4XrUcL8IEEAAAAA9bEhQeF6FK4nZyJBw/UoXFocI0GkcD0KjdEjQYXrUbi/hiRBZmZmZvI7JUFI4XoUJfElQSlcj8JXpiZBCtejcIpbJ0HsUbgevRAoQc3MzMzvxShBrkfheiJ7KUGPwvUoVTAqQXE9CteH5SpBUrgehbqaK0EzMzMz7U8sQRWuR+EfBS1B9ihcj1K6LUHXo3A9hW8uQbgeheu3JC9BmpmZmerZL0E9CtejjkcwQa5H4fonojBBH4XrUcH8MEGPwvWoWlcxQQ==\",\"dtype\":\"float64\",\"shape\":[50]},\"right\":{\"__ndarray__\":\"KVyPwpWm1kApXI/CdabmQB+F61HQ/PBAKVyPwmWm9kAzMzMz+0/8QB+F61HI/ABBpHA9CpPRA0EpXI/CXaYGQa5H4XooewlBMzMzM/NPDEG4HoXrvSQPQR+F61HE/BBB4XoUrilnEkGkcD0Kj9ETQWZmZmb0OxVBKVyPwlmmFkHsUbgevxAYQa5H4XokexlBcT0K14nlGkEzMzMz708cQfYoXI9Uuh1BuB6F67kkH0E9Ctejj0cgQR+F61HC/CBBAAAAAPWxIUHhehSuJ2ciQcP1KFxaHCNBpHA9Co3RI0GF61G4v4YkQWZmZmbyOyVBSOF6FCXxJUEpXI/CV6YmQQrXo3CKWydB7FG4Hr0QKEHNzMzM78UoQa5H4XoieylBj8L1KFUwKkFxPQrXh+UqQVK4HoW6mitBMzMzM+1PLEEVrkfhHwUtQfYoXI9Sui1B16NwPYVvLkG4HoXrtyQvQZqZmZnq2S9BPQrXo45HMEGuR+H6J6IwQR+F61HB/DBBj8L1qFpXMUEAAAAA9LExQQ==\",\"dtype\":\"float64\",\"shape\":[50]},\"top\":{\"__ndarray__\":\"ESnQat+XBj9Io/KZJuBGPrIzm8RT+C4+w/t+LNBWKT7Xp1TIiuQQPtSnVMiK5AA+yt9wYA6G9j3K33BgDoYGPsrfcGAOhgY+yt9wYA6G5j3K33BgDobmPcLfcGAOhvY90d9wYA6G9j0AAAAAAAAAANHfcGAOhuY9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwt9wYA6G5j0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADR33BgDobmPQAAAAAAAAAA0d9wYA6G9j0AAAAAAAAAANHfcGAOhuY9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADR33BgDobmPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACy33BgDobmPQ==\",\"dtype\":\"float64\",\"shape\":[50]}},\"selected\":{\"id\":\"7943d353-b7e9-497c-941c-0cc71a00d1b8\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"b96dab66-8473-45de-912b-4452edffcc26\",\"type\":\"UnionRenderers\"}},\"id\":\"11dc6d38-a529-4f85-9e8b-0a70904ba171\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"callback\":null,\"data\":{\"left\":{\"__ndarray__\":\"AAAAAAAAAACkcD0K16PgP6RwPQrXo/A/9ihcj8L1+D+kcD0K16MAQM3MzMzMzARA9ihcj8L1CEAfhetRuB4NQKRwPQrXoxBAuB6F61G4EkDNzMzMzMwUQOJ6FK5H4RZA9ihcj8L1GEAK16NwPQobQB+F61G4Hh1ANDMzMzMzH0CkcD0K16MgQK5H4XoUriFAuB6F61G4IkDD9Shcj8IjQM3MzMzMzCRA16NwPQrXJUDiehSuR+EmQOxRuB6F6ydA9ihcj8L1KEAAAAAAAAAqQArXo3A9CitAFa5H4XoULEAfhetRuB4tQClcj8L1KC5ANDMzMzMzL0AfhetRuB4wQKRwPQrXozBAKVyPwvUoMUCuR+F6FK4xQDMzMzMzMzJAuB6F61G4MkA+CtejcD0zQMP1KFyPwjNASOF6FK5HNEDNzMzMzMw0QFK4HoXrUTVA16NwPQrXNUBcj8L1KFw2QOJ6FK5H4TZAZ2ZmZmZmN0DsUbgehes3QHE9CtejcDhA9ihcj8L1OEB7FK5H4Xo5QA==\",\"dtype\":\"float64\",\"shape\":[50]},\"right\":{\"__ndarray__\":\"pHA9Ctej4D+kcD0K16PwP/YoXI/C9fg/pHA9CtejAEDNzMzMzMwEQPYoXI/C9QhAH4XrUbgeDUCkcD0K16MQQLgehetRuBJAzczMzMzMFEDiehSuR+EWQPYoXI/C9RhACtejcD0KG0AfhetRuB4dQDQzMzMzMx9ApHA9CtejIECuR+F6FK4hQLgehetRuCJAw/UoXI/CI0DNzMzMzMwkQNejcD0K1yVA4noUrkfhJkDsUbgehesnQPYoXI/C9ShAAAAAAAAAKkAK16NwPQorQBWuR+F6FCxAH4XrUbgeLUApXI/C9SguQDQzMzMzMy9AH4XrUbgeMECkcD0K16MwQClcj8L1KDFArkfhehSuMUAzMzMzMzMyQLgehetRuDJAPgrXo3A9M0DD9Shcj8IzQEjhehSuRzRAzczMzMzMNEBSuB6F61E1QNejcD0K1zVAXI/C9ShcNkDiehSuR+E2QGdmZmZmZjdA7FG4HoXrN0BxPQrXo3A4QPYoXI/C9ThAexSuR+F6OUAAAAAAAAA6QA==\",\"dtype\":\"float64\",\"shape\":[50]},\"top\":{\"__ndarray__\":\"E+TLU2kv5D9kaqt/mv/iP9GorlJPd9U/HHg1mbzexD+9KCBXrym1P3zHStvJk6Q/zpxj1+xDmj/m9ekJpnGNP0rQDQH2aIQ/JzwCOAcbfD8nPAI4BxtsP+316QmmcW0/aW7EqBBmYT9hbsSoEGZhPxkorHqvvGI/Iiiseq+8Uj+vtNzWcQ9QP5Wbex7taUU/oLTc1nEPQD+Vm3se7WlFP3uCGmZoxEo/gJt7Hu1pNT+Vm3se7WklP5Wbex7taSU/lZt7Hu1pNT8AAAAAAAAAAICbex7taTU/AAAAAAAAAAAAAAAAAAAAAICbex7taSU/AAAAAAAAAAAAAAAAAAAAAJWbex7taSU/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJWbex7taSU/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJWbex7taSU/AAAAAAAAAACVm3se7WklPw==\",\"dtype\":\"float64\",\"shape\":[50]}},\"selected\":{\"id\":\"23205a30-754c-4340-a6cb-b15f8f1ffb6c\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"50a1d710-dc91-4d9e-8d62-bb18aa2dc7dd\",\"type\":\"UnionRenderers\"}},\"id\":\"94a1304b-f1ab-4fa5-bb7c-0943de200fa7\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"f22a0a98-8f4f-4c4f-9d81-9ebb12bb5446\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"3edf89de-f91a-42f3-b251-b118ab7425a0\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"eb6eb7c4-e747-4a9e-9a15-11daba4d83ff\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"axis_label\":\"relative count\",\"formatter\":{\"id\":\"3aeebf71-064c-465e-8368-63a5e80976ae\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"45e1d527-512c-450e-aa6e-9defda4c7f4f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"83d3abb2-e620-42f4-ad49-aefb35d8de73\",\"type\":\"BasicTicker\"}},\"id\":\"c8e832d8-739d-42fc-a6ad-94257d1e0f4a\",\"type\":\"LinearAxis\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"b87e15d1-b4bb-426f-932d-e7c2832a9a2b\",\"type\":\"SaveTool\"}]},\"id\":\"44a2db1e-26f9-4c46-af3b-4a293b81285c\",\"type\":\"Toolbar\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_color\":{\"value\":\"#036564\"},\"left\":{\"field\":\"left\"},\"line_color\":{\"value\":\"#033649\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"15a67c4e-43bd-4c97-9d33-8a0832dac24d\",\"type\":\"Quad\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"45e1d527-512c-450e-aa6e-9defda4c7f4f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"83d3abb2-e620-42f4-ad49-aefb35d8de73\",\"type\":\"BasicTicker\"}},\"id\":\"7472d447-783c-4674-a542-645fa0706ebf\",\"type\":\"Grid\"},{\"attributes\":{\"background_fill_color\":{\"value\":\"#E8DDCB\"},\"below\":[{\"id\":\"d4ce491f-ce2a-46ee-9e94-00a26f117318\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"6dfc012a-a82a-4d7d-a8ca-bbfd37a18a8f\",\"type\":\"LinearAxis\"}],\"plot_height\":400,\"plot_width\":400,\"renderers\":[{\"id\":\"d4ce491f-ce2a-46ee-9e94-00a26f117318\",\"type\":\"LinearAxis\"},{\"id\":\"7f700055-d2fc-481a-a2b6-2927ee4d696a\",\"type\":\"Grid\"},{\"id\":\"6dfc012a-a82a-4d7d-a8ca-bbfd37a18a8f\",\"type\":\"LinearAxis\"},{\"id\":\"ce3bd480-60de-424a-a906-715938a9b8f9\",\"type\":\"Grid\"},{\"id\":\"3b47c96f-3206-49a9-b3f4-98e04dff9b24\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"7a2342e3-2c1a-4204-9fef-20f3b64b9530\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"bc06d4d3-f5ba-461b-a234-da36a60c4482\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"387ef1cd-e104-451b-9d94-aaf13372978d\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"b0e3357a-964d-433a-99bb-269a74ab8c1a\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"e322f4cf-29d9-4402-8b6d-1c40a4b56ebb\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"bfe2b96d-761f-4207-b6cf-d946bf5f09b4\",\"type\":\"LinearScale\"}},\"id\":\"f91df3cf-a1d3-49e0-ad48-153aaf8f6e9a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"axis_label\":\"relative count\",\"formatter\":{\"id\":\"f22a0a98-8f4f-4c4f-9d81-9ebb12bb5446\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"f91df3cf-a1d3-49e0-ad48-153aaf8f6e9a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"dada7d90-8a38-4f64-a716-db6bc49a2090\",\"type\":\"BasicTicker\"}},\"id\":\"6dfc012a-a82a-4d7d-a8ca-bbfd37a18a8f\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"83d3abb2-e620-42f4-ad49-aefb35d8de73\",\"type\":\"BasicTicker\"},{\"attributes\":{\"callback\":null},\"id\":\"d573e480-6a1d-4286-ad02-5ad5ae107dc7\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"23205a30-754c-4340-a6cb-b15f8f1ffb6c\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"a9dd7902-7377-422b-8873-721c7053be0a\",\"type\":\"LinearScale\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"fa9f3eec-400b-43da-932b-6bf6175d0d6f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"0d526931-51bf-4a95-bc56-cd8850ef8f05\",\"type\":\"BasicTicker\"}},\"id\":\"c66be886-14aa-43af-8f19-92478d76f176\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null},\"id\":\"e322f4cf-29d9-4402-8b6d-1c40a4b56ebb\",\"type\":\"DataRange1d\"},{\"attributes\":{\"callback\":null},\"id\":\"414a5b30-fa24-4798-b63a-5d41ddac7479\",\"type\":\"DataRange1d\"},{\"attributes\":{\"axis_label\":\"pos/neg ratio\",\"formatter\":{\"id\":\"7fd3b8aa-0ec4-470c-8e02-672fa401a973\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"45e1d527-512c-450e-aa6e-9defda4c7f4f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"7171c8f5-0925-48f8-b058-090b6066753d\",\"type\":\"BasicTicker\"}},\"id\":\"057b5c7c-a9c8-4607-ab9e-e16db67fc933\",\"type\":\"LinearAxis\"},{\"attributes\":{\"callback\":null},\"id\":\"3063728b-fe78-4753-a242-d76ad51166b5\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"08a723ea-7244-4a6f-916c-bf526af4c477\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"3aeebf71-064c-465e-8368-63a5e80976ae\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"callback\":null},\"id\":\"e3320d3a-0087-4cb8-8c21-14b404bcd627\",\"type\":\"DataRange1d\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"be858f97-d9a9-403b-b66e-fa5cbe46751a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"9c2486d2-eb53-454d-a624-7fdd74c21b85\",\"type\":\"BasicTicker\"}},\"id\":\"3e1bd11a-a204-43da-90e1-0c48cb47d93e\",\"type\":\"Grid\"},{\"attributes\":{\"plot\":null,\"text\":\"Discriminating Word Distribution\"},\"id\":\"44828041-3839-4466-9e62-ee32f5fb7e18\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"50a1d710-dc91-4d9e-8d62-bb18aa2dc7dd\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"0d526931-51bf-4a95-bc56-cd8850ef8f05\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"737e8201-0961-4793-bf19-9b424e06cead\",\"type\":\"LinearScale\"},{\"attributes\":{\"children\":[{\"id\":\"45e1d527-512c-450e-aa6e-9defda4c7f4f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"id\":\"be858f97-d9a9-403b-b66e-fa5cbe46751a\",\"subtype\":\"Figure\",\"type\":\"Plot\"}]},\"id\":\"60b7b19f-5c69-49dc-81bf-2300fd5c9af9\",\"type\":\"Row\"},{\"attributes\":{\"axis_label\":\"word frequency (above cutoff)\",\"formatter\":{\"id\":\"f0ad77c9-61d2-44b6-b97c-4f63ba86970f\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"f91df3cf-a1d3-49e0-ad48-153aaf8f6e9a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"08a723ea-7244-4a6f-916c-bf526af4c477\",\"type\":\"BasicTicker\"}},\"id\":\"d4ce491f-ce2a-46ee-9e94-00a26f117318\",\"type\":\"LinearAxis\"},{\"attributes\":{\"axis_label\":\"word frequency\",\"formatter\":{\"id\":\"d25a846f-be00-4617-9d6d-7f1e223070c3\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"fa9f3eec-400b-43da-932b-6bf6175d0d6f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"79e88870-b456-43a5-b1f9-02df5dcddad3\",\"type\":\"BasicTicker\"}},\"id\":\"1d0c2611-d305-4e6f-97cc-3b742d313017\",\"type\":\"LinearAxis\"},{\"attributes\":{\"children\":[{\"id\":\"4b7a6f55-254a-4244-ace5-fd2cd3d646ef\",\"type\":\"Row\"},{\"id\":\"60b7b19f-5c69-49dc-81bf-2300fd5c9af9\",\"type\":\"Row\"}]},\"id\":\"dec1db7c-ba41-4023-84c4-23da64b012ce\",\"type\":\"Column\"},{\"attributes\":{\"plot\":{\"id\":\"be858f97-d9a9-403b-b66e-fa5cbe46751a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"3edf89de-f91a-42f3-b251-b118ab7425a0\",\"type\":\"BasicTicker\"}},\"id\":\"9f2f5257-031e-41a9-8bfb-78752c1f8004\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null},\"id\":\"8be02e8f-8d7b-4053-a7f3-bbe7c37cb0cb\",\"type\":\"DataRange1d\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"left\":{\"field\":\"left\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"34075348-babd-410b-b30a-c6d6065dcfc9\",\"type\":\"Quad\"},{\"attributes\":{},\"id\":\"d25a846f-be00-4617-9d6d-7f1e223070c3\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"source\":{\"id\":\"11dc6d38-a529-4f85-9e8b-0a70904ba171\",\"type\":\"ColumnDataSource\"}},\"id\":\"f3d464ab-0f7a-41fc-9082-20c2681ea662\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"9c2486d2-eb53-454d-a624-7fdd74c21b85\",\"type\":\"BasicTicker\"},{\"attributes\":{\"plot\":null,\"text\":\"Raw Word Distribution\"},\"id\":\"75b48d52-40f6-4393-8a9c-c0a9dfb4dcf9\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"0c4441c9-c022-4b61-844f-424f032337aa\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"children\":[{\"id\":\"fa9f3eec-400b-43da-932b-6bf6175d0d6f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"id\":\"f91df3cf-a1d3-49e0-ad48-153aaf8f6e9a\",\"subtype\":\"Figure\",\"type\":\"Plot\"}]},\"id\":\"4b7a6f55-254a-4244-ace5-fd2cd3d646ef\",\"type\":\"Row\"},{\"attributes\":{\"axis_label\":\"relative count\",\"formatter\":{\"id\":\"0c4441c9-c022-4b61-844f-424f032337aa\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"fa9f3eec-400b-43da-932b-6bf6175d0d6f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"0d526931-51bf-4a95-bc56-cd8850ef8f05\",\"type\":\"BasicTicker\"}},\"id\":\"32ddc11e-d4b4-48fa-9fb8-3185c1217d92\",\"type\":\"LinearAxis\"},{\"attributes\":{\"plot\":null,\"text\":\"Pos/Neg Distribution\"},\"id\":\"69926ff7-926b-43de-ab98-4d31168fd8d9\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"c6428b1f-1afe-43aa-b7a2-422fed94ed7f\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"c5b43a8b-33b3-4c6f-9826-d75fe5dcdd64\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"ff90dea2-b065-4453-97bc-2a1f56de8957\",\"type\":\"ColumnDataSource\"}},\"id\":\"22dfb797-5537-4566-b316-68e1c60e45a8\",\"type\":\"CDSView\"},{\"attributes\":{\"plot\":null,\"text\":\"Min Count Word Distribution\"},\"id\":\"7a2342e3-2c1a-4204-9fef-20f3b64b9530\",\"type\":\"Title\"},{\"attributes\":{\"callback\":null},\"id\":\"387ef1cd-e104-451b-9d94-aaf13372978d\",\"type\":\"DataRange1d\"},{\"attributes\":{\"bottom\":{\"value\":0},\"fill_color\":{\"value\":\"#036564\"},\"left\":{\"field\":\"left\"},\"line_color\":{\"value\":\"#033649\"},\"right\":{\"field\":\"right\"},\"top\":{\"field\":\"top\"}},\"id\":\"3234fc5b-0935-45d1-8208-c7a683d47cd7\",\"type\":\"Quad\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"c2babdea-7cb4-40e8-a097-37870ecb439c\",\"type\":\"SaveTool\"}]},\"id\":\"bc06d4d3-f5ba-461b-a234-da36a60c4482\",\"type\":\"Toolbar\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"77c9f0a7-5f44-4af7-9d03-6dd8faf7c3d6\",\"type\":\"SaveTool\"}]},\"id\":\"f406c684-32a4-43a7-8e77-ae9bcfef600a\",\"type\":\"Toolbar\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"4a4269e9-fe2e-4e25-8e21-255b8f0febb5\",\"type\":\"SaveTool\"}]},\"id\":\"10240fdb-38a5-4c6f-aebf-1dc6b5156437\",\"type\":\"Toolbar\"},{\"attributes\":{\"data_source\":{\"id\":\"ff90dea2-b065-4453-97bc-2a1f56de8957\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"fbfb19e4-9603-4eb3-a082-375b3dde2f52\",\"type\":\"Quad\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"bdc097dd-840e-4488-920c-bdc982ab2407\",\"type\":\"Quad\"},\"selection_glyph\":null,\"view\":{\"id\":\"22dfb797-5537-4566-b316-68e1c60e45a8\",\"type\":\"CDSView\"}},\"id\":\"40cbe9c0-2367-4760-b72e-d2ec7f8fae18\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"c2babdea-7cb4-40e8-a097-37870ecb439c\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"7171c8f5-0925-48f8-b058-090b6066753d\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"6d7cdff1-3287-4122-93f0-8e1fd2d157b0\",\"type\":\"LinearScale\"},{\"attributes\":{\"axis_label\":\"log(pos/neg ratio)\",\"formatter\":{\"id\":\"d088c02d-f2d8-4f4f-b577-faf2b737c1d2\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"be858f97-d9a9-403b-b66e-fa5cbe46751a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"3edf89de-f91a-42f3-b251-b118ab7425a0\",\"type\":\"BasicTicker\"}},\"id\":\"b86a2b67-03c6-4d31-ac26-0f6ac6bd3e92\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"77c9f0a7-5f44-4af7-9d03-6dd8faf7c3d6\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"f0ad77c9-61d2-44b6-b97c-4f63ba86970f\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"plot\":{\"id\":\"fa9f3eec-400b-43da-932b-6bf6175d0d6f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"79e88870-b456-43a5-b1f9-02df5dcddad3\",\"type\":\"BasicTicker\"}},\"id\":\"4c8001a1-42cc-4ba4-a039-35d52df12b6e\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"9f99de56-5473-40a9-8793-d7cd664b86db\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"b0e3357a-964d-433a-99bb-269a74ab8c1a\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"bfe2b96d-761f-4207-b6cf-d946bf5f09b4\",\"type\":\"LinearScale\"},{\"attributes\":{\"plot\":{\"id\":\"45e1d527-512c-450e-aa6e-9defda4c7f4f\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"7171c8f5-0925-48f8-b058-090b6066753d\",\"type\":\"BasicTicker\"}},\"id\":\"d242b9d7-28e9-4c22-86e3-1dac9ead99fa\",\"type\":\"Grid\"},{\"attributes\":{\"background_fill_color\":{\"value\":\"#E8DDCB\"},\"below\":[{\"id\":\"b86a2b67-03c6-4d31-ac26-0f6ac6bd3e92\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"5a969e6c-91b3-4b64-9d04-c3b3a5253b79\",\"type\":\"LinearAxis\"}],\"plot_height\":400,\"plot_width\":400,\"renderers\":[{\"id\":\"b86a2b67-03c6-4d31-ac26-0f6ac6bd3e92\",\"type\":\"LinearAxis\"},{\"id\":\"9f2f5257-031e-41a9-8bfb-78752c1f8004\",\"type\":\"Grid\"},{\"id\":\"5a969e6c-91b3-4b64-9d04-c3b3a5253b79\",\"type\":\"LinearAxis\"},{\"id\":\"3e1bd11a-a204-43da-90e1-0c48cb47d93e\",\"type\":\"Grid\"},{\"id\":\"40cbe9c0-2367-4760-b72e-d2ec7f8fae18\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"44828041-3839-4466-9e62-ee32f5fb7e18\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"44a2db1e-26f9-4c46-af3b-4a293b81285c\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"3063728b-fe78-4753-a242-d76ad51166b5\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"c5b43a8b-33b3-4c6f-9826-d75fe5dcdd64\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"d573e480-6a1d-4286-ad02-5ad5ae107dc7\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"754b97cd-0033-4f57-ad83-02b3c791442c\",\"type\":\"LinearScale\"}},\"id\":\"be858f97-d9a9-403b-b66e-fa5cbe46751a\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"data_source\":{\"id\":\"94a1304b-f1ab-4fa5-bb7c-0943de200fa7\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"3234fc5b-0935-45d1-8208-c7a683d47cd7\",\"type\":\"Quad\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"5d522f84-7d74-45c7-96d6-acb051e71e44\",\"type\":\"Quad\"},\"selection_glyph\":null,\"view\":{\"id\":\"f761a6b5-6a6b-4c01-b5c8-96199d623dfd\",\"type\":\"CDSView\"}},\"id\":\"8f660d45-c1f4-4395-92ea-97c26be4733b\",\"type\":\"GlyphRenderer\"}],\"root_ids\":[\"dec1db7c-ba41-4023-84c4-23da64b012ce\"]},\"title\":\"Bokeh Application\",\"version\":\"0.13.0\"}};\n",
       "  var render_items = [{\"docid\":\"c5082536-8d38-48cc-b93b-0f8c229390dd\",\"roots\":{\"dec1db7c-ba41-4023-84c4-23da64b012ce\":\"515dda20-28ec-47e6-93c3-ad781336c903\"}}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "dec1db7c-ba41-4023-84c4-23da64b012ce"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.layouts import gridplot\n",
    "from bokeh.plotting import figure, show, output_file\n",
    "\n",
    "p1 = figure(title=\"Discriminating Word Distribution\",tools=\"save\",\n",
    "            background_fill_color=\"#E8DDCB\")\n",
    "\n",
    "measured = []\n",
    "for word in review_vocab:\n",
    "    measured.append(pos_neg_ratios[word])\n",
    "    \n",
    "measured = np.array(measured)\n",
    "hist, edges = np.histogram(measured, density=True, bins=50)\n",
    "\n",
    "p1.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],\n",
    "        fill_color=\"#036564\", line_color=\"#033649\")\n",
    "\n",
    "p1.legend.location = \"center_right\"\n",
    "p1.legend.background_fill_color = \"darkgrey\"\n",
    "p1.xaxis.axis_label = 'log(pos/neg ratio)'\n",
    "p1.yaxis.axis_label = 'relative count'\n",
    "\n",
    "p2 = figure(title=\"Raw Word Distribution\",tools=\"save\",\n",
    "            background_fill_color=\"#E8DDCB\")\n",
    "\n",
    "measured = []\n",
    "for word in total_counts:\n",
    "    measured.append(total_counts[word])\n",
    "    \n",
    "measured = np.array(measured)\n",
    "hist, edges = np.histogram(measured, density=True, bins=50)\n",
    "\n",
    "p2.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],\n",
    "        fill_color=\"#036564\", line_color=\"#033649\")\n",
    "\n",
    "p2.legend.location = \"center_right\"\n",
    "p2.legend.background_fill_color = \"darkgrey\"\n",
    "p2.xaxis.axis_label = 'word frequency'\n",
    "p2.yaxis.axis_label = 'relative count'\n",
    "\n",
    "p3 = figure(title=\"Min Count Word Distribution\",tools=\"save\",\n",
    "            background_fill_color=\"#E8DDCB\")\n",
    "\n",
    "measured = []\n",
    "for word in total_counts:\n",
    "    c = total_counts[word]\n",
    "    if c > min_count:\n",
    "        measured.append(c)\n",
    "    \n",
    "measured = np.array(measured)\n",
    "hist, edges = np.histogram(measured, density=True, bins=50)\n",
    "\n",
    "p3.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],\n",
    "        fill_color=\"#036564\", line_color=\"#033649\")\n",
    "\n",
    "p3.legend.location = \"center_right\"\n",
    "p3.legend.background_fill_color = \"darkgrey\"\n",
    "p3.xaxis.axis_label = 'word frequency (above cutoff)'\n",
    "p3.yaxis.axis_label = 'relative count'\n",
    "\n",
    "p4 = figure(title=\"Pos/Neg Distribution\",tools=\"save\",\n",
    "            background_fill_color=\"#E8DDCB\")\n",
    "\n",
    "measured = []\n",
    "for term,cnt in list(total_counts.most_common()):\n",
    "    if(cnt >= min_count):\n",
    "        pos_neg_ratio = positive_counts[term] / float(negative_counts[term]+1)\n",
    "        measured.append(pos_neg_ratio)\n",
    "    \n",
    "measured = np.array(measured)\n",
    "hist, edges = np.histogram(measured, density=True, bins=50)\n",
    "\n",
    "p4.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],\n",
    "        fill_color=\"#036564\", line_color=\"#033649\")\n",
    "\n",
    "p4.legend.location = \"center_right\"\n",
    "p4.legend.background_fill_color = \"darkgrey\"\n",
    "p4.xaxis.axis_label = 'pos/neg ratio'\n",
    "p4.yaxis.axis_label = 'relative count'\n",
    "\n",
    "show(gridplot(p2,p3,p4,p1, ncols=2, plot_width=400, plot_height=400, toolbar_location=None))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  2%|▏         | 2328/100000 [00:00<00:08, 11632.00it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating 1-hot positive encodings\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100000/100000 [00:08<00:00, 11171.87it/s]\n",
      "  1%|          | 886/100000 [00:00<00:11, 8838.60it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating 1-hot negative encodings\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100000/100000 [00:12<00:00, 8294.29it/s]\n"
     ]
    }
   ],
   "source": [
    "# create mappings from words to numbers and vice versa\n",
    "\n",
    "word2index = {}\n",
    "index2word = {}\n",
    "for i, word in enumerate(review_vocab):\n",
    "    word2index[word] = i\n",
    "    index2word[i] = word\n",
    "\n",
    "n = len(review_vocab)\n",
    "samples = len(positive)+len(negative)\n",
    "all_words = word2index.keys()\n",
    "\n",
    "# encode 1-hot reviews\n",
    "x = np.zeros((samples, n))\n",
    "y = np.zeros((samples,2))\n",
    "\n",
    "idx = -1\n",
    "print(\"Creating 1-hot positive encodings\")\n",
    "for review in tqdm(positive):\n",
    "    idx += 1\n",
    "    for word in review.split(\" \"):\n",
    "        if word in all_words:\n",
    "            x[idx, word2index[word]] = 1\n",
    "            y[idx,0] = 1\n",
    " \n",
    "print(\"Creating 1-hot negative encodings\")\n",
    "for review in tqdm(negative):\n",
    "    idx += 1\n",
    "    for word in review.split(\" \"):\n",
    "        if word in all_words:\n",
    "            x[idx, word2index[word]] = 1\n",
    "            y[idx,1] = 1\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Done\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "# We'll bundle groups of examples during training for efficiency.\n",
    "# This defines the size of the batch.\n",
    "BATCH_SIZE = 100\n",
    "VOCAB_SIZE = len(review_vocab)\n",
    "EMBEDDING_SIZE = 64\n",
    "NUM_LABELS = 2\n",
    "NUM_GPUS = 2\n",
    "LEARNING_RATE = 0.0005\n",
    "DISPLAY_STEP = 100\n",
    "NUM_STEPS = 2000\n",
    "\n",
    "# The random seed that defines initialization.\n",
    "SEED = 42\n",
    "\n",
    "def model(x, prefix='model', reuse=True, is_training=True):\n",
    "    # Define a scope for reusing the variables\n",
    "    with tf.variable_scope('Model', reuse=reuse):\n",
    "        nn = tf.layers.dense(x, EMBEDDING_SIZE, activation=tf.nn.sigmoid, name=prefix+'_embedding')\n",
    "        nn = tf.layers.dense(nn, NUM_LABELS, activation=tf.nn.sigmoid, name=prefix+'_logits')\n",
    "        # We only apply need to apply softmax to testing network\n",
    "        out = tf.nn.softmax(nn) if not is_training else nn\n",
    "        return out\n",
    "\n",
    "print('Done')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Done\n"
     ]
    }
   ],
   "source": [
    "# Build the function to average the gradients\n",
    "def average_gradients(tower_grads):\n",
    "    average_grads = []\n",
    "    \n",
    "   # print(tower_grads)\n",
    "\n",
    "    for grad_and_vars in zip(*tower_grads):\n",
    "        # Note that each grad_and_vars looks like the following:\n",
    "        #   ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN))\n",
    "        grads = []\n",
    "        for g, _ in grad_and_vars:\n",
    "            # Add 0 dimension to the gradients to represent the tower.\n",
    "            expanded_g = tf.expand_dims(g, 0)\n",
    "\n",
    "            # Append on a 'tower' dimension which we will average over below.\n",
    "            grads.append(expanded_g)\n",
    "\n",
    "        # Average over the 'tower' dimension.\n",
    "        grad = tf.concat(grads, 0)\n",
    "        grad = tf.reduce_mean(grad, 0)\n",
    "\n",
    "        # Keep in mind that the Variables are redundant because they are shared\n",
    "        # across towers. So .. we will just return the first tower's pointer to\n",
    "        # the Variable.\n",
    "        v = grad_and_vars[0][1]\n",
    "        grad_and_var = (grad, v)\n",
    "        average_grads.append(grad_and_var)\n",
    "    return average_grads\n",
    "\n",
    "print('Done')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Done\n"
     ]
    }
   ],
   "source": [
    "# wire everything up\n",
    "# By default, all variables will be placed on '/gpu:0'\n",
    "# So we need a custom device function, to assign all variables to '/cpu:0'\n",
    "# Note: If GPUs are peered, '/gpu:0' can be a faster option\n",
    "PS_OPS = ['Variable', 'VariableV2', 'AutoReloadVariable']\n",
    "\n",
    "def assign_to_device(device, ps_device='/cpu:0'):\n",
    "    def _assign(op):\n",
    "        node_def = op if isinstance(op, tf.NodeDef) else op.node_def\n",
    "        if node_def.op in PS_OPS:\n",
    "            return \"/\" + ps_device\n",
    "        else:\n",
    "            return device\n",
    "\n",
    "    return _assign\n",
    "\n",
    "print('Done')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-12-33ad52df70a9>:37: softmax_cross_entropy_with_logits (from tensorflow.python.ops.nn_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "\n",
      "Future major versions of TensorFlow will allow gradients to flow\n",
      "into the labels input on backprop by default.\n",
      "\n",
      "See tf.nn.softmax_cross_entropy_with_logits_v2.\n",
      "\n",
      "GPU 0 configured\n",
      "GPU 1 configured\n",
      "Step 1: Minibatch Loss= 0.6962, Training Accuracy= 0.600, 143 Examples/sec\n",
      "Step 100: Minibatch Loss= 0.5726, Training Accuracy= 0.810, 14454 Examples/sec\n",
      "Step 200: Minibatch Loss= 0.5195, Training Accuracy= 0.890, 13153 Examples/sec\n",
      "Step 300: Minibatch Loss= 0.4557, Training Accuracy= 0.940, 12475 Examples/sec\n",
      "Step 400: Minibatch Loss= 0.4271, Training Accuracy= 0.950, 13539 Examples/sec\n",
      "Step 500: Minibatch Loss= 0.4394, Training Accuracy= 0.930, 13104 Examples/sec\n",
      "Step 600: Minibatch Loss= 0.3987, Training Accuracy= 0.970, 13046 Examples/sec\n",
      "Step 700: Minibatch Loss= 0.4068, Training Accuracy= 0.940, 13251 Examples/sec\n",
      "Step 800: Minibatch Loss= 0.3721, Training Accuracy= 0.930, 13309 Examples/sec\n",
      "Step 900: Minibatch Loss= 0.3927, Training Accuracy= 0.980, 13131 Examples/sec\n",
      "Step 1000: Minibatch Loss= 0.3614, Training Accuracy= 0.960, 13528 Examples/sec\n",
      "Optimization Finished!\n",
      "Testing Accuracy: 0.9358\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "tf.reset_default_graph()\n",
    "\n",
    "NUM_STEPS=1000\n",
    "\n",
    "# Place all ops on CPU by default\n",
    "with tf.device('/cpu:0'):\n",
    "    tower_grads = []\n",
    "    reuse_vars = False\n",
    "    #reuse_vars = True\n",
    "    num_samples = X_train.shape[0]\n",
    "\n",
    "    # tf Graph input\n",
    "    X = tf.placeholder(tf.float32, [None, VOCAB_SIZE])\n",
    "    Y = tf.placeholder(tf.float32, [None, NUM_LABELS])\n",
    "\n",
    "    # Loop over all GPUs and construct their own computation graph\n",
    "    for i in range(NUM_GPUS):\n",
    "        with tf.device(assign_to_device('/gpu:{}'.format(i), ps_device='/cpu:0')):\n",
    "\n",
    "            # Split data between GPUs\n",
    "            _x = X[i * BATCH_SIZE: (i+1) * BATCH_SIZE]\n",
    "            _y = Y[i * BATCH_SIZE: (i+1) * BATCH_SIZE]\n",
    "\n",
    "            # Because Dropout have different behavior at training and prediction time, we\n",
    "            # need to create 2 distinct computation graphs that share the same weights.\n",
    "\n",
    "            # Create a graph for training\n",
    "            logits_train = model(_x, reuse=reuse_vars, prefix=\"yelp\")\n",
    "            \n",
    "            # Create another graph for testing that reuse the same weights\n",
    "            logits_test = model(_x, reuse=True, prefix=\"yelp\", is_training=False)\n",
    "\n",
    "            # Define loss and optimizer (with train logits, for dropout to take effect)\n",
    "            loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(\n",
    "                logits=logits_train, labels=_y))\n",
    "            optimizer = tf.train.AdamOptimizer(learning_rate=LEARNING_RATE)\n",
    "            grads = optimizer.compute_gradients(loss_op)\n",
    "            \n",
    "            print(\"GPU\",i,\"configured\")\n",
    "            \n",
    "            # Only first GPU compute accuracy\n",
    "            if i == 0:\n",
    "                # Evaluate model (with test logits, for dropout to be disabled)\n",
    "                correct_pred = tf.equal(tf.argmax(logits_test, 1), tf.argmax(_y, 1))\n",
    "                accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))\n",
    "\n",
    "            reuse_vars = True\n",
    "            tower_grads.append(grads)\n",
    "\n",
    "    tower_grads = average_gradients(tower_grads)\n",
    "    train_op = optimizer.apply_gradients(tower_grads)\n",
    "    \n",
    "    # Initializing the variables\n",
    "    init = tf.global_variables_initializer()\n",
    "\n",
    "    # Launch the graph\n",
    "    with tf.Session() as sess:\n",
    "        sess.run(init)\n",
    "        step = 1\n",
    "        # Keep training until reach max iterations\n",
    "        for step in range(1, NUM_STEPS + 1):\n",
    "            # Get a batch for each GPU\n",
    "            indices = np.random.choice(num_samples, BATCH_SIZE*NUM_GPUS)\n",
    "            batch_x = X_train[indices]\n",
    "            batch_y = y_train[indices]\n",
    "            \n",
    "            # Run optimization op (backprop)\n",
    "            ts = time.time()\n",
    "            sess.run(train_op, feed_dict={X: batch_x, Y: batch_y})\n",
    "            te = time.time() - ts\n",
    "            if step % DISPLAY_STEP == 0 or step == 1:\n",
    "                # Calculate batch loss and accuracy\n",
    "                loss, acc = sess.run([loss_op, accuracy], feed_dict={X: batch_x,\n",
    "                                                                     Y: batch_y})\n",
    "                print(\"Step \" + str(step) + \": Minibatch Loss= \" + \\\n",
    "                      \"{:.4f}\".format(loss) + \", Training Accuracy= \" + \\\n",
    "                      \"{:.3f}\".format(acc) + \", %i Examples/sec\" % int(len(batch_x)/te))\n",
    "            step += 1\n",
    "        print(\"Optimization Finished!\")\n",
    "        \n",
    "        graph = tf.get_default_graph()\n",
    "        t1 = graph.get_tensor_by_name('Model/yelp_embedding/kernel:0')\n",
    "        embeddings = np.array(sess.run(t1))\n",
    "\n",
    "        # Calculate accuracy for 1000 mnist test images\n",
    "        print(\"Testing Accuracy:\", \\\n",
    "            np.mean([sess.run(accuracy, feed_dict={X: X_test[i:i+BATCH_SIZE],\n",
    "            Y: y_test[i:i+BATCH_SIZE]}) for i in range(0, X_test.shape[0], BATCH_SIZE)]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('amazing', 4.0019403),\n",
       " ('delicious', 3.989573),\n",
       " ('awesome', 3.978746),\n",
       " ('excellent', 3.960814),\n",
       " ('great', 3.8401873),\n",
       " ('perfect', 3.6464357),\n",
       " ('fantastic', 3.565358),\n",
       " ('love', 3.2784226),\n",
       " ('best', 3.2371793),\n",
       " ('thank', 3.1843255)]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def get_most_similar_words(focus = \"love\"):\n",
    "    keys = word2index.keys()\n",
    "    if focus not in keys:\n",
    "        print(\"Sorry, word not found\")\n",
    "        return\n",
    "    \n",
    "    most_similar = Counter()\n",
    "    for word in word2index.keys():\n",
    "        most_similar[word] = np.dot(embeddings[word2index[word]],\n",
    "                                    embeddings[word2index[focus]])\n",
    "    \n",
    "    return most_similar.most_common()[0:10]\n",
    "\n",
    "get_most_similar_words('yummy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.colors as colors\n",
    "\n",
    "words_to_visualize = list()\n",
    "for word, ratio in pos_neg_ratios.most_common(500):\n",
    "    if(word in word2index.keys()):\n",
    "        words_to_visualize.append(word)\n",
    "    \n",
    "for word, ratio in list(reversed(pos_neg_ratios.most_common()))[0:500]:\n",
    "    if(word in word2index.keys()):\n",
    "        words_to_visualize.append(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pos 500 neg 500\n"
     ]
    }
   ],
   "source": [
    "pos = 0\n",
    "neg = 0\n",
    "\n",
    "colors_list = list()\n",
    "vectors_list = list()\n",
    "for word in words_to_visualize:\n",
    "    if word in pos_neg_ratios.keys():\n",
    "        vectors_list.append(embeddings[word2index[word]])\n",
    "        if(pos_neg_ratios[word] > 0):\n",
    "            pos+=1\n",
    "            colors_list.append(\"#00ff00\")\n",
    "        else:\n",
    "            neg+=1\n",
    "            colors_list.append(\"#000000\")\n",
    "            \n",
    "print(\"Pos\",pos,\"neg\",neg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TSNE visualization ready\n"
     ]
    }
   ],
   "source": [
    "from sklearn.manifold import TSNE\n",
    "tsne = TSNE(n_components=2, random_state=0)\n",
    "words_top_ted_tsne = tsne.fit_transform(vectors_list)\n",
    "print(\"TSNE visualization ready\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "  <div class=\"bk-root\" id=\"deba4cf8-d90c-431c-a2bc-e2c817dfd9e3\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"05ec4ef3-b65f-4ba0-a5c4-c6a64e3ded5b\":{\"roots\":{\"references\":[{\"attributes\":{},\"id\":\"7d4f8178-f8f8-4324-9d8c-808e54815d6c\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"84ea9f80-0bb8-4022-9c73-bd206d9c3e02\",\"type\":\"SaveTool\"},{\"attributes\":{\"callback\":null},\"id\":\"80a80ece-a971-4137-b0fb-7d0ee6cfdec7\",\"type\":\"DataRange1d\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"units\":\"screen\",\"value\":8},\"x\":{\"field\":\"x1\"},\"y\":{\"field\":\"x2\"}},\"id\":\"13c651db-a16d-494e-a46b-0b3653f391d7\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"ab6a2523-0ea6-4399-90e4-c9db9daa0d15\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"714ecf93-b6d8-415f-b7c5-fcce475bb0f4\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null},\"id\":\"79d6a7c2-798b-43fb-bf89-f5bcf55688d9\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"47594223-a4e0-4a39-b2c5-34f028d75ce0\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"699a746e-2010-4679-8142-ff340e09ec1a\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"78f0759e-01c6-4437-8b2d-a1018d3251a3\",\"type\":\"ColumnDataSource\"}},\"id\":\"0a8b5e6f-4382-4531-9e7e-b18d4bceb17e\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"abef5fd0-5c9f-4afe-9c15-9fa63cd010f3\",\"type\":\"Selection\"},{\"attributes\":{\"plot\":{\"id\":\"1590e92e-6015-43b3-a675-a16e96426141\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"e96f0b1f-7a58-4a60-a114-6af8031f7989\",\"type\":\"BasicTicker\"}},\"id\":\"c60623b7-db06-481d-af0a-46372beca0dd\",\"type\":\"Grid\"},{\"attributes\":{\"formatter\":{\"id\":\"ab6a2523-0ea6-4399-90e4-c9db9daa0d15\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"1590e92e-6015-43b3-a675-a16e96426141\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"e96f0b1f-7a58-4a60-a114-6af8031f7989\",\"type\":\"BasicTicker\"}},\"id\":\"26b2befc-c139-417d-b848-ad9b06bdbcd6\",\"type\":\"LinearAxis\"},{\"attributes\":{\"plot\":{\"id\":\"1590e92e-6015-43b3-a675-a16e96426141\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"source\":{\"id\":\"78f0759e-01c6-4437-8b2d-a1018d3251a3\",\"type\":\"ColumnDataSource\"},\"text\":{\"field\":\"names\"},\"text_align\":\"center\",\"text_color\":{\"value\":\"#555555\"},\"text_font_size\":{\"value\":\"8pt\"},\"x\":{\"field\":\"x1\"},\"y\":{\"field\":\"x2\"},\"y_offset\":{\"value\":6}},\"id\":\"364a5dc2-426c-4d6f-b309-7ec1d57c20df\",\"type\":\"LabelSet\"},{\"attributes\":{},\"id\":\"e96f0b1f-7a58-4a60-a114-6af8031f7989\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"eb99db9a-e31c-4c6c-a248-4979fd20a806\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"formatter\":{\"id\":\"47594223-a4e0-4a39-b2c5-34f028d75ce0\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"1590e92e-6015-43b3-a675-a16e96426141\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"a14fca16-2892-4c83-912c-61a26d8b5262\",\"type\":\"BasicTicker\"}},\"id\":\"04f9968b-119e-4dcf-a7b4-df9dfa3410c3\",\"type\":\"LinearAxis\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"8f3b88e1-ceb2-43e3-aaa1-4a12c8d9a973\",\"type\":\"PanTool\"},{\"id\":\"a6cb7df9-08d6-4543-892e-f35f1de8972d\",\"type\":\"WheelZoomTool\"},{\"id\":\"7d4f8178-f8f8-4324-9d8c-808e54815d6c\",\"type\":\"ResetTool\"},{\"id\":\"84ea9f80-0bb8-4022-9c73-bd206d9c3e02\",\"type\":\"SaveTool\"}]},\"id\":\"78339bb8-bfd7-4e3e-a05d-8e012101e7a5\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"a14fca16-2892-4c83-912c-61a26d8b5262\",\"type\":\"BasicTicker\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"1590e92e-6015-43b3-a675-a16e96426141\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"a14fca16-2892-4c83-912c-61a26d8b5262\",\"type\":\"BasicTicker\"}},\"id\":\"24461be5-1eb5-4ba2-9ec7-82bc8df4a53e\",\"type\":\"Grid\"},{\"attributes\":{\"plot\":null,\"text\":\"vector T-SNE for most polarized words\"},\"id\":\"859c13cd-5521-42ca-bd57-ca7c1e787a8f\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"8f3b88e1-ceb2-43e3-aaa1-4a12c8d9a973\",\"type\":\"PanTool\"},{\"attributes\":{\"data_source\":{\"id\":\"78f0759e-01c6-4437-8b2d-a1018d3251a3\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"fc352e61-294b-4899-a490-06edacbdd2c7\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"13c651db-a16d-494e-a46b-0b3653f391d7\",\"type\":\"Circle\"},\"selection_glyph\":null,\"view\":{\"id\":\"0a8b5e6f-4382-4531-9e7e-b18d4bceb17e\",\"type\":\"CDSView\"}},\"id\":\"d324087c-d57d-452c-9b48-b5b84301c931\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"below\":[{\"id\":\"26b2befc-c139-417d-b848-ad9b06bdbcd6\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"04f9968b-119e-4dcf-a7b4-df9dfa3410c3\",\"type\":\"LinearAxis\"}],\"renderers\":[{\"id\":\"26b2befc-c139-417d-b848-ad9b06bdbcd6\",\"type\":\"LinearAxis\"},{\"id\":\"c60623b7-db06-481d-af0a-46372beca0dd\",\"type\":\"Grid\"},{\"id\":\"04f9968b-119e-4dcf-a7b4-df9dfa3410c3\",\"type\":\"LinearAxis\"},{\"id\":\"24461be5-1eb5-4ba2-9ec7-82bc8df4a53e\",\"type\":\"Grid\"},{\"id\":\"d324087c-d57d-452c-9b48-b5b84301c931\",\"type\":\"GlyphRenderer\"},{\"id\":\"364a5dc2-426c-4d6f-b309-7ec1d57c20df\",\"type\":\"LabelSet\"}],\"title\":{\"id\":\"859c13cd-5521-42ca-bd57-ca7c1e787a8f\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"78339bb8-bfd7-4e3e-a05d-8e012101e7a5\",\"type\":\"Toolbar\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"80a80ece-a971-4137-b0fb-7d0ee6cfdec7\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"714ecf93-b6d8-415f-b7c5-fcce475bb0f4\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"79d6a7c2-798b-43fb-bf89-f5bcf55688d9\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"699a746e-2010-4679-8142-ff340e09ec1a\",\"type\":\"LinearScale\"}},\"id\":\"1590e92e-6015-43b3-a675-a16e96426141\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"fill_color\":{\"field\":\"color\"},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"units\":\"screen\",\"value\":8},\"x\":{\"field\":\"x1\"},\"y\":{\"field\":\"x2\"}},\"id\":\"fc352e61-294b-4899-a490-06edacbdd2c7\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"a6cb7df9-08d6-4543-892e-f35f1de8972d\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"callback\":null,\"data\":{\"color\":[\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#00ff00\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\",\"#000000\"],\"names\":[\"acupuncture\",\"addicting\",\"scrumptious\",\"cutest\",\"unassuming\",\"mmmmm\",\"gem\",\"trails\",\"meticulous\",\"nom\",\"perfection\",\"devoured\",\"unbeatable\",\"expertly\",\"growler\",\"deliciously\",\"addictive\",\"coolest\",\"pinball\",\"unpretentious\",\"superb\",\"faves\",\"deliciousi\",\"pleasantly\",\"rhubarb\",\"addicted\",\"wonderfully\",\"amazingthe\",\"delectable\",\"exceeded\",\"delightfully\",\"decadent\",\"awesomeness\",\"amazingi\",\"phenomenal\",\"deliciousness\",\"divine\",\"incredible\",\"listens\",\"delish\",\"dedication\",\"familyowned\",\"drawback\",\"jeden\",\"impeccable\",\"coma\",\"delicious\",\"elk\",\"refreshing\",\"heaven\",\"painless\",\"yummy\",\"sweetest\",\"complemented\",\"deliciousthe\",\"pasties\",\"exquisite\",\"yum\",\"disappoint\",\"heavenly\",\"perfect\",\"enhanced\",\"luscious\",\"goodies\",\"knowledgeable\",\"magnificent\",\"downside\",\"compliments\",\"informative\",\"fantastic\",\"passionate\",\"produits\",\"knowledgable\",\"melts\",\"amazing\",\"favorites\",\"guava\",\"delighted\",\"sublime\",\"laidback\",\"intimate\",\"savory\",\"eclectic\",\"drool\",\"affordable\",\"relaxed\",\"topnotch\",\"notch\",\"mmm\",\"favs\",\"outstanding\",\"creaminess\",\"paired\",\"perfectionist\",\"secrets\",\"excellent\",\"talented\",\"drooling\",\"terrific\",\"awesome\",\"trail\",\"beautifully\",\"hearty\",\"flawless\",\"cozy\",\"obsessed\",\"surpassed\",\"mouthwatering\",\"favourites\",\"pairings\",\"crossfit\",\"wonderful\",\"transformed\",\"complimented\",\"mascarpone\",\"masterpiece\",\"concoctions\",\"byob\",\"textures\",\"disappoints\",\"nutty\",\"bryan\",\"uniquely\",\"apricot\",\"fab\",\"perfectly\",\"diverse\",\"serene\",\"immaculate\",\"delight\",\"succulent\",\"adventurous\",\"unique\",\"customize\",\"amaze\",\"delightful\",\"stumbled\",\"arepas\",\"highly\",\"homey\",\"bliss\",\"nestled\",\"cosy\",\"punctual\",\"awsome\",\"fav\",\"compares\",\"asset\",\"rivals\",\"lowkey\",\"combinations\",\"torte\",\"savoury\",\"ease\",\"bomb\",\"favorite\",\"marvelous\",\"toasty\",\"comforting\",\"fabulous\",\"adorable\",\"approachable\",\"favourite\",\"fave\",\"compote\",\"guu\",\"lecker\",\"buttery\",\"brilliant\",\"restored\",\"mmmm\",\"personalized\",\"exemplary\",\"calming\",\"explosion\",\"warmly\",\"pilates\",\"stunning\",\"choix\",\"supportive\",\"richness\",\"seamless\",\"aromatic\",\"rarity\",\"defiantly\",\"macadamia\",\"thyme\",\"edinburgh\",\"peaceful\",\"loved\",\"indecisive\",\"kiwi\",\"breathtaking\",\"reasonably\",\"burrata\",\"botanical\",\"spacious\",\"quaint\",\"randy\",\"brews\",\"resist\",\"carnivore\",\"compassionate\",\"frankie\",\"secluded\",\"wealth\",\"energetic\",\"thoughtful\",\"beginner\",\"shaded\",\"balanced\",\"bonus\",\"lucked\",\"juste\",\"upbeat\",\"bouche\",\"personable\",\"gems\",\"elegant\",\"gorgeous\",\"endroit\",\"magical\",\"montral\",\"jeremy\",\"adobada\",\"fascinating\",\"juicy\",\"creative\",\"homemade\",\"stout\",\"toffee\",\"infused\",\"intimidated\",\"inventive\",\"tastefully\",\"jy\",\"wholesome\",\"plusieurs\",\"indulged\",\"soju\",\"gifted\",\"unwind\",\"patisserie\",\"hooked\",\"fluffy\",\"amazingly\",\"pleasure\",\"lovers\",\"freshest\",\"quail\",\"savor\",\"charlie\",\"fragrant\",\"treasures\",\"ian\",\"thorough\",\"sorbet\",\"breads\",\"handmade\",\"sweetness\",\"toujours\",\"tuscan\",\"almonds\",\"porchetta\",\"paths\",\"caramelized\",\"galleries\",\"roomy\",\"classics\",\"spotless\",\"tastings\",\"creations\",\"sexy\",\"ginormous\",\"guides\",\"hiking\",\"contemporary\",\"soothing\",\"hesitate\",\"efficient\",\"airy\",\"romantic\",\"kiddos\",\"grassy\",\"crafted\",\"candies\",\"exceptional\",\"addiction\",\"paninis\",\"bustle\",\"smiley\",\"creation\",\"indulge\",\"coco\",\"woohoo\",\"sweets\",\"love\",\"reasonable\",\"assortment\",\"heartbeat\",\"hesitation\",\"complement\",\"sweeter\",\"andy\",\"burgh\",\"winner\",\"tucked\",\"iconic\",\"gruyere\",\"beatles\",\"nicest\",\"casual\",\"skeptical\",\"exceeds\",\"durian\",\"moist\",\"goals\",\"trifecta\",\"incline\",\"nailed\",\"array\",\"dreaming\",\"killer\",\"saki\",\"accompaniment\",\"flavorful\",\"adore\",\"overlooks\",\"delights\",\"blends\",\"tortas\",\"graham\",\"mecca\",\"gorgonzola\",\"daikon\",\"recommendations\",\"unforgettable\",\"happier\",\"barre\",\"earthy\",\"workouts\",\"raspberries\",\"expanded\",\"dope\",\"comfy\",\"baba\",\"definite\",\"friendliest\",\"scottish\",\"shines\",\"crisps\",\"conscientious\",\"cheerful\",\"enjoyed\",\"chandeliers\",\"rich\",\"luv\",\"scones\",\"great\",\"truffles\",\"glam\",\"craft\",\"loves\",\"spicier\",\"chill\",\"dreams\",\"gentle\",\"goto\",\"accommodating\",\"colorful\",\"casey\",\"skyline\",\"maine\",\"housed\",\"wonderland\",\"blessed\",\"definetly\",\"gardens\",\"dream\",\"courteous\",\"cristo\",\"pistachios\",\"gabriel\",\"bravo\",\"twists\",\"furry\",\"bonne\",\"helpful\",\"vegan\",\"hoover\",\"wagyu\",\"cycling\",\"aussi\",\"brle\",\"historic\",\"breeze\",\"scenery\",\"fritters\",\"intrusive\",\"stephen\",\"genuine\",\"silky\",\"skilled\",\"northeast\",\"baguettes\",\"prompt\",\"confit\",\"ales\",\"friendly\",\"mountains\",\"creamy\",\"additions\",\"testament\",\"hazelnut\",\"tender\",\"hike\",\"tangy\",\"comfortable\",\"appreciative\",\"vindaloo\",\"def\",\"devils\",\"beautiful\",\"stylish\",\"earls\",\"brasserie\",\"yuzu\",\"seasonal\",\"watering\",\"pleased\",\"dulce\",\"explore\",\"croissants\",\"flavourful\",\"glad\",\"chocolates\",\"hannah\",\"medallions\",\"rebecca\",\"cheesecakes\",\"distillery\",\"welcoming\",\"crme\",\"innovative\",\"blossom\",\"tastiest\",\"foie\",\"pistachio\",\"beaten\",\"secret\",\"bustling\",\"turkish\",\"charts\",\"guided\",\"apprehensive\",\"picnic\",\"blessing\",\"handsome\",\"elote\",\"threading\",\"bursting\",\"duo\",\"perfected\",\"tremendous\",\"flexible\",\"performances\",\"views\",\"museums\",\"attentive\",\"intimidating\",\"tartare\",\"refreshed\",\"croque\",\"spiciness\",\"absinthe\",\"belle\",\"candied\",\"pate\",\"rocked\",\"amuse\",\"pam\",\"loving\",\"featuring\",\"utmost\",\"escargot\",\"butternut\",\"stroll\",\"variety\",\"styles\",\"cheers\",\"noda\",\"crudo\",\"artistic\",\"leek\",\"lunchdinner\",\"tako\",\"praises\",\"bosa\",\"girly\",\"bellini\",\"humiliated\",\"disregarded\",\"harassment\",\"discriminated\",\"unprofessionalism\",\"aggravation\",\"confrontational\",\"thief\",\"uncalled\",\"disrespected\",\"disgrace\",\"unethical\",\"liars\",\"worthless\",\"unprofessional\",\"rancid\",\"centurylink\",\"rudest\",\"violations\",\"incompetence\",\"scammers\",\"compensation\",\"inept\",\"feces\",\"appalling\",\"incompetent\",\"reimbursement\",\"unresponsive\",\"disrespectful\",\"ignores\",\"accusing\",\"disrespect\",\"unacceptable\",\"abusive\",\"insulting\",\"enemy\",\"blaming\",\"forwarded\",\"argumentative\",\"refunding\",\"uncaring\",\"livid\",\"unhelpful\",\"unattentive\",\"disputing\",\"vile\",\"audacity\",\"filth\",\"dissatisfaction\",\"scam\",\"blatant\",\"threatened\",\"cockroach\",\"worst\",\"fraudulent\",\"accused\",\"refund\",\"apology\",\"rudely\",\"harassing\",\"slowest\",\"inexcusable\",\"unwilling\",\"lied\",\"careless\",\"poisoning\",\"uneducated\",\"unevenly\",\"disgusted\",\"insult\",\"crooks\",\"discrimination\",\"appalled\",\"acknowledgement\",\"acknowledgment\",\"defensive\",\"liar\",\"overcharged\",\"expressing\",\"disgusting\",\"argued\",\"sarcastically\",\"unseasoned\",\"theft\",\"misfortune\",\"redeeming\",\"pathetic\",\"refused\",\"mumbled\",\"dispute\",\"dishonest\",\"tasteless\",\"laughable\",\"belligerent\",\"dismissive\",\"cancelling\",\"modem\",\"harassed\",\"filthy\",\"supervisor\",\"nonchalant\",\"deplorable\",\"horrible\",\"reeked\",\"furious\",\"tablespoon\",\"hostile\",\"incapable\",\"blankly\",\"undrinkable\",\"acetone\",\"fraud\",\"mildew\",\"yuck\",\"arguing\",\"thieves\",\"decency\",\"rude\",\"snide\",\"gossiping\",\"voicemails\",\"yelled\",\"bait\",\"lawsuit\",\"abysmal\",\"shrugged\",\"shorted\",\"negligence\",\"confronted\",\"poorly\",\"threatening\",\"refusing\",\"inedible\",\"refunds\",\"demanded\",\"bureau\",\"flavorless\",\"visibly\",\"terrible\",\"blamed\",\"unsanitary\",\"demeaning\",\"lousy\",\"moron\",\"mislead\",\"runaround\",\"blatantly\",\"denied\",\"scammed\",\"congealed\",\"downhill\",\"disconnected\",\"scum\",\"payless\",\"unfriendly\",\"sewage\",\"moldy\",\"diarrhea\",\"awful\",\"unwelcoming\",\"racist\",\"rudeness\",\"saddest\",\"horrendous\",\"insulted\",\"swearing\",\"uninterested\",\"disgustingly\",\"disinterested\",\"behaviour\",\"contaminated\",\"disgust\",\"ignorant\",\"roaches\",\"reimburse\",\"inconsiderate\",\"violently\",\"dispatch\",\"agitated\",\"cockroaches\",\"authorization\",\"unapologetic\",\"dumbfounded\",\"unappealing\",\"wtf\",\"smh\",\"horrid\",\"faxed\",\"eff\",\"reciept\",\"displeasure\",\"verbally\",\"refunded\",\"voicemail\",\"condescending\",\"roach\",\"robbery\",\"impolite\",\"sloppily\",\"stormed\",\"apologies\",\"vomiting\",\"microwaved\",\"bbb\",\"aweful\",\"immature\",\"disorganized\",\"pissed\",\"cancel\",\"issued\",\"flirting\",\"threaten\",\"inaccurate\",\"sarcasm\",\"upsetting\",\"unorganized\",\"untrained\",\"inattentive\",\"atrocious\",\"ripoff\",\"refuses\",\"indicating\",\"acted\",\"slop\",\"asshole\",\"robbed\",\"cancelled\",\"stale\",\"ignored\",\"waste\",\"passive\",\"apologizes\",\"filed\",\"billed\",\"shameful\",\"defective\",\"rotten\",\"improperly\",\"excuses\",\"unclean\",\"unimpressed\",\"ignoring\",\"poor\",\"reply\",\"bully\",\"snippy\",\"replied\",\"urine\",\"documentation\",\"crooked\",\"worse\",\"acknowledging\",\"caked\",\"lukewarm\",\"deceptive\",\"substandard\",\"unanswered\",\"leaked\",\"arrogant\",\"meanwhile\",\"possession\",\"rotting\",\"harass\",\"horrific\",\"dissapointing\",\"supervisors\",\"reporting\",\"response\",\"existent\",\"apologizing\",\"ticked\",\"plague\",\"responsibility\",\"mediocre\",\"unappetizing\",\"acknowledge\",\"notify\",\"ontrac\",\"losses\",\"morons\",\"argument\",\"mysteriously\",\"yells\",\"ruined\",\"proceeded\",\"canceling\",\"horribly\",\"unreliable\",\"rip\",\"misunderstood\",\"zero\",\"garbage\",\"nauseous\",\"acknowledged\",\"accountability\",\"displeased\",\"agreement\",\"irritated\",\"apologize\",\"undercooked\",\"apathetic\",\"clueless\",\"expired\",\"wasted\",\"dirtiest\",\"questioned\",\"waitedand\",\"measly\",\"notified\",\"replies\",\"idiots\",\"renter\",\"arrogance\",\"nasty\",\"overbooked\",\"bogus\",\"embarrassment\",\"stating\",\"consumers\",\"horrified\",\"piss\",\"payed\",\"inconveniencing\",\"informs\",\"complained\",\"flagged\",\"monopoly\",\"recieve\",\"behavior\",\"principle\",\"mold\",\"flavourless\",\"claiming\",\"false\",\"receipt\",\"hostage\",\"disaster\",\"billing\",\"shield\",\"incidents\",\"revenue\",\"reiterated\",\"smug\",\"incomplete\",\"violation\",\"shoddy\",\"grossly\",\"credited\",\"owed\",\"laziness\",\"chalked\",\"dumped\",\"gross\",\"honoring\",\"yelling\",\"interrupt\",\"implied\",\"deleted\",\"confirming\",\"uninspired\",\"remorse\",\"snarky\",\"inefficient\",\"marginal\",\"childish\",\"rescheduled\",\"meager\",\"grossed\",\"charged\",\"cancellation\",\"surly\",\"stares\",\"attempted\",\"wth\",\"useless\",\"disturbing\",\"blech\",\"thawed\",\"subpar\",\"argue\",\"screwed\",\"canceled\",\"medication\",\"cox\",\"rung\",\"interrupting\",\"receipts\",\"letter\",\"uneven\",\"frustration\",\"repeatedly\",\"shitty\",\"unhappy\",\"forgiving\",\"inappropriate\",\"notification\",\"lease\",\"absurd\",\"upset\",\"expire\",\"deposits\",\"operator\",\"disappointing\",\"infested\",\"underwhelmed\",\"interrupted\",\"nausea\",\"bouncer\",\"dissatisfied\",\"proceeds\",\"incorrectly\",\"stared\",\"unremarkable\",\"excuse\",\"edible\",\"rubbery\",\"stolen\",\"excused\",\"deteriorated\",\"misinformed\",\"compensate\",\"puddle\",\"contract\",\"irate\",\"honour\",\"barked\",\"inconvenienced\",\"illegal\",\"inexperienced\",\"unwelcome\",\"insisting\",\"alerted\",\"angry\",\"damages\",\"strep\",\"misery\",\"discrepancy\",\"overrated\",\"submitted\",\"reschedule\",\"explicitly\",\"profanity\",\"unsatisfactory\",\"investigation\",\"reluctantly\",\"cursing\",\"stinks\",\"incorrect\",\"policy\",\"emailing\",\"avail\",\"rotors\",\"ruining\",\"annoyed\",\"tells\",\"gristle\",\"moral\",\"disabled\",\"indifferent\",\"repeated\",\"confirmation\",\"limp\",\"supposedly\",\"bland\",\"dispatcher\",\"sympathy\",\"representatives\",\"reimbursed\",\"deductible\",\"anger\",\"unimpressive\",\"sorely\",\"pos\",\"frustrated\",\"deaf\",\"permission\",\"smeared\",\"consent\",\"wiped\",\"inform\",\"sucks\",\"abruptly\",\"blah\",\"slimy\",\"letdown\",\"cheated\",\"phoned\",\"wasting\",\"deposit\",\"severely\",\"file\",\"delete\",\"arbys\",\"blaring\",\"errors\",\"miserable\",\"disappeared\",\"baffled\",\"uneaten\",\"faulty\"],\"x1\":{\"__ndarray__\":\"[encoded data, 5336 characters]\",\"dtype\":\"float32\",\"shape\":[1000]},\"x2\":{\"__ndarray__\":\"[encoded data, 5336 characters]\",\"dtype\":\"float32\",\"shape\":[1000]}},\"selected\":{\"id\":\"abef5fd0-5c9f-4afe-9c15-9fa63cd010f3\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"eb99db9a-e31c-4c6c-a248-4979fd20a806\",\"type\":\"UnionRenderers\"}},\"id\":\"78f0759e-01c6-4437-8b2d-a1018d3251a3\",\"type\":\"ColumnDataSource\"}],\"root_ids\":[\"1590e92e-6015-43b3-a675-a16e96426141\"]},\"title\":\"Bokeh Application\",\"version\":\"0.13.0\"}};\n",
       "  var render_items = [{\"docid\":\"05ec4ef3-b65f-4ba0-a5c4-c6a64e3ded5b\",\"roots\":{\"1590e92e-6015-43b3-a675-a16e96426141\":\"deba4cf8-d90c-431c-a2bc-e2c817dfd9e3\"}}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "1590e92e-6015-43b3-a675-a16e96426141"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "p = figure(tools=\"pan,wheel_zoom,reset,save\",\n",
    "           toolbar_location=\"above\",\n",
    "           title=\"vector T-SNE for most polarized words\")\n",
    "\n",
    "source = ColumnDataSource(data=dict(x1=words_top_ted_tsne[:,0],\n",
    "                                    x2=words_top_ted_tsne[:,1],\n",
    "                                    names=words_to_visualize,\n",
    "                                    color=colors_list))\n",
    "\n",
    "p.scatter(x=\"x1\", y=\"x2\", size=8, source=source, fill_color=\"color\")\n",
    "\n",
    "word_labels = LabelSet(x=\"x1\", y=\"x2\", text=\"names\", y_offset=6,\n",
    "                  text_font_size=\"8pt\", text_color=\"#555555\",\n",
    "                  source=source, text_align='center')\n",
    "p.add_layout(word_labels)\n",
    "\n",
    "show(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
