{ "metadata": { "name": "", "signature": "sha256:86564bad5313b96435ba5ebb4296073d836c1febfb0ffedd95f33fdaba0edeb9" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "##1. Intro to low level NLP - Tokenization, Stopwords, POS, Stemming, Concordances\n", "\n", "### Lynn Cherny, 2/8/15, arnicas@gmail\n", "Full repo here: https://github.com/arnicas/NLP-in-Python" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%matplotlib inline" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "import itertools\n", "import nltk\n", "import string" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Tokenization\n", "\n", "Read in a file to use for practice." ] }, { "cell_type": "code", "collapsed": false, "input": [ "with file(\"data/stories/A_THE FIR TREE.txt\",'r') as handle:\n", " text = handle.read()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "text[0:100]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "'THE FIR TREE\\r\\n\\r\\nOut in the woods stood a nice little Fir Tree. The place he had was a\\r\\nvery good one'" ] } ], "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ "tokens = nltk.word_tokenize(text)\n", "tokens[60:110]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "['so',\n", " 'very',\n", " 'much',\n", " 'to',\n", " 'be',\n", " 'a',\n", " 'grown-up',\n", " 'tree',\n", " '.',\n", " 'He',\n", " 'did',\n", " 'not',\n", " 'think',\n", " 'of',\n", " 'the',\n", " 'warm',\n", " 'sun',\n", " 'and',\n", " 'of',\n", " 'the',\n", " 'fresh',\n", " 'air',\n", " ';',\n", " 'he',\n", " 'did',\n", " 'not',\n", " 'care',\n", " 'for',\n", " 'the',\n", " 'little',\n", " 'cottage',\n", " 'children',\n", " 'that',\n", " 'ran',\n", " 'about',\n", " 'and',\n", " 'prattled',\n", " 'when',\n", " 'they',\n", " 'were',\n", " 'in',\n", " 'the',\n", " 'woods',\n", " 'looking',\n", " 'for',\n", " 'wild-strawberries',\n", " '.',\n", " 'The',\n", " 'children',\n", " 'often']" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the difference below - look for \"wild-strawberries\":" ] }, { "cell_type": "code", "collapsed": false, "input": [ "nltk.wordpunct_tokenize(text)[60:120]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "['Fir',\n", " 'wanted',\n", " 'so',\n", " 'very',\n", " 'much',\n", " 'to',\n", " 'be',\n", " 'a',\n", " 'grown',\n", " '-',\n", " 'up',\n", " 'tree',\n", " '.',\n", " 'He',\n", " 'did',\n", " 'not',\n", " 'think',\n", " 'of',\n", " 'the',\n", " 'warm',\n", " 'sun',\n", " 'and',\n", " 'of',\n", " 'the',\n", " 'fresh',\n", " 'air',\n", " ';',\n", " 'he',\n", " 'did',\n", " 'not',\n", " 'care',\n", " 'for',\n", " 'the',\n", " 'little',\n", " 'cottage',\n", " 'children',\n", " 'that',\n", " 'ran',\n", " 'about',\n", " 'and',\n", " 'prattled',\n", " 'when',\n", " 'they',\n", " 'were',\n", " 'in',\n", " 'the',\n", " 'woods',\n", " 'looking',\n", " 'for',\n", " 'wild',\n", " '-',\n", " 'strawberries',\n", " '.',\n", " 'The',\n", " 'children',\n", " 'often',\n", " 'came',\n", " 'with',\n", " 'a',\n", " 'whole']" ] } ], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "nltk.sent_tokenize(text)[0:10]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "['THE FIR TREE\\r\\n\\r\\nOut in the woods stood a nice little Fir Tree.',\n", " 'The place he had was a\\r\\nvery good one: the sun shone on him: as to fresh air, there was enough\\r\\nof that, and round him grew many large-sized comrades, pines as well as\\r\\nfirs.',\n", " 'But the little Fir wanted so very much to be a grown-up tree.',\n", " 'He did not think of the warm sun and of the fresh air; he did not care\\r\\nfor the little cottage children that ran about and prattled when they\\r\\nwere in the woods looking for wild-strawberries.',\n", " 'The children often came\\r\\nwith a whole pitcher full of berries, or a long row of them threaded on\\r\\na straw, and sat down near the young tree and said, \"Oh, how pretty he\\r\\nis!',\n", " 'What a nice little fir!\"',\n", " 'But this was what the Tree could not bear\\r\\nto hear.',\n", " 'At the end of a year he had shot up a good deal, and after another year\\r\\nhe was another long bit taller; for with fir trees one can always tell\\r\\nby the shoots how many years old they are.',\n", " '\"Oh!',\n", " 'Were I but such a high tree as the others are,\" sighed he.']" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "**You'll want to choose your word tokenization carefully - and sometimes you have to use regex patterns instead. Note especially what happens with contractions here:http://text-processing.com/demo/tokenize/**" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "StopWords" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"Stopwords\" are words that are usually excluded because they are common connectors (or determiners) that are not considered to carry meaning. **BEWARE** hidden stopword filtering in libraries you use and always check stopword lists to see if you agree with their contents!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from nltk.corpus import stopwords" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "english_stops = stopwords.words('english')" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ "english_stops" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 10, "text": [ "[u'i',\n", " u'me',\n", " u'my',\n", " u'myself',\n", " u'we',\n", " u'our',\n", " u'ours',\n", " u'ourselves',\n", " u'you',\n", " u'your',\n", " u'yours',\n", " u'yourself',\n", " u'yourselves',\n", " u'he',\n", " u'him',\n", " u'his',\n", " u'himself',\n", " u'she',\n", " u'her',\n", " u'hers',\n", " u'herself',\n", " u'it',\n", " u'its',\n", " u'itself',\n", " u'they',\n", " u'them',\n", " u'their',\n", " u'theirs',\n", " u'themselves',\n", " u'what',\n", " u'which',\n", " u'who',\n", " u'whom',\n", " u'this',\n", " u'that',\n", " u'these',\n", " u'those',\n", " u'am',\n", " u'is',\n", " u'are',\n", " u'was',\n", " u'were',\n", " u'be',\n", " u'been',\n", " u'being',\n", " u'have',\n", " u'has',\n", " u'had',\n", " u'having',\n", " u'do',\n", " u'does',\n", " u'did',\n", " u'doing',\n", " u'a',\n", " u'an',\n", " u'the',\n", " u'and',\n", " u'but',\n", " u'if',\n", " u'or',\n", " u'because',\n", " u'as',\n", " u'until',\n", " u'while',\n", " u'of',\n", " u'at',\n", " u'by',\n", " u'for',\n", " u'with',\n", " u'about',\n", " u'against',\n", " u'between',\n", " u'into',\n", " u'through',\n", " u'during',\n", " u'before',\n", " u'after',\n", " u'above',\n", " u'below',\n", " u'to',\n", " u'from',\n", " u'up',\n", " u'down',\n", " u'in',\n", " u'out',\n", " u'on',\n", " u'off',\n", " u'over',\n", " u'under',\n", " u'again',\n", " u'further',\n", " u'then',\n", " u'once',\n", " u'here',\n", " u'there',\n", " u'when',\n", " u'where',\n", " u'why',\n", " u'how',\n", " u'all',\n", " u'any',\n", " u'both',\n", " u'each',\n", " u'few',\n", " u'more',\n", " u'most',\n", " u'other',\n", " u'some',\n", " u'such',\n", " u'no',\n", " u'nor',\n", " u'not',\n", " u'only',\n", " u'own',\n", " u'same',\n", " u'so',\n", " u'than',\n", " u'too',\n", " u'very',\n", " u's',\n", " u't',\n", " u'can',\n", " u'will',\n", " u'just',\n", " u'don',\n", " u'should',\n", " u'now']" ] } ], "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, "input": [ "tokens = nltk.word_tokenize(text)\n", "tokens[0:15]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 12, "text": [ "['THE',\n", " 'FIR',\n", " 'TREE',\n", " 'Out',\n", " 'in',\n", " 'the',\n", " 'woods',\n", " 'stood',\n", " 'a',\n", " 'nice',\n", " 'little',\n", " 'Fir',\n", " 'Tree',\n", " '.',\n", " 'The']" ] } ], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "len(tokens)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 12, "text": [ "3925" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "**We want to strip out stopwords - use a list comprehension. Notice you need to lower case the words before you check for membership!**" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# try this without .lower in the if-statement and check the size!\n", "tokens = [token.lower() for token in tokens if token.lower() not in english_stops]\n", "len(tokens)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 14, "text": [ "2158" ] } ], "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ "tokens[0:15]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 15, "text": [ "['fir',\n", " 'tree',\n", " 'woods',\n", " 'stood',\n", " 'nice',\n", " 'little',\n", " 'fir',\n", " 'tree',\n", " '.',\n", " 'place',\n", " 'good',\n", " 'one',\n", " ':',\n", " 'sun',\n", " 'shone']" ] } ], "prompt_number": 15 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's get rid of punctuation too, which isn't used in most bag-of-words analyses." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import string\n", "string.punctuation" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 16, "text": [ "'!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~'" ] } ], "prompt_number": 16 }, { "cell_type": "code", "collapsed": false, "input": [ "tokens = [token for token in tokens if token not in string.punctuation]\n", "len(tokens)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 19, "text": [ "1647" ] } ], "prompt_number": 19 }, { "cell_type": "code", "collapsed": false, "input": [ "# There's some awful stuff still in here:\n", "sorted(tokens)[0:20]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 22, "text": [ "[\"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\",\n", " \"''\"]" ] } ], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ugliness of some of those tokens! You have some possibilities now - add to your stopwords list the ones you want removed; or remove all very short words, which will get rid of our puntuation problem too." ] }, { "cell_type": "code", "collapsed": false, "input": [ "[token for token in tokens if len(token) <= 2][0:20]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 24, "text": [ "['``',\n", " 'oh',\n", " \"''\",\n", " '``',\n", " 'oh',\n", " \"''\",\n", " '``',\n", " \"''\",\n", " 'oh',\n", " 'go',\n", " '``',\n", " \"''\",\n", " '--',\n", " \"''\",\n", " \"''\",\n", " 'go',\n", " \"''\",\n", " \"''\",\n", " '``',\n", " \"''\"]" ] } ], "prompt_number": 24 }, { "cell_type": "code", "collapsed": false, "input": [ "def clean_tokens(tokens):\n", " \"\"\" Lowercases, takes out punct and stopwords and short strings \"\"\"\n", " return [token.lower() for token in tokens if (token not in string.punctuation) and \n", " (token.lower() not in english_stops) and len(token) > 2]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 25 }, { "cell_type": "code", "collapsed": false, "input": [ "clean = clean_tokens(tokens)\n", "clean[0:20]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 27, "text": [ "['fir',\n", " 'tree',\n", " 'woods',\n", " 'stood',\n", " 'nice',\n", " 'little',\n", " 'fir',\n", " 'tree',\n", " 'place',\n", " 'good',\n", " 'one',\n", " 'sun',\n", " 'shone',\n", " 'fresh',\n", " 'air',\n", " 'enough',\n", " 'round',\n", " 'grew',\n", " 'many',\n", " 'large-sized']" ] } ], "prompt_number": 27 }, { "cell_type": "code", "collapsed": false, "input": [ "len(clean)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 28, "text": [ "1445" ] } ], "prompt_number": 28 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The obvious thing you want to do next is count frequencies of words in texts - NLTK has you covered." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from nltk import Text\n", "text = Text(clean)\n", "text.vocab().most_common()[0:20]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 29, "text": [ "[('tree', 66),\n", " ('fir', 27),\n", " ('said', 25),\n", " ('little', 24),\n", " ('one', 23),\n", " ('came', 15),\n", " ('thought', 14),\n", " ('know', 14),\n", " ('branches', 12),\n", " ('mice', 12),\n", " ('still', 10),\n", " ('trees', 10),\n", " ('children', 9),\n", " ('large', 9),\n", " ('would', 9),\n", " ('story', 9),\n", " ('humpy-dumpy', 9),\n", " ('come', 9),\n", " ('old', 9),\n", " ('like', 8)]" ] } ], "prompt_number": 29 }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "# NLTK Text Collection methods" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def makeTextCollection(files):\n", " from nltk import Text\n", " from nltk import TextCollection\n", " textlist = [open(filen).read() for filen in files]\n", " texts= [Text(clean_tokens(nltk.word_tokenize(text))) for text in textlist]\n", " collection = TextCollection(texts)\n", " return collection" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 30 }, { "cell_type": "code", "collapsed": false, "input": [ "filelist = !ls data/stories/*" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 31 }, { "cell_type": "code", "collapsed": false, "input": [ "filelist" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 32, "text": [ "['data/stories/A_THE BELL.txt',\n", " 'data/stories/A_THE DREAM OF LITTLE TUK.txt',\n", " 'data/stories/A_THE ELDERBUSH.txt',\n", " \"data/stories/A_THE EMPEROR'S NEW CLOTHES.txt\",\n", " 'data/stories/A_THE FALSE COLLAR.txt',\n", " 'data/stories/A_THE FIR TREE.txt',\n", " 'data/stories/A_THE HAPPY FAMILY.txt',\n", " 'data/stories/A_THE LEAP-FROG.txt',\n", " 'data/stories/A_THE LITTLE MATCH GIRL.txt',\n", " 'data/stories/A_THE NAUGHTY BOY.txt',\n", " 'data/stories/A_THE OLD HOUSE.txt',\n", " 'data/stories/A_THE REAL PRINCESS.txt',\n", " 'data/stories/A_THE RED SHOES.txt',\n", " 'data/stories/A_THE SHADOW.txt',\n", " 'data/stories/A_THE SHOES OF FORTUNE.txt',\n", " 'data/stories/A_THE SNOW QUEEN.txt',\n", " 'data/stories/A_THE STORY OF A MOTHER.txt',\n", " 'data/stories/A_THE SWINEHERD.txt',\n", " 'data/stories/G_BEARSKIN.txt',\n", " 'data/stories/G_BRIAR ROSE.txt',\n", " 'data/stories/G_CATHERINE AND FREDERICK.txt',\n", " 'data/stories/G_CINDERELLA.txt',\n", " 'data/stories/G_DUMMLING AND THE THREE FEATHERS.txt',\n", " 'data/stories/G_FAITHFUL JOHN.txt',\n", " 'data/stories/G_HANSEL AND GRETHEL.txt',\n", " 'data/stories/G_LITTLE ONE-EYE, TWO-EYES AND THREE-EYES.txt',\n", " 'data/stories/G_LITTLE RED-CAP.txt',\n", " 'data/stories/G_LITTLE SNOW-WHITE.txt',\n", " 'data/stories/G_MOTHER HOLLE.txt',\n", " 'data/stories/G_OH, IF I COULD BUT SHIVER!.txt',\n", " 'data/stories/G_RAPUNZEL.txt',\n", " 'data/stories/G_RUMPELSTILTSKIN.txt',\n", " 'data/stories/G_SNOW-WHITE AND ROSE-RED.txt',\n", " 'data/stories/G_THE FROG PRINCE.txt',\n", " 'data/stories/G_THE GOLDEN GOOSE.txt',\n", " 'data/stories/G_THE GOOSE-GIRL.txt',\n", " 'data/stories/G_THE LITTLE BROTHER AND SISTER.txt',\n", " 'data/stories/G_THE SIX SWANS.txt',\n", " 'data/stories/G_THE THREE LITTLE MEN IN THE WOOD.txt',\n", " 'data/stories/G_THE TRAVELS OF TOM THUMB.txt',\n", " 'data/stories/G_THE VALIANT LITTLE TAILOR.txt',\n", " 'data/stories/G_THE WATER OF LIFE.txt',\n", " 'data/stories/G_THUMBLING.txt']" ] } ], "prompt_number": 32 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol = makeTextCollection(filelist)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 33 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.concordance('witch')\n", "# Note that a concordance view should really retain original format; see below for how to do this \n", "# with an IndexedText object." ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Displaying 14 of 14 matches:\n", " woman behaved kindly reality wicked witch waylaid children built bread-house o\n", "grethel came next shaking till awoke witch said get lazy thing fetch water cook\n", "ll eat grethel began cry useless old witch made wished nice meal cooked hansel \n", " nothing crab claw every morning old witch came cage said hansel stretch finger\n", "n wild beasts wood died together old witch called leave noise help bit early mo\n", "n flames burning fiercely creep said witch see hot enough put bread intended gr\n", "howled grethel ran away left ungodly witch burn ashes ran hansel opening door c\n", "opening door called hansel saved old witch dead sprang like bird cage door open\n", "l upon neck kissed nothing fear went witch house every corner caskets full pear\n", "de called hal called rumpelstiltskin witch told witch told shrieked little man \n", "al called rumpelstiltskin witch told witch told shrieked little man stamped rig\n", "look brook wicked stepmother however witch witnessed departure two children sne\n", "little boy happened king hunting old witch took form chambermaid got room queen\n", "utiful charming ever told king fraud witch daughter practised upon tried senten\n" ] } ], "prompt_number": 34 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.similar('king')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "man father woman went home however replied queen eldest toads still\n", "prince westwards dwarfs folks lord giants wished garden get\n" ] } ], "prompt_number": 35 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.similar('queen')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "man country rats love palace people share gerda son see another church\n", "dear sees yes prince dost blow takes would\n" ] } ], "prompt_number": 36 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.collocations(num=25, window_size=3)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "faithful john; old woman; little boy; learned man; old man; red shoes;\n", "pewter soldier; snow queen; tom thumb; next morning; thou art; little\n", "girl; little gerda; robber maiden; fir tree; take care; king son; king\n", "daughter; weg weg; could see; little maiden; pick pick; shivering\n", "means; east street; fairy tale\n" ] } ], "prompt_number": 37 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.dispersion_plot(['queen','king','girl', 'boy', 'daughter','son'])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "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\n", "text": [ "" ] } ], "prompt_number": 38 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.plot(50)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "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\nhgxp5b334JJL7Pjm5la22Qb22KORww4DqFx+fNu3fdu307anTp3KxIkTAVaWl4moalUX4HTgp8BM\nYEBI2wSYGdZbgJbY8ROBXYrlNDc3axoLFixYo/T27ovSV6xQffVV1QkTVM8+W/WQQ1R33XWBmrFJ\nde21VQ8/XPWuu1SXLcs+f11RV97lZamr3uRlqSvv8iqhy6qB0rK5GtFKG0aRSCKyDvBZ4CngTuDI\ncNiRwF/C+p3AESLSU0Q2B7YCHs0212uGiH1R7sAD4bTT4Lbb4Pbb4brrYO+94b//NZ/F/vvbcffe\nW+0cO47jtCVzn4OIbIc5nLuF5QZVvVBE+gLjgSHAHOAwVW0N55wKHA0sB36kqncnyNWsr6W9vPoq\n3HCDVRYvvghrrQX33Qe77VbtnDmOU2/43Eo5RBVOOAF+8xsYONDCYQcMqHauHMepJ3IzCK5SZDHO\nobPlidggum98o5U33oBDDzWTU17ylyddeZeXpa56k5elrrzLq4SuNGqmcuiqrLWWzds0cCA8+KAN\nqnMcx6k2blbKCQ8/DHvuaT2Ha6+FI49c5SmO4zgdpubNSl2dXXc13wNEU3RUNz+O49Q3NVM5dEWf\nQ/G+Y46x5aOP4JBDYM6cfOWvmrryLi9LXfUmL0tdeZdXCV1p1EzlUCtcfrlN5Pfqq3DWWbBsWbVz\n5DhOPeI+hxzy+uswciTMn2+/114L225b7Vw5jlOLuM+hC7HppjBhgs34+sQTVkGce65/N8JxnOyo\nmcqhFnwOcXbaCR56qJVjj7UIptNOM6f1s8/mI39Z68q7vCx11Zu8LHXlXV4ldKVRM5VDLdKrF/z+\n9zBpks3BFO9FfPxxtXPnOE4t4z6HLsKiRXDyyfCHP9j2rrtapdG7d3Xz5ThO18Z9Dl2cPn0KvYhB\ng2zQ3De+0fYDQ47jOJ1FzVQOteZzSEv/7Gfhnntg9OhW/vpXm3qjWvnLUlfe5WWpq97kZakr7/Iq\noSuNmqkc6omttoIzzoBu3eAXv4Bbbql2jhzHqTXc59CFueQSOOkkWGcd+Ne/YIcdqp0jx3G6Gv49\nhxpEFY4+2gbJDR4Mjz8OG29c7Vw5jtOVyI1DWkQGi8i9IvKciDwrIieE9L4iMllEZonIpOhTomHf\nWBF5UURmisi+SXLrxecQ3ycCV15pkUuvvQZf/rKNiejK9s+uKi9LXfUmL0tdeZdXCV1pVMPnsAw4\n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\n", "text": [ "" ] } ], "prompt_number": 39 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.vocab().most_common()[0:15]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 40, "text": [ "[('said', 911),\n", " ('one', 571),\n", " ('little', 557),\n", " ('old', 368),\n", " ('came', 321),\n", " ('could', 304),\n", " ('went', 299),\n", " ('king', 289),\n", " ('would', 255),\n", " ('man', 237),\n", " ('must', 204),\n", " ('see', 194),\n", " ('thought', 192),\n", " ('away', 184),\n", " ('like', 182)]" ] } ], "prompt_number": 40 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.common_contexts(['queen'])" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "snow_passed form_cradle day_heard snow_kissed snow_playfellow\n", "day_walking bed_place king_fragrant real_far snow_said body_hearts\n", "young_bore kissed_going snow_first hid_chamber shall_child king_great\n", "year_brought enemy_dressing snow_home\n" ] } ], "prompt_number": 41 }, { "cell_type": "code", "collapsed": false, "input": [ "len(fairyCol.vocab())" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 42, "text": [ "6698" ] } ], "prompt_number": 42 }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "To see more details about the NLTK Text methods, read the code/doc here: http://www.nltk.org/_modules/nltk/text.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parts of Speech - Abbreviated POS\n", "*To do this, you need to download the MaxEnt Treebank POS tagger with nltk.download() (on the models tab) - it may have downloaded with the full book collection, if you already got that.*" ] }, { "cell_type": "code", "collapsed": false, "input": [ "nltk.download()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "showing info http://nltk.github.com/nltk_data/\n" ] }, { "metadata": {}, "output_type": "pyout", "prompt_number": 36, "text": [ "True" ] } ], "prompt_number": 36 }, { "cell_type": "code", "collapsed": false, "input": [ "text = nltk.word_tokenize(\"And now for something completely different\")\n", "tagged = nltk.pos_tag(text) # there are a few options for taggers, details in NLTK books\n", "tagged" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 43, "text": [ "[('And', 'CC'),\n", " ('now', 'RB'),\n", " ('for', 'IN'),\n", " ('something', 'NN'),\n", " ('completely', 'RB'),\n", " ('different', 'JJ')]" ] } ], "prompt_number": 43 }, { "cell_type": "code", "collapsed": false, "input": [ "nltk.untag(tagged)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 44, "text": [ "['And', 'now', 'for', 'something', 'completely', 'different']" ] } ], "prompt_number": 44 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "source: https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html\n", "\n", "Parts of speech are used in anaysis that's \"deeper\" than bags-of-words approaches. For instance, chunking (parsing for structure) may be used for entity identification and semantics. See http://www.nltk.org/book/ch07.html for a little more info, and the 2 Perkins NLTK books." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Stemming / Lemmatizing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*The goal is to merge data items that are the same at some \"root\" meaning level, and reduce the number of features in your data set. \"Cats\" and \"Cat\" might want to be treated as the same thing, from a topic or summarization perspective.*" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# stemming removes affixes. This is the default choice for stemming although other algs exist\n", "from nltk.stem import PorterStemmer\n", "stemmer = PorterStemmer()\n", "stemmer.stem('believes')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 45, "text": [ "u'believ'" ] } ], "prompt_number": 45 }, { "cell_type": "code", "collapsed": false, "input": [ "# lemmatizing transforms to root words using grammar rules. It is slower. Stemming is more common.\n", "from nltk.stem import WordNetLemmatizer\n", "lemmatizer = WordNetLemmatizer()\n", "lemmatizer.lemmatize('said', pos='v') # if you don't specify POS, you get zilch." ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 46, "text": [ "u'say'" ] } ], "prompt_number": 46 }, { "cell_type": "code", "collapsed": false, "input": [ "lemmatizer.lemmatize('cookbooks')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 47, "text": [ "u'cookbook'" ] } ], "prompt_number": 47 }, { "cell_type": "code", "collapsed": false, "input": [ "stemmer.stem('cookbooks')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 48, "text": [ "u'cookbook'" ] } ], "prompt_number": 48 }, { "cell_type": "code", "collapsed": false, "input": [ "# an apparently recommended compression recipe in Perkins Python 3 NLTK book? Not sure I agree.\n", "stemmer.stem(lemmatizer.lemmatize('buses'))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 50, "text": [ "u'bu'" ] } ], "prompt_number": 50 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Usefulness of lemmatizing / stemming ... vocab reduction, indexing" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def tokenize_and_stem(text):\n", " tokens = clean_tokens(nltk.word_tokenize(text))\n", " #return no_stops\n", " stems = [stemmer.stem(t) for t in tokens]\n", " return stems" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 51 }, { "cell_type": "code", "collapsed": false, "input": [ "def makeStemTextCollection(files):\n", " from nltk import Text\n", " from nltk import TextCollection\n", " textlist = [open(filen).read() for filen in files]\n", " tokens = [tokenize_and_stem(text) for text in textlist]\n", " texts= [Text(text) for text in tokens]\n", " collection = TextCollection(texts)\n", " return collection" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 52 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyStems = makeStemTextCollection(filelist)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 53 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyStems.concordance('witch')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Displaying 16 of 16 matches:\n", " old woman behav kindli realiti wick witch waylaid children built bread-hous or\n", " kill cook ate made great festiv day witch red eye see far fine sens smell like\n", "se grethel came next shake till awok witch said get lazi thing fetch water cook\n", "ll eat grethel began cri useless old witch made wish nice meal cook hansel gret\n", "el got noth crab claw everi morn old witch came cage said hansel stretch finger\n", "eaten wild beast wood die togeth old witch call leav nois help bit earli morn g\n", "hel oven flame burn fierc creep said witch see hot enough put bread intend gret\n", "l howl grethel ran away left ungodli witch burn ash ran hansel open door call h\n", "ansel open door call hansel save old witch dead sprang like bird cage door open\n", "d fell upon neck kiss noth fear went witch hous everi corner casket full pearl \n", "conrad call hal call rumpelstiltskin witch told witch told shriek littl man sta\n", " hal call rumpelstiltskin witch told witch told shriek littl man stamp right fo\n", " went look brook wick stepmoth howev witch wit departur two children sneak secr\n", "ur two children sneak secretli habit witch enchant spring forest present found \n", "eauti littl boy happen king hunt old witch took form chambermaid got room queen\n", "ci beauti charm ever told king fraud witch daughter practis upon tri sentenc pr\n" ] } ], "prompt_number": 54 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyStems.collocations(num=25, window_size=2)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "faith john; old woman; littl boy; old man; pewter soldier; learn man;\n", "littl girl; red shoe; snow queen; tom thumb; next morn; littl gerda;\n", "fir tree; fairi tale; open door; king son; robber maiden; king\n", "daughter; could see; thou art; east street; littl kay; mother holl;\n", "turn round; take care\n" ] } ], "prompt_number": 55 }, { "cell_type": "code", "collapsed": false, "input": [ "# reminder of above\n", "fairyCol.collocations(num=25, window_size=2)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "faithful john; old woman; little boy; old man; learned man; pewter\n", "soldier; red shoes; snow queen; little girl; tom thumb; next morning;\n", "little gerda; robber maiden; fir tree; king son; king daughter; could\n", "see; thou art; shivering means; east street; take care; fairy tale;\n", "little kay; mother holle; kid milk\n" ] } ], "prompt_number": 56 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyStems.vocab().most_common()[0:10]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 57, "text": [ "[(u'said', 911),\n", " (u'one', 585),\n", " (u'littl', 557),\n", " (u'old', 368),\n", " (u'came', 321),\n", " (u'could', 304),\n", " (u'went', 299),\n", " (u'king', 293),\n", " (u'look', 270),\n", " (u'would', 255)]" ] } ], "prompt_number": 57 }, { "cell_type": "code", "collapsed": false, "input": [ "len(fairyStems.vocab()) # a huge savings over the vocab size of the unstemmed one!" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 51, "text": [ "4861" ] } ], "prompt_number": 51 }, { "cell_type": "code", "collapsed": false, "input": [ "len(fairyCol.vocab())" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 52, "text": [ "6698" ] } ], "prompt_number": 52 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyStems.common_contexts(['witch'])" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "awok_said ungodli_burn day_red wick_waylaid howev_wit old_dead\n", "old_came old_took went_hous said_see old_made habit_enchant\n", "rumpelstiltskin_told old_call fraud_daughter told_told\n" ] } ], "prompt_number": 53 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyCol.common_contexts(['witch'])" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "awoke_said old_called wicked_waylaid old_dead went_house old_came\n", "old_took ungodly_burn said_see however_witnessed old_made\n", "rumpelstiltskin_told fraud_daughter told_told\n" ] } ], "prompt_number": 54 }, { "cell_type": "code", "collapsed": false, "input": [ "fairyStems.similar('witch')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "woman man said old hous peasant-woman ladi eldest chivalri poet hansel\n", "hen emperor\n" ] } ], "prompt_number": 55 }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Stemming can be useful for search engines... Concordances should retain original formats.\n", "\n", "This code example is from the NLTK book, http://www.nltk.org/book/ch03.html, ex 3.6 This is a search method that saves original context, but allows indexing into it by stemmed words.\n", "\n", "*Also requires downloading from nltk.download() if you want to run it.*" ] }, { "cell_type": "code", "collapsed": false, "input": [ "nltk.download()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "showing info http://nltk.github.com/nltk_data/\n" ] }, { "metadata": {}, "output_type": "pyout", "prompt_number": 56, "text": [ "True" ] } ], "prompt_number": 56 }, { "cell_type": "code", "collapsed": false, "input": [ "porter = nltk.PorterStemmer()\n", "grail = nltk.corpus.webtext.words('grail.txt')" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 57 }, { "cell_type": "code", "collapsed": false, "input": [ "class IndexedText(object):\n", "\n", " def __init__(self, stemmer, text):\n", " self._text = text\n", " self._stemmer = stemmer\n", " self._index = nltk.Index((self._stem(word), i)\n", " for (i, word) in enumerate(text))\n", "\n", " def concordance(self, word, width=40):\n", " key = self._stem(word)\n", " wc = int(width/4) # words of context\n", " for i in self._index[key]:\n", " lcontext = ' '.join(self._text[i-wc:i])\n", " rcontext = ' '.join(self._text[i:i+wc])\n", " ldisplay = '{:>{width}}'.format(lcontext[-width:], width=width) # right justify\n", " rdisplay = '{:{width}}'.format(rcontext[:width], width=width) # left justify\n", " print(ldisplay, rdisplay)\n", "\n", " def _stem(self, word):\n", " return self._stemmer.stem(word).lower()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 58 }, { "cell_type": "code", "collapsed": false, "input": [ "text = IndexedText(porter, grail)\n", "text.concordance('lie')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "('r king ! DENNIS : Listen , strange women', 'lying in ponds distributing swords is no')\n", "(' beat a very brave retreat . ROBIN : All', 'lies ! MINSTREL : [ singing ] Bravest of')\n", "(' Nay . Nay . Come . Come . You may', 'lie here . Oh , but you are wounded ! ')\n", "('doctors immediately ! No , no , please !', 'Lie down . [ clap clap ] PIGLET : Well ')\n", "('ere is much danger , for beyond the cave', 'lies the Gorge of Eternal Peril , which ')\n", "(' you . Oh ... TIM : To the north there', 'lies a cave -- the cave of Caerbannog --')\n", "('h it and lived ! Bones of full fifty men', 'lie strewn about its lair . So , brave k')\n", "(\"not stop our fight ' til each one of you\", 'lies dead , and the Holy Grail returns t')\n" ] } ], "prompt_number": 59 }, { "cell_type": "code", "collapsed": false, "input": [ "text.concordance('say')" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "(\" dead ! CART - MASTER : ' Ere . He\", \"says he ' s not dead ! CUSTOMER : Yes \")\n", "(\" you ' Man '. DENNIS : Well , you could\", \"say ' Dennis '. ARTHUR : Well , I didn \")\n", "(' find out , did you ? ARTHUR : I did', \"say ' sorry ' about the ' old woman ', \")\n", "(\" DENNIS : I mean , if I went ' round\", 'saying I was an emperor just because som')\n", "(' you see ? ARTHUR : What ? GALAHAD : He', \"says they ' ve already got one ! ARTHUR \")\n", "('u ? HEAD KNIGHT : We are the Knights Who', \"Say ... ' Ni '! RANDOM : Ni ! ARTHUR \")\n", "(' Ni ! ARTHUR : No ! Not the Knights Who', \"Say ' Ni '! HEAD KNIGHT : The same ! \")\n", "('the tale ! HEAD KNIGHT : The Knights Who', \"Say ' Ni ' demand a sacrifice ! ARTHUR :\")\n", "(' ! Ow ! Agh ! HEAD KNIGHT : We shall', \"say ' ni ' again to you if you do \")\n", "(' Who sent you ? ARTHUR : The Knights Who', \"Say ' Ni '. CRONE : Aggh ! No ! \")\n", "('n buy a shrubbery , my friend and I will', \"say ... we will say ... ' ni '. CRONE \")\n", "(' , my friend and I will say ... we will', \"say ... ' ni '. CRONE : Agh ! Do \")\n", "('VERE : Ni ! ROGER THE SHRUBBER : Are you', \"saying ' ni ' to that old woman ? ARTHUR\")\n", "('his period in history . ARTHUR : Did you', \"say ' shrubberies '? ROGER : Yes . Shrub\")\n", "('We are now ... no longer the Knights Who', \"Say ' Ni '. KNIGHTS OF NI : Ni ! \")\n", "('NIGHT : Shh ! We are now the Knights Who', \"Say ' Ecky - ecky - ecky - ecky - \")\n", "(\" HEAD KNIGHT : Augh ! Ohh ! Don ' t\", 'say that word . ARTHUR : What word ? HEA')\n", "('HEAD KNIGHT : I cannot tell , suffice to', 'say is one of the words the Knights of N')\n", "('Ni cannot hear . ARTHUR : How can we not', \"say the word if you don ' t tell us \")\n", "(\" You wouldn ' t get vary far in life not\", \"saying ' is '. KNIGHTS OF NI : No , \")\n", "(': Aaaaugh ! HEAD KNIGHT : Aaaaugh ! Stop', 'saying the word ! The word ... ARTHUR : ')\n", "('ila raised the hand grenade up on high ,', \"saying ,' O Lord , bless this thy hand g\")\n", "(' . SECOND BROTHER : And the Lord spake ,', \"saying , ' First shalt thou take out the\")\n", "(' There ! Look ! LAUNCELOT : What does it', 'say ? GALAHAD : What language is that ? ')\n", "(\"CELOT : ' Course ! ARTHUR : What does it\", \"say ? MAYNARD : It reads , ' Here may \")\n", "(\" ! MAYNARD : Well , that ' s what it\", 'says . ARTHUR : Look , if he was dying ')\n", "(\"bother to carve ' aaggggh '. He ' d just\", \"say it ! MAYNARD : Well , that ' s \")\n", "(' : Oh , shut up . Well , does it', 'say anything else ? MAYNARD : No . Just ')\n", "('ided us ! FRENCH GUARD : How you English', \"say , ' I one more time , mac , \")\n" ] } ], "prompt_number": 60 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Wrapping up: Some of these tricks are used in today's search engines. You know now about some of the methods used in ElasticSearch analyzers, for instance." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### For a few more concordance links:\n", "* A Wallace Steven's poetry concordance: http://www.wallacestevens.com/concordance/WSdb.cgi\n", "* A Shakespearean concordance: http://www.opensourceshakespeare.org/concordance/\n", "* Software http://neon.niederlandistik.fu-berlin.de/en/textstat/\n", "* More deluxe software: http://www.concordancesoftware.co.uk/screenshots.htm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Javascript:\n", "\n", "Take a detour now to RiTa.js (https://github.com/dhowe/RiTaJS and http://rednoise.org/rita/) for related functionality in Javascript! And my own little toy project using it and POS: http://www.ghostweather.com/files/image_replacement/" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 60 } ], "metadata": {} } ] }