{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Natural language Processing With SpaCy and Python\n", "+ NLP a form of AI or Artificial Intelligence (Building systems that can do intelligent things)\n", "+ NLP or Natural Language Processing – Building systems that can understand everyday language. It is a subset of Artificial Intelligence. \n", "+ SpaCy by Explosion.ai (Matthew Honnibal)\n", "![alt text](SpaCy_logo.png \"Title\")\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Basic Terms\n", "+ Tokenization:\tSegmenting text into words, punctuations marks etc.\n", "+ Part-of-speech: (POS) Tagging\tAssigning word types to tokens, like verb or noun.\n", "+ Dependency Parsing:\tAssigning syntactic dependency labels, describing the relations between individual tokens, like subject or object.\n", "+ Lemmatization:\tAssigning the base forms of words. For example, the lemma of \"was\" is \"be\", and the lemma of \"rats\" is \"rat\".\n", "+ Named Entity Recognition (NER):\tLabelling named \"real-world\" objects, like persons, companies or locations.\n", "+ Similarity:\tComparing words, text spans and documents and how similar they are to each other.\n", "+ Sentence Boundary Detection (SBD):\tFinding and segmenting individual sentences.\n", "+ Text Classification:\tAssigning categories or labels to a whole document, or parts of a document.\n", "+ Rule-based Matching:\tFinding sequences of tokens based on their texts and linguistic annotations, similar to regular expressions.\n", "+ Training:\tUpdating and improving a statistical model's predictions.\n", "+ Serialization:\tSaving objects to files or byte strings." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Installing the Library on Linux/Unix\n", "+ sudo pip install spacy\n", "+ sudo python -m spacy download en\n", "+ sudo python -m spacy download fr\n", "\n", "### Installing On Windows using Conda\n", "\n", "+ conda install tqdm\n", "+ conda install -c conda-forge spacy /conda install spacy\n", "+ python -m spacy download en\n", "- - with cmd administrator\n", "\n", "\n", "### Installing using Conda\n", "+ conda install -c conda-forge spacy\n", "+ sudo python -m spacy download en\n", "+ sudo python -m spacy download fr\n", "\n", "\n", "\n", "\n", "#### For Download the Models of other languages\n", "+ sudo python -m spacy download de\n", "+ sudo python -m spacy download es\n", "+ sudo python -m spacy download xx \n", "\n", "\n", "### Installing On Windows using Conda\n", "+ conda config-add channel conda-forge\n", "+ conda update anaconda\n", "+ conda install tqdm\n", "+ conda install -c conda-forge spacy\n", "+ sudo python -m spacy download en" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Loading the package\n", "import spacy\n", "nlp = spacy.load('en')\n", "\n", "#nlp = en_core_web_sm.load()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![alt text](BehindSpacy.jpg \"Title\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reading A Document or Text" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Reading the text /tokens\n", "docx = nlp(\"SpaCy is a cool tool\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "SpaCy is a cool tool" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "docx" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "docx2 = nlp(u\"SpaCy is an amazing tool like nltk\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Reading a file\n", "myfile = open(\"examplefile.txt\").read()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "doc_file = nlp(myfile)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "The best error message is the one that never shows up.\n", "Gates, currently a journalist in America, played with David Cotton in the final years of the seventies in Newcastle.\n", "\n", "You Learn More From Failure Than From Success. \n", "The purpose of software engineering is to control complexity, not to create it\n", "\n", "This is one of the most interesting programming books I have ever read, and it's so easy to jump right in and play with the NLTK. I have devoured this book.\n", "\n", "Although this text is available for free online through NLTK, it is an incredible resource for anybody trying to get started with NLP in Python. With only basic knowledge of Python and a week with this book, I was able to write a work application to identify key themes in survey data utilizing part of speech tagging and a custom built Regex parser. I highly recommend this text." ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Calling the file\n", "doc_file" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# Simplified one liner\n", "doc_file2 = nlp(open(\"examplefile.txt\").read())" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "The best error message is the one that never shows up.\n", "Gates, currently a journalist in America, played with David Cotton in the final years of the seventies in Newcastle.\n", "\n", "You Learn More From Failure Than From Success. \n", "The purpose of software engineering is to control complexity, not to create it\n", "\n", "This is one of the most interesting programming books I have ever read, and it's so easy to jump right in and play with the NLTK. I have devoured this book.\n", "\n", "Although this text is available for free online through NLTK, it is an incredible resource for anybody trying to get started with NLP in Python. With only basic knowledge of Python and a week with this book, I was able to write a work application to identify key themes in survey data utilizing part of speech tagging and a custom built Regex parser. I highly recommend this text." ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "doc_file2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# Decoding the file as UTF-8\n", "#myfile2 = open(\"examplefile.txt\").read().decode('utf8')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Sentence Tokens\n", "+ Tokenization == Splitting or segmenting the text into sentences or tokens\n", "+ .sent" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "The best error message is the one that never shows up.\n", "Gates, currently a journalist in America, played with David Cotton in the final years of the seventies in Newcastle.\n", "\n", "You Learn More From Failure Than From Success. \n", "The purpose of software engineering is to control complexity, not to create it\n", "\n", "This is one of the most interesting programming books I have ever read, and it's so easy to jump right in and play with the NLTK. I have devoured this book.\n", "\n", "Although this text is available for free online through NLTK, it is an incredible resource for anybody trying to get started with NLP in Python. With only basic knowledge of Python and a week with this book, I was able to write a work application to identify key themes in survey data utilizing part of speech tagging and a custom built Regex parser. I highly recommend this text." ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List of Sentences in File\n", "doc_file" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0: The best error message is the one that never shows up.\n", "\n", "1: Gates, currently a journalist in America, played with David Cotton in the final years of the seventies in Newcastle.\n", "\n", "\n", "2: You Learn More From Failure\n", "3: Than From Success. \n", "\n", "4: The purpose of software engineering is to control complexity, not to create it\n", "\n", "\n", "5: This is one of the most interesting programming books I have ever read, and it's so easy to jump right in and play with the NLTK.\n", "6: I have devoured this book.\n", "\n", "\n", "7: Although this text is available for free online through NLTK, it is an incredible resource for anybody trying to get started with NLP in Python.\n", "8: With only basic knowledge of Python and a week with this book, I was able to write a work application to identify key themes in survey data utilizing part of speech tagging and a custom built Regex parser.\n", "9: I highly recommend this text.\n" ] } ], "source": [ "# Sentence Tokens\n", "for num,sentence in enumerate(doc_file.sents):\n", " #print(f'{num}: {sentence}') # For Python 3.6 upwards\n", " print('{0}: {1}'.format(num,sentence))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Word Tokens\n", "+ Splitting or segmenting the text into words\n", "+ .text" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "doc = nlp(u\"Spacy is an amazing tool\")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Spacy\n", "is\n", "an\n", "amazing\n", "tool\n" ] } ], "source": [ "# Word Tokens\n", "for token in doc:\n", " print(token.text)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Spacy', 'is', 'an', 'amazing', 'tool']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List of Word Tokens\n", "[token.text for token in doc ]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['Spacy', 'is', 'an', 'amazing', 'tool']" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Similar to splitting on spaces\n", "doc.text.split(\" \")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### More about words\n", "+ .shape_ ==> for shape of word eg. capital,lowercase,etc\n", "+ .is_alpha ==> returns boolean(true or false) if word is alphabet\n", "+ .is_stop ==> returns boolean(true or false) if word is a stop word" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "SpaCy is a cool tool" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "docx" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SpaCy 14101195205177134206\n", "is 4370460163704169311\n", "a 11123243248953317070\n", "cool 13110060611322374290\n", "tool 13110060611322374290\n" ] } ], "source": [ "# Word Shape As Hash Value\n", "for word in docx:\n", " print(word.text,word.shape)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SpaCy XxxXx\n", "is xx\n", "a x\n", "cool xxxx\n", "tool xxxx\n" ] } ], "source": [ "# Word Shape As readable representation\n", "for word in docx:\n", " print(word.text,word.shape_)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "ex_doc = nlp(\"Hello hello HELLO HeLLO\")" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Token => Hello Shape Xxxxx True False\n", "Token => hello Shape xxxx True False\n", "Token => HELLO Shape XXXX True False\n", "Token => HeLLO Shape XxXXX True False\n" ] } ], "source": [ "for word in ex_doc:\n", " print(\"Token =>\", word.text, \"Shape \",word.shape_,word.is_alpha,word.is_stop)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part of Speech Tagging\n", "+ NB attribute_ ==> Returns readable string representation of attribute\n", "+ .pos\n", "+ .pos_ ==> exposes Google Universal pos_tag,simple \n", "+ .tag\n", "+ .tag_ ==> exposes Treebank, detailed,for training your own model\n", "+ + Uses \n", "- - Sentiment Analysis,Homonym Disambuguity ,Prediction" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "# Parts of Speech\n", "ex1 = nlp(\"He drinks a drink\")" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "He PRON\n", "drinks VERB\n", "a DET\n", "drink NOUN\n" ] } ], "source": [ "# pos_ = Parts of Speech Simplified\n", "for word in ex1:\n", " print(word.text,word.pos_)\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "# Parts of Speech Simple Term (.pos_)\n", "ex2 = nlp(\"I fish a fish\")" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I PRON PRP\n", "fish VERB VBP\n", "a DET DT\n", "fish NOUN NN\n" ] } ], "source": [ "for word in ex2:\n", " print(word.text,word.pos_,word.tag_)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I PRON PRP\n", "fish VERB VBP\n", "a DET DT\n", "fish NOUN NN\n" ] } ], "source": [ "# Parts of Speech Detailed (.tag_) (Good for training your own model,features) \n", "# Parts of Speech of Tag \n", "for word in ex2:\n", " print(word.text,word.pos_,word.tag_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### If you want to know the meaning of the pos abbreviation\n", "+ spacy.explain('DT')" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'verb, non-3rd person singular present'" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spacy.explain('VBP')" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "exercise1 = nlp(u\"All the faith he had had had had no effect on the outcome of his life\")\n", "#the first is a modifier while the second is the main verb of the sentence\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('All', 'PDT', 'ADJ')\n", "('the', 'DT', 'DET')\n", "('faith', 'NN', 'NOUN')\n", "('he', 'PRP', 'PRON')\n", "('had', 'VBD', 'VERB')\n", "('had', 'VBN', 'VERB')\n", "('had', 'VBN', 'VERB')\n", "('had', 'VBN', 'VERB')\n", "('no', 'DT', 'DET')\n", "('effect', 'NN', 'NOUN')\n", "('on', 'IN', 'ADP')\n", "('the', 'DT', 'DET')\n", "('outcome', 'NN', 'NOUN')\n", "('of', 'IN', 'ADP')\n", "('his', 'PRP$', 'ADJ')\n", "('life', 'NN', 'NOUN')\n" ] } ], "source": [ "for word in exercise1:\n", " print((word.text,word.tag_,word.pos_))" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "exercise2 = nlp(\"The man the professor the student has studies Rome.\")\n", "#The student has the professor who knows the man who studies ancient Rome" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('The', 'DT', 'DET')\n", "('man', 'NN', 'NOUN')\n", "('the', 'DT', 'DET')\n", "('professor', 'NN', 'NOUN')\n", "('the', 'DT', 'DET')\n", "('student', 'NN', 'NOUN')\n", "('has', 'VBZ', 'VERB')\n", "('studies', 'NNS', 'NOUN')\n", "('Rome', 'NNP', 'PROPN')\n", "('.', '.', 'PUNCT')\n" ] } ], "source": [ "for word in exercise2:\n", " print((word.text,word.tag_,word.pos_))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Syntactic Dependency\n", "+ It helps us to know the relation between tokens \n", "+ How each word is connected and dependent on each other" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "ex3 = nlp(\"Sally likes Sam\")" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Sally', 'NNP', 'PROPN', 'advmod')\n", "('likes', 'VBZ', 'VERB', 'ROOT')\n", "('Sam', 'NNP', 'PROPN', 'dobj')\n" ] } ], "source": [ "for word in ex3:\n", " print((word.text,word.tag_,word.pos_,word.dep_))" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'adverbial modifier'" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# What does Advmod mean?\n", "spacy.explain('advmod')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualizing Dependency using displaCy\n", "+ from spacy import displacy\n", "+ displacy.serve()\n", "+ displacy.render(jupyter=True) # for jupyter notebook" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "# To dispay the dependences and any other visualization\n", "from spacy import displacy" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " Sally\n", " PROPN\n", "\n", "\n", "\n", " likes\n", " VERB\n", "\n", "\n", "\n", " Sam\n", " PROPN\n", "\n", "\n", "\n", " \n", " \n", " advmod\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " dobj\n", " \n", " \n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# For Jupyter Notebooks you can set jupter=True to render it properly\n", "displacy.render(ex3,style='dep',jupyter=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Visualizing Named Entity Recognistion \n", "#displacy.render(ex1,style='ent',jupyter=True,options={'distance':140})\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualizing using displaCy\n", "+ For IDEs\n", "+ For Jupyter notebook\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# For IDEs\n", "#from spacy import displacy" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "docx3 = nlp('Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo')" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('Buffalo', 'NNP', 'PROPN', 'compound')\n", "('buffalo', 'NN', 'NOUN', 'compound')\n", "('Buffalo', 'NNP', 'PROPN', 'compound')\n", "('buffalo', 'NN', 'NOUN', 'compound')\n", "('buffalo', 'NN', 'NOUN', 'compound')\n", "('buffalo', 'NN', 'NOUN', 'compound')\n", "('Buffalo', 'NNP', 'PROPN', 'compound')\n", "('buffalo', 'NN', 'NOUN', 'ROOT')\n" ] } ], "source": [ "for word in docx3:\n", " print((word.text,word.tag_,word.pos_,word.dep_))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Start a server running on your localhost\n", "#displacy.serve(docx3,style='dep')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using displaCy in Jupyter notebooks\n", "+ displacy.render(jupyter=True)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "displacy.render(docx3,style='dep',jupyter=True)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "## Customizing the Diplays\n", "# Compact set it to square arrows or curved arrows\n", "# Color:#09a3d5\n", "options = {'compact': True, 'bg': 'cornflowerblue',\n", " 'color': '#fff', 'font': 'Sans Serif'}\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "displacy.render(docx3,style='dep',options=options,jupyter=True)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "# Adding Title\n", "docx3.user_data['title']= 'Buffalo Complex Sentence'" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " Buffalo\n", " PROPN\n", "\n", "\n", "\n", " buffalo\n", " NOUN\n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " compound\n", " \n", " \n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "displacy.render(docx3,style='dep',options=options,jupyter=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Rendering HTML\n", "+ Default is svg\n", "+ set page to True\n", "+ minify=True For Minified format" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "html = displacy.render(docx3,style='dep',page=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exporting The Rendered Graphic" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "svg = displacy.render(doc, style='dep')\n", "output = 'buffalosentence.svg'\n", "with open(output,'w', encoding='utf-8') as f:\n", " f.write(svg)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Alternative Method\n", "# svg = displacy.render(doc, style='dep')\n", "# output_path = Path('/images/sentence.svg')\n", "# output_path.open('w', encoding='utf-8').write(svg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Named Entity Recognition or Detection\n", "+ Classifying a text into predefined categories or real world object entities.\n", "+ takes a string of text (sentence or paragraph) as input and identifies relevant nouns (people, places, and organizations) that are mentioned in that string.\n", "\n", "##### Uses\n", "+ Classifying or Categorizing contents by getting the relevant tags\n", "+ Improve search algorithms\n", "+ For content recommendations\n", "+ For info extraction\n", "\n", "+ .ents\n", "+ .label_" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "wikitext = nlp(u\"By 2020 the telecom company Orange, will relocate from Turkey to Orange County in the U.S. close to Apple.It will cost them 2 billion dollars.\")" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2020 DATE\n", "Turkey GPE\n", "Orange County GPE\n", "U.S. GPE\n", "Apple ORG\n", "2 billion dollars MONEY\n" ] } ], "source": [ "for entity in wikitext.ents:\n", " print(entity.text,entity.label_)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Countries, cities, states'" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# What does GPE means\n", "spacy.explain('GPE')" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
By \n", "\n", " 2020\n", " DATE\n", "\n", " the telecom company Orange, will relocate from \n", "\n", " Turkey\n", " GPE\n", "\n", " to \n", "\n", " Orange County\n", " GPE\n", "\n", " in the \n", "\n", " U.S.\n", " GPE\n", "\n", " close to \n", "\n", " Apple\n", " ORG\n", "\n", ".It will cost them \n", "\n", " 2 billion dollars\n", " MONEY\n", "\n", ".
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize With DiSplaCy\n", "displacy.render(wikitext,style='ent',jupyter=True)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "wikitext2 = nlp(u\"Linus Benedict Torvalds is a Finnish-American software engineer who is the creator, and for a long time, principal developer of the Linux kernel, which became the kernel for operating systems such as the Linux operating systems, Android, and Chrome OS.\")" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " Linus Benedict Torvalds\n", " PERSON\n", "\n", " is a \n", "\n", " Finnish\n", " NORP\n", "\n", "-American software engineer who is the creator, and for a long time, principal developer of the \n", "\n", " Linux\n", " ORG\n", "\n", " kernel, which became the kernel for operating systems such as the \n", "\n", " Linux\n", " ORG\n", "\n", " operating systems, \n", "\n", " Android\n", " GPE\n", "\n", ", and Chrome OS.
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize With DiSplaCy\n", "displacy.render(wikitext2,style='ent',jupyter=True)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Nationalities or religious or political groups'" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spacy.explain('NORP')" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "doc1 = nlp(\"Facebook, Explosion.ai, JCharisTech are all internet companies\")" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " Facebook\n", " ORG\n", "\n", ", \n", "\n", " Explosion.ai\n", " ORG\n", "\n", ", \n", "\n", " JCharisTech\n", " ORG\n", "\n", " are all internet companies
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize With DiSplaCy\n", "displacy.render(doc1,style='ent',jupyter=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Text Normalization and Word Inflection\n", "+ Word inflection == syntactic differences between word forms \n", "+ Reducing a word to its base/root form\n", "+ Lemmatization **\n", "- - a word based on its intended meaning\n", "+ Stemming \n", "- - Cutting of the prefixes/suffices to reduce a word to base form\n", "+ Word Shape Analysis" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "## Lemmatization \n", "docx_lemma = nlp(\"studying student study studies studio studious\")" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Token=> studying Lemma=> study VERB\n", "Token=> student Lemma=> student NOUN\n", "Token=> study Lemma=> study NOUN\n", "Token=> studies Lemma=> study NOUN\n", "Token=> studio Lemma=> studio NOUN\n", "Token=> studious Lemma=> studious ADJ\n" ] } ], "source": [ "for word in docx_lemma:\n", " print(\"Token=>\",word.text,\"Lemma=>\",word.lemma_,word.pos_)" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [], "source": [ "docx_lemma1 = nlp(\"good goods run running runner was be were\")" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Token=> good Lemma=> good ADJ\n", "Token=> goods Lemma=> good NOUN\n", "Token=> run Lemma=> run VERB\n", "Token=> running Lemma=> run VERB\n", "Token=> runner Lemma=> runner NOUN\n", "Token=> was Lemma=> be VERB\n", "Token=> be Lemma=> be VERB\n", "Token=> were Lemma=> be VERB\n" ] } ], "source": [ "for word in docx_lemma1:\n", " print(\"Token=>\",word.text,\"Lemma=>\",word.lemma_,word.pos_)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": [ "docx_lemma2 = nlp(\"walking walks walk walker\")" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Token=> walking Lemma=> walk VERB\n", "Token=> walks Lemma=> walk NOUN\n", "Token=> walk Lemma=> walk VERB\n", "Token=> walker Lemma=> walker ADV\n" ] } ], "source": [ "for word in docx_lemma2:\n", " print(\"Token=>\",word.text,\"Lemma=>\",word.lemma_,word.pos_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Semantic Similarity\n", "+ object1.similarity(object2)\n", "+ Uses:\n", "+ - Recommendation systems\n", "+ - Data Preprocessing eg removing duplicates\n", "- - python -m spacy download en_core_web_lg" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "# Loading Packages\n", "import spacy\n", "nlp = spacy.load('en')" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "# Similarity of object\n", "doc1 = nlp(\"wolf\")\n", "doc2 = nlp(\"dog\")" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.6759108958707175" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "doc1.similarity(doc2)" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "doc3 = nlp(\"cat\")" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.7344887997583573" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "doc3.similarity(doc2)" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [], "source": [ "# Synonmys\n", "doc4 = nlp(\"smart\")\n", "doc5 = nlp(\"clever\")" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.8051825859624082" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Similarity of words\n", "doc4.similarity(doc5)" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [], "source": [ "similarword = nlp(\"wolf dog cat bird fish\")" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "wolf\n", "dog\n", "cat\n", "bird\n", "fish\n" ] } ], "source": [ "for token in similarword:\n", " print(token.text)" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('wolf', 'wolf') similarity=> 1.0\n", "('wolf', 'dog') similarity=> 0.5234999\n", "('wolf', 'cat') similarity=> 0.30953428\n", "('wolf', 'bird') similarity=> 0.52796596\n", "('wolf', 'fish') similarity=> 0.051317338\n", "('dog', 'wolf') similarity=> 0.5234999\n", "('dog', 'dog') similarity=> 1.0\n", "('dog', 'cat') similarity=> 0.62507194\n", "('dog', 'bird') similarity=> 0.4794655\n", "('dog', 'fish') similarity=> 0.32915178\n", "('cat', 'wolf') similarity=> 0.30953428\n", "('cat', 'dog') similarity=> 0.62507194\n", "('cat', 'cat') similarity=> 1.0\n", "('cat', 'bird') similarity=> 0.4474155\n", "('cat', 'fish') similarity=> 0.447517\n", "('bird', 'wolf') similarity=> 0.52796596\n", "('bird', 'dog') similarity=> 0.4794655\n", "('bird', 'cat') similarity=> 0.4474155\n", "('bird', 'bird') similarity=> 1.0\n", "('bird', 'fish') similarity=> 0.35412988\n", "('fish', 'wolf') similarity=> 0.051317338\n", "('fish', 'dog') similarity=> 0.32915178\n", "('fish', 'cat') similarity=> 0.447517\n", "('fish', 'bird') similarity=> 0.35412988\n", "('fish', 'fish') similarity=> 1.0\n" ] } ], "source": [ "# Similarity Between Tokens\n", "for token1 in similarword:\n", " for token2 in similarword:\n", " print((token1.text,token2.text),\"similarity=>\",token1.similarity(token2))" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [], "source": [ "#[x for b in a for x in b] \n", "mylist = [(token1.text,token2.text,token1.similarity(token2)) for token2 in similarword for token1 in similarword]" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('wolf', 'wolf', 1.0),\n", " ('dog', 'wolf', 0.5234999),\n", " ('cat', 'wolf', 0.30953428),\n", " ('bird', 'wolf', 0.52796596),\n", " ('fish', 'wolf', 0.051317338),\n", " ('wolf', 'dog', 0.5234999),\n", " ('dog', 'dog', 1.0),\n", " ('cat', 'dog', 0.62507194),\n", " ('bird', 'dog', 0.4794655),\n", " ('fish', 'dog', 0.32915178),\n", " ('wolf', 'cat', 0.30953428),\n", " ('dog', 'cat', 0.62507194),\n", " ('cat', 'cat', 1.0),\n", " ('bird', 'cat', 0.4474155),\n", " ('fish', 'cat', 0.447517),\n", " ('wolf', 'bird', 0.52796596),\n", " ('dog', 'bird', 0.4794655),\n", " ('cat', 'bird', 0.4474155),\n", " ('bird', 'bird', 1.0),\n", " ('fish', 'bird', 0.35412988),\n", " ('wolf', 'fish', 0.051317338),\n", " ('dog', 'fish', 0.32915178),\n", " ('cat', 'fish', 0.447517),\n", " ('bird', 'fish', 0.35412988),\n", " ('fish', 'fish', 1.0)]" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mylist" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using DataFrames" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [], "source": [ "df = pd.DataFrame(mylist)" ] }, { "cell_type": "code", "execution_count": 74, "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", "
012
0wolfwolf1.000000
1dogwolf0.523500
2catwolf0.309534
3birdwolf0.527966
4fishwolf0.051317
\n", "
" ], "text/plain": [ " 0 1 2\n", "0 wolf wolf 1.000000\n", "1 dog wolf 0.523500\n", "2 cat wolf 0.309534\n", "3 bird wolf 0.527966\n", "4 fish wolf 0.051317" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
2
21.0
\n", "
" ], "text/plain": [ " 2\n", "2 1.0" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Correlation\n", "df.corr()" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [], "source": [ "df.columns = [\"Token1\",\"Token2\",\"Similarity\"]" ] }, { "cell_type": "code", "execution_count": 77, "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", "
Token1Token2Similarity
0wolfwolf1.000000
1dogwolf0.523500
2catwolf0.309534
3birdwolf0.527966
4fishwolf0.051317
\n", "
" ], "text/plain": [ " Token1 Token2 Similarity\n", "0 wolf wolf 1.000000\n", "1 dog wolf 0.523500\n", "2 cat wolf 0.309534\n", "3 bird wolf 0.527966\n", "4 fish wolf 0.051317" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Token1 object\n", "Token2 object\n", "Similarity float64\n", "dtype: object" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Types\n", "df.dtypes" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [], "source": [ "# Visualization Package with Seaborn\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [], "source": [ "# Encoding it\n", "df_viz = df.replace({'wolf':0,'dog':1,'cat':2,'fish':3,'bird':4})" ] }, { "cell_type": "code", "execution_count": 81, "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", "
Token1Token2Similarity
0001.000000
1100.523500
2200.309534
3400.527966
4300.051317
\n", "
" ], "text/plain": [ " Token1 Token2 Similarity\n", "0 0 0 1.000000\n", "1 1 0 0.523500\n", "2 2 0 0.309534\n", "3 4 0 0.527966\n", "4 3 0 0.051317" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_viz.head()" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Plotting with Correlation\n", "plt.figure(figsize=(20,10))\n", "sns.heatmap(df_viz.corr(),annot=True)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABAYAAAJDCAYAAACYHxY8AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzs3Xl4VOX5xvH7mSTsiBQI2VBAFBEVKIu02rKo4AZaRVyqiEWxxQVKK1g3FJUWfgqCdcMioCibouyb7CBbVFQ2QRYhGwFkkdVk5v39QRqNYRKqzJxJ5vu5rnN1zjnvzNyTqx4yT57zvuacEwAAAAAAiE4+rwMAAAAAAADvUBgAAAAAACCKURgAAAAAACCKURgAAAAAACCKURgAAAAAACCKURgAAAAAACCKURgAAAAAAKCEMLMYM/vMzKad5FxZMxtvZl+b2Uozq30qr0lhAAAAAACAkqOnpA1BznWTtM85V0/SEEkDT+UFKQwAAAAAAFACmFmKpGsl/SfIkOsljc57/J6ky83MintdCgMAAAAAAJQML0rqIykQ5HyypJ2S5JzLlXRAUrXiXjT2dKUL+gZlkl2o3wMAAKC06pL0G68jAECR3tz+XrF/kS7JcvZsDdt32jI1zrlPUvcfHRrunBsuSWZ2naRs59wnZtb6dL5vyAsDAAAAAACgeHlFgOFBTl8qqaOZXSOpnKQzzGyMc+6OH41Jl1RLUpqZxUqqImlvce/LrQQAAAAAAEQ459w/nHMpzrnakm6VNP8nRQFJmiLprrzHnfLGFNvxQMcAAAAAAADBBPxeJyiSmfWXlOqcmyJphKS3zexrSd/qRAGhWBQGAAAAAAAoQZxzCyUtzHv85I+OH5N08//6ehQGAAAAAAAIxgVbAKD0YI4BlBjt27XWurWLtXH9UvV5+H6v4wBAIVynAESyuwf10IupI9R/9mCvowCIMBQGUCL4fD4NG/qcrutwhy5q1Ea33HKDGjQ41+tYAJCP6xSASLfsvQUafNezXscASp5AIHybR4q9lcDMzpd0vaTkvEPpkqY45zaEMhjwYy2aN9GWLdu1bdsOSdKECZPVsUN7bdiw2eNkAHAC1ykAkW7Tqg2qllLD6xgAIlCRHQNm1lfSOEkmaVXeZpLGmtkjoY8HnJCUnKCdaRn5+2npmUpKSvAwEQAUxHUKAIDSyblA2DavFNcx0E1SQ+dczo8PmtlgSesk/StUwQAAAAAAQOgVVxgISEqS9M1PjifmnTspM+suqbskWUwV+XwVf0lGQBnpWaqVkpS/n5KcqIyMLA8TAUBBXKcAACilPLz3P1yKKwz0kjTPzDZL2pl37CxJ9SQ9EOxJzrnhkoZLUmyZZHcaciLKrU5do3r16qh27VpKT89S587X684uzPgNIHJwnQIAACVVkYUB59wsMztPUgsVnHxwtXPOH+pwwH/5/X717PW4Zkx/VzE+n0aNHq/16zd5HQsA8nGdAhDp7hvWS/VbNlSlqpX1/PLXNXnIeC2ZMN/rWEDk8/De/3Ax50L7B306BgAAAH6+Lkm/8ToCABTpze3vmdcZQun7nZ+H7TttmVqNPPlZFrkqAQAAAAAAKN2Km2MAAAAAAIDoFSj9d9HTMQAAAAAAQBSjYwAAAAAAgGCiYPJBOgYAAAAAAIhidAwAAAAAABBMoPR3DIS8MMASOwAi2VsZy72OAABFWnM8y+sIAIBSjo4BAAAAAACCcMwxAAAAAAAASjM6BgAAAAAACCYK5higYwAAAAAAgChGxwAAAAAAAMEwxwAAAAAAACjNKAygxLh7UA+9mDpC/WcP9joKAJxU+3attW7tYm1cv1R9Hr7f6zgAotBv21yiSUve1eSPx6nrA3cUOt+h89Wat3aqxs4dqbFzR+qG26+TJJ3XsJ5GTX1NExe+rfHzRqldx7bhjg5EroA/fJtHuJUAJcay9xZo3uiZumfwg15HAYBCfD6fhg19Tlddc5vS0jK1YvkMTZ02Rxs2bPY6GoAo4fP51HdAb/W45a/alZmtMTP/o0Vzlmrbpu0Fxs2ZPF8DHxtS4Nixo8f1xEPPaue2NFWvWU3vzB6hjxeu0qGDh8L4CQB4hY4BlBibVm3Q4QP84wQgMrVo3kRbtmzXtm07lJOTowkTJqtjh/ZexwIQRS5s0kBp29OUviNDuTm5mj35I7Vuf9kpPXfH1p3auS1NkrRn117t27NfVaudGcq4QMnhAuHbPPKzCwNmdvfpDAIAQEmWlJygnWkZ+ftp6ZlKSkrwMBGAaFMjoYay0rPz97Mzdys+oUahcW2vbaXx80Zp0BvPqGZSfKHzDRs3UFyZWKVtTw9pXgCR45d0DDx92lIAAAAACLnFc5fpuhY365bLu2rl4lT1H/pYgfPV46vpmZee0FO9/innnDchAYRdkXMMmNkXwU5JqlnE87pL6i5Jv/1VE9WvXPdnBwQAoCTISM9SrZSk/P2U5ERlZGR5mAhAtNmdtVsJyT90AMQn1lB21u4CYw7sO5j/+IN3puqhx/+Sv1+xUgUNHTNIL/9ruL78dF3oAwMlRYDlCmtK6iKpw0m2vcGe5Jwb7pxr5pxrRlEAABANVqeuUb16dVS7di3FxcWpc+frNXXaHK9jAYgi69ZsVK06tZRUK1GxcbFqf/0VWjR7WYEx1eOr5T9u1f4ybd/8jSQpNi5WL7w5QNMnztK86QvDGRtABChuVYJpkio559b89ISZLQxJIiCI+4b1Uv2WDVWpamU9v/x1TR4yXksmzPc6FgBIkvx+v3r2elwzpr+rGJ9Po0aP1/r1m7yOBSCK+P1+DXx0sF4eO1i+GJ+mjJuurZu26c8Pd9P6zzdq8ZxluvWeTmrV7jL5c/06sP+g+vV6TpLUrmNbNWnZWFWqVlGHztdIkvr1ek6b1n3t5UcCIoOHkwKGi4X63qE/1e7EzUkAItZbGcu9jgAARbq4Wh2vIwBAkT7NXGpeZwil42vnhu07bdkLr/TkZ1lcxwAAAAAAANGLOQYAAAAAAEBpRscAAAAAAABBOOf3OkLI0TEAAAAAAEAUo2MAAAAAAIBgomBVAjoGAAAAAACIYiHvGOiRmxvqtwCAn+0trwMAQDH2HD/gdQQAiG6sSgAAAAAAAEoz5hgAAAAAACAY5hgAAAAAAAClGR0DAAAAAAAEE/B7nSDk6BgAAAAAACCKURgAAAAAACCKURhAiRGXWF3nTXhGDee/pIbzhim+23VeRwKAAtq3a611axdr4/ql6vPw/V7HARCFWl1+qRasnKLFqdPVo2e3Qufv6Hqz5iydpJmLJur9GaN1bv26kqQzq1bRuMkjtGHHSvUf+Gi4YwORzQXCt3mEOQZQcvj9Sus/UkfWbpWvYjldMPMFHVy8Rsc2p3mdDADk8/k0bOhzuuqa25SWlqkVy2do6rQ52rBhs9fRAEQJn8+nZwc9pj/e2F2ZGVmaOm+c5s5aoM1fbc0f8+H7MzRm1ERJ0pVXtdYTzz6sLjf/RcePf68XBvxb9RvU03kNzvXqIwDwSLEdA2Z2vpldbmaVfnL8qtDFAgrLyd6nI2tP/MMWOHxMRzenqUxCNY9TAcAJLZo30ZYt27Vt2w7l5ORowoTJ6tihvdexAESRxk0v0vZtO7TjmzTl5ORq6qSZand1mwJjDn13OP9x+Qrl5dyJx0ePHNXqlZ/p2PHvwxkZKBkCgfBtHimyMGBmD0maLOlBSWvN7PofnR4QymBAUcqkxKvChXV16LNNXkcBAElSUnKCdqZl5O+npWcqKSnBw0QAok1CYrwy0rPy9zMzdqlmYs1C47p0u1VLPpmhR5/urX6P/DOcEQFEqOI6Bu6V1NQ5d4Ok1pKeMLOeeecslMGAYHwVyumc4X2186kRChw66nUcAACAEuWtEeP0u6bX6J9PDdFDf+vudRwg8kXBHAPFFQZ8zrlDkuSc264TxYGrzWywiigMmFl3M0s1s9RJh7efpqiAZLExOmd4X337wSLtn7nC6zgAkC8jPUu1UpLy91OSE5WRkVXEMwDg9MrKzFZS8g+dSolJNbUrc1fQ8VMmzVS7a9uGIxqACFdcYWCXmTX+705ekeA6SdUlXRTsSc654c65Zs65ZjdWrH1aggKSdPbzD+jY12na9cYUr6MAQAGrU9eoXr06ql27luLi4tS58/WaOm2O17EARJHPP12rOnXPVq2zkhUXF6sON16tubMWFhhTu+5Z+Y8vb/d7bd+yI8wpgRIoCuYYKG5Vgi6Scn98wDmXK6mLmb0eslTASVRq3kDVO7XRkQ3bdcHsIZKk9IFjdGD+Jx4nAwDJ7/erZ6/HNWP6u4rx+TRq9HitX888KADCx+/364k+A/T2e68pJiZG49/5QJs2blHvf9yvLz9bp7mzFqrrvbfpslYtlZOTqwP7D6r3/Y/lP3/ZmlmqXLmS4uLi1P7atrrjpu4FVjQAUHqZ++9UpCGSmnJDaN8AAH6BltmrvY4AAEVKqvQrryMAQJF2fPtlqZ5/7tiSt8P2nbbc7+705GdZ7HKFAAAAAACg9CruVgIAAAAAAKKWc36vI4QcHQMAAAAAAEQxOgYAAAAAAAjGw9UCwoWOAQAAAAAAohgdAwAAAAAABONKf8dAyAsDjdYMDvVbAMDPl/Q7rxMAQJGql63idQQAQCnHrQQAAAAAAEQxbiUAAAAAACAYJh8EAAAAAAClGR0DAAAAAAAEEwWTD9IxAAAAAABAFKMwgBLF7/erU9f71ePhfl5HAYBC2rdrrXVrF2vj+qXq8/D9XscBEIV+2+YSTVryriZ/PE5dH7ij0PkOna/WvLVTNXbuSI2dO1I33H6dJCkxpabemTNCY+eO1MSFb+umLteHOzoQuQKB8G0e4VYClChjJk5W3dpn6dDhI15HAYACfD6fhg19Tlddc5vS0jK1YvkMTZ02Rxs2bPY6GoAo4fP51HdAb/W45a/alZmtMTP/o0Vzlmrbpu0Fxs2ZPF8DHxtS4NjuXXvV9bo/K+f7HJWvUF4TF76lRbOXas+uvWH8BAC8QscASoys7N1a/PEq3dShvddRAKCQFs2baMuW7dq2bYdycnI0YcJkdeR6BSCMLmzSQGnb05S+I0O5ObmaPfkjtW5/2Sk9NzcnVznf50iSypSNk/n4mgDkc4HwbR4p9r94M2thZs3zHl9gZr3N7JrQRwMKGjj0dfXu0U1m/EMFIPIkJSdoZ1pG/n5aeqaSkhI8TAQg2tRIqKGs9Oz8/ezM3YpPqFFoXNtrW2n8vFEa9MYzqpkUn3+8ZlK8xs8bpRmfTNLof79DtwAQRYr8hmVm/SQNk/Sqmf1T0r8lVZT0iJk9FoZ8gCRp4bKV+lXVM9Xw/HO9jgIAAFBiLZ67TNe1uFm3XN5VKxenqv/QH36l35WRrVsu76rrf3OLrut8lX5VvapnOYGIEgVzDBT3p9dOki6V9HtJ90u6wTn3jKT2km4J9iQz625mqWaW+p+3xp62sIhen32xXguXrlC7m+7Sw/3+pVWffK6+Tw/yOhYA5MtIz1KtlKT8/ZTkRGVkZHmYCEC02Z21WwnJP3QAxCfWUHbW7gJjDuw7mH/LwAfvTNX5F9cv9Dp7du3Vlo3b1OSSRqENDCBiFFcYyHXO+Z1zRyRtcc4dlCTn3FFJQcsZzrnhzrlmzrlm93S57TTGRbT661/u1rwPx2jO+6P1f08/ohZNG2lgvz5exwKAfKtT16hevTqqXbuW4uLi1Lnz9Zo6bY7XsQBEkXVrNqpWnVpKqpWo2LhYtb/+Ci2avazAmOrx1fIft2p/mbZv/kbSiSJC2XJlJEmVq1RW4xYX65stO8IXHohkUdAxUNyqBN+bWYW8wkDT/x40syoqojAAAEC08fv96tnrcc2Y/q5ifD6NGj1e69dv8joWgCji9/s18NHBennsYPlifJoybrq2btqmPz/cTes/36jFc5bp1ns6qVW7y+TP9evA/oPq1+s5SVKdc89W734PyDnJTHr7tbH6euNWjz8RgHAx51zwk2ZlnXPHT3K8uqRE59yXxb1Bzp6twd8AADxWPul3XkcAgCJdXK2O1xEAoEifZi41rzOE0tFpg8P2nbb8db09+VkW2TFwsqJA3vE9kvaEJBEAAAAAAAib4m4lAAAAAAAgenl473+4sCA8AAAAAABRjMIAAAAAAABRjFsJAAAAAAAIxnErAQAAAAAAKMXoGAAAAAAAIJgomHww5IWBnBHPhPotAAAASq11+77xOgIAoJSjYwAAAAAAgGCYYwAAAAAAAJRmdAwAAAAAABBMFMwxQMcAAAAAAABRjI4BAAAAAACCoWMAiCAxsSp75xMqd/fTKtftWcVddoPXiQCggPbtWmvd2sXauH6p+jx8v9dxAESJdle21pdfLNT6dUv097/3KHS+TJkyGvP2K1q/bomWLJ6is89OkSSdfXaK9u/brFUrZ2nVyln690sD8p/z9NN99PXXK7V3z8awfQ4A3qFjACWHP1fHxw2Sco5LvhiV/eM/5Nv6hQIZW71OBgDy+XwaNvQ5XXXNbUpLy9SK5TM0ddocbdiw2etoAEoxn8+noUOf1TXX3q60tEx9vGyapk2bq40bf7j23N31Vu3fv18XNPydbr65o5579lHdceeJAsLWrd+oxSVXFXrd6dPn6tVXR2nd2sVh+yxAxHLO6wQh9z93DJjZW6EIApySnOMn/tcXI/PFSqX/v1EAJUSL5k20Zct2bdu2Qzk5OZowYbI6dmjvdSwApVzz5o0LXnsmTlGHDu0KjOnQoZ3eHvOeJGnSpOlq0+bSYl931arPlJWVHZLMACJPkR0DZjblp4cktTGzMyXJOdcxVMGAkzJTubueklWNV+6n8xXIpFsAQGRISk7QzrSM/P209Ey1aN7Ew0QAokFSUsFrT/pJrj1JSQlKyxvj9/t18OB3qlatqiSpdu1aWrlipg5+d0hPPfV/WrZsVfjCAyVFFMwxUNytBCmS1kv6j078bdYkNZP0QohzASfnnI6N6ieVLa+yf3hQVj1Zbk+616kAAABKnMzMbNU79xJ9++1+NWlykSZO/I+aNLlc3313yOtoAMKsuFsJmkn6RNJjkg445xZKOuqcW+ScWxTsSWbW3cxSzSz1zZVfnb60wH8dPyr/jo2KqXuR10kAQJKUkZ6lWilJ+fspyYnKyMjyMBGAaJCRUfDak5ycqPSfXHsyMrKUkjcmJiZGZ5xRWXv37tP333+vb7/dL0n67LMvtXXrNzr33LrhCw+UFIFA+DaPFFkYcM4FnHNDJN0t6TEz+7dOYcJC59xw51wz51yzP11S/zRFRdQrX1kqW/7E49g4xdRuqMDeTG8zAUCe1alrVK9eHdWuXUtxcXHq3Pl6TZ02x+tYAEq51NTPVa9e7R+uPTd31LRpcwuMmTZtru68o5Mk6cYbr9XChcskSdWr/0o+34mvA3XqnKV659TRtm07wvsBAESEU1qVwDmXJulmM7tW0sHQRgJOzipVUdlr75HMJ5kpd+NqBbZ87nUsAJB04r7dnr0e14zp7yrG59Oo0eO1fv0mr2MBKOX8fr969XpC06aOUUxMjEaNHq8NGzbpySf/pk8/+ULTps/VyFHjNPLNF7V+3RJ9++1+3dnlxHKql112ifo9+Tfl5OQqEAjowQf/oX37TnQQDHjuUd1yyw2qUKG8tny9SiNHjdWzzw7x8qMC3nGlf44BcyFeeuHIwLuZNx5AxDrjCf6iCyCyxfj+50WkACCsjh/baV5nCKWjYx4L23fa8nc858nPkn9pAAAAAACIYqd0KwEAAAAAAFEpCpYrpGMAAAAAAIAoRmEAAAAAAIBgnAvfVgwzK2dmq8zsczNbZ2ZPn2RMbzNbb2ZfmNk8Mzu7uNelMAAAAAAAQMlwXFJb51wjSY0lXWVmLX8y5jNJzZxzF0t6T9Kg4l6UOQYAAAAAAAgmguYYcCeWFTyUtxuXt7mfjFnwo90Vku4o7nVDXhhgKTAAkaxL0m+8jgAARVpzPMvrCACACGJmMZI+kVRP0svOuZVFDO8maWZxr0nHAAAAAAAAwYSxY8DMukvq/qNDw51zw388xjnnl9TYzM6U9IGZXeicW3uS17pDUjNJrYp7XwoDAAAAAABEgLwiwPBiB54Yu9/MFki6SlKBwoCZXSHpMUmtnHPHi3stJh8EAAAAACAYFwjfVgwzq5HXKSAzKy/pSkkbfzKmiaTXJXV0zmWfykekYwAAAAAAgJIhUdLovHkGfJImOOemmVl/SanOuSmS/k9SJUkTzUySdjjnOhb1ohQGAAAAAAAIwgVc8YPCxDn3haQmJzn+5I8eX/G/vi63EgAAAAAAEMUoDKDEaN+utdatXayN65eqz8P3ex0HAAq5e1APvZg6Qv1nD/Y6CoAo9ds2l2jSknc1+eNx6vpA4aXLO3S+WvPWTtXYuSM1du5I3XD7dZKk8xrW06ipr2niwrc1ft4otevYNtzRgcgVCIRv8wi3EqBE8Pl8Gjb0OV11zW1KS8vUiuUzNHXaHG3YsNnraACQb9l7CzRv9EzdM/hBr6MAiEI+n099B/RWj1v+ql2Z2Roz8z9aNGeptm3aXmDcnMnzNfCxIQWOHTt6XE889Kx2bktT9ZrV9M7sEfp44SodOngojJ8AgFf+p44BM7vMzHqbWbtQBQJOpkXzJtqyZbu2bduhnJwcTZgwWR07tPc6FgAUsGnVBh0+wC/RALxxYZMGStuepvQdGcrNydXsyR+pdfvLTum5O7bu1M5taZKkPbv2at+e/apa7cxQxgVKjghalSBUiiwMmNmqHz2+V9K/JVWW1M/MHglxNiBfUnKCdqZl5O+npWcqKSnBw0QAAACRpUZCDWWl/7AyWXbmbsUn1Cg0ru21rTR+3igNeuMZ1UyKL3S+YeMGiisTq7Tt6SHNCyByFNcxEPejx90lXemce1pSO0l/DFkqAAAAAKfd4rnLdF2Lm3XL5V21cnGq+g99rMD56vHV9MxLT+ipXv+Uc5EzEzuA0CquMOAzs6pmVk2SOed2S5Jz7rCk3GBPMrPuZpZqZqmBwOHTGBfRKiM9S7VSkvL3U5ITlZGR5WEiAACAyLI7a7cSkn/oAIhPrKHsrN0FxhzYd1A53+dIkj54Z6rOv7h+/rmKlSpo6JhBevlfw/Xlp+vCExooCQIufJtHiisMVJH0iaRUSb8ys0RJMrNKkizYk5xzw51zzZxzzXy+iqctLKLX6tQ1qlevjmrXrqW4uDh17ny9pk6b43UsAACAiLFuzUbVqlNLSbUSFRsXq/bXX6FFs5cVGFM9vlr+41btL9P2zd9IkmLjYvXCmwM0feIszZu+MJyxAUSAIlclcM7VDnIqIOkPpz0NEITf71fPXo9rxvR3FePzadTo8Vq/fpPXsQCggPuG9VL9lg1VqWplPb/8dU0eMl5LJsz3OhaAKOH3+zXw0cF6eexg+WJ8mjJuurZu2qY/P9xN6z/fqMVzlunWezqpVbvL5M/168D+g+rX6zlJUruObdWkZWNVqVpFHTpfI0nq1+s5bVr3tZcfCYgMHi4jGC4W6nuHYsskc3MSgIjVJek3XkcAgCKtOc6tcwAi26eZS4N2k5cGR17qEbbvtBUefMWTn2WRHQMAAAAAAES1KOgYKG6OAQAAAAAAUIrRMQAAAAAAQDBRsHQnHQMAAAAAAEQxOgYAAAAAAAiGOQYAAAAAAEBpFvKOAZYCAwAA+Pkal03wOgIARLcAcwwAAAAAAIBSjDkGAAAAAAAIxjHHAAAAAAAAKMXoGAAAAAAAIBjmGAAAAAAAAKUZhQEAAAAAAKIYtxKgxLh7UA81attUB/ce0JPte3sdBwAK4ToFIJJxjQJ+Hhdg8kEgYix7b4EG3/Ws1zEAICiuUwAiGdcoAMEUWRgws0vM7Iy8x+XN7Gkzm2pmA82sSngiAidsWrVBhw8c8joGAATFdQpAJOMaBfxMARe+zSPFdQy8KelI3uOhkqpIGph3bGQIcwEAAAAAgDAobo4Bn3MuN+9xM+fcr/MeLzWzNSHMBQAAAACA9xxzDKw1s7vzHn9uZs0kyczOk5QT7Elm1t3MUs0s9avvtp6mqAAAAAAA4HQrrjBwj6RWZrZF0gWSlpvZVklv5J07KefccOdcM+dcs/qV656+tAAAAAAAhFMUzDFQ5K0EzrkDkrrmTUBYJ298mnNuVzjCAT9237Beqt+yoSpVraznl7+uyUPGa8mE+V7HAoB8XKcARDKuUQCCMedCW5X4U+1O3pU9AAAAAAAh9eb298zrDKF0+KnbwvadtuJTYz35WRZ3KwEAAAAAACjFiluVAAAAAACA6OXhvf/hQscAAAAAAABRjI4BAAAAAACCcQGvE4QcHQMAAAAAAEQxOgYAAAAAAAgmCuYYCHlhoEdubqjfAgB+tldiqY8CiGybc/Z5HQEAUMpxKwEAAAAAAFGMP5UBAAAAABCECzD5IAAAAAAAKMXoGAAAAAAAIJgomHyQjgEAAAAAAKIYHQMoMeISq6vO0J6Kq36m5Jx2vztH2SOmeR0LAPLdPaiHGrVtqoN7D+jJ9r29jgMgCrVo3Vw9+98vn8+naWNn6J2XxxUa06ZDK/2p911yzunr9VvU/4EBqpkcrwEj+st8ptjYWL0/8gNNfpvfswBJUdExQGEAJYffr7T+I3Vk7Vb5KpbTBTNf0MHFa3Rsc5rXyQBAkrTsvQWaN3qm7hn8oNdRAEQhn8+n3s89pL/e1ke7M3frjRmvaNmc5dq++Zv8MSl1knXHA7fpLzc8pEMHDunMamdKkvZmf6s/d3xQOd/nqHyFcho9f4SWzlmuvbv2evVxAIQRtxKgxMjJ3qcja7dKkgKHj+no5jSVSajmcSoA+MGmVRt0+MAhr2MAiFINmpyv9O3pytyRqdycXM2bvECXtf9tgTEdbr9WH4yaokN516r9e/dLknJzcpXzfY4kKa5sGfl8Ft7wQCRzgfBtHimyMGBmD5lZrXCFAU5VmZR4Vbiwrg59tsnrKAAAABGhRkJ1ZWfszt/fnblb1ROqFxhTq26KatVN0SsfDtVrU19Si9bN88/FJ9XQqLlv6P3VY/XOy+PpFgCiSHEdA89IWmlmS8ysh5nVCEcooCi+CuV0zvC+2vnUCAUOHfU6DgAAQIkRExtzVVy+AAAgAElEQVSjlDrJerBTbz3d4zn1+b/eqnRGRUlSdsZudb3yXt16aRdddXM7Va1e1eO0QIQIuPBtHimuMLBVUopOFAiaSlpvZrPM7C4zqxzsSWbW3cxSzSx10uHtpy8top7Fxuic4X317QeLtH/mCq/jAAAARIzdWXsUn/TD3/FqJNbQnqw9BcZkZ+7Wsjkfy5/rV+bOLKVtTVNKnZQCY/bu2qttX21To0suCktuAN4rrjDgnHMB59wc51w3SUmSXpF0lU4UDYI9abhzrplzrtmNFWufvrSIemc//4COfZ2mXW9M8ToKAABARNm4ZqNS6iQrsVaCYuNidfn1bbR0zscFxiyZtUyNf9tYklSl6hlKqZuijB2ZqpFYXWXKlZEkVapSSRe3uEg7tuwM+2cAIpELuLBtXiluVYICs44453IkTZE0xcwqhCwVcBKVmjdQ9U5tdGTDdl0we4gkKX3gGB2Y/4nHyQDghPuG9VL9lg1VqWplPb/8dU0eMl5LJsz3OhaAKOH3BzTk8Zf0wrsD5fP5NH38TG3f9I26/b2rNn7+lZbNXa5VC1erRatmenvBm/L7/Xr1meE6uO+gmv2uqR548s9ycjKZxr42QVs3bvP6IwEIE3MueFXCzM5zzv2i2d1SU24o/Ys+AiixXoll1VYAkW1zzj6vIwBAkZakzyvVy1h899B1YftOW3nYNE9+lkXeSvBLiwIAAAAAACCy8acyAAAAAACCCQS8ThByxU0+CAAAAAAASjEKAwAAAAAARDFuJQAAAAAAIBgPlxEMFzoGAAAAAACIYnQMAAAAAAAQTBR0DIS8MNBozeBQvwUA/HzN+nidAACKdMB/xOsIAIBSjo4BAAAAAACCcK70dwwwxwAAAAAAAFGMjgEAAAAAAIKJgjkG6BgAAAAAACCK0TEAAAAAAEAwdAwAkcXv96tT1/vV4+F+XkcBgELuHtRDL6aOUP/ZrMgDwBuXtmmpKUvHadryifrTA3cGHXfFta31RdZyXdDofElSbGyMnh32hN5fMEYfLh6rbg92CVdkABGAwgBKlDETJ6tu7bO8jgEAJ7XsvQUafNezXscAEKV8Pp8e/eff9Jfbe+uG39+mq/9wpeqeV7vQuAoVK+iP93TWF5+szT/WrsPliisTp5va3KFb23dVpy43KKlWQhjTA5HLBVzYNq8UWRgwszJm1sXMrsjbv93M/m1m95tZXHgiAidkZe/W4o9X6aYO7b2OAgAntWnVBh0+cMjrGACi1IVNLtCObWlK35Gh3JxczfrwI7Vp//tC4x7o211vvjxGx49/n3/MOacKFcorJiZGZcuVVc73OTr03ZFwxgfgoeI6BkZKulZSTzN7W9LNklZKai7pPyHOBhQwcOjr6t2jm8xodAEAAPipmok1tCsjO39/V2a24hNrFBjT4KLzlJAUryUffVzg+Nxp83XkyFHN+2Kq5nzyoUa/+q4O7j8YltxAxAu48G0eKW7ywYuccxebWaykdElJzjm/mY2R9Hno4wEnLFy2Ur+qeqYann+uVn36hddxAAAAShwz09+f7qknej5T6NyFTRoq4A/oikYddMaZZ2jUh69qxeLVSt+R4UFSAOFW3J9efWZWRlJlSRUkVck7XlZS0FsJzKy7maWaWep/3hp7epIiqn32xXotXLpC7W66Sw/3+5dWffK5+j49yOtYAAAAEWNX5m7VTIrP36+ZGK/szN35+xUrVVC9+nU1YtIrmrl6ki7+dUMNGz1IFzQ6X9fc2E7LFqxQbq5f3+7Zp89Wf6mGjRt48TGAyBMI4+aR4joGRkjaKClG0mOSJprZVkktJY0L9iTn3HBJwyUpZ8/W0r+2A0Lur3+5W3/9y92SpFWffqFRY9/XwH59PE4FAAAQOdat2aCz69ZS8lmJ2pW5W1fdcIUe6fHDSk6HvjusVg2vzt8fMellvfD0S1r/+UZd8rtmanFZU017b5bKVyini5s21JjhQX/dB1DKFFkYcM4NMbPxeY8zzOwtSVdIesM5tyocAQEAKCnuG9ZL9Vs2VKWqlfX88tc1ech4LZkw3+tYAKKE3+/XgEdf0KtjX1RMjE8fjp2mLV9tU48+92r9mg1aOGdp0OeOe/N9PTP0cU1a9I7MTJPHTdfmDVvCmB6Al8y50P5Bn44BAJHsvmZ0ngCIbKnH0r2OAABF+iJruXmdIZT2/7Ft2L7TnvnOfE9+lkzvDgAAAABAFCtujgEAAAAAAKKXh8sIhgsdAwAAAAAARDE6BgAAAAAACMbDZQTDhY4BAAAAAACiGB0DAAAAAAAE4aJgjoGQFwZyRjwT6rcAAAAotb7LOeJ1BABAKUfHAAAAAAAAwTDHAAAAAAAAKM3oGAAAAAAAIIhomGOAjgEAAAAAAKIYHQMAAAAAAATDHAMAAAAAAKA0o2MAJUdMrMre/g9ZbKzki5H/q1TlLP3Q61QAkO/uQT3UqG1THdx7QE+27+11HABR6Pdtf6t+/+wrn8+n8WM+0GtD3yxw/vauN+vObrco4Pfr8OGjerR3f3391VY1+vWFGjD4CUmSmenFQa9pzvT5XnwEIOK4KOgYMOdCO5HCkYF3l/6ZGhA+cWWlnOOSL0Zl//gP5cx7V4GMrV6nQgn2wKvfeR0Bpch5LRro2OFjumfwgxQGcNos+G6z1xFQQvh8Ps1fNUV33nSfsjJ2afJH7+qh7o/o669++F2pUuWKOvTdYUnSFVe10h1/ukVdO/dQufLllPN9jvx+v2rUrK4ZiyaqZcMr5Pf7vfo4KEG27f3cvM4QSns7tArbd9pqUxd58rMstmPAzOpKulFSLUl+SZskveucOxjibEBhOcdP/K8vRuaLlSg7AYggm1ZtULWUGl7HABClGv36Qn2zbad2fpMuSZr6wSxdeXXrAoWB/xYFJKl8hfL67x8Jjx09ln+8bNmyUoj/eAggshRZGDCzhyRdJ2mxpOaSPtOJAsEKM+vhnFsY8oTAj5mp3F1PyarGK/fT+Qpk0i0AAAAgSQmJ8cpMz8rfz8rIVuOmFxUad2e3W9TtL3cqrkyc/njDvfnHGze9SAOHPa3klET17vEY3QLAf0XBrQTFTT54r6SrnXPPSrpCUkPn3GOSrpI0JNThgEKc07FR/XT0ld7yJdaRVU/2OhEAAECJ8vaI8Wrd7DoNfPpFPfC3HwoDaz75Uu0vvVHXX3m7evTqpjJly3iYEkA4ncqqBP/tKigrqZIkOed2SIoL9gQz625mqWaW+ubKr355SuCnjh+Vf8dGxdQtXAUHAACIRlmZ2UpMTsjfT0iKV1bmrqDjp06apSuvaVPo+JZN23T48BHVb1AvJDmBksYFwrd5pbjCwH8krTazNyQtl/SyJJlZDUnfBnuSc264c66Zc67Zny6pf9rCIsqVryyVLX/icWycYmo3VGBvpreZAAAAIsQXn61T7bpnKeWsZMXFxarDH67SRzMXFRhTu+5Z+Y/btvu9tm/dIUlKOStZMTExkqTklESdc25tpe3ICF94AJ4qco4B59xQM/tIUgNJLzjnNuYd3y3p92HIB+SzSlVU9tp7JPNJZsrduFqBLZ97HQsA8t03rJfqt2yoSlUr6/nlr2vykPFaMoHlvgCEh9/vV7++/9RbE1+VL8anie9+qM1fbdFfH+mhL9es00ezFqnLPbfq0lYtlZuTowP7v9Pfe5xYorB5yyb6c88/KTcnR4GA0xMPD9C+b/d7/ImACBEFcwywXCGAqMZyhQAiHcsVAoh0pX25wj3tw7dcYfXZEbpcIQAAAAAA0crLe//D5VQmHwQAAAAAAKUUHQMAAAAAAARBxwAAAAAAAIgIZlbLzBaY2XozW2dmPYsY29zMcs2sU3GvS8cAAAAAAABBRFjHQK6kvznnPjWzypI+MbO5zrn1Px5kZjGSBkqacyovSscAAAAAAAAlgHMu0zn3ad7j7yRtkJR8kqEPSnpfUvapvG7IOwbOeOKUChQA4IkV8c29jgAARfoowv5UBQBRx0XmaoxmVltSE0krf3I8WdIfJLWRdEq/7NIxAAAAAABABDCz7maW+qOte5BxlXSiI6CXc+7gT06/KKmvc6deWWaOAQAAAAAAgghn45Zzbrik4UWNMbM4nSgKvOOcm3SSIc0kjTMzSaou6Rozy3XOfRjsNSkMAAAAAABQAtiJb/sjJG1wzg0+2RjnXJ0fjR8laVpRRQGJwgAAAAAAACXFpZLulPSlma3JO/aopLMkyTn32s95UQoDAAAAAAAE4QKRM/mgc26ppFMO5JzreirjmHwQAAAAAIAoRmEAJUb7dq21bu1ibVy/VH0evt/rOABQQFxidZ034Rk1nP+SGs4bpvhu13kdCUAUanX5pVqwcooWp05Xj57dCp2/o+vNmrN0kmYumqj3Z4zWufXrSpLOrFpF4yaP0IYdK9V/4KPhjg1ENBcI3+YVbiVAieDz+TRs6HO66prblJaWqRXLZ2jqtDnasGGz19EA4AS/X2n9R+rI2q3yVSynC2a+oIOL1+jY5jSvkwGIEj6fT88Oekx/vLG7MjOyNHXeOM2dtUCbv9qaP+bD92dozKiJkqQrr2qtJ559WF1u/ouOH/9eLwz4t+o3qKfzGpzr1UcA4BE6BlAitGjeRFu2bNe2bTuUk5OjCRMmq2OH9l7HAoB8Odn7dGTtiV++A4eP6ejmNJVJqOZxKgDRpHHTi7R92w7t+CZNOTm5mjppptpd3abAmEPfHc5/XL5CeTl34vHRI0e1euVnOnb8+3BGBkoE5yxsm1foGECJkJScoJ1pGfn7aemZatG8iYeJACC4MinxqnBhXR36bJPXUQBEkYTEeGWkZ+XvZ2bsUuOmFxca16Xbrbq3RxfFlYnTrdcXvt0AQPQpsmPAzKqY2b/MbKOZfWtme81sQ96xM8MVEgCAksJXoZzOGd5XO58aocCho17HAYBC3hoxTr9reo3++dQQPfS37l7HASJeNMwxUNytBBMk7ZPU2jn3K+dcNUlt8o5NCPYkM+tuZqlmlhoIHA42DDhlGelZqpWSlL+fkpyojIysIp4BAOFnsTE6Z3hfffvBIu2fucLrOACiTFZmtpKSE/L3E5NqalfmrqDjp0yaqXbXtg1HNAARrrjCQG3n3EDnXP43MOdclnNuoKSzgz3JOTfcOdfMOdfM56t4urIiiq1OXaN69eqodu1aiouLU+fO12vqtDlexwKAAs5+/gEd+zpNu96Y4nUUAFHo80/Xqk7ds1XrrGTFxcWqw41Xa+6shQXG1K57Vv7jy9v9Xtu37AhzSqDkcQEL2+aV4uYY+MbM+kga7ZzbJUlmVlNSV0k7Q5wNyOf3+9Wz1+OaMf1dxfh8GjV6vNav595dAJGjUvMGqt6pjY5s2K4LZg+RJKUPHKMD8z/xOBmAaOH3+/VEnwF6+73XFBMTo/HvfKBNG7eo9z/u15efrdPcWQvV9d7bdFmrlsrJydWB/QfV+/7H8p+/bM0sVa5cSXFxcWp/bVvdcVP3AisaACi9zP13KtKTnTSrKukRSddLis87vEvSFEn/cs7tK+4NYsskB38DAPDYivjmXkcAgCLdeGSL1xEAoEg7vv3Suz91h8GOZpeH7TvtWanzPPlZFtkxkPfFv2/eVoCZ3S1pZIhyAQAAAACAMPglyxU+LQoDAAAAAIBSzMt7/8OlyMKAmX0R7JSkmqc/DgAAAAAACKfiOgZqSmqvE8sT/phJ+jgkiQAAAAAAiBBR3zEgaZqkSs65NT89YWYLQ5IIAAAAAACETXGTD3Yr4tztpz8OAAAAAAAIp18y+eAp6ZL0m1C/BQD8fLm5XicAgCKdXT6++EEAgJBxYVus0Ds+rwMAAAAAAADvhLxjAAAAAACAkioaJh+kYwAAAAAAgChGxwAAAAAAAEE4R8cAAAAAAAAoxegYQIlx96AeatS2qQ7uPaAn2/f2Og4AFBCXWF11hvZUXPUzJee0+905yh4xzetYAKJMi9bN1bP//fL5fJo2dobeeXlcoTFtOrTSn3rfJeecvl6/Rf0fGKCayfEaMKK/zGeKjY3V+yM/0OS3uYYBkuQCXicIPQoDKDGWvbdA80bP1D2DH/Q6CgAU5vcrrf9IHVm7Vb6K5XTBzBd0cPEaHduc5nUyAFHC5/Op93MP6a+39dHuzN16Y8YrWjZnubZv/iZ/TEqdZN3xwG36yw0P6dCBQzqz2pmSpL3Z3+rPHR9Uzvc5Kl+hnEbPH6Glc5Zr7669Xn0cAGHErQQoMTat2qDDBw55HQMATione5+OrN0qSQocPqajm9NUJqGax6kARJMGTc5X+vZ0Ze7IVG5OruZNXqDL2v+2wJgOt1+rD0ZN0aG836n2790vScrNyVXO9zmSpLiyZeTzlf57qoFTFXAWts0rdAwAAHCalUmJV4UL6+rQZ5u8jgIgitRIqK7sjN35+7szd6tBkwYFxtSqmyJJeuXDofLF+PTmC29p1cLVkqT4pBoaNHqAkusk6ZVnhtMtAEQRCgMAAJxGvgrldM7wvtr51AgFDh31Og4AFBATG6OUOsl6sFNvxSfW0EuThqjr5ffo0MHDys7Yra5X3qtqNatpwIj+Wjh9sfbt2ed1ZMBzrEpQBDObWcS57maWamapX3239ee+BQAAJYrFxuic4X317QeLtH/mCq/jAIgyu7P2KD6pRv5+jcQa2pO1p8CY7MzdWjbnY/lz/crcmaW0rWlKqZNSYMzeXXu17attanTJRWHJDcB7RRYGzOzXQbamkhoHe55zbrhzrplzrln9ynVPe2gAACLR2c8/oGNfp2nXG1O8jgIgCm1cs1EpdZKVWCtBsXGxuvz6Nlo65+MCY5bMWqbGvz3xa3yVqmcopW6KMnZkqkZidZUpV0aSVKlKJV3c4iLt2LIz7J8BiEQuYGHbvFLcrQSrJS2SdLKEZ57+OEBw9w3rpfotG6pS1cp6fvnrmjxkvJZMmO91LACQJFVq3kDVO7XRkQ3bdcHsIZKk9IFjdGD+Jx4nAxAt/P6Ahjz+kl54d6B8Pp+mj5+p7Zu+Ube/d9XGz7/SsrnLtWrharVo1UxvL3hTfr9frz4zXAf3HVSz3zXVA0/+WU5OJtPY1yZo68ZtXn8kAGFizrngJ83WSvqDc27zSc7tdM7VKu4N/lS7U/A3AACP9cjN9ToCABTpr+47ryMAQJGWpM8r1Tfhbzj3mrB9p22weYYnP8vi5hh4qogxLCYPAAAAAEAJV+StBM6594o4XfU0ZwEAAAAAAGH2S5YrfFrSyNMVBAAAAACASOPlpIDhUmRhwMy+CHZKUs3THwcAAAAAAIRTcR0DNSW1l7TvJ8dN0seFhwMAAAAAUHoEXJR3DEiaJqmSc27NT0+Y2cKQJAIAAAAAAGFT3OSD3Yo4d/vpjwMAAAAAQORwdAz8cqwRDgAA8POdG8dCUACA0Ap5YQAAAAAAgJLKOa8ThJ7P6wAAAAAAAMA7dAwAAAAAABBENKxKQMcAAAAAAABRjI4BAAAAAACCYFUCIILEJVZXnaE9FVf9TMk57X53jrJHTPM6FgBI4hoFIPLdPaiHGrVtqoN7D+jJ9r29jgMgglAYQMnh9yut/0gdWbtVvorldMHMF3Rw8Rod25zmdTIA4BoFIOIte2+B5o2eqXsGP+h1FKBEYVUCIILkZO/TkbVbJUmBw8d0dHOayiRU8zgVAJzANQpApNu0aoMOHzjkdQwAEYiOAZRIZVLiVeHCujr02SavowBAIVyjAAAoPViVAIhAvgrldM7wvtr51AgFDh31Og4AFMA1CgAAlDRFFgbM7Awz+6eZvW1mt//k3CtFPK+7maWaWeqkw9tPU1RAstgYnTO8r779YJH2z1zhdRwAKIBrFAAApY9zFrbNK8V1DIyUZJLel3Srmb1vZmXzzrUM9iTn3HDnXDPnXLMbK9Y+PUkBSWc//4COfZ2mXW9M8ToKABTCNQoAAJRExRUGznHOPeKc+9A511HSp5LmmxmzKSHsKjVvoOqd2qjypRfpgtlDdMHsIarStqnXsQBAEtcoAJHvvmG99NikAUqom6Tnl7+u33Vu63UkABGiuMkHy5qZzzkXkCTn3HNmli5psaRKIU8H/Mih1RuUmnKD1zEA4KS4RgGIdK8/9KLXEYASickHpamSCpQSnXOjJP1N0vchygQAAAAAAMKkyI4B51yfIMdnmdmA0EQCAAAAACAyOK8DhMEvWa7w6dOWAgAAAAAAeKLIjgEz+yLYKUk1T38cAAAAAAAiRzTMMVDc5IM1JbWXtO8nx03SxyFJBAAAAAAAwqa4wsA0SZWcc2t+esLMFoYkEQAAAAAAEcJFe8eAc65bEeduP5U3aLRm8P+aCQDC5vPGvb2OAABFWnl0p9cRAAClXHEdAwAAAAAARK2A1wHC4JesSgAAAAAAAEo4OgYAAAAAAAjCqfTPMUDHAAAAAAAAUYyOAQAAAAAAggg4rxOEHh0DAAAAAABEMQoDKFH8fr86db1fPR7u53UUACggLrG6zpvwjBrOf0kN5w1TfLfrvI4EIApd1qalpi2boJkr3tM9D3YJOu7Ka9to3a6VatjofElSUq1EfbJ9kd6f97ben/e2nhzUN1yRgYgXkIVt8wq3EqBEGTNxsurWPkuHDh/xOgoAFOT3K63/SB1Zu1W+iuV0wcwXdHDxGh3bnOZ1MgBRwufz6bF/Pax7Oz+oXRnZGj97lBbMXqItm7YVGFehYgXdce8t+vyTtQWO7/wmXTddfmc4IwOIEHQMoMTIyt6txR+v0k0d2nsdBQAKycnepyNrt0qSAoeP6ejmNJVJqOZxKgDR5KJfX6Cd29KU9k2GcnJyNePDuWpz1e8LjXvokfs04t9v6/ix4x6kBBCJKAygxBg49HX17tFNZvzfFkBkK5MSrwoX1tWhzzZ5HQVAFKmZEK/MjF35+7syslUzoUaBMQ0uqq+EpJpa/NGyQs9PPitJ7330lkZ98Kp+fUnjkOcFSgonC9vmlSK/YZlZgpm9amYvm1k1M3vKzL40swlmlhiukMDCZSv1q6pnquH553odBQCK5KtQTucM76udT41Q4NBRr+MAQD4zU5+ne2rQU0MLndu9a4+u+HVHdbqiiwb9P3t3Hh5Vef5//HNPgmGziiKBsEXUrwhaUHBpaxVcwH2pft1FEcWCUJWvoNZaBJefUKqFWq3UBZUKbghIVXBDEJVNFtmVPSQEUBbDZjJz//5IGtkyo5KZM5N5v7jmypzzPGfmc3JdHjPP3Od5+g7WwKf6q1btWgGkBBCEWF+9DpO0QNJqSR9J2i7pPEmTJf2zooPMrKuZzTCzGc+8OKKSoiKdzZq7QBM/+VwdLrtBvfs+qmkz5+jufgODjgUAu7HMDB0x9G59++bH2vTO50HHAZBmCteuU4Oc7PLt7Jx6Kly7vny7Vu2aOqr5ERo26klNmP6mWrU5Vk+8OEgtWzVX8ffF2rxxiyRpwdxFWr0iT7lHNE74OQDJKJLAR1BiTT6Y7e5/lyQz6+7uA8r2/93MulR0kLsPlTRUkoo3LEuDVR8Rb3d266w7u3WWJE37Yq6GjXhDA/r2CTgVAOyu6aAe2vF1ngr/NTboKADS0LxZC9WkWWM1bNJA6wrW67xLzlbvbveXtxd9t1WntvhhrqbnRz2pQf2GaP6cRapz6MHavHGLIpGIGjXNUdNmjZW3Mj+I0wAQgFgDA7tWFLy4R1tGJWcBACBl1T7xGNW9vL22LVyhFuMflyStGTBcmz+cGXAyAOkiHA7r4XsHaejIIQplhPTmiLe0dPFy9ejTVfPnLNRH4ydXeGzbU45Xjz5dVVJSokgkov59Bmjzpi0JTA8kryDv/U8Uc6/4C30z6y9poLsX7bH/SEmPuvvlsd6AigEAyWxO615BRwCAqG4oLgg6AgBENb9wapX+5Dwh+6qEfabtUDgykN9l1IoBd/9zBfu/NrP/xCcSAAAAAADJIch7/xNlf9Z961dpKQAAAAAAQCCiVgyY2dyKmiRlV9AGAAAAAECVkA4VAzFXJZDUUdLGPfabpE/jkggAAAAAACRMrIGBcZJqu/vsPRvMbGJcEgEAAAAAkCTSYVWCWJMPdonSdk3lxwEAAAAAAIkUq2JgvxU/+2C83wIAAAAAgLiIVP2Cgf1alQAAAAAAAKS4uFcMAAAAAACQqiJpMMcAFQMAAAAAAKQxBgYAAAAAAEhj3EoAAAAAAEAFPOgACcDAAFJHRqayrrlXlpkphTIUXjxDxZ+MDjoVAEiSqjWoq8MH365qdQ+W3LX+5Qla9+y4oGMBSDOntj9F9zzUSxkZIb3x77F65u8v7rPf2ee319+ee1RXdLhB8+csUk7jBnpr8kitWLpKkjRn5jz17zMgkdEBBIiBAaSOcIl2jhwoFe+UQhnKuvZehZbNVSR/WdDJAEAKh5XX/3ltm7dMoVrV1eKdv2rLpNna8VVe0MkApIlQKKT7Hu2tW67oqcL8dXpl/DB9NH6yli5Zvlu/mrVq6rpbrtScmfN227965Rpddub1iYwMpIRI0AESgDkGkFqKd5b+DGXIQpnpUdcDICUUr9uobfNKByojW3do+1d5OqD+oQGnApBOjjuhhVYvz1PeynwVF5fo7dHvqf05p+3V7w/33Kpnn3hJO3fsDCAlgGTEwABSi5mq39hPNXoOVnjFfEUKqBYAkHwOaFRPNY9tpqJZS4KOAiCNZNevp4L8wvLtwvx1yq5/2G59jjnuaNXPydak96fsdXzDJjl6/f0XNezNp3TCya3jnhdIFRGzhD2C8pNvJTCzeu6+Lh5hgJjctWNYXymrhrIu7Smr21C+YU3QqQCgXKhmdR0x9G6tfuBZRYq2Bx0HAMqZmfr0u1333f7gXm3rCzforBMu0uaNW9Til801ZNhAXXza1dpatDWApAASLWrFgJkdssfjUEnTzKyOmR0S5biuZjbDzGY8N3VxpYcGtHO7wqsWKaPZcUEnAYBylpmhI4berWZBaPcAACAASURBVG/f/Fib3vk86DgA0kzh2nVqkJNdvp2dU0+Fa9eXb9eqXVNHNT9Cw0Y9qQnT31SrNsfqiRcHqWWr5ir+vlibN26RJC2Yu0irV+Qp94jGCT8HIBl5Ah9BiVUxsEHSyj32NZT0hUpzN9vXQe4+VNJQSdo2oDN3gaNy1DhQipRIO7dLmdWUkdtSxVPfDjoVAJRrOqiHdnydp8J/jQ06CoA0NG/WQjVp1lgNmzTQuoL1Ou+Ss9W72/3l7UXfbdWpLTqWbz8/6kkN6jdE8+csUp1DD9bmjVsUiUTUqGmOmjZrrLyV+UGcBoAAxBoY6C3pbEm93f1LSTKz5e5+eNyTAXuw2gcp6/ybJQtJZipZNF2RpXOCjgUAkqTaJx6jupe317aFK9Ri/OOSpDUDhmvzhzMDTgYgXYTDYT187yANHTlEoYyQ3hzxlpYuXq4efbpq/pyF+mj85AqPbXvK8erRp6tKSkoUiUTUv88Abd60JYHpgeSVDqsSmHv0L/TNrJGkxyWtltRX0hx332elwL5QMQAgmS34+8agIwBAVDcUFwQdAQCiml84NbhZ8xLglQbXJuwz7ZUF/w7kdxlz8kF3z5P0v2Z2kaT3JNWMeyoAAAAAAJJApEoPe5T60csVuvtYSe0lnSVJZtY5XqEAAAAAAEBi/OiBAUly9+3uPq9ss18c8gAAAAAAkDQisoQ9ghL1VgIzm1tRk6TsCtoAAAAAAEAlM7PnJF0gaZ27H1tBn3aS/iapmqQN7n56rNeNNcdAtqSOkvacncskfRrrxQEAAAAASGVJNpv+MElPSHpxX41mdrCkJyWd4+6rzKzej3nRWAMD4yTVdvfZ+3jDiT/mDQAAAAAAwP5z90lmlhulyzWSRrn7qrL+637M60YdGHD3LlHarvkxbwAAAAAAABLifyRVK/si/0BJg919n9UFu4q5XOH++sX9E+L9FgDws23Pnxx0BACIKuu4TkFHAIC0lsjlCs2sq6Suu+wa6u5Df8JLZEpqI+lMSTUkfWZmn7v7klgHAQAAAACAgJUNAvyUgYA95Un6xt23StpqZpMktZIUdWDgJy1XCAAAAABAOokk8FEJxkg61cwyzaympJMlLYx1EBUDAAAAAACkADMbIamdpLpmliepr0qXJZS7/9PdF5rZu5LmqnSs4Rl3nxfrdRkYAAAAAACgAsm0XKG7X/0j+vxF0l9+yutyKwEAAAAAAGmMgQGkjI4d2mn+vElatOAT9el9W9BxAGCfwuGwLr/xNnXv3TfoKADS0K/bn6xRk1/WmE9H6sYe1+3VfuEV5+qDeW9pxHvPa8R7z+uSay6QJDVolK1/T3hWI957Xq9NfEmXdbo40dGBpBWxxD2Cwq0ESAmhUEhDBj+sc867Wnl5Bfr8s7f11rgJWrjwq6CjAcBuhr82Rs1ym6ho67agowBIM6FQSHc/0kvdr7xThQXrNPydZ/TxhE+0fMmK3fpNGPOhBtz3+G771hd+oxsv+L2Kvy9WjZo19NrEF/Xx+E+0ofCbBJ4BgKBQMYCUcNKJx2vp0hVavnyViouL9eqrY3TRhR2DjgUAu1m7br0mfTpNl3F9AhCAY48/Rnkr8rRmVb5Kiks0fsz7atfx1B91bElxiYq/L5YkHZBVTRbiYwLwXym2KsHPwn/xSAk5DetrdV5++XbemgLl5NQPMBEA7G3A4KfVq3sXmfG/VwCJd1j9w7R2zbry7XUF61Wv/mF79Tvj/NP1ygfDNPBfDyo7p175/uycenrlg2F6e+YovfDEv6kWANIIf7kAAFAJJk6ZqkPqHKyWzY8KOgoAVGjSe1N0wUn/qyvPvFFTJ81Q/8H3lbcV5q/TlWfeqIt/daUuuOIcHVK3TmA5gWSS9hUDZnbOLs8PMrNnzWyumb1sZtlRjutqZjPMbEYksrUy8yJN5a9Zq8aNcsq3GzVsoPz8tQEmAoDdzZq7QBM/+VwdLrtBvfs+qmkz5+jufgODjgUgjaxfu171G/5QAVCvwWFat3b9bn02b9xSfsvAm/9+S81/efRer7Oh8BstXbRcx5/cKr6BASSNWBUDj+zy/K+SCiRdKGm6pKcrOsjdh7p7W3dvGwrV2v+USHvTZ8zWkUcertzcxqpWrZquuOJivTVuQtCxAKDcnd0664PRwzXhjRf0l3736KQ2rTSgb5+gYwFII/NnL1Ljwxsrp3EDZVbLVMeLz9LH46fs1qduvUPLn5/e8VSt+GqlpNJBhKzqB0iSDjzoQLU+6ZdauXRV4sIDScwtcY+g/JRVCdq6e+uy54+b2Q3xCATsSzgc1u13/Elv/+dlZYRCGvbCK1qwYEnQsQAAAJJGOBzWgD8+pn+MeEyhjJDGjvyPli1Zrt/37qIFcxZp0oQpuurmy3V6h1MVLglr86Yt6nvHw5Kkw49qql59e8hdMpNe+ucIfb1oWcBnBCBRzN0rbjTLk/SYJJN0m6QjvOwAM5vr7r+M9QaZBzSs+A0AIGDb8ycHHQEAojr5uE5BRwCAqL4o+CTA77rj78nG1yXsM2331cMD+V3GupXgX5IOlFRb0guS6kqSmdWXNDu+0QAAAAAAQLxFvZXA3ftVsH+tmX0Un0gAAAAAACBR9me5wn0OGgAAAAAAUFWkw3KFUSsGzGxuRU2SKlyuEAAAAAAApIZYqxJkS+ooaeMe+03Sp3FJBAAAAABAkkiH2fRjDQyMk1Tb3feaaNDMJsYlEQAAAAAASJhYkw92idJ2TeXHAQAAAAAgeUSq9GKMpWJVDOy3Tjm/ivdbAAAAVFklHg46AgCgiov7wAAAAAAAAKkqyNUCEmV/lisEAAAAAAApjooBAAAAAAAqQMUAAAAAAACo0qgYAAAAAACgAh50gASgYgApo/PA7vrbjGfVf/xjQUcBgAqFw2FdfuNt6t67b9BRAKSh37Q/RWM/Galxn72mm3pcX2G/s85vp7lrP1OLVs0lSZmZGXpoyP1646PhGj1phLr07JSoyACSAAMDSBlTXv9Ij93wUNAxACCq4a+NUbPcJkHHAJCGQqGQ/vj//k/drumlS067Wudeeraa/U/uXv1q1qqpa2++QnNnzivf1+HCM1XtgGq6rP11uqrjjbq80yXKaVw/gemB5BWxxD2CwsAAUsaSaQu1dXNR0DEAoEJr163XpE+n6bILOwYdBUAaOvb4Flq1PE9rVuWrpLhE745+X+07nrZXvx53d9Vz/xiunTu/L9/n7qpZs4YyMjKUVT1Lxd8Xq+i7bYmMDyBADAwAAFBJBgx+Wr26d5EZ/3sFkHjZDQ5TYf668u3CgnWq1+Cw3focc9z/qH5OPU1+/9Pd9r837kNt27ZdH8x9SxNmjtYLT72sLZu2JCQ3kOwiCXwE5Sf/5WJmh8YjCAAAqWzilKk6pM7Batn8qKCjAMA+mZnu6ne7BvUbslfbsce3VCQc0VmtLtS5J12mG35/tRo2yQkgJYAgRB0YMLNHzaxu2fO2ZrZM0lQzW2lmp0c5rquZzTCzGYu/W1bJkQEASD6z5i7QxE8+V4fLblDvvo9q2sw5urvfwKBjAUgjhQXrlZ1Tr3w7u0E9rStYX75dq3ZNHXl0Mz076km9M32UfnlCSw15YaBatGqu837XQVM++lwlJWF9u2GjZk3/Ui1bHxPEaQAIQKyKgfPdfUPZ879IutLdj5R0tqS/VnSQuw9197bu3vboA5tVUlQAAJLXnd0664PRwzXhjRf0l3736KQ2rTSgb5+gYwFII/NnL1TTZo3VsEkDZVbL1DmXnKWJEyaXtxd9t1WntzxX5574O5174u8094v5+sMNfbRgziIVrFmrk05tI0mqUbO6ftmmpZZ/tSKgMwGSiyfwEZRYAwOZZpZZ9ryGu0+XJHdfIikrrsmAPdw65A7dN+oR1W+Wo0GfPa3fXnFG0JEAAACSRjgc1iN//KueGvE3jZk8QhPGfqCli5ere59b1K7DqVGPHfncG6pZq6ZGffxvvfzucxoz8j/6auHSBCUHEDRzr3hcwsx6SrpQ0qOSTpNUR9IoSWdIaubuFS+OWuam3MuDHPgAgKienkGpN4Dk1ubYa4OOAABRzV37WYAL7cXfw02vTdhn2vtW/juQ32VmtEZ3/7uZfSmpm6T/Ket/lKTRkh6MfzwAAAAAABBPUQcGJMndJ0qauOd+M+ss6fnKjwQAAAAAQHIIchnBRNmfhZb7VVoKAAAAAAAQiKgVA2Y2t6ImSdmVHwcAAAAAgOSRDpPmxbqVIFtSR0kb99hvkj6NSyIAAAAAAJAwsQYGxkmq7e6z92wws4lxSQQAAAAAQJJIhzkGYq1K0CVK2zU/5g26l5T81EwAAAAoE/Z0+JMUABCkmKsSAAAAAACQriIWdIL4259VCQAAAAAAQIqjYgAAAAAAgApE0mBdAioGAAAAAABIY1QMAAAAAABQgapfL0DFAAAAAAAAaY2BAaSMag3q6n9efVAtP/y7Wn4wRPW6XBB0JADYSzgc1uU33qbuvfsGHQVAGjq1/SkaN+VVvfP567q5Z6cK+519fnvNL5yqlq2aS5JyGjfQzBUf640PXtIbH7ykPw+8O1GRASQBbiVA6giHldf/eW2bt0yhWtXV4p2/asuk2drxVV7QyQCg3PDXxqhZbhMVbd0WdBQAaSYUCum+R3vrlit6qjB/nV4ZP0wfjZ+spUuW79avZq2auu6WKzVn5rzd9q9euUaXnXl9IiMDKSESdIAEoGIAKaN43UZtm7dMkhTZukPbv8rTAfUPDTgVAPxg7br1mvTpNF12YcegowBIQ8ed0EKrl+cpb2W+iotL9Pbo99T+nNP26veHe27Vs0+8pJ07dgaQEkAyYmAAKemARvVU89hmKpq1JOgoAFBuwOCn1at7F5nxv1cAiZddv54K8gvLtwvz1ym7/mG79TnmuKNVPydbk96fstfxDZvk6PX3X9SwN5/SCSe3jnteIFVE5Al7BCXqrQRm9oWkUZJGuPvSxEQCogvVrK4jht6t1Q88q0jR9qDjAIAkaeKUqTqkzsFq2fwoTftibtBxAGAvZqY+/W7Xfbc/uFfb+sINOuuEi7R54xa1+GVzDRk2UBefdrW2Fm0NICmARIv1lUYdSQdL+sjMppnZnWaWE+tFzayrmc0wsxmjtq6ojJyAJMkyM3TE0Lv17Zsfa9M7nwcdBwDKzZq7QBM/+VwdLrtBvfs+qmkz5+jufgODjgUgjRSuXacGOdnl29k59VS4dn35dq3aNXVU8yM0bNSTmjD9TbVqc6yeeHGQWrZqruLvi7V54xZJ0oK5i7R6RZ5yj2ic8HMAkpEn8BGUWJMPbnT3uyTdZWa/lXS1pC/MbKFKqwiG7uugsv1DJWlGo0vSYdlHJEjTQT204+s8Ff5rbNBRAGA3d3brrDu7dZYkTftiroaNeEMD+vYJOBWAdDJv1kI1adZYDZs00LqC9TrvkrPVu9v95e1F323VqS1+mAPl+VFPalC/IZo/Z5HqHHqwNm/cokgkokZNc9S0WWPlrcwP4jQABOBHr0rg7pMlTTaznpLOlnSlyj78A4lQ+8RjVPfy9tq2cIVajH9ckrRmwHBt/nBmwMkAAACCFw6H9fC9gzR05BCFMkJ6c8RbWrp4uXr06ar5cxbqo/GTKzy27SnHq0efriopKVEkElH/PgO0edOWBKYHklc6rEpg7hV/oW9mI939qv15AyoGACSzVrMfCzoCAETVuuXVQUcAgKjmF061oDPE0125VyfsM+2gFSMC+V1GnWMg2qCAmXWu/DgAAAAAACSPdFiVYH/WU+pXaSkAAAAAAEAgYi1XWNF6SyYpu4I2AAAAAACqhHS4Nz7W5IPZkjpK2rjHfpP0aVwSAQAAAACAhIk1MDBOUm13n71ng5lNjEsiAAAAAACSRDqsShB1YMDdu0Rpu6by4wAAAAAAgESKVTGw31gKDAAA4Oc7uUbjoCMAQFrzNJhlYH9WJQAAAAAAACmOgQEAAAAAANJY3G8lAAAAAAAgVaXD5INUDAAAAAAAkMaoGAAAAAAAoAIRJh8Ekks4HNblN96m7r37Bh0FAPaJ6xSAZNV5YHf9bcaz6j+eVcMA7I6BAaSU4a+NUbPcJkHHAIAKcZ0CkKymvP6RHrvhoaBjACnHE/gICgMDSBlr163XpE+n6bILOwYdBQD2iesUgGS2ZNpCbd1cFHQMAEmIOQaQMgYMflq9unfR1m3bg44CAPvEdQoAgKqHOQaAJDFxylQdUudgtWx+VNBRAGCfuE4BAIBUFXVgwMzamtlHZjbczBqb2XtmttnMppvZ8VGO62pmM8xsxjMvjqj81Eg7s+Yu0MRPPleHy25Q776PatrMObq738CgYwFAOa5TAABUTZEEPoIS61aCJyX1lXSwpE8l3enuZ5vZmWVtv9rXQe4+VNJQSSresKzq110g7u7s1ll3dussSZr2xVwNG/GGBvTtE3AqAPgB1ykAAJCqYt1KUM3d33H3EZLc3V9X6ZMPJFWPezoAAAAAleLWIXfovlGPqH6zHA367Gn99oozgo4EpARP4L+gxKoY2GFmHSQdJMnN7BJ3H21mp0sKxz8esLeTTvilTjrhl0HHAIAKcZ0CkIye/sPfgo4AIEnFGhj4vaSBKr3doaOkbmY2TNIaSbfENxoAAAAAAMEK8t7/RIl6K4G7z3H3ju5+rrsvcvfb3f1gd28p6egEZQQAAAAAAHGyP8sV9qu0FAAAAAAAJKG0n2PAzOZW1CQpu/LjAAAAAACARIo1x0C2SucW2LjHflPp8oUAAAAAACCFxRoYGCeptrvP3rPBzCbGJREAAAAAAEkiHSYfjDow4O5dorRdU/lxAAAAAABAIsWqGNhvxc8+GO+3AICfrVqX+4OOAABRTSxaGnQEAEhrEQ9uUsBE2Z9VCQAAAAAAQIqLe8UAAAAAAACpqurXC1AxAAAAAABAWqNiAAAAAACACkTSoGaAigEAAAAAANIYFQNIHRmZyrrmXllmphTKUHjxDBV/MjroVACwm3A4rCu7/EH1DqurJ//SL+g4ANLMaWf8Wn9+pLdCoZBeHT5a/xzy/G7t19x4ua6/6QqFwxFt27pNf+z1kL5eskwNGzfQe5+O0rKvV0qSZs/8Un+66+EgTgFIOp4GFQMMDCB1hEu0c+RAqXinFMpQ1rX3KrRsriL5y4JOBgDlhr82Rs1ym6ho67agowBIM6FQSP0G3KNOl3fT2vxCjX7v33r/3Y/19ZIf/lYa+/o7ennY65KkM885Xfc92Eudr+whSVq5Ik8XtL8qkOwAgsWtBEgtxTtLf4YyZKHM9JgiFEDKWLtuvSZ9Ok2XXdgx6CgA0lCrE47VyuWrtXrlGhUXl2jcm+N19rntdutTVLS1/HnNmjWUBsuzA/stksBHUKgYQGoxU/UbHpDVqaeSLz5UpIBqAQDJY8Dgp9Wrexdt3bY96CgA0lD9BvVUkF9Yvl2QX6jWbY7dq9/1N12hm7pdp2oHVNN1l95avr9xk4Z668MRKiraqsce+Yemfz4rIbkBBI+KAaQWd+0Y1lfbn+ylUIPDZXUbBp0IACRJE6dM1SF1DlbL5kcFHQUAonrpuVfV/sSLNLD/YN3W62ZJ0vrCDTq19bm68Iyr9fD9f9XjTz+i2rVrBZwUSA4RecIeQYk6MGBmtc2sv5nNN7PNZrbezD43sxtjHNfVzGaY2Yznpi6u1MCAJGnndoVXLVJGs+OCTgIAkqRZcxdo4iefq8NlN6h330c1beYc3d1vYNCxAKSRtQXr1CAnu3y7QU62CgvWV9j/rVHj1eG8dpKk778v1qaNmyVJ8+Ys1KoVeTr8yKZxzQsgecSqGPi3pGWSOkrqJ2mIpOsltTezRyo6yN2Huntbd29708lHV1pYpLkaB0pZNUqfZ1ZTRm5LRb4pCDYTAJS5s1tnfTB6uCa88YL+0u8endSmlQb07RN0LABpZO6s+cpt1kSNmuSoWrVMXXBpR73/7sTd+uQ2a1L+vH2H32rFstWSpEMOraNQqPSjQeOmDZXbrIlWrchLWHYgmXkC/wUl1hwDue4+rOz5Y2Y23d0fNLPOkhZI+mNc0wG7sNoHKev8myULSWYqWTRdkaVzgo4FAACQFMLhsB64Z4BeeO1JhUIhvfbyGH21eJnuuKebvpy9QB+8+7Gu73KlfnP6ySopLtHmzVt01233S5JO+tUJuuOebiopLlHEI/rTXQ9r86YtAZ8RgEQxjzIVqZl9KqmPu39iZhdJus3dO5a1LXb3mOUA2wZ0Zq5TAEmrWpf7g44AAFEd3fyyoCMAQFTLNsyyoDPE0+VNL0rYZ9rXV44N5HcZq2Lg95KeMbOjJM2XdJMkmdlhkv4R52wAAAAAAAQqyGUEEyXqwIC7z5V00j72rzez7+KWCgAAAAAAJMT+LFfYr9JSAAAAAACQhNw9YY+gRK0YMLO5FTVJyq6gDQAAAAAAxIGZnSNpsKQMSc+4+6N7tDeR9IKkg8v63OPub0d7zVhzDGSrdKnCjXtmkfTpj48OAAAAAEDqiQS4jOCezCxDpfP9nS0pT9J0Mxvr7gt26fYnSa+6+1Nm1kLS25Jyo71urIGBcZJqu/vsfQSa+OPjAwAAAACA/XSSpK/dfZkkmdlISRdL2nVgwCX9ouz5QZLyY71orMkHu0RpuybWiwMAAAAAkMqSbFWChpJW77KdJ+nkPfo8IGmCmfWUVEvSWbFeNFbFwH77xf0T4v0WAPCzbQk6AADEsKZoQ9ARAAAJYmZdJXXdZddQdx/6E1/maknD3P2vZvYrSS+Z2bHuXuEYR9wHBgAAAAAASFWewDkGygYBog0ErJHUeJftRmX7dtVF0jllr/eZmVWXVFfSuopedH+WKwQAAAAAAIkzXdJRZna4mR0g6SpJY/fos0rSmZJkZsdIqi5pfbQXpWIAAAAAAIAKJNOqBO5eYmY9JI1X6VKEz7n7fDPrL2mGu4+V9H+S/mVmd6p0IsIb3T3qSTAwAAAAAABAinD3t1W6BOGu+/68y/MFkn7zU16TgQEAAAAAACoQ48v2KoE5BpAyOnZop/nzJmnRgk/Up/dtQccBgN1lZCrr+vtVvXM/Ve/ykKqdeknQiQCkiQ5nt9OXcydqwfzJuuuu7nu1H3DAARr+0pNaMH+yJk8aq6ZNG0mSmjZtpE0bv9K0qe9q2tR39cTfHyk/pl+/Pvr666n6ZsOihJ0HgOBQMYCUEAqFNGTwwzrnvKuVl1egzz97W2+Nm6CFC78KOhoAlAqXaOfIgVLxTimUoaxr71Vo2VxF8pcFnQxAFRYKhTR48EM67/xrlJdXoE+njNO4ce9p0aIf/kbqfONV2rRpk1q0/K3+938v0sMP/VHXXV86gLBs2UqddPI5e73uf/7znp56apjmz5uUsHMBklWFa/xVIVQMICWcdOLxWrp0hZYvX6Xi4mK9+uoYXXRhx6BjAcDuineW/gxlyEKZSqK5igBUUSee2Hr3v5FeG6sLL+ywW58LL+ygl4a/LkkaNeo/at8+9q3H06bN0tq1Fa5sBqCKYWAAKSGnYX2tzssv385bU6CcnPoBJgKAfTBT9Rv7qUbPwQqvmK9IAdUCAOIrJ2f3v5HWrClQwz3+RsrJqa+8sj7hcFhbtnynQw+tI0nKzW2sqZ+/o/fee02/+c1JiQsOpBBP4L+gRL2VwMwOknSvpEsk1VPpdx/rJI2R9Ki7b4p7QgAAUoW7dgzrK2XVUNalPWV1G8o3rAk6FQDsU0HBOh151Mn69ttNOv744/Taa8/o+OPP1HffFQUdDUCCxaoYeFXSRknt3P0Qdz9UUvuyfa9WdJCZdTWzGWY2IxLZWnlpkbby16xV40Y55duNGjZQfv7aABMBQBQ7tyu8apEymh0XdBIAVVx+/u5/IzVs2EBr9vgbKT9/rRqV9cnIyNAvfnGgvvlmo77//nt9+23p93yzZn2pZctW6qijmiUuPICkEWtgINfdB7h7+dXF3de6+wBJTSs6yN2Huntbd28bCtWqrKxIY9NnzNaRRx6u3NzGqlatmq644mK9NW5C0LEA4Ac1DpSyapQ+z6ymjNyWinxTEGwmAFXejBlzdOSRuT/8jfS/F2ncuPd26zNu3Hu6/rrLJUm/+935mjhxiiSpbt1DFAqVfhw4/PAmOvKIw7V8+arEngCQAiLyhD2CEmtVgpVm1kfSC+5eKElmli3pRkmr45wNKBcOh3X7HX/S2/95WRmhkIa98IoWLFgSdCwAKGe1D1LW+TdLFpLMVLJouiJL5wQdC0AVFw6Hdccd92vcW8OVkZGhYS+8ooULl+jPf/4/fTFzrsb95z09P2yknn/ub1owf7K+/XaTru9UuuzzqaeerL5//j8VF5coEomoZ897tXFjaQXBIw//UVdeeYlq1qyhpV9P0/PDRuihhx4P8lQBxJG5VzwqYWZ1JN0j6WJJ2SqdY6BQ0lhJA9z921hvkHlAQ+ZkBpC0tjzYIXYnAAhQnb7vBx0BAKLauWO1BZ0hns5s1CFhn2k/yJsQyO8yasWAu280s+clvSfpc3cvn4nEzM6R9G6c8wEAAAAAgDiKOseAmf1BpSsQ9JA0z8wu3qX5kXgGAwAAAAAgaMwxIN0iqY27F5lZrqTXzSzX3QdLqtLlIgAAAAAApINYAwOh/94+4O4rzKydSgcHmoqBAQAAAABAFecBfpOfKLGWKyw0s9b/3SgbJLhAUl1JLM4MAAAAAECKi1Ux0ElSya473L1EUiczezpuqQAAAAAASAKRKCv5VRWxViXIi9I25ce8QaecX/3UTAAAACiTU+uQoCMAAKq4WBUDAAAAAACkrapfLxB7jgEAAAAAAFCFUTEAAAAAAEAFImlQM0DFAAAAAAAAaYyKAQAAAAAAKkDFAAAAAAAAqNKoGEDK6Dywu1qd0UZbvtmsP3fsFXQcANhdRqayrrlXlpkphTIUXjxDxZ+MDjoVgDRz2hm/Vt//d7dCoZBeimUOlgAAF1lJREFUGf6m/jn4ud3ar7nxf3V9lysVCYe1det2/bFXf329eJlanXCsHnnsfkmSmelvA/+pCf/5MIhTABAABgaQMqa8/pE+eOEd3fxYz6CjAMDewiXaOXKgVLxTCmUo69p7FVo2V5H8ZUEnA5AmQqGQ+g/8o66/7FatzS/UmPdf1vvvTtTXi3+4Do194229POw1SdJZ55yuPz14l268orsWL/xaF515jcLhsA7Lrqu3P35NH7z7scLhcFCnAyQNd24lAJLGkmkLtXVzUdAxAKBixTtLf4YyZKHM9Fj4GEDSaHXCsVq5fLVWr1yj4uISvfXmuzr73Ha79Sn6bmv58xo1a5R/4NmxfUf5IEBWVpaUBh+EAPzgZ1cMmNk77n5uZYYBACClman6DQ/I6tRTyRcfKlJAtQCAxKnfoJ4K1qwt316bv06t2xy3V7/ru1ypLt2uV7UDqunaS24p39+6zXEaMKSfGjZqoF7d76NaACiT9pMPmtkJFTzaSGqdoIwAAKQGd+0Y1lfbn+ylUIPDZXUbBp0IAPby0rOvqF3bCzSg39/U4/9+GBiYPfNLdfzN73Tx2deo+x1ddEDWAQGmBJBIsSoGpkv6WJLto+3gig4ys66SukrSrw85Xkcf2OxnBwQAIOXs3K7wqkXKaHacSjasCToNgDSxtmCdGjSsX75dP6ee1hYUVtj/rVHv6sFB9+21f+mS5dq6dZuOPuZIfTl7QVyyAqnE071iQNJCSbe6e/s9H5I2VHSQuw9197bu3pZBAQBAWqhxoJRVo/R5ZjVl5LZU5JuCYDMBSCtzZ81XbrMmatSkoapVy9SFl56j99/5eLc+uc2alD8/o8NpWrFslSSpUZOGysjIkCQ1bNRARxyVq7xV+YkLDyBQsSoGHlDFgwdMDY+EunXIHTr6lJaqXedADfrsaY15/BVNfpVldAAkB6t9kLLOv1mykGSmkkXTFVk6J+hYANJIOBxW37v/n1587SmFMkJ67eXR+mrxUt15T3d9OXu+3n/3Y3W6+Sr95vRTVFJcrM2bvtNd3UuXKDzxlOP1+9tvUklxsSIR1/29H9HGbzcFfEZAckiHVQks1kmaWXNJDSVNdfeiXfaf4+7vxnqDm3Ivr/q/RQAp64luBwYdAQCiajnwi6AjAEBUy7+Zs69bz6uMtg1+m7DPtDMKJgfyu4w1+eAfJI1RaXXAPDO7eJfmR+IZDAAAAACAoEXkCXsEJdatBLdIauPuRWaWK+l1M8t198Ha94SEAAAAAAAghcQaGAj99/YBd19hZu1UOjjQVAwMAAAAAACquHSYYyDWqgSFZtb6vxtlgwQXSKor6bh4BgMAAAAAAPEXq2Kgk6SSXXe4e4mkTmb2dNxSAQAAAACQBIK89z9Rog4MuHtelLYplR8HAAAAAAAkUqyKgf3WvaQkdicAAADsU83M6kFHAIC05mlQMRBrjgEAAAAAAFCFMTAAAAAAAEAai/utBAAAAAAApKoIyxUCAAAAAICqjIoBAAAAAAAqkA6TDzIwgJRRrUFdHT74dlWre7DkrvUvT9C6Z8cFHQsASmVkKuuae2WZmVIoQ+HFM1T8yeigUwFIM6e2P0X3PNRLGRkhvfHvsXrm7y/us9/Z57fX3557VFd0uEHz5yxSTuMGemvySK1YukqSNGfmPPXvMyCR0QEEiIEBpI5wWHn9n9e2ecsUqlVdLd75q7ZMmq0dX+UFnQwApHCJdo4cKBXvlEIZyrr2XoWWzVUkf1nQyQCkiVAopPse7a1bruipwvx1emX8MH00frKWLlm+W7+atWrquluu1JyZ83bbv3rlGl125vWJjAykBOYYAJJI8bqN2jav9A/syNYd2v5Vng6of2jAqQBgF8U7S3+GMmShTKVB5SGAJHLcCS20enme8lbmq7i4RG+Pfk/tzzltr35/uOdWPfvES9q5Y2cAKQEkIwYGkJIOaFRPNY9tpqJZS4KOAgA/MFP1G/upRs/BCq+Yr0gB1QIAEie7fj0V5BeWbxfmr1N2/cN263PMcUerfk62Jr0/Za/jGzbJ0evvv6hhbz6lE05uHfe8QKrwBP4LStRbCczsF5LuldRI0jvu/vIubU+6e/c45wP2EqpZXUcMvVurH3hWkaLtQccBgB+4a8ewvlJWDWVd2lNWt6F8w5qgUwGAJMnM1Kff7brv9gf3altfuEFnnXCRNm/coha/bK4hwwbq4tOu1tairQEkBZBosSoGnpdkkt6QdJWZvWFmWWVtp1R0kJl1NbMZZjZj1NYVlZMUkGSZGTpi6N369s2Ptemdz4OOAwD7tnO7wqsWKaPZcUEnAZBGCteuU4Oc7PLt7Jx6Kly7vny7Vu2aOqr5ERo26klNmP6mWrU5Vk+8OEgtWzVX8ffF2rxxiyRpwdxFWr0iT7lHNE74OQDJKOKesEdQYg0MHOHu97j7aHe/SNIXkj40s6g3drv7UHdv6+5tf1crt7KyAmo6qId2fJ2nwn+NDToKAOyuxoFSVo3S55nVlJHbUpFvCoLNBCCtzJu1UE2aNVbDJg1UrVqmzrvkbH00flJ5e9F3W3Vqi47qcOKl6nDipZozc556dLpL8+csUp1DD1YoVPrRoFHTHDVt1lh5K/ODOhUACRZrVYIsMwu5e0SS3P1hM1sjaZKk2nFPB+yi9onHqO7l7bVt4Qq1GP+4JGnNgOHa/OHMgJMBgGS1D1LW+TdLFpLMVLJouiJL5wQdC0AaCYfDevjeQRo6cohCGSG9OeItLV28XD36dNX8OQv10fjJFR7b9pTj1aNPV5WUlCgSiah/nwHavGlLAtMDySvIe/8TxTxKuYKZDZQ0wd3f32P/OZL+7u5HxXqDGY0uqfq/RQApq0XPOkFHAICoTnxsQdARACCq+YVTLegM8XTUYW0S9pn2q/UzA/ldRq0YcPc+ZtbczM6UNNXdi8r2v2tmf0hIQgAAAAAAAhLkvf+JEnWOATPrKWmMpJ6S5pnZxbs0PxzPYAAAAAAAIP5izTHQVVIbdy8ys1xJr5tZrrsPVulqBQAAAAAAVFnpMMdArIGB0C63D6wws3YqHRxoKgYGAAAAAABIebGWKyw0s9b/3SgbJLhAUl1JLM4MAAAAAECKi1Ux0ElSya473L1EUiczezpuqQAAAAAASALukaAjxF2sVQnyorRNqfw4AAAAAAAgkWJVDOy3VrMfi/dbAMDPVvzsg0FHAICotoe/DzoCAKS1SBpMPhhrjgEAAAAAAFCFxb1iAAAAAACAVOVOxQAAAAAAAKjCqBgAAAAAAKACzDEAAAAAAACqNCoGkFLC4bCu7PIH1Tusrp78S7+g4wDADzIylXXNvbLMTCmUofDiGSr+ZHTQqQCkmdPO+LX+/EhvhUIhvTp8tP455Pnd2q+58XJdf9MVCocj2rZ1m/7Y6yF9vWSZGjZuoPc+HaVlX6+UJM2e+aX+dNfDQZwCkHTSYY4BBgaQUoa/NkbNcpuoaOu2oKMAwO7CJdo5cqBUvFMKZSjr2nsVWjZXkfxlQScDkCZCoZD6DbhHnS7vprX5hRr93r/1/rsf6+slP1yHxr7+jl4e9rok6cxzTtd9D/ZS5yt7SJJWrsjTBe2vCiQ7gGBxKwFSxtp16zXp02m67MKOQUcBgH0r3ln6M5QhC2UqDW5JBJBEWp1wrFYuX63VK9eouLhE494cr7PPbbdbn6KireXPa9asoTT4IhTYbxH3hD2CQsUAUsaAwU+rV/cu2rpte9BRAGDfzFT9hgdkdeqp5IsPFSmgWgBA4tRvUE8F+YXl2wX5hWrd5ti9+l1/0xW6qdt1qnZANV136a3l+xs3aai3PhyhoqKteuyRf2j657MSkhtA8KJWDJhZfTN7ysz+YWaHmtkDZvalmb1qZg0SFRKYOGWqDqlzsFo2PyroKABQMXftGNZX25/spVCDw2V1GwadCAD28tJzr6r9iRdpYP/Buq3XzZKk9YUbdGrrc3XhGVfr4fv/qseffkS1a9cKOCmQHDyB/4IS61aCYZIWSFot6SNJ2yWdJ2mypH9WdJCZdTWzGWY245kXR1RSVKSzWXMXaOInn6vDZTeod99HNW3mHN3db2DQsQBg33ZuV3jVImU0Oy7oJADSyNqCdWqQk12+3SAnW4UF6yvs/9ao8epwXjtJ0vffF2vTxs2SpHlzFmrVijwdfmTTuOYFkDxi3UqQ7e5/lyQz6+7uA8r2/93MulR0kLsPlTRUkoo3LOPOJey3O7t11p3dOkuSpn0xV8NGvKEBffsEnAoAdlHjQClSIu3cLmVWU0ZuSxVPfTvoVADSyNxZ85XbrIkaNclRYcE6XXBpR91x67279clt1kQrlq2SJLXv8FutWLZaknTIoXW0aeNmRSIRNW7aULnNmmjViryEnwOQjFiVYPeKghf3aMuo5CwAAKQsq32Qss6/WbKQZKaSRdMVWTon6FgA0kg4HNYD9wzQC689qVAopNdeHqOvFi/THfd005ezF+iDdz/W9V2u1G9OP1klxSXavHmL7rrtfknSSb86QXfc000lxSWKeER/uuthbd60JeAzApAoFm30w8z6Sxro7kV77D9S0qPufnmsN6BiAEAyK372waAjAEBUx/5ldtARACCqZRtmWdAZ4in7oOYJ+0xbuHlRIL/LqBUD7v5nM2tuZg0lTf3vAIG7f21mzyQkIQAAAAAAAYmkwfrDsVYl6ClpjKSekuaZ2cW7ND8Sz2AAAAAAACD+Ys0x0FVSG3cvMrNcSa+bWa67D5ZUpctFAAAAAABg8kEptMvtAyvMrJ1KBweaioEBAAAAAABSXtRbCSQVmlnr/26UDRJcIKmuJBZnBgAAAABUaRH3hD2CEmtgoJOktbvucPcSd+8k6bS4pQIAAAAAAAkRa1WCvChtUyo/DgAAAAAAyYM5BioBa4QDAAD8fO1qHxF0BABAFRf3gQEAAAAAAFJVRFW/YiDWHAMAAAAAAKAKo2IAAAAAAIAKpMMcA1QMAAAAAACQxqgYAAAAAACgApE0qBhgYACpIyNTWdfcK8vMlEIZCi+eoeJPRgedCgBKcY0CkOQ6D+yuVme00ZZvNuvPHXsFHQdAEmFgAKkjXKKdIwdKxTulUIayrr1XoWVzFclfFnQyAOAaBSDpTXn9I33wwju6+bGeQUcBUoqzKgGQZIp3lv4MZchCmUqD/0YBpBKuUQCS2JJpC7V1c1HQMQAkoZ9cMWBm9dx9XTzCADGZqfoND8jq1FPJFx8qUsA3cQCSCNcoAACQgqIODJjZIXvukjTNzI6XZO7+bdySAfvirh3D+kpZNZR1aU9Z3YbyDWuCTgUApbhGAQBQ5aTD5IOxbiXYIGnmLo8ZkhpK+qLs+T6ZWVczm2FmM56buriysgI/2Lld4VWLlNHsuKCTAMDeuEYBAIAUEmtgoLekxZIucvfD3f1wSXllz5tVdJC7D3X3tu7e9qaTj67MvEhnNQ6UsmqUPs+spozclop8UxBsJgD4L65RAABUSe6esEdQot5K4O5/NbNXJD1uZqsl9RVTKSEgVvsgZZ1/s2QhyUwli6YrsnRO0LEAQBLXKADJ79Yhd+joU1qqdp0DNeizpzXm8Vc0+dUPg44FIAnYjx2VMLOLJP1RUq671/+xb7BtQGcGEgAAAH6mHk99F3QEAIjquRWvW9AZ4imreuOEfabduWN1IL/LmMsVmllzMztT0oeS2ks6q2z/OXHOBgAAAAAA4izqwICZ/UHSGEk9Jc2T1MHd55U1PxLnbAAAAAAABCrt5xiQdIukNu5eZGa5kl43s1x3H6zSpQsBAAAAAEAKi3UrQcjdiyTJ3VdIaifpXDN7TAwMAAAAAACquGSrGDCzc8xssZl9bWb37KM9y8xeKWufWvYlf1SxBgYKzaz1Lr+QIkkXSKoricWZAQAAAABIEDPLkPQPSedKaiHpajNrsUe3LpI2uvuRkh6XNCDW68YaGOgkae2uO9y9xN07STrtR2YHAAAAACAleQIfP8JJkr5292Xu/r2kkZIu3qPPxZJeKHv+uqQzzSxqxX/UgQF3z3P3tRW0TflRsQEAAAAAQGVoKGn1Ltt5Zfv22cfdSyRtlnRotBeNNfngfqt59/PMRYBKZWZd3X1o0DkAoCJcp1CZnrs76ASoarhGAT9NyfdrEvaZ1sy6Suq6y66hifjvNdatBEAy6hq7CwAEiusUgGTGNQpIUu4+1N3b7vLYc1BgjaTGu2w3Ktu3zz5mlinpIEnfRHtfBgYAAAAAAEgN0yUdZWaHm9kBkq6SNHaPPmMl3VD2/HJJH3qMJQ/ifisBAAAAAADYf+5eYmY9JI2XlCHpOXefb2b9Jc1w97GSnpX0kpl9LelblQ4eRGU/dq1EIFlwXxyAZMd1CkAy4xoFYE8MDAAAAAAAkMaYYwAAAAAAgDTGwAASxswONbPZZY+1ZrZml+0D9tH/SDObXUnvfbuZLTUzN7ODK+M1AVQtAV+jRprZYjObZ2bPlM0gDCDNmdl9ZjbfzOaWXYtOLrtGtPgJr9HWzIaUPb/RzJ74iRl2Pb6dmf36p50FgFTAHx5IGHf/RlJrSTKzByQVufugBL39JEmjJU1J0PsBSDEBX6NelHS1JJP0iqTOkv6VoPcGkITM7FeSLpB0grvvNLO6kg5w95t/yuu4+wxJM35mhsw9jm8nqUjSpz/n9QAkLyoGkBTMrE/ZN2XzzKznPtqPNLNZZnaCmWWa2WNmNq1sBP3msj5nmdkHZjaq7Ju3F/97vLvPcveViTwnAFVHAq5Rb3upiKRpKl2TGEB6ayBpg7vvlCR33+Du+WY20czaSpKZFZnZX8qqCt43s5PK2peZ2UVlfdqZ2bg9X9zMLjSzqWXXrvfNLLts/wNm9pKZTVHprObtzGycmeVK+r2kO8uqF35rZsvNrFrZcb/YdRtAamFgAIEzs5MlXSvpREm/ktTdzI7bpf0YSa9J6uTuX0jqKmmdu59UdsxtZtakrPsJknpIaiHpGDM7JXFnAqAqSuQ1quyWhWslvRvfswKQAiZIamxmS8zsSTM7fR99aql0ffKWkr6T9JCksyVdKql/jNf/RNIp7n68pJGS+uzS1kLSWe5+9X93uPsKSf+U9Li7t3b3yZImSjq/rMtVkka5e/FPO00AyYCBASSDUyW94e7b3f07lZb8/7asLVvSm5Kudvcvy/Z1kNS57N7eqZIOlnRUWdvn7p7v7mFJsyXlJugcAFRdibxGPS3pfXf/LG5nAyAluHuRpDYqHWxcL+kVM7txj27f64eBxC8lfVz2wfxLxf4bqJGk8Wb2paTeklru0jbW3bf/iJjPqPTWJ5X9fP5HHAMgCTHHAJLdJkn5kn6t/9/e/bNGEUVxGH5/xCYQETtLG7H1I1jY+AcWQawUCy3E0sbCZiF9mgjBUkEt7LSyEAIiBEUIEkWw1c5OLCQk12JuyBAQR91xs877VMvducsZWM6yh3PPwIe6FuBGKeV5+8Ikp4DvraUt/I5L6tfEclSSReAgcLXPgCXNjlpEXAVW6x/4K3su2Sy7zx7fpuaYUsp2hyGmy8BSKeVJkpPAuPXet47xvUxytO6fK6VsdNknaf+xY0D7wQvgfJL5JAvAqK5B8wM3Aq4luVjXntG08h4ASHI8yfy/DlrSYPSeo5JcpxnqdanOGZA0cDV3HGstnQAmOS/pEPC5vt5bcPiZrzQFzLb7wEPsFpBmmoUBTV0p5RXwCHgNrAErrZbcnVa6c8CtJGdpWm0/AutJNoAVftEZkORmkk/AEeBdkru93Iyk/07fOSrJHHCHZtDYWh3qdbuv+5E0MxaAe0neJ3lLc+5/PMHPHwOPk7wBvnTc85SmULqeZOdI1QPgME2elDSjstt9JEmSJEndJbkAjEopl6cdi6Q/5/lrSZIkSb8tyTJwGjgz7Vgk/R07BiRJkiRJGjBnDEiSJEmSNGAWBiRJkiRJGjALA5IkSZIkDZiFAUmSJEmSBszCgCRJkiRJA2ZhQJIkSZKkAfsBQO/YLCMtDvQAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Plotting without correlation\n", "plt.figure(figsize=(20,10))\n", "sns.heatmap(df_viz,annot=True)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Word Analysis\n", "+ shape of word\n", "+ is_alpha\n", "+ is_stop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Noun Chunks\n", "+ noun + word describing the noun\n", "+ noun phrases\n", "+ adnominal\n", "+ root.text" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [], "source": [ "import spacy\n", "nlp = spacy.load('en')" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [], "source": [ "# Noun Phrase or Chunks\n", "doc_phrase1 = nlp(\"The man reading the news is very tall.\")" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The man\n", "the news\n" ] } ], "source": [ "for word in doc_phrase1.noun_chunks:\n", " print(word.text)" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "man\n", "news\n" ] } ], "source": [ "# Root Text\n", "# the Main Noun \n", "for word in doc_phrase1.noun_chunks:\n", " print(word.root.text)" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "man connector_text to root head : is\n", "news connector_text to root head : reading\n" ] } ], "source": [ "# Text of the root token head\n", "for token in doc_phrase1.noun_chunks:\n", " print(token.root.text,\"connector_text to root head :\",token.root.head.text)" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [], "source": [ "doc_phrase2 = nlp(\"For us the news is a concern.\")" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "us Connector: us Text of Root Tokens Head: For\n", "the news Connector: news Text of Root Tokens Head: is\n", "a concern Connector: concern Text of Root Tokens Head: is\n" ] } ], "source": [ "for word in doc_phrase2.noun_chunks:\n", " print(word.text,\"Connector:\",word.root.text,\"Text of Root Tokens Head: \",word.root.head.text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sentence Segmentation or Boundary Detection\n", "+ Deciding where sentences begin and end\n", "+ =================================================== \n", "+ a) If it's a period, it ends a sentence.\n", "+ (b) If the preceding token is in the hand-compiled list of abbreviations, then it doesn't end a sentence.\n", "+ (c) If the next token is capitalized, then it ends a sentence.\n", "+ =================================================== \n", "+ Default = Uses the Dependency parser\n", "+ Custom Rule Based or Manual\n", " - - You set boundaries before parsing the doc" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [], "source": [ "# Manual or Custom Based\n", "def mycustom_boundary(docx):\n", " for token in docx[:-1]:\n", " if token.text == '...':\n", " docx[token.i+1].is_sent_start = True\n", " return docx\n" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [], "source": [ "import spacy \n", "nlp = spacy.load('en')" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [], "source": [ "# Adding the rule before parsing\n", "nlp.add_pipe(mycustom_boundary,before='parser')" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [], "source": [ "mydoc = nlp(u\"This is my first sentence...the last comment was so cuul... what if...? this is the last sentence\")" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is my first sentence...\n", "the last comment was so cuul...\n", "what if...\n", "?\n", "this is the last sentence\n" ] } ], "source": [ "for sentence in mydoc.sents:\n", " print(sentence.text)" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [], "source": [ "# Manual or Custom Based\n", "def mycustom_boundary2(docx):\n", " for token in docx[:-1]:\n", " if token.text == '---':\n", " docx[token.i+1].is_sent_start = True\n", " return docx" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [], "source": [ "nlp2 = spacy.load('en')" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [], "source": [ "# Adding the rule before parsing\n", "nlp2.add_pipe(mycustom_boundary2,before='parser')" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [], "source": [ "mydoc2 = nlp2(u\"Last year was great---this year 2018-05-22 will be so cuul. when was your birthday? ---this is the last sentence\")" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Last year was great---\n", "this year 2018-05-22 will be so cuul.\n", "when was your birthday?\n", "---this is the last sentence\n" ] } ], "source": [ "for sentence in mydoc2.sents:\n", " print(sentence.text)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Removing the parsing\n", "nlp.remove_pipe('parser')" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [], "source": [ "nlp = spacy.load('en')" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [], "source": [ "mydoc3 = nlp(u\"This is my first sentence...the last comment was so cuul... what if...? this is the last sentence\")" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is my first sentence...the last comment was so cuul...\n", "what if...?\n", "this is the last sentence\n" ] } ], "source": [ "# Normal Sentence Segmenter\n", "for sentence in mydoc3.sents:\n", " print(sentence.text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Custome Rule Based" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [], "source": [ "from spacy.lang.en import English\n", "from spacy.pipeline import SentenceSegmenter\n" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [], "source": [ "def split_on_newlines(doc):\n", " start = 0\n", " seen_newline = False\n", " for word in doc:\n", " if seen_newline and not word.is_space:\n", " yield doc[start:word.i]\n", " start = word.i\n", " seen_newline = False\n", " elif word.text == '\\n':\n", " seen_newline = True\n", " if start < len(doc):\n", " yield doc[start:len(doc)]" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [], "source": [ "def split_on_tab(doc):\n", " start = 0\n", " seen_newline = False\n", " for word in doc:\n", " if seen_newline and not word.is_space:\n", " yield doc[start:word.i]\n", " start = word.i\n", " seen_newline = False\n", " elif word.text == '\\t':\n", " seen_newline = True\n", " if start < len(doc):\n", " yield doc[start:len(doc)]" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [], "source": [ "nlp = English() # just the language with no model\n", "sbd = SentenceSegmenter(nlp.vocab, strategy=split_on_newlines)\n", "nlp.add_pipe(sbd)" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is a great sentence\n", "\n", "This is another comment\n", "\n", "And more\n" ] } ], "source": [ "doc = nlp(u\"This is a great sentence\\n\\nThis is another comment\\nAnd more\")\n", "for sent in doc.sents:\n", " print(sent.text)\n", " " ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['This', 'is', 'a', 'great', 'sentence', '\\n\\n', 'This', 'is', 'another', 'comment', '\\n']\n", "['And', 'more']\n" ] } ], "source": [ "doc = nlp(u\"This is a great sentence\\n\\nThis is another comment\\nAnd more\")\n", "for sent in doc.sents:\n", " print([token.text for token in sent])" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [], "source": [ "nlp_tab = English() # just the language with no model\n", "sbd_tab = SentenceSegmenter(nlp.vocab, strategy=split_on_tab)\n", "nlp_tab.add_pipe(sbd_tab)" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [], "source": [ "## Spliting on Tabs\n", "doc_tab = nlp_tab(u\"This is a great sentence\\t This is another\\t comment\\t And more\")" ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is a great sentence\t This is another\t comment\t And more\n" ] } ], "source": [ "for sent in doc_tab.sents:\n", " print(sent.text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Stops Words In Spacy\n", "+ A Stop word/Stop list\n", "+ Words filtered out before preprocessing\n", "+ Most Common words*\n", "\n", "#### Uses\n", "+ Improve performance in search engines\n", "+ + eg how to perform sentiment analysis\n", "+ Eliminating noise and distraction in sentiment classification\n", "+ + Make ML learning faster due to less features\n", "+ + Make Prediction more accurate due to noise reduction" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [], "source": [ "import spacy \n", "nlp = spacy.load('en')" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [], "source": [ "from spacy.lang.en.stop_words import STOP_WORDS" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'although', 'ours', 'since', 'she', 'last', 'anyone', 'together', 'herself', 'besides', 'was', 'else', 'one', 'toward', 'often', 'unless', 'indeed', 'something', 'itself', 'becomes', 'several', 'front', 'meanwhile', 'whereafter', 'will', 'whereby', 'two', 'before', 'each', 'empty', 'do', 'fifteen', 'otherwise', 'own', 'has', 'anywhere', 'really', 'i', 'an', 'have', 'hundred', 'nine', 'the', 'all', 'others', 'beyond', 'hereby', 'yet', 'bottom', 'perhaps', 'into', 'anyway', 'when', 'both', 'sixty', 'onto', 'whereupon', 'once', 'six', 'where', 'would', 'about', 'by', 'because', 'no', 'except', 'ten', 'yourselves', 'above', 'cannot', 'thereby', 'forty', 'on', 'hers', 'myself', 'name', 'side', 'latter', 'from', 'nowhere', 'then', 'throughout', 'for', 'himself', 'same', 'their', 'again', 'there', 'full', 'done', 'under', 'it', 'thus', 'might', 'already', 'whether', 'call', 'now', 'via', 'could', 'make', 'elsewhere', 'always', 'many', 'seems', 'they', 'third', 'seemed', 'did', 'get', 'his', 'well', 'does', 'may', 'few', 'whence', 'please', 'say', 'such', 'while', 'whom', 'hereupon', 'beside', 'who', 'anyhow', 'however', 'amongst', 'your', 'move', 'be', 'along', 'ca', 'back', 'none', 'therein', 'within', 'how', 'nothing', 'among', 'than', 'across', 'but', 'neither', 'whither', 'here', 'if', 'nor', 'being', 'below', 'is', 'afterwards', 'seem', 'through', 'whole', 'take', 'nobody', 'sometimes', 'with', 'became', 'he', 'see', 'less', 'over', 'am', 'either', 'various', 'most', 'five', 'somehow', 'twelve', 'becoming', 'whenever', 'beforehand', 'anything', 'become', 'sometime', 'very', 'are', 'just', 'mine', 'its', 'noone', 'ever', 'must', 'part', 'against', 'thereupon', 'though', 'hence', 'another', 'any', 'behind', 'everyone', 'until', 'mostly', 'can', 'namely', 'only', 'or', 'enough', 'someone', 'a', 'us', 'without', 'of', 'whoever', 'seeming', 'more', 'these', 'themselves', 'also', 'due', 'formerly', 'them', 'eleven', 'give', 'keep', 'using', 'off', 'former', 'therefore', 'up', 'first', 'whereas', 'after', 'as', 'every', 'made', 'towards', 'fifty', 'what', 'yourself', 're', 'my', 'our', 'which', 'quite', 'wherever', 'three', 'used', 'had', 'regarding', 'been', 'between', 'everywhere', 'somewhere', 'this', 'too', 'still', 'we', 'whose', 'even', 'hereafter', 'thru', 'almost', 'ourselves', 'and', 'doing', 'four', 'never', 'next', 'during', 'eight', 'whatever', 'rather', 'further', 'much', 'out', 'him', 'least', 'those', 'not', 'some', 'should', 'moreover', 'amount', 'to', 'you', 'twenty', 'down', 'why', 'thence', 'were', 'serious', 'everything', 'wherein', 'around', 'in', 'other', 'thereafter', 'upon', 'nevertheless', 'per', 'alone', 'go', 'show', 'top', 'her', 'herein', 'at', 'that', 'so', 'me', 'latterly', 'put', 'yours'}\n" ] } ], "source": [ "# Print List of Stop words\n", "print(STOP_WORDS)" ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "305" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(STOP_WORDS)" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 119, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Checking If A Word is a Stopword\n", "nlp.vocab[\"the\"].is_stop" ] }, { "cell_type": "code", "execution_count": 120, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 120, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nlp.vocab[\"theme\"].is_stop" ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [], "source": [ "mysentence = nlp(u\"This is a group of word to check for stop words\")" ] }, { "cell_type": "code", "execution_count": 122, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "is\n", "a\n", "of\n", "to\n", "for\n" ] } ], "source": [ "# Filtering Non Stop Words\n", "for word in mysentence:\n", " if word.is_stop == True:\n", " print(word)\n", " " ] }, { "cell_type": "code", "execution_count": 123, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This\n", "group\n", "word\n", "check\n", "stop\n", "words\n" ] } ], "source": [ "# Filtering Stop Words\n", "filterdwords = []\n", "for word in mysentence:\n", " if word.is_stop == False:\n", " print(word)" ] }, { "cell_type": "code", "execution_count": 124, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[This, group, word, check, stop, words]\n" ] } ], "source": [ "# Filtering Stop Words\n", "filteredwords = []\n", "for word in mysentence:\n", " if word.is_stop == False:\n", " filteredwords.append(word)\n", "print(filteredwords)" ] }, { "cell_type": "code", "execution_count": 125, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[This, group, word, check, stop, words]" ] }, "execution_count": 125, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[ word for word in mysentence if word.is_stop == False]" ] }, { "cell_type": "code", "execution_count": 126, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[This, is, a, group, of, word, to, check, for, stop, words]\n" ] } ], "source": [ "# Filtering Stop Words\n", "filtered = []\n", "for word in mysentence:\n", " if word not in STOP_WORDS:\n", " filtered.append(word)\n", "print(filtered)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Filtering Stop Words\n", "\n", "# for word in STOP_WORDS:\n", "# if nlp.vocab[word].is_stop == True:\n", "# print(word)\n", "\n", "# for mysentence in STOP_WORDS:\n", "# lexeme = nlp.vocab[mysentence]\n", "# lexeme.is_stop = True\n", "# print(lexeme)\n", " \n", " \n", "\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Adding Your Own Stop Words" ] }, { "cell_type": "code", "execution_count": 127, "metadata": {}, "outputs": [], "source": [ "stoplist = STOP_WORDS.add(\"lol\")" ] }, { "cell_type": "code", "execution_count": 128, "metadata": {}, "outputs": [], "source": [ "example2 = nlp(u\"There are a lot of lol in this sentence but what does it mean.\")" ] }, { "cell_type": "code", "execution_count": 129, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "are\n", "a\n", "of\n", "lol\n", "in\n", "this\n", "but\n", "what\n", "does\n", "it\n" ] } ], "source": [ "for word in example2:\n", " if word.is_stop == True:\n", " print(word)" ] }, { "cell_type": "code", "execution_count": 130, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 130, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Lol Has been Added as A Stop Word\n", "nlp.vocab[\"lol\"].is_stop " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Removing Stop Words\n", "STOP_WORDS.remove(\"lol\")\n", "# Remove the Last word added\n", "STOP_WORDS.pop(\"lol\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Text Similarity With ML" ] }, { "cell_type": "code", "execution_count": 131, "metadata": {}, "outputs": [], "source": [ "# Using ML\n", "from sklearn.feature_extraction.text import CountVectorizer\n", "from sklearn.metrics.pairwise import euclidean_distances\n" ] }, { "cell_type": "code", "execution_count": 133, "metadata": {}, "outputs": [], "source": [ "documents = ['wolf','dog','cat','bird','fish']\n" ] }, { "cell_type": "code", "execution_count": 134, "metadata": {}, "outputs": [], "source": [ "vectorizer = CountVectorizer()\n", "features = vectorizer.fit_transform(documents).todense()" ] }, { "cell_type": "code", "execution_count": 135, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'dog': 2, 'fish': 3, 'wolf': 4, 'cat': 1, 'bird': 0}\n" ] } ], "source": [ "print(vectorizer.vocabulary_)\n" ] }, { "cell_type": "code", "execution_count": 136, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0.]] [[0 0 0 0 1]]\n", "[[0.]] [[0 0 1 0 0]]\n", "[[0.]] [[0 1 0 0 0]]\n", "[[0.]] [[1 0 0 0 0]]\n", "[[0.]] [[0 0 0 1 0]]\n" ] } ], "source": [ "for word in features:\n", " print(euclidean_distances(features[0]),word)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sentence Similarity\n", "+ To do" ] }, { "cell_type": "code", "execution_count": 137, "metadata": {}, "outputs": [], "source": [ "# Using Three Sentences\n", "corpus1 = [\"I like that bachelor\",\"I like that unmarried man\",\"I don't like the married man\"]\n", "corpus2 = [\"Jane is very nice.\", \"Is Jane very nice?\"]\n", "corpus3 = [\"He is a bachelor\",\"He is an unmarried man\"]\n", "corpus4 = [\"She is a wife\",\"She is a wife\"]\n", "corpus5 = [\"He is a king\",\"He is a doctor\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Rule-based Matching\n", "+ Tokenize\n", "+ Pattern matching" ] }, { "cell_type": "code", "execution_count": 138, "metadata": {}, "outputs": [], "source": [ "from spacy.matcher import Matcher\n", "import spacy\n", "nlp = spacy.load('en')\n" ] }, { "cell_type": "code", "execution_count": 139, "metadata": {}, "outputs": [], "source": [ "patterns = {'HelloWorld': [{'LOWER': 'hello'}, {'LOWER': 'world'}]}\n", "matcher = Matcher(nlp.vocab)\n" ] }, { "cell_type": "code", "execution_count": 140, "metadata": {}, "outputs": [], "source": [ "matcher = Matcher(nlp.vocab)\n" ] }, { "cell_type": "code", "execution_count": 141, "metadata": {}, "outputs": [], "source": [ "pattern = [{'LOWER': \"hello\"}, {'LOWER': \"world\"}]\n", "# matcher.add(\"HelloWorld\", None, pattern)\n" ] }, { "cell_type": "code", "execution_count": 142, "metadata": {}, "outputs": [], "source": [ "matcher.add(\"HelloWorld\", None, pattern)\n" ] }, { "cell_type": "code", "execution_count": 143, "metadata": {}, "outputs": [], "source": [ "doc = nlp(u'hello world this is not it!')\n", "matches = matcher(doc)\n" ] }, { "cell_type": "code", "execution_count": 144, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(15578876784678163569, 0, 2)]\n" ] } ], "source": [ "print(matches)" ] }, { "cell_type": "code", "execution_count": 145, "metadata": {}, "outputs": [], "source": [ "### Thanks\n", "# By Jesse JCharis\n", "# J-Secur1ty\n", "# Jesus Saves @ JCharisTech" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "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.5.2" } }, "nbformat": 4, "nbformat_minor": 2 }