{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": true }, "source": [ "

Table of Contents

\n", "
" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# code for loading the format for the notebook\n", "import os\n", "\n", "# path : store the current path to convert back to it later\n", "path = os.getcwd()\n", "os.chdir(os.path.join('..', '..', 'notebook_format'))\n", "\n", "from formats import load_style\n", "load_style(plot_style = False)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ethen 2018-09-17 18:09:27 \n", "\n", "CPython 3.6.4\n", "IPython 6.4.0\n", "\n", "numpy 1.14.1\n", "pandas 0.23.0\n", "matplotlib 2.2.2\n", "sklearn 0.19.1\n" ] } ], "source": [ "os.chdir(path)\n", "\n", "# 1. magic for inline plot\n", "# 2. magic to print version\n", "# 3. magic so that the notebook will reload external python modules\n", "# 4. magic to enable retina (high resolution) plots\n", "# https://gist.github.com/minrk/3301035\n", "%matplotlib inline\n", "%load_ext watermark\n", "%load_ext autoreload\n", "%autoreload 2\n", "%config InlineBackend.figure_format = 'retina'\n", "\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "from collections import Counter\n", "from sklearn.neighbors import NearestNeighbors\n", "from sklearn.metrics.pairwise import paired_distances\n", "from sklearn.feature_extraction.text import CountVectorizer\n", "from sklearn.feature_extraction.text import TfidfTransformer, TfidfVectorizer\n", "\n", "%watermark -a 'Ethen' -d -t -v -p numpy,pandas,matplotlib,sklearn" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Nearest Neighbors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When exploring a large set of text documents -- such as Wikipedia, news articles, StackOverflow, etc. -- it can be useful to get a list of related material. To find relevant documents you typically need to convert the text document into bag of words or TF-IDF format and choose the distance metric to measure the notion of similarity. In this documentation we'll explore the tradeoffs with representing documents using bag of words and TF-IDF.\n", "\n", "We will be using the Wikipedia pages dataset. Each row of the dataset consists of a link to the Wikipedia article, the name of the person, and the text of the article (in lowercase). To follow along, please download the file from this [dropbox link](https://www.dropbox.com/s/mriz0nq35ore8cr/people_wiki.csv?dl=0)." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
URInametext
0<http://dbpedia.org/resource/Digby_Morrell>Digby Morrelldigby morrell born 10 october 1979 is a former...
1<http://dbpedia.org/resource/Alfred_J._Lewy>Alfred J. Lewyalfred j lewy aka sandy lewy graduated from un...
2<http://dbpedia.org/resource/Harpdog_Brown>Harpdog Brownharpdog brown is a singer and harmonica player...
3<http://dbpedia.org/resource/Franz_Rottensteiner>Franz Rottensteinerfranz rottensteiner born in waidmannsfeld lowe...
4<http://dbpedia.org/resource/G-Enka>G-Enkahenry krvits born 30 december 1974 in tallinn ...
\n", "
" ], "text/plain": [ " URI name \\\n", "0 Digby Morrell \n", "1 Alfred J. Lewy \n", "2 Harpdog Brown \n", "3 Franz Rottensteiner \n", "4 G-Enka \n", "\n", " text \n", "0 digby morrell born 10 october 1979 is a former... \n", "1 alfred j lewy aka sandy lewy graduated from un... \n", "2 harpdog brown is a singer and harmonica player... \n", "3 franz rottensteiner born in waidmannsfeld lowe... \n", "4 henry krvits born 30 december 1974 in tallinn ... " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# the file is placed one level above this notebook,\n", "# since it's also used by other notebooks\n", "# change this if you liked\n", "filepath = os.path.join('..', 'people_wiki.csv')\n", "wiki = pd.read_csv(filepath)\n", "wiki.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start by converting the document into bag of words format and utilize the euclidean distance to find the nearest neighbors of the Barack Obama." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idnamedistance
035817Barack Obama0.000000
124478Joe Biden33.015148
228447George W. Bush34.307434
314754Mitt Romney35.791060
435357Lawrence Summers36.069378
531423Walter Mondale36.249138
613229Francisco Barrio36.276714
736364Don Bonker36.400549
822745Wynn Normington Hugh-Jones36.441734
97660Refael (Rafi) Benvenisti36.837481
\n", "
" ], "text/plain": [ " id name distance\n", "0 35817 Barack Obama 0.000000\n", "1 24478 Joe Biden 33.015148\n", "2 28447 George W. Bush 34.307434\n", "3 14754 Mitt Romney 35.791060\n", "4 35357 Lawrence Summers 36.069378\n", "5 31423 Walter Mondale 36.249138\n", "6 13229 Francisco Barrio 36.276714\n", "7 36364 Don Bonker 36.400549\n", "8 22745 Wynn Normington Hugh-Jones 36.441734\n", "9 7660 Refael (Rafi) Benvenisti 36.837481" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# bag of words\n", "vect = CountVectorizer()\n", "word_weight = vect.fit_transform(wiki['text'])\n", "\n", "# query Barack Obama's top 10 nearest neighbors\n", "nn = NearestNeighbors(metric = 'euclidean')\n", "nn.fit(word_weight)\n", "obama_index = wiki[wiki['name'] == 'Barack Obama'].index[0]\n", "distances, indices = nn.kneighbors(word_weight[obama_index], n_neighbors = 10)\n", "\n", "# 1. flatten the 2d-array distance and indices to 1d\n", "# 2. merge the distance information with the original wiki dataset, \n", "# to obtain the name matching the id.\n", "neighbors = pd.DataFrame({'distance': distances.flatten(), 'id': indices.flatten()})\n", "nearest_info = (wiki.\n", " merge(neighbors, right_on = 'id', left_index = True).\n", " sort_values('distance')[['id', 'name', 'distance']])\n", "nearest_info" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Looking at the result, it seems nice that all of the 10 people are politicians. Let's dig a bit deeper and find out why Joe Biden was considered a close neighbor of Obama by looking at the most frequently used words in both pages. To do this, we'll take the sparse row matrix that we had and extract the word count dictionary for each document." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def unpack_word_weight(vect, word_weight):\n", " \"\"\"\n", " Given the CountVector and the fit_transformed\n", " word count sparse array obtain each documents' \n", " word count dictionary\n", " \n", " In the Compressed Sparse Row format,\n", " `indices` stands for indexes inside the row vectors of the matrix \n", " and `indptr` (index pointer) tells where the row starts in the data and in the indices \n", " attributes. nonzero values of the i-th row are data[indptr[i]:indptr[i+1]] \n", " with column indices indices[indptr[i]:indptr[i+1]]\n", " \n", " References\n", " ----------\n", " http://www.scipy-lectures.org/advanced/scipy_sparse/csr_matrix.html\n", " \"\"\"\n", " feature_names = np.array(vect.get_feature_names())\n", " data = word_weight.data\n", " indptr = word_weight.indptr\n", " indices = word_weight.indices\n", " n_docs = word_weight.shape[0]\n", " \n", " word_weight_list = []\n", " for i in range(n_docs):\n", " doc = slice(indptr[i], indptr[i + 1])\n", " count, idx = data[doc], indices[doc]\n", " feature = feature_names[idx]\n", " word_weight_dict = Counter({k: v for k, v in zip(feature, count)})\n", " word_weight_list.append(word_weight_dict)\n", " \n", " return word_weight_list" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
URInametextword_weight
0<http://dbpedia.org/resource/Digby_Morrell>Digby Morrelldigby morrell born 10 october 1979 is a former...{'melbourne': 1, 'college': 1, 'parade': 1, 'e...
1<http://dbpedia.org/resource/Alfred_J._Lewy>Alfred J. Lewyalfred j lewy aka sandy lewy graduated from un...{'every': 1, 'capsule': 1, 'take': 1, 'they': ...
2<http://dbpedia.org/resource/Harpdog_Brown>Harpdog Brownharpdog brown is a singer and harmonica player...{'society': 1, 'hamilton': 1, 'membership': 1,...
\n", "
" ], "text/plain": [ " URI name \\\n", "0 Digby Morrell \n", "1 Alfred J. Lewy \n", "2 Harpdog Brown \n", "\n", " text \\\n", "0 digby morrell born 10 october 1979 is a former... \n", "1 alfred j lewy aka sandy lewy graduated from un... \n", "2 harpdog brown is a singer and harmonica player... \n", "\n", " word_weight \n", "0 {'melbourne': 1, 'college': 1, 'parade': 1, 'e... \n", "1 {'every': 1, 'capsule': 1, 'take': 1, 'they': ... \n", "2 {'society': 1, 'hamilton': 1, 'membership': 1,... " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wiki['word_weight'] = unpack_word_weight(vect, word_weight)\n", "wiki.head(3)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def get_top_words(wiki, name, column_name, top_n = None):\n", " row = wiki.loc[wiki['name'] == name, column_name]\n", "\n", " # when converting Series to dictionary, the row index \n", " # will be the key to the content\n", " word_weight_dict = row.to_dict()[row.index[0]]\n", " \n", " if top_n is None:\n", " top_n = len(word_weight_dict)\n", " \n", " word_weight_table = pd.DataFrame(word_weight_dict.most_common(top_n), \n", " columns = ['word', 'weight'])\n", " return word_weight_table" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
wordObamaBiden
0the4033
1in3016
2and2119
3of1812
4to1411
5his115
\n", "
" ], "text/plain": [ " word Obama Biden\n", "0 the 40 33\n", "1 in 30 16\n", "2 and 21 19\n", "3 of 18 12\n", "4 to 14 11\n", "5 his 11 5" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "words_obama = get_top_words(wiki, name = 'Barack Obama', column_name = 'word_weight')\n", "words_biden = get_top_words(wiki, name = 'Joe Biden', column_name = 'word_weight')\n", "\n", "# merge the two DataFrame, since both tables contained the same column name weight, \n", "# it will automatically renamed one of them by adding suffix _x and _y to prevent confusion.\n", "# hence we'll rename the columns to tell which one is for which\n", "words_combined = (words_obama.\n", " merge(words_biden, on = 'word').\n", " rename(columns = {'weight_x': 'Obama', 'weight_y': 'Biden'}))\n", "words_combined.head(6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next question we want to ask is, among these common words that appear in both documents, how many other documents in the Wikipedia dataset also contain them?" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def has_top_words(word_weight_vector, common_words):\n", " \"\"\"\n", " return True if common_words is a subset of unique_words\n", " return False otherwise\n", " \n", " References\n", " ----------\n", " http://stackoverflow.com/questions/12182744/python-pandas-apply-a-function-with-arguments-to-a-series\n", " \"\"\"\n", " # extract the keys of word_weight_vector and convert it to a set\n", " unique_words = set(word_weight_vector.keys())\n", " boolean = common_words.issubset(unique_words)\n", " return boolean" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "top 5 common words: {'in', 'the', 'and', 'to', 'of'}\n", "number of articles that also contain the common words: 56066\n" ] } ], "source": [ "# we'll extract the 5 most frequent\n", "common_words = set(words_combined['word'].head(5))\n", "print('top 5 common words: ', common_words)\n", "\n", "wiki['has_top_words'] = wiki['word_weight'].apply(has_top_words, args = (common_words,))\n", "print('number of articles that also contain the common words: ', wiki['has_top_words'].sum())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Given this result, we saw that much of the perceived commonalities between the two articles were due to occurrences of extremely frequent words, such as \"the\", \"and\", and \"his\". All of these words appear very often in all of the documents. To retrieve articles that are more relevant, maybe we should be focusing more on rare words that don't happen in every article. And this is where TF-IDF (term frequency–inverse document frequency) comes in. Note that although we can remove stop words to prevent some of this behavior, sometimes the frequently appeared words might not be a stop word." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## TF-IDF" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "TF-IDF, short for term frequency–inverse document frequency, is a numeric measure that is use to score the importance of a word in a document based on how often did it appear in that document and a given collection of documents. The intuition for this measure is : If a word appears frequently in a document, then it should be important and we should give that word a high score. But if a word appears in too many other documents, it's probably not a unique identifier, therefore we should assign a lower score to that word. In short, it is a feature representation that penalizes words that are too common.\n", "\n", "Let us consider the following toy dataset that consists of 3 documents." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "docs = np.array([\n", " 'The sun is shining',\n", " 'The weather is sweet',\n", " 'The sun is shining and the weather is sweet'\n", "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Most commonly, TF-IDF is calculated as follows:\n", "\n", "$$\\text{tf-idf}(t, d, D) = \\text{tf}(t, d) \\times \\text{idf}(t, d, D)$$\n", "\n", "Where `t` denotes the terms; `d` denotes each document; `D` denotes the collection of documents.\n", "\n", "The first part of the formula $tf(t, d)$ stands for term frequency, which is defined by the number of times a term $t$ occurs in a document $d$." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 1, 1, 0, 1, 0],\n", " [0, 1, 0, 0, 1, 1, 1],\n", " [1, 2, 1, 1, 1, 2, 1]], dtype=int64)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vect = CountVectorizer()\n", "tf = vect.fit_transform(docs).toarray()\n", "tf" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'the': 5, 'sun': 3, 'is': 1, 'shining': 2, 'weather': 6, 'sweet': 4, 'and': 0}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vect.vocabulary_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Based on the vocabulary, the word \"and\" would be the first column in each document vector in `tf` and it appears once in the third document.\n", "\n", "In order to understand the second part of the formlua $\\text{idf}(t, d, D)$, inverse document frequency, let's first write down the complete math formula for IDF.\n", "\n", "$$ idf(t, d, D) = log \\frac{ \\mid \\text{ } D \\text{ } \\mid }{ 1 + \\mid \\{ d : t \\in d \\} \\mid } $$\n", "\n", "- The numerator : `D` is infering to our document space. It can also be seen as D = ${ d_{1}, d_{2}, \\dots, d_{n} }$ where n is the number of documents in your collection. Thus for our example $\\mid \\text{ } D \\text{ } \\mid$, the size of our document space is 3, since we have 3 documents.\n", "- The denominator : $\\mid \\{ d: t \\in d \\} \\mid$ is the document freqency. To be explicit, it is the number of documents $d$ that contain the term $t$. Note that this implies it doesn't matter if a term appeared 1 time or 100 times in a document, it will still be counted as 1, since the term simply did appear in the document.\n", "- The constant 1 is added to the denominator to avoid a zero-division error if a term is not contained in any document in the test dataset.\n", "\n", "Note that there are very different variation of the formula. For example, The tf-idfs in scikit-learn are calculated by:\n", "\n", "$$ idf(t, d, D) = log \\frac{ \\mid \\text{ } D \\text{ } \\mid }{ \\mid \\{ d : t \\in d \\} \\mid } + 1 $$\n", "\n", "Here, the `+1` count is added directly to the idf, instead of the denominator. The effect of this is that terms with zero idf, i.e. that occur in all documents of a training set, will not be entirely ignored. We can demonstrate this by calculating the idfs manually using the equation above and do the calculation ourselves and compare the results to the TfidfTransformer output using the settings `use_idf=True, smooth_idf=False, norm=None` (more on `smooth_idf` and `norm` later)." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 1. 1.40546511 1.40546511 0. 1.\n", " 0. ]\n", "\n", "[0. 1. 1.40546511 1.40546511 0. 1.\n", " 0. ]\n" ] } ], "source": [ "# compute manually the tfidf score for the first document\n", "n_docs = len(docs)\n", "df = np.sum(tf != 0, axis = 0)\n", "idf = np.log(n_docs / df) + 1\n", "tf_idf = tf[0] * idf\n", "print(tf_idf)\n", "print()\n", "\n", "# use the library to do the computation\n", "tfidf = TfidfTransformer(use_idf = True, smooth_idf = False, norm = None)\n", "doc_tfidf = tfidf.fit_transform(tf).toarray()\n", "print(doc_tfidf[0])\n", "\n", "assert np.allclose(tf_idf, doc_tfidf[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, recall that in the tf (term frequency) section, we’re representing each term as the number of times they appeared in the document. The main issue for this representation is that it will create a bias towards long documents, as a given term has more chance to appear in longer document, making them look more important than actually they are. Thus the approach to resolve this issue is the good old L2 normalization. i.e., dividing the raw term frequency vector $v$ by its length $||v||_2$ (L2- or Euclidean norm).\n", "\n", "$$v_{norm} = \\frac{v}{ \\parallel v \\parallel_2} = \\frac{v}{\\sqrt{v{_1}^2 + v{_2}^2 + \\dots + v{_n}^2}} = \\frac{v}{\\big(\\sum_{i=1}^n v_i^2 \\big)^{\\frac{1}{2}}}$$" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0.40993715 0.57615236 0.57615236 0. 0.40993715\n", " 0. ]\n", "\n", "[0. 0.40993715 0.57615236 0.57615236 0. 0.40993715\n", " 0. ]\n" ] } ], "source": [ "# manual\n", "tf_norm = tf_idf / np.sqrt(np.sum(tf_idf ** 2))\n", "print(tf_norm)\n", "print()\n", "\n", "# library\n", "tfidf = TfidfTransformer(use_idf = True, smooth_idf = False, norm = 'l2')\n", "doc_tfidf = tfidf.fit_transform(tf).toarray()\n", "print(doc_tfidf[0])\n", "\n", "assert np.allclose(tf_norm, doc_tfidf[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another parameter in the `TfidfTransformer` is the `smooth_idf`, which is described as\n", "\n", "> smooth_idf : boolean, default=True \n", "Smooth idf weights by adding one to document frequencies, as if an extra document was seen containing every term in the collection exactly once. Prevents zero divisions.\n", "\n", "So, our idf would then be defined as follows:\n", "\n", "$$idf(t, d, D) = log \\frac{ 1 + \\mid D \\text{ } \\mid }{ 1 + \\mid \\{ d : t \\in d \\} \\mid } + 1 $$ \n", "\n", "Again let's confirm this by computing it manually and using the library." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0.43370786 0.55847784 0.55847784 0. 0.43370786\n", " 0. ]\n", "\n", "[0. 0.43370786 0.55847784 0.55847784 0. 0.43370786\n", " 0. ]\n" ] } ], "source": [ "# manual\n", "n_docs = len(docs)\n", "df = np.sum(tf != 0, axis = 0)\n", "idf = np.log((1 + n_docs) / (1 + df)) + 1\n", "tf_idf = tf[0] * idf\n", "tf_norm = tf_idf / np.sqrt(np.sum(tf_idf ** 2))\n", "print(tf_norm)\n", "print()\n", "\n", "# library\n", "tfidf = TfidfTransformer(use_idf = True, smooth_idf = True, norm = 'l2')\n", "doc_tfidf = tfidf.fit_transform(tf).toarray()\n", "print(doc_tfidf[0])\n", "\n", "assert np.allclose(tf_norm, doc_tfidf[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To sum it up, the default settings in the `TfidfTransformer` is:\n", "\n", "- `use_idf=True`\n", "- `smooth_idf=True`\n", "- `norm='l2'`\n", "\n", "And we can use the `TfidfVectorizer` to compute the TF-IDF score from raw text in one step without having to do use `CountVectorizer` to convert it to bag of words representation and then transform it to TF-IDF using `TfidfTransformer`. For those interested, this [link](https://github.com/ethen8181/machine-learning/blob/master/clustering/tfidf/feature_extraction.py) contains the full TF-IDF implemented from scratch.\n", "\n", "Now that we've understood the inner details on TF-IDF let's return back to our initial task and use this weighting scheme instead of bag of words. We start by converting the document into TF-IDF format and use this along with cosine distance to find the nearest neighbors of the Barack Obama (if we normalized our articles in the TF-IDF transformation, then the euclidean distance and the cosine distance is proportional to each other, hence they're doing the same thing). Then we extract the commonly used words (now weighted by the TF-IDF score instead of word count) in both the Joe Biden and Obama article. Finally we compute how many other documents in the Wikipedia dataset also contain these words. In short, we're doing the exact same thing as the beginning except we now use TF-IDF to represent the documents and use cosine distance to measure similarity between documents." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idnamecosine
035817Barack Obama0.000000
124478Joe Biden0.570781
257108Hillary Rodham Clinton0.615934
338376Samantha Power0.624993
438714Eric Stern (politician)0.649765
\n", "
" ], "text/plain": [ " id name cosine\n", "0 35817 Barack Obama 0.000000\n", "1 24478 Joe Biden 0.570781\n", "2 57108 Hillary Rodham Clinton 0.615934\n", "3 38376 Samantha Power 0.624993\n", "4 38714 Eric Stern (politician) 0.649765" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# tf-idf instead of bag of words\n", "tfidf_vect = TfidfVectorizer()\n", "tfidf_weight = tfidf_vect.fit_transform(wiki['text'])\n", "\n", "# this time, query Barack Obama's top 100 nearest neighbors using\n", "# cosine distance, we have to specify the algorithm to `brute` since\n", "# the default 'auto' does not work with cosine distance\n", "# http://stackoverflow.com/questions/32745541/dbscan-error-with-cosine-metric-in-python\n", "nn_cosine = NearestNeighbors(metric = 'cosine', algorithm = 'brute')\n", "nn_cosine.fit(tfidf_weight)\n", "obama_index = wiki[wiki['name'] == 'Barack Obama'].index[0]\n", "cosine, indices = nn_cosine.kneighbors(tfidf_weight[obama_index], n_neighbors = 100)\n", "\n", "# 1. flatten the 2d-array distance and indices to 1d\n", "# 2. merge the distance information with the original wiki dataset, \n", "# to obtain the name matching the id.\n", "neighbors_cosine = pd.DataFrame({'cosine': cosine.flatten(), 'id': indices.flatten()})\n", "nearest_info = (wiki.\n", " merge(neighbors_cosine, right_on = 'id', left_index = True).\n", " sort_values('cosine')[['id', 'name', 'cosine']])\n", "\n", "nearest_info.head()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
URInametextword_weighthas_top_wordstfidf_weight
0<http://dbpedia.org/resource/Digby_Morrell>Digby Morrelldigby morrell born 10 october 1979 is a former...{'melbourne': 1, 'college': 1, 'parade': 1, 'e...True{'digby': 0.09377484096114971, 'morrell': 0.51...
1<http://dbpedia.org/resource/Alfred_J._Lewy>Alfred J. Lewyalfred j lewy aka sandy lewy graduated from un...{'every': 1, 'capsule': 1, 'take': 1, 'they': ...True{'is': 0.018289389212318905, 'with': 0.0214013...
2<http://dbpedia.org/resource/Harpdog_Brown>Harpdog Brownharpdog brown is a singer and harmonica player...{'society': 1, 'hamilton': 1, 'membership': 1,...True{'is': 0.08336282198056562, 'who': 0.022133364...
\n", "
" ], "text/plain": [ " URI name \\\n", "0 Digby Morrell \n", "1 Alfred J. Lewy \n", "2 Harpdog Brown \n", "\n", " text \\\n", "0 digby morrell born 10 october 1979 is a former... \n", "1 alfred j lewy aka sandy lewy graduated from un... \n", "2 harpdog brown is a singer and harmonica player... \n", "\n", " word_weight has_top_words \\\n", "0 {'melbourne': 1, 'college': 1, 'parade': 1, 'e... True \n", "1 {'every': 1, 'capsule': 1, 'take': 1, 'they': ... True \n", "2 {'society': 1, 'hamilton': 1, 'membership': 1,... True \n", "\n", " tfidf_weight \n", "0 {'digby': 0.09377484096114971, 'morrell': 0.51... \n", "1 {'is': 0.018289389212318905, 'with': 0.0214013... \n", "2 {'is': 0.08336282198056562, 'who': 0.022133364... " ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wiki['tfidf_weight'] = unpack_word_weight(tfidf_vect, tfidf_weight)\n", "wiki.head(3)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
wordObamaBiden
0obama0.3650180.174794
1the0.2793230.248287
2act0.2490890.167737
3in0.2096730.120486
4iraq0.1518090.040891
5and0.1467390.143045
\n", "
" ], "text/plain": [ " word Obama Biden\n", "0 obama 0.365018 0.174794\n", "1 the 0.279323 0.248287\n", "2 act 0.249089 0.167737\n", "3 in 0.209673 0.120486\n", "4 iraq 0.151809 0.040891\n", "5 and 0.146739 0.143045" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "words_obama = get_top_words(wiki, name = 'Barack Obama', column_name = 'tfidf_weight')\n", "words_biden = get_top_words(wiki, name = 'Joe Biden', column_name = 'tfidf_weight')\n", "\n", "words_combined = (words_obama.\n", " merge(words_biden, on = 'word').\n", " rename(columns = {'weight_x': 'Obama', 'weight_y': 'Biden'}))\n", "words_combined.head(6)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "top 5 common words: {'iraq', 'obama', 'in', 'the', 'act'}\n", "number of articles that also contain the common words: 5\n" ] } ], "source": [ "# we'll extract the 5 most frequent\n", "common_words = set(words_combined['word'].head(5))\n", "print('top 5 common words: ', common_words)\n", "\n", "wiki['has_top_words'] = wiki['tfidf_weight'].apply(has_top_words, args = (common_words,))\n", "print('number of articles that also contain the common words: ', wiki['has_top_words'].sum())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the huge difference in this calculation using TF-IDF scores instead of raw word counts. We've eliminated noise arising from extremely common words. Happily ever after? Not so fast. To illustrate another possible issue, let's first compute the length of each Wikipedia document, and examine the document lengths for the 100 nearest neighbors to Obama's page." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
URInametextword_weighthas_top_wordstfidf_weightlength
0<http://dbpedia.org/resource/Digby_Morrell>Digby Morrelldigby morrell born 10 october 1979 is a former...{'melbourne': 1, 'college': 1, 'parade': 1, 'e...False{'digby': 0.09377484096114971, 'morrell': 0.51...251
1<http://dbpedia.org/resource/Alfred_J._Lewy>Alfred J. Lewyalfred j lewy aka sandy lewy graduated from un...{'every': 1, 'capsule': 1, 'take': 1, 'they': ...False{'is': 0.018289389212318905, 'with': 0.0214013...223
2<http://dbpedia.org/resource/Harpdog_Brown>Harpdog Brownharpdog brown is a singer and harmonica player...{'society': 1, 'hamilton': 1, 'membership': 1,...False{'is': 0.08336282198056562, 'who': 0.022133364...226
\n", "
" ], "text/plain": [ " URI name \\\n", "0 Digby Morrell \n", "1 Alfred J. Lewy \n", "2 Harpdog Brown \n", "\n", " text \\\n", "0 digby morrell born 10 october 1979 is a former... \n", "1 alfred j lewy aka sandy lewy graduated from un... \n", "2 harpdog brown is a singer and harmonica player... \n", "\n", " word_weight has_top_words \\\n", "0 {'melbourne': 1, 'college': 1, 'parade': 1, 'e... False \n", "1 {'every': 1, 'capsule': 1, 'take': 1, 'they': ... False \n", "2 {'society': 1, 'hamilton': 1, 'membership': 1,... False \n", "\n", " tfidf_weight length \n", "0 {'digby': 0.09377484096114971, 'morrell': 0.51... 251 \n", "1 {'is': 0.018289389212318905, 'with': 0.0214013... 223 \n", "2 {'is': 0.08336282198056562, 'who': 0.022133364... 226 " ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def compute_length(row):\n", " return len(row.split(' '))\n", "\n", "\n", "wiki['length'] = wiki['text'].apply(compute_length) \n", "wiki.head(3)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idnamecosinelength
035817Barack Obama0.000000540
124478Joe Biden0.570781414
257108Hillary Rodham Clinton0.615934580
338376Samantha Power0.624993310
438714Eric Stern (politician)0.649765255
\n", "
" ], "text/plain": [ " id name cosine length\n", "0 35817 Barack Obama 0.000000 540\n", "1 24478 Joe Biden 0.570781 414\n", "2 57108 Hillary Rodham Clinton 0.615934 580\n", "3 38376 Samantha Power 0.624993 310\n", "4 38714 Eric Stern (politician) 0.649765 255" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nearest_cosine = (wiki.\n", " merge(neighbors_cosine, right_on = 'id', left_index = True).\n", " sort_values('cosine')[['id', 'name', 'cosine', 'length']])\n", "\n", "nearest_cosine.head()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "image/png": "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ICIiIiIiIhKOc47MzEx2797N3r17OXLkCM654g5LREREioiZkZCQQKVKlahSpQoVK1bEzIo7LCXVRUREROLNRkf/R54bpYSQiEhesrKy2LhxI3v37i3uUERERKSYOOc4fPgwO3fuZOfOnVSqVIl69epRpkzxTsCipLqIiIiIiIiUKM65YEI9ISGBqlWrUrlyZRITE4v9f6JFRESk6GRlZXHw4EH27NnDjh072Lt3Lxs3bqR+/frFOmJdSXUREREREREpUTIzM4MJ9RNOOIHy5csXd0giIiJSDMqUKUP58uUpX748lStXZv369ezdu5fMzEySk5OLL65i61lEREREREQkjN27dwNQtWpVJdRFREQEgPLly5Oamgr89m+F4qKkuoiIiIiIiJQogXnUK1euXMyRiIiISElSpUoVgGJfc0VJdRERERERESlRjhw5AkBiYmIxRyIiIiIlSeDfBoF/KxQXJdVFRERERESkRHHOAWhRUhEREckmsDhp4N8KxUX/QhERERERERERERGREi+QVC9uSqqLiIiIiIiIiIiIiMRISXURERERERERERERkRgpqS4iIiIiIiIiIiIiEiMl1UVEREREREREREREYqSkuoiIiIiIiIhIEcnIyMDMMDOGDRtW3OEUyJEjR3j22Wfp1KkT1atXJyEhIXhOy5cvL+7wBOjSpUvwPSnNFixYEDyPtLS04g5HJKhscQcgIiIiIiIiIiVXaFLOOVeMkZRc48aNY+fOnaSmpjJ8+PDiDueoysrKom/fvsycOTMu7TVs2JB169ZFPJ6cnEzt2rU588wzueyyyxgwYABlyyqdVZL9+uuvvPnmm8yePZsvvviCLVu2sH//fmrUqMEJJ5xA9+7d6d+/Py1btizuUEUKTH+FREREREREREQKYdy4caxbt44GDRoc80n16dOnBxPqDRo04JZbbqFBgwaUK1cOgEaNGsW1v3379rF27VrWrl3L1KlTGTNmDDNmzIh7PxIfr776KiNGjGDDhg25jm3cuJGNGzeyaNEi7r//fgYNGsRjjz1G3bp1iyFSkcJRUl1ERERERERERGIya9as4PPJkyfTrl27uLX9n//8h1q1agVfZ2VlsXPnTpYuXcorr7zCrl27+PLLL+nRowcrV66kYsWKcetbCsc5x1//+lceffTR4L7GjRtz6aWX0qxZMypVqsSmTZuYP38+c+bM4eDBg0yePJmFCxcya9YsWrRoUYzRi+SfkuoiIiIiIiIiIhKT0BHIZ555Zlzb7tmzJw0bNsy1/9prr+Wuu+7inHPOYcOGDaxZs4aXXnqJm266Ka79S8Hdd999wYR62bJleeSRR7j11ltJSEjIVm748OGsXr2aoUOHsmjRItavX0+PHj1Yvnx5ti9UREo6LVQqIiIiIiIiIiIxOXDgQPB5UlJSkfVbv3597rzzzuDrDz74oMj6lug++eQT7rvvPsBbgyE9PZ3hw4fnSqgHNG3alLlz59K+fXsANm3aVGoX7ZXfLyXVRURERERERKRIrF+/npEjR3LWWWdRs2ZNEhMTqVOnDj169ODZZ5/l4MGDUeubGWZGly5dAG++7bFjx9KmTRuqVq1KcnIyLVq0YMSIEezYsSOmmJYtW8awYcNo0KAB5cuXp27dupx//vmkp6cDkJGREew3Z+KvYcOGmFlwoc1169YFy4Y+Jk6cGDWGrVu3kpaWxmmnnUblypWpXLkyrVq1YsyYMWRmZsZ0HrFwzjFlyhT69+/PCSecQPny5UlNTaVly5b85S9/YfXq1WHrLViwIHguocnsnOeZlpYWt1jDadasWfD5rl27IpZbv349Tz/9NAMGDODkk0+mUqVKJCYmUqtWLbp06cLDDz8ctT6Ef983btzIyJEjadmyJVWrVg17zv/73/945JFHuPjii2ncuDEVK1YkKSmJunXr0qtXL5555hl+/fXXmM85MzOTZ555hgsvvJDjjz+eChUqUKFCheDUKuPHj2f37t0xt5dTWlpa8DxPPfVUNm7cmO82Ro0aRVZWFgA33ngjl156aZ51kpOTeeWVV4JT+MyePZuFCxfG1N+XX37JDTfcQJMmTahQoQI1a9ake/fuvP7663nW3b9/P9OmTePmm2/m7LPPpnr16pQrV46UlBRatGjBTTfdxIoVK/Jsp0uXLsHrBt5URS+++CJdunShVq1aJCcnc+qpp3L//fezZ8+ebHV//vln/vGPf9CyZUuqVKlCSkoKnTp1YsqUKXn2G497W+LEOadHKX4AS1q1auVERESk5CCNqA8REYlu1apVbtWqVcUdhviA4KMwHnzwQZeUlJStvZyPpk2bum+//TbPWDp37uzWrFnjmjdvHrGtBg0auB9++CFqTGPHjnUJCQkR2xgwYID77rvvgq+HDh2arX6DBg2ink/gMWHChGCdH374IVt7ixcvdvXq1YtY94wzznDbtm0rxJX3/Pzzz659+/ZR4yxXrpwbM2ZMrrrz58+P6TxHjRqV77hCr2Fe79err74aLHvDDTeELTN//nxnZnnGWrNmTffRRx9F7Cvn+zRnzhxXtWrVqOc8ceLEmK5TkyZNYvobN3v2bFe7du082xs2bFiuup07d476uT1y5Ii78cYbg2XOOecct3379jxjyunrr78OtlG2bFn3008/5av+TTfdFKw/cODAXMdD771Ro0a5SZMmRf070qdPH7d///6I/TVs2DCm92jEiBG8Mj9PAAAgAElEQVRR4w69vnv27HHdunWL2NaZZ54ZvLYLFy50NWvWjFj2jjvuiNhnvO7tY0Fh/p3QqlUrByxxhczJak51ERERERERKfVstBV5n9e3up7xF43PV50b3r6B55c+X+i+3ShX6DaK0p///GfGjRsHQGpqKpdffjlt27alcuXKbNq0ienTpzN//nxWr15N586dWbZsGXXq1InY3u7du+nTpw/ffvstffv2pVevXlSrVo21a9fy7LPPsn79etatW8fVV1/Nhx9+GLaNl156Kdt0IhdddBEXXnghKSkprF69mhdffJE33ngj6nmNHz+ezMxMbrjhBn755Rdq1qzJ+PG574lWrVqFrb9hwwb69OnD9u3bGTx4MF27dqVSpUqsWrWKf//732zbto3ly5czfPhwJk2aFDWWaPbs2UOnTp347rvvAKhbty7XXnstLVq0IDMzk7lz5/LGG29w6NAhRowYQVZWFnfffXew/qmnnsq0adMAuOeee/j6668BgvsCQkeSx1tWVhYTJkwIvu7evXvYcr/++ivOOVq0aEHXrl055ZRTqF69Or/++isbNmxg+vTpLFmyhF9++YULL7yQ5cuXh53HPdT333/PgAED2LdvH4MGDaJbt25UqVKFH374gXr16gXL7d+/HzOjdevWdOrUiZNPPpmqVauye/du1q1bR3p6Ot999x1r1qzhggsuYPny5aSmpobtc8qUKVx55ZUcOXIEgJYtW3LZZZdx4oknYmZs2LCBhQsX8s477wQGXcbswIEDDB48mKlTpwLQu3dv3njjjQIt/Dp37tzg8+7du1O3bt181b/66qt59tlnAZg3bx7OueDo75wWL17Mgw8+CHjz7Hfq1ImEhAQWL17MCy+8wL59+5g5cyZXXXUVb775Ztg29u/fT7Vq1ejRowdnnnkm9erVo1y5cmzcuJGlS5cyZcoUDh06xJgxY6hVqxbDhw/P8xyuueYa5s2bR4cOHRg4cCB16tRh3bp1/Pvf/2bdunUsW7aM4cOHM3r0aM4//3wOHjzIddddR8eOHUlMTOSjjz7i+eef5/Dhwzz66KP06tUr7P19NO5tKYTCZuX10Eh1ERERyU4j1UVECqcgI9Dy+tt7NB7Xv3V9vs/t+reuj0vfRYmQEZAFMX369GD97t27u61bt4Yt99xzzwXLDRo0KM9YEhMT3dtvv52rzNatW12jRo2C5T777LOwZVJTUx3gypQp41599dVcZTIzM12vXr2y9ZlzpHpAYLR1gwYNIl8IX+gIaMClpqa6Tz/9NFe5tWvXBmNMSEhwGzduzLPtSEJHJHfs2NHt3LkzV5l33nnHlS9fPjjiePny5WHbymsEdH5FG6melZXlduzY4ebNm+cuuOCCYLmuXbu6rKyssO1lZGS4lStXRu3ztddec2XKlIk4ytu53O9TpUqV3AcffBC13a+++sqtXbs24vEjR464Rx55JNhmWlpa2HJr1qxxycnJwftz3LhxEc93+/btbv78+bn2R3qfdu3a5bp27Ro8NmTIEHfo0KGo5xXNwIEDg22NHj063/UPHDjgEhMTg21888032Y7n/JVE5cqV3aJFi3K1891337njjjsuWO7NN98M29/s2bOjnm9GRoZr1qxZsK/du3eHLRd6fQH3wAMP5CqzZcuWYEwJCQnu9NNPdzVr1nQrVqzIVXbSpEnBti644IKIscXj3j4WlISR6ppTXURERERERESOmnvvvReA448/nunTp1O9evWw5f74xz8yZMgQAN588002bNgQtd177rmHCy+8MNf+6tWrZxtl/c477+QqM2HCBHbu3AnADTfcwJVXXpmrTIUKFXj11VepWrVq1DgK68knn+Tss8/Otb9Ro0bcfPPNABw5coR58+YVqP1ffvklOMK7SpUqvPHGG6SkpOQq17NnT/75z38CcPjwYR555JEC9VcYjRo1yjZHe5kyZahatSrdunVj9uzZNG7cmHvuuYc5c+ZEHM3coEEDTjvttKj9XHHFFVx11VUApKenc+jQoTxje+CBB+jUqVPUMi1atKBRo0YRj5cpU4Y777wz2M7LL78cttxDDz3Evn37APj73//O7bffHvF8q1atGlxjIC9btmyhS5cuzJ8/H4C//OUvvPTSS5QtW/CJLH788cfg85NPPjnf9RMTE7Nds7zmdH/kkUdo165drv1NmzblhRdeCL4eO3Zs2Pq9evWKer4NGjTgmWeeAbxfeMyYMSNqPADnn39+tr85ATVr1uSWW24BvM/wihUrePrpp2nZsmWuskOGDKFp06YAvP/++xw+fDhsbEfj3paCUVJdRERERERERI6KFStWsHLlSgBuuukmkpOTo5YPJIPySiInJCQEk1XhnHfeecHnq1atynU8NFF2++23R2ynWrVqwUT/0VCzZs2wCf2AvM4jFjNnzuTAgQMADB06NOq0On/605+oXLkyAG+99VZw6pGSIjExkUqVKgUXxSyMc845B/CmAwnco5FUrFiRP/zhD4XuM2ffa9asYevWrdmOHTlyJLhIbuXKlRkxYkRc+ly7di0dOnRg2bJlAIwZM4ZHH300YrI+Vtu3bw8+jzSVTV5C623bti1iuapVq3LNNddEPN6rVy+aN28OwKeffsrPP/9coHgC7w/AZ599lmf5aH+LOnToEHxeu3Zt+vfvH7Fsx44dAW96njVr1sQSalj5ubel4DSnuoiIiIiIiIgcFR999FHw+YEDB5g+fXrU8qGjVL/55puI5U466aSoI8hD57nesWNHtmNZWVksXboUgDp16uQ5D3iXLl148skno5YpqDZt2pCQkBDxeLTziNXnn38efN6zZ8+oZStWrEjHjh2ZPXs2e/bsYdWqVXmOjI2n//znP9SqVSvbvszMTNasWcPUqVNZsWIFd911F6+99hrvvfceNWvWjNjWZ599xiuvvMKnn37K2rVr2bNnT8RRuz/++COtW7eO2NaZZ56Z5xdCod577z0mT57M4sWLWb9+PXv27In4BcXGjRupUaNG8PXKlSvZvXs3AF27dg1+yVEYK1asoFevXvz8888kJCQwfvx4rr322kK3W9TOPfdcEhMTo5Y577zzgl9ALV68mIsuuihXmS1btjBp0iTeffddVq1axY4dO8jMzAzbXuhI/EjC/dIkoHbt2sHnrVu3pkyZyOObQ8tG+7zH896WglNSXURERERERESOioyMjODz0aNH56tutKRSaBIynKSkpODzX3/9NduxXbt2BRNojRs3zjOOWMoUVGHOI1abNm0KPj/ppJPyLH/SSScxe/bsYN2iTKr37Nkz4sKK99xzD3fddRf/+te/WLlyJVdccQXvvfdernKBRSAjTa0STiCJHUnolxvR7Nq1i4EDB/Luu+8WuO/QJO4pp5wSczvRdO7cmV27dpGUlER6ejp9+/aNS7vg/ZojIDClUn6F1os0PRTAiSeemGdboWV++umnXMfT09P54x//yK5du2KKLa97A6LHHPoZjlYuZ9lwn/ejcW9LwSmpLiIiIiIiIiJHRayJq3AOHjwY8Vi00Z55CcxVDd7I7LzkZ4RyfhXmPGK1Z8+e4PNYzqVSpUph6xY3M+PBBx9k6tSprFmzhnnz5rFw4cJsU3UA3HzzzcGkY1JSEr1796Zt27bUq1eP5OTk4C8D3n//fZ566imAPKe5qVChQkwx9u/fP5jor1y5MhdddBFnnHEGdevWpWLFisH3e/LkycEpXnL2HZoEDX0vCiMwP/fhw4cL/OVMJPXr1w8+/+677/Jd/9ChQ9m+fIv2BUZ+P6979+7NduzDDz/kyiuvDE4f1KpVK7p3706TJk1ISUnJltTu168fkPe9AbF/jgv7eT8a97YUnJLqIiIiIiIiInJUhCYF33//fbp27VqM0XhCk26RpnwIFZqEL41Cpw+J5VxCE5HxmHoknhISEujevXtwvum5c+dmS6pnZGQEF6usX78+H3zwQcRfGuS1IGZ+ffjhh8GE+umnn87cuXMjTk/zySefRGynSpUqwec5k8IFNXPmTPr06cO+ffsYPHgwAIMGDYpL2+eccw5TpkwBYNGiRfmuv3Tp0uCc/zVq1Ii62Gl+P685v5RIS0sLJtTHjx/P9ddfn2cbJUVx3tsSnpLqIiIiIiIiUuq5Ua64Q4jJ+IvGM/6i8cUdRpEJHXUay9zERSElJYWKFSuSmZnJ2rVr8ywfS5mSrG7dusHnq1evznMKmNWrVwefH3fccUctroIKnUIj5/Qe77//Ps55fwvuuuuuqFP3rFu3Lq5xhU5F88ADD0Sd7z1a36Ejv6OtK5AfnTt3ZtasWfTu3TuYWHfOcfnllxe67R49egSfz507l59//jnqYrg5TZo0Kfi8W7duURdO/f777/NsL7RM6P178ODB4BoPbdq0iZhQh/jfG/FQnPe2hHf0f2ckIiIi8jtzfavroz5ERER+Lzp37hx8np95po+mMmXK0KpVKwB+/vln/ve//0Utv2DBgpjaBIJJr5LkrLPOCj6fO3du1LL79+/n448/BrxR6vGa0zuetm3bFnyeczqbzZs3B583adIkajvvvPNOXOOKte+DBw8yf/78iMdbtmwZHK0+f/78uE3B06lTJ2bPnk2lSpU4cuQIV111FZMnTy50u82bN6dbt26AN73M/fffH3PdjIwMXnrppeDr2267LWr5jz/+OOKCnAGh17Zt27bB59u2bQtOg1PU90Y8FOe9LeEpqS4iIiISZ4FRiJEeIiIivxdt2rShRYsWgLdA4Ndff13MEXlCF2p84oknIpbbvn07r7zySp7tBaaZKInTRvTp0yc4V/RLL73Eli1bIpZ99tlng3N69+3bNzhHc0lx5MiRbCPCcyb9Q+fcDkwRE86MGTNYuXJlXGOLte9nn32WrVu3RjyekJDAFVdcAXhz2o8ZMyZuMZ577rnMmjUrW2L99ddfL3S7o0ePDn6x9MwzzzB9+vQ862RmZjJkyJDgZ+aCCy7INT9+Ttu3b2fixIkRj7/77rvBvzHt27fPNmI+1vdnz549PP7443nGX9SK896W8JRUFxEREREREZGjwsyCScFDhw7Ru3dvFi9eHLXOqlWruOmmm45qXNdccw2pqamAN7fya6+9lqvM/v37GTx4MNu3b8+zvUaNGgHeaNj169fHN9hCqlmzJtdeey0AO3fuZODAgdkWwwyYN28e99xzDwBly5blzjvvLNI48+Kc4+677w4mFCtWrJjtyxHIPjJ57Nix7NixI1c7n332WfB6xFNo3/fdd19wnvBQb7/9NnfddVeebf39738PflHz8MMP88QTT0T8FcTOnTv54IMPYo7z3HPPzTZifciQIYVOrHfo0IF7770X8N6ngQMH8tRTTwXnL8/p+++/p2fPnsFfRdStWzdqsjzUnXfeGfZvyJo1a7K9r3fccUe24ykpKTRt2hSAL774gmnTpuVqY+/evQwYMIANGzbEFEtRKs57W8LTnOoiIiIiIiIiEpNA0jUvrVq14tJLLwXgoosu4t577+W+++5j/fr1nH322fTs2ZPu3btTv359zIxt27bx9ddfs2DBAlatWkVCQgLPPvvsUTuP6tWr8/jjj3PNNdeQlZXF4MGDSU9Pp0+fPqSkpLB69WomTJjA2rVrGTBgAG+88Qbw2zQvOXXr1o233noLgEsvvZSbbrqJunXrBsufdtpp2eaXL2oPP/ww8+bN47vvvuODDz6gefPmXHvttTRv3pzMzEzee+890tPTg0nQ0aNHc/rppxd5nO+++y61atXKtm///v2sWbOGqVOnsnz58uD+Bx98MFfZ9u3b07p1a5YsWUJGRgbNmjXjxhtv5OSTT2b//v28//77pKenAzB48GBeffXVuMXer18/6tWrx8aNG/n8889p3rw5f/jDH2jcuDE7d+5k1qxZvP322yQnJ3PZZZcxderUiG01atSIF154gSuuuIKsrCyGDx/Oiy++SP/+/WnSpAllypRh48aNLFq0iNmzZzNgwIBsUy3lpWPHjsyZM4devXqxd+9ehgwZAhAcIV8Q9957L7t37+axxx7j0KFD3HbbbTzxxBNceumlNGvWjOTkZDZv3sz8+fOZPXt28EuH448/nlmzZuV6L8Pp3bs3c+fOpUOHDgwdOpRzzz2XhIQEFi9ezAsvvBBc2PWyyy7jsssuy1X/1ltvDU4x079/fwYPHkzHjh2pXLkyX331FRMnTuSnn37i6quvzjbXe0lQnPe2ROCc06MUP4AlrVq1ciIiIiIiIseKVatWuVWrVhV3GOID8v0YOnRornaef/55V6VKlZjqN2jQIGosnTt3jjnuaGUfeeQRl5CQEDGO/v37u1WrVgVf33bbbWHb2bNnjzvppJMitjNhwoRg2R9++CHqdQqVn7J52bRpk2vXrl3U6162bFn34IMPRm2nc+fOwfLx0KBBg3zdWxUqVHBPPvlkxPZWr17tjj/++Ij1y5cv71544QU3YcKEsO9PQEGu/aJFi1zVqlUj9p2amupmzpzpRo0aFdw3f/78iO29/fbbrkaNGnlek2uuuSZX3Vjep48//thVrlzZAS4hIcG9+uqrMZ1nNC+//LKrX79+njGbmRs4cKD76aeforY3f/78YJ1Ro0a5l19+2SUlJUVst3fv3m7//v1h28rKynKDBw+OGlffvn1dZmZmnn8/Yv0c5Oc+yuu+iNe9fSwozL8TWrVq5YAlrpA5WU3/IiIiIiIiIiJH3XXXXce6det49NFH6dmzJ8cddxxJSUkkJSVRp04dOnXqxF//+lfmzZvH2rVriySmO++8k88//5whQ4ZQv359EhMTqV27Nj169GDy5Mm88cYb2aZKqVatWth2KlWqxKeffsrIkSNp1aoVKSkpEUe1F5c6deqwcOFC0tPT6devH/Xr1ycpKYkqVarQokULhg8fzqpVqxgxYkRxh5pN4P4477zzuP/++/n++++59dZbI5Y/8cQTWbZsGSNGjOCUU06hfPnyVKpUiZNPPplbbrmFJUuWHLUpMtq1a8eKFSu45ZZbaNKkCYmJiaSkpHDqqafy97//nRUrVtC7d++Y27vwwgtZu3Ytjz32GN26daN27dqUK1eOChUq0KRJE/r378+ECRN46qmnChRvhw4dmDNnDpUrV+bIkSNcffXVYadCyo+rrrqK1atX8/LLL3P55ZfTtGlTUlJSSExMpG7dupx99tmMHDmSZcuWkZ6eTt26dfPd/uLFi7nuuuto3Lgx5cuXp1q1apx33nm8+uqrzJw5k/Lly4eta2a88sorvPbaa3Tt2pXU1FQSExOpX78+F154Ienp6UyfPp0KFSoU6hocLcV5b0tu5rzRzlJKmdmSVq1atVqyZElxhyIiIiIiIhIX33zzDZB7EUKR4vDUU08Fp4z473//S79+/Yo5IhGR37fC/DuhdevWLF26dKlzrnVhYihZX5uKiIiIiIiIiJQQhw4d4j//+Q8A5cqVo0OHDsUckYiIlARKqouIiIiIiIjI787evXuJ9qvvAwcOcO211/L1118D3kKUsSymKCIix76yxR2AiIiIiIiIiEhR27lzJ23atKFly5b06NGD5s2bk5KSwt69e1m5ciXp6els3LgRgKpVq/Loo48Wc8QiIlJSKKkuIiIiIiIiIr9bK1euZOXKlRGPn3DCCbz11lvUr1+/CKMSEZGSTEl1EREREREREfndqVu3Lv/973+ZNWsWS5cu5ZdffmHr1q0456hevTqnn346F110EcOGDaN8+fLFHa6IiJQgSqqLiIiIiIiIyO9OQkIC/fr1o1+/fsUdioiIlDJKqouIiIjE2Q1v3xD1+PiLxhdRJCIiIiIiIhJvpTKpbmb1gfuAXkB1YBMwHRjtnNuRj3aqAfcClwB1gW3AHOBe59yPYco/DLQBTgJqAPuBdX7fTzvntuUo3xD4IUoI6c65y2ONV0REREqH55c+H/W4kuoiIiIiIiKlV6lLqptZE2AhUAuYAfwPOAu4HehlZh1yJrcjtFPdb+ck4H1gMtAMuAboY2btnXNrc1T7M7AUmAtsAZKBdkAacIOZtXPObQjT3Qq8xHtOX+UVp4iIiIiIiIiIiIiUHKUuqQ48g5dQv80591Rgp5k9hpf0fgC4MYZ2HsRLqD/mnLsjpJ3bgCf8fnrlqFPFOfdrzobM7AHgbmAE8KcwfS13zqXFEJOIiIiIiIiIiIiIlGBlijuA/PBHqfcEMoB/5zg8CtgHDDGz5DzaqQQM8cun5Tj8NN6ULuebWePQA+ES6r4p/rZp9DMQERERERERERERkdKsVCXVga7+9l3nXFboAefcHuAToCLelCzRtAMqAJ/49ULbyQLeydFfXi7ytysjHD/OzP5oZnf725YxtisiIiIiIiIiIiIiJUhpm/7lZH/7XYTjq/FGsp8EzCtkO/jt5GJmdwKVgBS8hUs74iXUH4rQXg//EdrGAmCoc259lDhDyy+JcKhZLPVFREREREREREREpPBKW1I9xd/uinA8sD/1KLdzJ1A75PUcYJhz7pcc5TKBf+ItUhpY9LQl3pQzXYF5ZnaGc25fHvGKiIiIiIiIiIiISAlQ2pLqJYJzrg6AmdUGzsEbob7MzC50zi0NKbcFuDdH9Q/NrCfwMXA2cB3ewqh59dk63H5/BHurgpyHiIiIiIiIiIiIiORPaZtTPTCCPCXC8cD+nUXRjnNus3NuGt6UM9WBSXn0G6h3GPg//2WnWOqIiIiIiIiIiIiISPErbUn1b/1t2LnOgab+NtJc6fFuBwDn3DpgFdDCzGrEUgcITBWTHGN5ERERERERERERESlmpS2pPt/f9jSzbLGbWWWgA9485p/m0c6nwH6gg18vtJ0yeCPPQ/uLxXH+9kiM5dv527VRS4mIiIiIiIiIiIhIiVGqkurOuTXAu0BD4OYch0fjjfp+OXThTzNrZmbNcrSzF3jZL5+Wo51b/Pbfcc4FE95mdpKZ5ZouxszKmNkDQC1goXNuR8ixVjmT//7+bsCf/ZevRDllERERERERERERESlBSuNCpX8CFgJP+snpb/AW/OyKN13LyBzlv/G3lmP/3UAX4C9mdgbwOXAK0BfYQu6kfW9gjJl9DPwAbANqA52BxsDPwPU56jwGNDWzhcCP/r6WwHn+83845xbGdNYiIiIiIiIiIiIiUuxK1Uh1CI5WbwNMxEum3wE0AZ4A2jnntsXYzjagPfAkcKLfztnABKC130+o94AXgJrApcBfgcuA7Xij5Fs451blqPMysAxoi5dw/xPefO1TgE7OuftjPW8RERERERERKZiJEydiZpgZEydOLO5wSpUuXboEr1048bq2efVzLGjYsCFmRsOGDcMeT0tLC16DBQsWFGlsIpI/pS6pDuCc2+Ccu8Y5V9c5l+ica+CcGx469UpIWXPOhf2L7Jzb7py73a+f6Ld3rXPuxzBlv3LO3eKcO8M5V8M5V9Y5l+Kca+ucS3PObQ9T5wXn3IXOuYbOuUrOuSTn3AnOuUHOuY/iczVEREREREREjp5Aki8/jzPOOOOoxpSRkUFaWhppaWnHfPIxIyMjeF2bNm2aZ/kvvvgi23vx0ksv5VnnkksuCZafPn16PMIWETmmlcbpX0RERERERESyeXzud8UdQpH6c4+TijuEYpWRkcHo0aODr7t06VJ8wRxlDRs2pEGDBqxbt47vv/+en376ieOOOy5i+Q8++CDX66FDh0Ys75zjo4+8cX9mRqdOneITuIjIMUxJdRERERERERGJybRp02Iql5KScpQjyZ9hw4YxbNiw4g6jwDp37sykSZMAL0l+xRVXRCwbLqkezZdffsn27d6P71u2bEm1atWyHS+qXwIc6784iEXg1xciUvIpqS4iIiIiIiIiMbnkkkuKO4TfpViT6llZWcFR5xdccAGzZ89m7dq1/Pjjj9SvXz9sndCk+7E84l9EJJ5K5ZzqIiIiIiIiIiK/F6HJ7mgjulesWMHOnTsB+Nvf/kZiYmKedUKPKakuIhIbJdVFRERERERE5KhbsGBBcDHMwBQX69ev54477qBZs2YkJyeTmprKOeecwzPPPMPhw4cjttG1a9fgvtGjR4ddLDXUxIkTg/snTpwYNr7A8UBieceOHYwZM4a2bdtSo0YNzCziFDLr169n5MiRnHXWWdSsWZPExETq1KlDjx49ePbZZzl48GC+r1eoxo0bc/zxxwPw7bffsnnz5rDlAqPOk5OT6dixI23bts22PyfnHB9++CEQeT71Ll26hL2m+bV48WJq1qyJmZGUlMSUKVPy1U+49/CTTz7hyiuvpGHDhpQvX546derQt29fZs+eHXNce/fuZdy4cfTo0YPjjjuOpKQkqlWrRtu2bbn33nv55ZdfYmpn69atjBgxgubNm5OcnBxsY+zYsWRmZsbURlpaWvAcI30Rsn//fqZNm8bNN9/M2WefTfXq1SlXrhwpKSm0aNGCm266iRUrVsR6+iJSQJr+RURERERERESK3Jw5c7jiiiuCI6sDFi1axKJFi5g+fTpvv/02SUlJRR7b0qVLueSSS9iwYUOeZceMGcPo0aM5cOBAtv2bN29m8+bNvPfeezz++OP8v//3/zjppIIvMNu5c2deeeUVwEuSDxw4MFeZQPK8ffv2lC1blk6dOvHJJ59ETKqvWrWKrVu3AuHnU4+Xd999l8suu4y9e/dSqVIlpk2bRvfu3QvV5kMPPcTIkSPJysoK7tu8eTNvvfUWb731Ftdffz3PPfccZcpEHk86e/Zshg0bxpYtW7LtP3jwIF988QVffPEF48aN45VXXuHiiy+O2M6iRYu4+OKLg9cSIDMzM9jGxIkTmTlzZiHO9jfNmzcnIyMj1/7du3ezatUqVq1axXPPPceIESN48MEH49KniOSmpLqIiIiIiIiIFKnly5fzyCOP4Jzjj3/8I+3btycpKYkvvviC5557jn379jF37lweeOAB7rvvvs4TYj8AACAASURBVGC9U089lWnTpvHVV1/xj3/8A4BBgwZx+eWXxy22bdu20bdvX3788Ud69+5Nnz59qFGjBhs3bsw1ivrPf/4z48aNAyA1NZXLL7+ctm3bUrlyZTZt2sT06dOZP38+q1evpnPnzixbtow6deoUKK4uXbpETao754LzqQdGnJ977rmMGTOG1atXs2nTJurWrZutTlHMp/76668zdOhQDh06RM2aNZk1axZt2rQpVJvTp09nxowZJCcn84c//IG2bdty5MgRPvzwQyZNmsThw4d5/vnnqVKlCmPHjg3bxtSpUxk0aBBHjhyhXLlyXHzxxXTp0oXatWuze/du5s+fz5QpU9izZw/9+vVj7ty5nHfeebna+f777+nVqxe7d+8G4LTTTuPqq6/m+OOPZ9OmTbz++ut8/vnnDBw4kEOHDhXqvMEbqV6tWjV69OjBmWeeSb169ShXrhwbN25k6dKlTJkyhUOHDjFmzBhq1arF8OHDC92niOSmpLqIiIiIiIiIFKkZM2Zwwgkn8N5779G0adPg/ssvv5yBAwfSoUMHDh8+zNNPP83IkSODo9Vr1KjBJZdcQmpqarBOs2bN4rqA6ldffUVCQgJTpkxhwIABUc8hkFDv3v3/s3ff8VFV+f/HX8eEUBISuiIgXUFE6b0EREBWhZUuKFWKCuICPwSlCywgIBZQiiJFEhEJqwsCS+i9CVJUihQpAqF3SO7vj8ncnSSTySSZELLf9/PxyGPuzD333HMzE5d93zOf04CwsDBy584dp03v3r354osv6NGjB2fOnKFPnz6EhYWlaFxJ1VX/5ZdfiIqKAhyz2gFq1qyJn58f0dHRrF69OsECp2ldT/2TTz7h7bffxrIsChcuzPLly1M1W99p8eLFPProo6xevTrO56dDhw68/vrrNGzYkKtXrzJp0iRat25tl8FxOnHiBJ07dyY6OprHHnuMH3/8kbJly8Zp06VLF3r37k3Dhg25fPkyHTp04MiRI2TKlClOux49etiBeqdOnZg2bRr+/v+N295++2369evHxIkTU33d4CiD06BBgzjncDVq1CgaN27Mr7/+ypAhQ+jSpQvZs2f3yblF5L9UU11EREREREREvOKudrm7n8TqlruaO3dunEDUqUqVKrRu3Rpw1DXfunWrry8jSb179/YYqAMMGTIEgEKFChEREZEgUHfq3r07r776KgDfffedVyVl3ClevDgFCxYEHGVb4tf6ds46z5w5M1WrVgUgODiYZ555Js5+V0nVU0+N999/n969e2NZFmXKlGHDhg0+CdSdvvzyS7efn2rVqjFu3DgAYmJi3IbZ48eP58qVK/j5+bF48eIEgbpTlSpV7OP//PNPFixYEGf/zz//zMqVKwF4/PHH+fzzzxOE3cYYPvzwQ6pUqZL8i3SjcePGiQbqAIULF2bKlCkAXL16lcWLF/vkvCISl0J1EREREREREbmvypcvT+3atRPd71pmY//+/fdjSHH06tXL4/7du3ezZ88eAHr27ElgYKDH9u3btwcgOjraDmFTwjkDHf4biDs5Q/OqVavGqUPvDMvjh+q//vqrveCpL+upR0dH8/rrrzNq1CgAatSowbp16yhQoIBP+gcoU6YMjRo1SnR/586dyZkzJwA//PAD0dHR9j7Lspg3bx4Azz77LOXKlfN4rtatW9sh9vLly+PsW7Rokb3dq1cvAgIC3PZhjKFv374ez+NLNWrUsLe3bNly384r8n+Jyr+IiIiIiIiIiFdcQ0RPKlSo4HF/tWrVPO53DWAvXrzo1Tl9pUCBAhQtWtRjG2ftcoDbt28TERHhsf3Jkyft7QMHDqR4bKGhoXYgvGbNGpo3b27vc4bs8Wec16lTh48++sgO0R9++GH7eNd+feHWrVu0bNnS/pw0adKEBQsWkC1bNp/07/Tss8963B8QEEDNmjX58ccfuX79Ovv377dno+/bt48LFy4AkD179iTfO4CgoCAuXbqU4L3btm2b12NKan9ynD17ltmzZ7N8+XL279/PxYsXuXHjhtu2f/75p8/OKyL/pVBdRERERERERLziq9rlefLk8bjfdab1rVu3fHJOb3kzo/ro0aP29vDhw5PVf2puErjOVHeth75v3z67HIxrG4BatWrZ264LnKZFPfV3332Xy5cvA47Z+V999ZXHUiUpVaJEiWS1OXXqlB2qu753CxcuZOHChV6fN/57d+rUKa/HlDt3bnLkyMGlS5e8Pp874eHhdO/e3f49J8VZ711EfEuhuoiIiIiIiIjcVw899OBWo82aNWuSbbwNNN25c+dOio8tWbIkjz76KKdOnWLv3r1ERUWRO3due9Z5pkyZqF69epxj8ubNS+nSpTlw4ECcUN15jC/rqd+7d8/evn79OpZl+aTf+LyZ+e5akufatWv2ti/fO2e//v7+CRYwTWxMqQnV165dyyuvvEJMTAzg+EZIgwYNKF68OCEhIXFuRv39738HiFP6RkR8R6G6iIiIiIiIiEgyBAUF2duRkZHUq1fvvp27bt26zJ8/H8uyWLduHc2aNbMD8goVKrit716nTh07VAc4ePAgp0+fBnxbT33MmDGEhYWxceNGFi1aROvWrQkPD/cqcE6OxEqduLp+/bq97fp+uW4PGTIk2d80cOXs6969e9y9ezfJ63QdU0oMGzbMDtSnTZvG66+/nibnEZGkPbi3hkVEREQyKGuo5fFHREREMjbXEjH3u2a1a6kWZ0jurKcev/SLk3Mm+v79+zl//nya1FMHR43yn376yV4o0xms371712fnADh06FCy2jz66KP2ti/fO9d+kxpTVFRUqmap37lzx67lX6lSpUQDdYBjx46l+Dwi4h2F6iIiIiIiIiKSobiWj0mrEiOeuIbXy5cvv6/ndg3BV69eza+//sqZM2eAhIuUOjlftyyLNWvWpEk9dSdnsF6zZk3AEay3atXKp8F6ZGSkx/137txhw4YNgKPkypNPPmnvK1++PMHBwQCsXLnSnvmdElWqVPF6TCtXrkzxecARyjvL6xQvXtxj22XLlqXqXCKSNIXqIiIiIiIiIpKhuJbwSI9SF5UqVaJMmTKAY+HIffv23bdzP/744+TPnx+APXv2EBERAThuNLguSuqqYMGCFClS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wWfQ1bZt2+ygu3PnztSpUwc/Pz+2bdvGzJkzuX79Ov/+979p37493333nds+bt68Sa5cuXjuuecoX748BQoUIFOmTJw8eZKdO3fy7bffcvfuXcaMGUO+fPno06dPktfQqVMnVq5cSc2aNWnVqhWPPPIIx44d47PPPuPYsWPs2rWLPn36MHz4cBo1asSdO3fo2rUrtWrVIiAggHXr1jF9+nTu3bvHhAkTaNy4MQ0aNEhwnlu3bmFZFmXKlKFevXqULl2a3Llzc+vWLU6cOEFERAQ7duzg3LlzvPDCC/z8888p+uaB05EjRzh8+DCAXd7Jk3PnzlG1alX++OMPwLEGQ9u2balcuTLBwcFERUXx888/8+OPPyY6e/vVV18lLCwMgCxZstChQwdq1KiBn58f27dvZ+bMmVy9epVvv/2Wy5cvs3Tp0gSfl08++cQO1HPkyEH79u0pX748ISEh3Lhxg6NHj7JlyxZWrVqV4t+N071792jevDkbNmygXr16NGvWjPz583Py5ElmzJjBvn37uHjxIm3atGHfvn0EBAQk6OPChQtUr17d/l0/88wzvPzyy5QoUYKHHnqIvXv3MmvWLE6ePMnMmTO5d+8es2bN8jiuatWqsWjRImJiYvjPf/5D69atU32t6SXDherAFByBem/LsuxloI0xE3GE3qOAHl70MxpHoD7Rsqy+Lv30BibHnqdxvGOCLcu6Fb8jY8woYBAwEHjD5fVgYDoQDYRalrU99vXBOIL8FsaYNpZlhXkxXhEREREREZEM6/fff7e3kwrU/P39KVCgAMePH+f69eucPHmSggULpqgvwA7Vncf6KlSvUaMGL774ol2m5V//+hcvvfSST/oePXo0K1assMvLNGzYMNFQ150dO3awa9cuAF544QUiIiISrSW+f/9+Hn744RSNc9OmTYwdOxZwlE5ZsmQJderUsfe3bduWfv360ahRI7Zv386ePXsYPHgw48ePt9s0bNgQgEuXLtmvVahQgWbNmqVoTECcGxzOGunJUaFCBQICArhz5w5RUVH89ttvlCpVym3bJUuWkD17dpYvX26X7gFo3749b731FqGhoZw6dYqFCxeycOFCmjdvnqCPWbNm0aBBA/z93Ud1o0aNonHjxvz6668MGTKELl26kD17do/X8N133zFq1KgE5Yk6duxIuXLlOHXqFPPmzWP37t1k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mDRpEhs2bKBjx44UK1aMLFmykCNHDipUqMCIESPYt28f9evXvw9XFlf79u0pU6aMz/v19/dn5MiRSbZ77733WL16NYMHD6ZRo0YUKVKErFmz4u/vT86cOalSpQoDBgxg//79ccpbpNSIESPYs2cPvXr14sknnyR79uxkzpyZggUL0rx5cxYuXMjq1avtxVbvt/bt23Pw4EHmzJlDmzZtKFmyJCEhIQQEBJA/f36qVq3Ke++9x65duwgPD/c6UHftf9u2bXTt2tX+HObKlYv69eszb948/v3vf5MlSxa3xxpjmDt3Lt988w316tUjR44cBAQEULBgQV544QXCw8OJiIi4rzcjkqNEiRLs2rWLgQMHUrp0abJkyUJQUBBPPPEEb731Fjt27PBp+RdwlEZx1rpP7GaFq4cffpjVq1ezZMkSXn31VYoVK0ZgYCCZMmUiX7581K1bl2HDhiW68Km/vz/Tp09n06ZNdOnShRIlShAYGEjWrFkpWrQo7du3Z+XKlSxYsMDt+1S4cGEOHTrEZ599xiuvvELZsmUJCQnBz8+PbNmyUbJkSdq2bcsPP/xAZGRkuv2dxBccHExYWBg7d+6kT58+lC9fnty5c+Pv709QUBAlS5akWbNmTJw4kcOHD3v8ForzfcqZMydt2rS5X5eQZoyqj2RsxpgdFSpUqLBjx470HoqIiIiIiIhPHDjgWBardOnS6TwSERF5UC1atIiXX34ZgI0bN1K9evV0HpEk5sqVKzz66KNcv36dAQMG8M9//jNV/aXm3wkVK1Zk586dOy3LSv5Ksi40U11EREREREREREQylGbNmtllncaMGZPOoxFPPv74Y65fv0727Nnp169feg/HJxSqi4iIiIiIiIiISIZijLFnPP/www+oisOD6cqVK0yaNAmA/v37kydPnnQekW8oVBcREREREREREZEMp1GjRjRt2hSAYcOGpe9gxK2PP/6YCxcuULRoUfr375/ew/EZ//QegIiIiMj/morTPJfn29FNs2hERERERHwhIiIivYcgHrz//vu8//776T0Mn1OoLiIiIuJjO0/vTO8hiIiIiIiISBpR+RcRERERERERERERES8pVBcRERERERERERER8ZJCdRERERERERERERERLylUFxERERERERERERHxkkJ1EREREREREREREREvKVQXERERERERERERkQeeZVnpPQRAobqIiIiIiIg8YIwxAMTExKTzSERERORB4gzVnf9WSC8K1UVEREREROSB4ufnB8CdO3fSeSQiIiLyIHH+28D5b4X0olBdREREREREHihBQUEAXL16NZ1HIiIiIg+SK1euAP/9t0J6UaguIiIiIiIiD5Tg4GAALl68yK1bt9J5NCIiIvIguHXrFpcuXQL++2+F9OKfrmcXERERERERiSdbtmwEBQVx7do1jh8/To4cOQgODiYgIABjTLrXURUREZG0Z1kWlmVx584drly5wqVLl4iOjiYoKIhs2bKl69gUqouIiIiIiMgDxRhDgQIFOHnyJNeuXSMqKoqoqKj0HpaIiIiks6CgIAoUKJDuN9gVqouIiIiIiMgD56GHHqJgwYLcuHGDK1eucO3aNaKjo7EsK72HJiIiIveJMQY/Pz+CgoIIDg4mW7Zs6R6og0J1EREREREReUAZYwgMDCQwMDC9hyIiIiJi00KlIiIiIiIiIiIiIiJeUqguIiIiIiIiIiIiIuIlheoiIiIiIiIiIiIiIl5SqC4iIiIiIiIiIiIi4iWF6iIiIiIiIiIiIiIiXlKoLiIiIiIiIiIiIiLiJYXqIiIiIiIiIiIiIiJeUqguIiIiIiIiIiIiIuIlheoiIiIiIiIiIiIiIl5SqC4iIiIiIiIiIiIi4iWF6iIiIiIiIiIiIiIiXlKoLiIiIiIiIiIiIiLiJYXqIiIiIiIiIiIiIiJe8k/vAYiIiIj8r6mQv0J6D0FERERERETSiEJ1ERERER/b0W1Heg9BRERERERE0ojKv4iIiIiIiIiIiIiIeEmhuoiIiIiIiIiIiIiIlxSqi4iIiIiIiIiIiIh4SaG6iIiIiIiIiIiIiIiXFKqLiIiIiIiIiIiIiHhJobqIiIiIiIiIiIiIiJcUqouIiIiIiIiIiIiIeEmhuoiIiIiIiIiIiIiIlxSqi4iIiIiIiIiIiIh4SaG6iIiIiIiIiIiIiIiXFKqLiIiIiIiIiIiIiHjJP70HICIiIvK/ZtqOaR73d6vY7T6NRERERERERHwtQ4bqxpiCwAigMZAbOA1EAMMty7qYjH5yAUOAZkB+IAr4CRhiWdaf8drmBv4O/A0oCxQA7gC/AF8BX1mWFRPvmCLAHx6GEG5ZVhtvxysiIiIZQ/cfu3vcr1BdREREREQk48pwoboxpjiwEcgHLAZ+BaoAbwONjTE1LcuK8qKf3LH9PA5EAmFAKaAT8DdjTHXLso64HNISmIojwF8FHAceBl4GZgDPG2NaWpZluTndbhyhf3x7k75iEREREREREREREXlQZLhQHZiCI1DvbVnWJ84XjTETgXeAUUAPL/oZjSNQn2hZVl+XfnoDk2PP09il/e/AS8C/XWekG2MGAVuB5jgC9oVuzvWzZVnDvLk4EREREREREREREXlwZaiFSmNnqTcEjgKfxds9FLgOvGqMCUyinyDg1dj2w+Lt/hQ4BjQyxhRzvmhZVqRlWT/EL/FiWdYZ4PPYp6HJuBwRERERERERERERyWAyVKgO1It9XO4m3L4KbACyAdWS6KcakBXYEHucaz8xwLJ450vK3djHe4nsf9QY090YMyj28Wkv+xURERERERERERGRB0hGK//yROzj74nsP4hjJvvjwMpU9kNsPx4ZY/yB12Kf/pRIs+dif1yPWw10sCzreFLniG2/I5Fdpbw5XkRERERERERERERSL6PNVA+JfbycyH7n6znuUz8A/wSeApZYlrUs3r4bwEigIpAz9qcujoVOQ4GVSZWqEREREREREREREZEHR0abqf5AiV3UtC/wK44a7XFYlnUWGBLv5bXGmIbAeqAq0BXHwqgeWZZVMZEx7AAqJG/kIiIiIiIiIiIiIpISGW2munMGeUgi+52vX0rrfowxb+EIw/cD9SzLupDEOW2WZd0DZsQ+rePtcSIiIiIiIiIiIiKSvjJaqP5b7GNitc5Lxj4mVivdJ/0YY/oAnwB7cQTqZ5I4nzvnYh9V/kVEREREREREREQkg8hoofqq2MeGxpg4YzfGZAdq4qhjvjmJfjYDN4Gasce59vMQjsVOXc/nun8AMAn4GUegfja5FxGrWuzjkRQeLyIiIiIiIiIiIiL3WYYK1S3LOgwsB4oAb8bbPRzHrO85lmVdd75ojClljCkVr59rwJzY9sPi9fNWbP/LLMuKE3gbYwbjWJh0B/CsZVnnPY3XGFMhfvgf+/qzwDuxT+d66kNEREREREREREREHhwZcaHSN4CNwMex4fQBHAt+1sNRruW9eO0PxD6aeK8PAkKBfxhjygFbgdJAU+As8UJ7Y0wHYAQQDawDehsTv0uOWpY1y+X5RKCkMWYj8Gfsa08D9WO3B1uWtTHJKxYRERERERERERGRB0KGC9UtyzpsjKmEI+BuDDQBTuNYNHS4ZVkXvewnyhhTHRgKNANqA1HAV8AQy7L+jHdI0dhHP6BPIt2uAWa5PJ8D/B2oDDwPZAL+Ar4FPrUsa503YxURERERERERERGRB0OGC9UBLMs6AXTysm2C6eQu+y4Ab8f+JNXPMBKWiknqmJnAzOQcIyIiIiIiIiIiIiIPrgxVU11EREREREREREREJD0pVBcRERERERERERER8VKahurGmJzGmEJpeQ4RERERERERERERkfvF56G6MSbIGDPBGHMGOA/84bKvqjFmiTGmgq/PKyIiIiIiIiIiIiKS1nwaqhtjQoBNwDvAKeAA4LpQ6C9AbaCtL88rIiIiIiIiIiIiInI/+Hqm+ntAGaCjZVkVgAWuOy3LugGsAZ718XlFRERERERERERERNKcr0P1l4FllmXN9tDmGFDAx+cVEREREREREREREUlzvg7VCwJ7kmhzDQjx8XlFRERERERERERERNKcr0P1q0C+JNoUxbGAqYiIiIiIiIiIiIhIhuLrUH0b8IIxJru7ncaY/EATYL2PzysiIiIiIiIiIiIikuZ8HapPBnIDS4wxpV13xD5fAGQBPvbxeUVERERERERERERE0py/LzuzLGuZMWY4MBTYC9wFMMacB3ICBhhgWdZGX55XREREREREREREROR+8PVMdSzLGg48C/wLuAhEAxawBGhgWdZ4X59TREREREREREREROR+8OlMdSfubx23AAAgAElEQVTLslYBq9KibxERERERERERERGR9JImobqIiIjI/2XbX9+e3kMQERERERGRNKJQXURERMTHKj5aMb2HICIiIiIiImnEp6G6MSYGR/10TyzgCnAA+B741LKs274ch4iIiIiIiIiIiIhIWvD1QqVrgT2AAWKAY8DW2MeY2Nd/AU4C5YFxwAZjTKCPxyEiIiIiIiIiIiIi4nO+DtXbAiFAGFDcsqxilmVVtyyrGFA89vVg4DngYeBLoALw/3w8DhERERERERERERERn/N1qD4WuGBZ1iuWZR133WFZ1nHLsl4BLgJjLcu6CvQAfgea+3gcIiIiIiIiIiIiIiI+5+tQvRGwIok2K4DGAJZlReMoGVPUx+MQEREREREREREREfE5X4fq2XGUd/EkJLad0wUfj0FEREREREREREREJE34OlT/FWhtjHnU3U5jTEGgNXDA5eVC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\n", "text/plain": [ "
" ] }, "metadata": { "image/png": { "height": 315, "width": 746 } }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize = (10.5, 4.5))\n", "plt.hist(wiki['length'], 50, histtype = 'stepfilled', \n", " normed = True, label = 'Entire Wikipedia', alpha = 0.5)\n", "\n", "plt.hist(nearest_cosine['length'], 50, histtype = 'stepfilled', \n", " normed = True, label = '100 NNs of Obama (cosine)', alpha = 0.8)\n", "\n", "plt.axvline(nearest_cosine.loc[nearest_cosine['name'] == 'Barack Obama', 'length'].values, \n", " color = 'g', linestyle = '--', linewidth = 4,\n", " label = 'Length of Barack Obama')\n", "\n", "plt.axis([0, 1500, 0, 0.04])\n", "plt.legend(loc = 'best', prop = {'size': 15})\n", "plt.title('Distribution of document length')\n", "plt.xlabel('# of words')\n", "plt.ylabel('Percentage')\n", "plt.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The visualization is basically telling us that 100 nearest neighbors using TF-IDF weighting and cosine distance provide a sampling across articles with different length. The thing is that whether we're choosing euclidean or cosine distance to measure our articles' similarity, both of them still ignore the document's length, which may be great in certain situations but not in others. For instance, consider the following (admittedly contrived) tweet.\n", "\n", "```\n", "+--------------------------------------------------------+\n", "| +--------+ |\n", "| One that shall not be named | Follow | |\n", "| @username +--------+ |\n", "| |\n", "| Democratic governments control law in response to |\n", "| popular act. |\n", "| |\n", "| 8:05 AM - 16 May 2016 |\n", "| |\n", "| Reply Retweet (1,332) Like (300) |\n", "| |\n", "+--------------------------------------------------------+\n", "```\n", "\n", "How similar is this tweet to Barack Obama's Wikipedia article? Let's transform the tweet into TF-IDF features; compute the cosine distance between the Barack Obama article and this tweet and compare this distance to the distance between the Barack Obama article and all of its Wikipedia 10 nearest neighbors." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "79" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tweet = tfidf_vect.transform(['democratic governments control law in response to popular act'])\n", "tweet_dist = paired_distances(tfidf_weight[obama_index], tweet, metric = 'cosine')\n", "\n", "# compare to the 100 articles that were nearest to Obama's,\n", "# the distance of this tweet is shorter than how many articles\n", "np.sum(tweet_dist < nearest_cosine['cosine'].values)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With cosine distances, the tweet is \"nearer\" to Barack Obama than most of the articles. If someone is reading the Barack Obama Wikipedia page, would we want to recommend they read this tweet? Ignoring article lengths completely resulted in nonsensical results. In practice, it is common to enforce maximum or minimum document lengths. After all, when someone is reading a long article from *The Atlantic*, we wouldn't recommend him/her a tweet." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Reference" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- [Coursera: Washington Clustering & Retrieval](https://www.coursera.org/learn/ml-clustering-and-retrieval)\n", "- [Notebooks: Tf-idf Walkthrough for scikit-learn](http://nbviewer.jupyter.org/github/rasbt/pattern_classification/blob/master/machine_learning/scikit-learn/tfidf_scikit-learn.ipynb)\n", "- [Blog: Machine Learning :: Text feature extraction (tf-idf)](http://blog.christianperone.com/2011/09/machine-learning-text-feature-extraction-tf-idf-part-i/)" ] } ], "metadata": { "anaconda-cloud": {}, "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" }, "toc": { "nav_menu": { "height": "126px", "width": "252px" }, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "335px" }, "toc_section_display": "block", "toc_window_display": true }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }