“认知”的核心技术是天然语言处理,这是人工智能领域中的一个重要方向,研究各类理论和方法,涉及的领域较多,主要包括机器翻译、阅读理解、智能写做、对话系统、基础技术和语义计算等。css
计算机能“理解并开口说话”,意味着与人类可进行更普遍的交流,从而一步步逼近并超越“图灵测试”,让人工智能掀开新的篇章。html
《Python和NLTK天然语言处理》python
做者 [印度] 尼天•哈登尼亚(Nitin Hardeniya) 雅各布•帕金斯(Jacob Perkins) 迪蒂•乔普拉(Deepti Chopra) 尼什•斯乔希(Nisheeth Joshi) 伊提•摩突罗(Iti Mathur)linux
语言是咱们平常生活的核心部分,处理与语言相关的任何问题都是很是有趣的。我但愿此书可以让你一嗅NLP的芬芳,激励你去了解更使人惊奇的NLP概念,并鼓励你开发一些具备挑战性的NLP应用。程序员
研究人类语言的过程称为NLP。深刻研究语言的人称为语言学家,而“计算语言学家”这个专有名词适用于应用计算研究语言处理的人。从本质上讲,计算语言学家是深刻了解语言的计算机科学家,计算语言学家能够运用计算技能,对语言的不一样方面进行建模。计算语言学家解决的是语言理论方面的问题,NLP只不过是计算语言学的应用。web
NLP更多探讨的是应用计算机,处理不一样语言的细微差异,以及使用NLP技术构建现实世界的应用。在实际情景下,NLP相似于教孩子学语言。一些最多见的任务(如理解单词和句子,造成在语法和结构上正确的句子)对人类而言是很天然。在NLP领域,把这样的一些任务转化为标记解析(tokenization)、组块(chunking)、词性标注(part of speech tagging)、解析(parsing)、机器翻译(machine translation)、语音识别(speech recognition),这些任务中的大部分依然是计算机所面临的最严峻的挑战。正则表达式
本文主要内容以下。算法
若是你历来没有据说过NLP这个词,那么请花一些时间来阅读这里提到的任何一本书籍,只要阅读最初几章便可。至少要快速阅读一些与NLP相关的维基百科网页。express
本节从Gartner的技术成熟度曲线开始讨论,从这条曲线上,你能够清楚地看到NLP处在技术成熟度曲线的顶部。目前,NLP是行业所需的稀有技能之一。在大数据到来以后,NLP面临的主要的挑战是,NLP须要大量不但精通结构化数据并且擅长于处理半结构化或非结构化数据的技术人员。咱们正在生成拍字节量级的网络博客、推特信息、脸书(Facebook)的推送信息、聊天记录、电子邮件和评论。一些公司正在收集全部这些不一样种类的数据,以便更好地为客户定位,并从中获得有意义的看法。为了处理这些非结构化数据源,咱们须要了解NLP的技术人员。编程
咱们身处信息时代;咱们甚至不能想象生活中没有谷歌。咱们使用Siri来处理大多数基本的语音功能。咱们使用垃圾邮件过滤器过滤垃圾邮件。在Word文档中,咱们须要拼写检查器。在咱们周围,存在许多NLP在现实世界中应用的例子。
(图片来自gartner网站)
下面也提供一些你可以使用可是没有意识它们是创建在NLP上的使人赞叹的NLP应用的示例。
构建这些应用须要一种很是特殊的技能集,你须要对语言很是了解,并具备能够有效处理语言的工具。所以,让NLP成为最具优点的领域之一的缘由不是广告宣传,而是可使用NLP建立的这种应用使得NLP成为必备的最独特技能之一。
为了实现上述的一些应用,以及其余基本的NLP预处理,咱们有不少可用的开源工具。在这些工具中,有一些是某些组织为创建本身的NLP应用而开发的,而有一些是开源的。这里是一张可用的NLP工具列表。
大部分工具是用Java编写的,具备类似的功能。其中一些工具很是健壮,能够得到NLP工具的不一样版本。可是,当涉及易于使用和易于解释这两个概念的时候,NLTK得分最高。因为Python(NLTK的编码语言)的学习曲线很是快,所以NLTK也是很是易于学习的工具包。NLTK已经将大部分的NLP任务归入篮中,很是优雅,容易用于工做中。出于全部这些缘由,NLTK已成为NLP界最流行的库之一。
建议使用Anaconda和Canopy Python的发行版本。理由是,这些版本绑定了一些库,如scipy、numpy、scikit等,你可使用这些库进行数据分析,开发出与NLP有关的应用,以及把这些库应用于相关领域。即便NLTK也是这个发行版本的一部分。
下面测试全部功能。
请在相应的操做系统中,启动终端。而后运行:
$ python复制代码
这应该打开了Python解释器。
1Python 2.6.6 (r266:84292, Oct 15 2013, 07:32:41)
2[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
3Type "help", "copyright", "credits" or "license" for more information.
4>>>复制代码
我但愿你获得的输出与这个相似。你有可能获得一个不一样的输出,可是在理想状况下,你得到了Python的最新版本(建议的版本是2.7)信息、编译器GCC的信息,以及操做系统的详细信息。Python的最新版本是3.0+,可是,与任何其余开源的系统同样,咱们应该试图保持相对稳定的版本,而不是跳跃到最新版本。若是你已经使用了Python 3.0+,那么请从python网站了解新版本中又添加了哪些新特征。
基于UNIX的系统将Python做为默认程序。Windows用户能够设置路径,让Python正常运行。下面检查一下是否已经正确安装了NLTK。
1>>>import nltk
2>>>print "Python and NLTK installed successfully"
3Python and NLTK installed successfully复制代码
咱们准备好了。
本节不会深刻探讨Python。然而,咱们会让你快速浏览一遍Python的基本知识。一样,为了读者的利益,我认为应该来一段5分钟的Python之旅。接下来的几节将谈论数据结构的基本知识、一些经常使用的函数,以及Python的通常构建方式。
在Python中,列表是最经常使用的数据结构之一。它们几乎至关于其余编程语言中的数组。下面从Python列表所提供的一些最重要的函数开始讲述。
在Python控制台中,尝试输入如下内容。
11>>> lst=[1,2,3,4]
22>>> # mostly like arrays in typical languages
33>>>print lst
44[1, 2, 3, 4]复制代码
可使用更加灵活的索引来访问Python列表。下面是一些例子。
>>>print 'First element' +lst[0]复制代码
你会获得这样的错误消息:
TypeError: cannot concatenate 'str' and 'int' objects复制代码
缘由是Python是一种解释性语言,咱们在声明变量时,不须要初始化变量并声明变量的类型,Python只有在计算表达式时,才检查变量类型。在列表中,对象是整数类型的,所以它们不能与print函数串接。这个函数只接受字符串对象。出于这个缘由,咱们须要将列表元素转换为字符串。这个过程也称为强制类型转换(typecasting)。
1>>>print 'First element :' +str(lst[0])
2>>>print 'last element :' +str(lst[-1])
3>>>print 'first three elements :' +str(lst[0:2])
4>>>print 'last three elements :'+str(lst[-3:])
5First element :1
6last element :4
7first three elements :[1, 2,3]
8last three elements :[2, 3, 4]复制代码
了解更多不一样的数据类型和函数的最佳方法是使用帮助函数,如help() 和 dir(lst)。
可使用dir(Python对象)命令,列出给定Python对象的全部给定的属性。若是传入一个列表对象,那么这个函数会列出全部可使用列表执行的酷炫的操做。
1>>>dir(lst)
2>>>' , '.join(dir(lst))
3'__add__ , __class__ , __contains__ , __delattr__ , __delitem__ , __ 4delslice__ , __doc__ , __eq__ , __format__ , __ge__ , __getattribute__ 5, __getitem__ , __getslice__ , __gt__ , __hash__ , __iadd__ , __imul__ 6, __init__ , __iter__ , __le__ , __len__ , __lt__ , __mul__ , __ne__ , 7__new__ , __reduce__ , __reduce_ex__ , __repr__ , __reversed__ , __rmul__ 8, __setattr__ , __setitem__ , __setslice__ , __sizeof__ , __str__ , __ 9subclasshook__ , append , count , extend , index , insert , pop , remove 10, reverse , sort'复制代码
使用help(Python对象)命令,咱们能够获得给定Python对象的详细文档,而且这个命令也给出一些示例,告诉咱们如何使用Python对象。
1>>>help(lst.index)
Help on built-in function index:
index(...)
4 L.index(value, [start, [stop]]) -> integer -- return first index of value.
This function raises a ValueError if the value is not present.复制代码
所以,在Python的任何数据类型上,均可以使用help和dir,而且这是一种很是不错的方式,可用于了解关于函数和对象的其余详细信息。这也提供了一些基本示例,供你在工做中参考,在大部分状况下,这些示例很是有用。
在Python和其余语言中,字符串都很是类似,可是对字符串的操做是Python的主要特征之一。在Python中,使用字符串很是容易。在Java/C中,即便是一些很简单的操做(例如将字符串分割),咱们也须要花很大的精力才能作到。然而,在Python中,你会发现这是多么容易。
在应用任何Python对象和函数时,你均可以从先前的help函数中得到帮助。下面使用最经常使用的数据类型字符串给你提供更多的例子。
1 >>> mystring="Monty Python ! And the holy Grail ! \n"
2 >>> print mystring.split()
3 ['Monty', 'Python', '!', 'and', 'the', 'holy', 'Grail', '!']复制代码
1 >>> print mystring.strip()
2 >>>Monty Python ! and the holy Grail !复制代码
你是否发现'\n'字符被移除了?还有其余方法(如lstrip()和rstrip())能够移除字符串左侧和右侧的尾随空格。
1 >>> print (mystring.upper()
2 >>>MONTY PYTHON !AND THE HOLY GRAIL !复制代码
1 >>> print mystring.replace('!','''''')
2 >>> Monty Python and the holy Grail复制代码
刚才谈到的是一些最经常使用的字符串函数,函数库中还存在大量的字符串函数。
提示:要了解更多函数和示例,请浏览Python网站。
NLP发烧友的另一个重要技能是使用正则表达式工做。正则表达式描述了字符串的有效模式匹配。咱们大量使用模式提取从众多杂乱无章的文本数据中得到有意义的信息。如下是读者所须要的正则表达式。在我一辈子中,我所用的正则表达式都不会超过这个范围。
例如,要匹配$符号,能够在它前面加上\。
在现行的例子(即mystring是相同的字符串对象)中,搜索一些内容,而且试图在此字符串对象上寻找一些模式。子字符串搜索是re模块的其中一个通用用例。下面实现这一功能。
1>>># We have to import re module to use regular expression
2>>>import re
3>>>if re.search('Python',mystring):
4>>> print "We found python "
5>>>else:
6>>> print "NO "复制代码
一旦执行代码,获得的消息以下。
We found python复制代码
可使用正则表达式进行更多的模式查找。为了找到字符串中的全部模式,咱们使用的其中一个普通的函数是findall。这个函数搜索字符串中特定的模式,而且会给出一个包含全部匹配对象的列表。
1>>>import re
2>>>print re.findall('!',mystring)
3['!', '!']复制代码
正如咱们所见,在mystring中,有两个“!”实例,findall使用一个列表,返回了这两个对象。
词典是另外一种最经常使用的数据结构,在其余编程语言中,这也称为关联数组/关联记忆(associative array/memory)。词典是使用键(key)进行索引的数据结构,这些键能够是任何不可变的类型,如字符串和数字能够用做键。
词典是很是方便的数据结构,普遍应用于各类编程语言中来实现多种算法。在众多的编程语言中,Python词典是其中一个优雅地实现了散列表的词典。在其余语言中,相同的任务,可能须要花费更多的时间进行更繁重的编码工做,可是使用词典,工做就变得很是容易。最棒的事情是,程序员仅仅使用少许的代码块,就能够创建很是复杂的数据结构。这使得程序员摆脱了数据结构自己,花更多时间专一于算法。
我使用词典中一个很常见的用例,在给定的文本中,得到单词的频率分布。使用如下几行代码,就能够获得单词的频率。你可试着使用任意其余的语言执行相同的任务,立刻就会明白Python是多么让人赞叹不已。
1>>># declare a dictionary
2>>>word_freq={}
3>>>for tok in string.split():
4>>> if tok in word_freq:
5>>> word_freq [tok]+=1
6>>> else:
7>>> word_freq [tok]=1
8>>>print word_freq
9{'!': 2, 'and': 1, 'holy': 1, 'Python': 1, 'Grail': 1, 'the': 1, 'Monty':
101}复制代码
正如其余编程语言,Python也有其编写函数的方式。在Python中,函数以关键字def开始,而后是函数名和圆括号()。这与其余编程语言类似,即任何参数和参数的类型都放在圆括号内。实际的代码以冒号(:)开头。代码的初始行一般是文档字符串(注释),而后才是代码体,函数使用return语句结束。例如,在给定的例子中,函数wordfreq以def关键字开始,这个函数没有参数,而且以return语句结束。
1>>>import sys
2>>>def wordfreq (mystring):
3>>> ''' 4>>> Function to generated the frequency distribution of the given text 5>>> '''
6>>> print mystring
7>>> word_freq={}
8>>> for tok in mystring.split():
9>>> if tok in word_freq:
10>>> word_freq [tok]+=1
11>>> else:
12>>> word_freq [tok]=1
13>>> print word_freq
14>>>def main():
15>>> str="This is my fist python program"
16>>> wordfreq(str)
17>>>if __name__ == '__main__':
18>>> main()复制代码
这与上一节中所写的代码是相同的,使用函数的形式进行编写的思想使得代码可重用和可读。虽然在编写Python代码时解释器方式也很常见,可是对于大型程序,使用函数/类是一种很是好的作法,这也是一种编程范式。咱们也但愿用户可以编写和运行第一个Python程序。你须要按照下列步骤来实现这一目标。
(1)在首选的文本编辑器中,打开一个空的Python文件mywordfreq.py。
(2)编写或复制以上代码段中的代码到文件中。
(3)在操做系统中,打开命令提示符窗口。
(4)运行如下命令。
$ python mywordfreq,py "This is my fist python program !!"复制代码
(5)输出应该为:
{'This': 1, 'is': 1, 'python': 1, 'fist': 1, 'program': 1, 'my': 1}复制代码
如今,对Python提供的一些常见的数据结构,你有了一个很是基本的了解。你能够写一个完整而且可以运行的Python程序。我认为这些已经足够了,使用这些Python的入门知识,你能够看懂本书前几章。
提示:请观看维基百科网站中的一些Python教程,学习更多的Python命令。
无须进一步研究天然语言处理的理论,下面开始介绍NLTK。咱们从一些NLTK的基本示例用例开始。大家中的一些人,可能已经作过了相似的事情。首先,本节会给出一些典型Python程序员的作法,而后会转到NLTK,寻找一个更加高效、更增强大和更加清晰的解决方案。
下面从某个示例文本内容的分析开始。对于当前的例子,从Python的主页上得到了一些内容以下所示。
1>>>import urllib2
2>>># urllib2 is use to download the html content of the web link
3>>>response = urllib2.urlopen('http://python.org/')
4>>># You can read the entire content of a file using read() method
5>>>html = response.read()
6>>>print len(html)
747020复制代码
因为咱们对在这个URL中所讨论的主题类型没有任何线索,所以从探索性数据分析(EDA)开始。通常来讲,在文本领域,EDA具备多种含义,可是这里讨论一种简单的状况,即在文档中,何种术语占据了主导地位。主题是什么?它们出现的频率有多大?这一过程将涉及某种层次的预处理步骤。咱们首先使用纯Python方式,尝试执行这个任务,而后会使用NLTK执行这个任务。
让咱们从清理HTML标签开始。完成这个任务的一种方式是仅仅选择包括了数字和字符的标记(token)。任何可以使用正则表达式工做的人员应该可以将HTML字符串转换成标记列表。
1>>># Regular expression based split the string
2>>>tokens = [tok for tok in html.split()]
3>>>print "Total no of tokens :"+ str(len(tokens))
4>>># First 100 tokens
5>>>print tokens[0:100]
6Total no of tokens :2860
7['', '', '', ''type="text/css"', 'media="not', 'print,', 'braille,'...] 8 复制代码
正如你所看到的,使用前面的方法,存在过量的HTML标签和其余可有可无的字符。执行同一任务的相对清洁的版本,以下所示。
1>>>import re
2>>># using the split function
3>>>#https://docs.python.org/2/library/re.html
4>>>tokens = re.split('\W+',html)
5>>>print len(tokens)
6>>>print tokens[0:100]
75787
8['', 'doctype', 'html', 'if', 'lt', 'IE', '7', 'html', 'class', 'no',
9'js', 'ie6', 'lt', 'ie7', 'lt', 'ie8', 'lt', 'ie9', 'endif', 'if',
10'IE', '7', 'html', 'class', 'no', 'js', 'ie7', 'lt', 'ie8', 'lt', 'ie9',
11'endif', 'if', 'IE', '8', 'msapplication', 'tooltip', 'content', 'The',
12'official', 'home', 'of', 'the', 'Python', 'Programming', 'Language',
13'meta', 'name', 'apple' ...]复制代码
如今,这看起来清爽多了。可是,你能够作更多的事情,使代码变得更加简洁。这里将这项工做留给你,让你尝试移除尽量多的噪声。能够清除一些仍然弹出的HTML标签。在这个例子中,字长为1的单词(如7和8这样的元素)仅仅是噪声,你可能但愿以字长做为标准,移除这些单词。如今,与其从头开始编写一些预处理步骤的代码,不如将目光转移到NLTK,使用NTLK执行相同的任务。有一个函数clean_html(),这个函数能够执行所须要的全部清洁工做。
1>>>import nltk
2>>># http://www.nltk.org/api/nltk.html#nltk.util.clean_html
3>>>clean = nltk.clean_html(html)
4>>># clean will have entire string removing all the html noise
5>>>tokens = [tok for tok in clean.split()]
6>>>print tokens[:100]
7['Welcome', 'to', 'Python.org', 'Skip', 'to', 'content', '▼',
8'Close', 'Python', 'PSF', 'Docs', 'PyPI', 'Jobs', 'Community', '▲',
9'The', 'Python', 'Network', '≡', 'Menu', 'Arts', 'Business' ...]复制代码
这很酷炫,对吧?这种方法绝对更加清洁,也更容易执行。
下面尝试得到这些术语的频率分布。首先,咱们使用纯Python的方式执行这个任务,而后,我将告诉你NLTK的秘诀。
1>>>import operator
2>>>freq_dis={}
3>>>for tok in tokens:
4>>> if tok in freq_dis:
5>>> freq_dis[tok]+=1
6>>> else:
7>>> freq_dis[tok]=1
8>>># We want to sort this dictionary on values ( freq inthis case )
9>>>sorted_freq_dist= sorted(freq_dis.items(), key=operator.itemgetter(1),
10reverse=True)
11>>> print sorted_freq_dist[:25]
12[('Python', 55), ('>>>', 23), ('and', 21), ('to', 18), (',', 18), ('the',
1314), ('of', 13), ('for', 12), ('a', 11), ('Events', 11), ('News', 11),
14('is', 10), ('2014-', 10), ('More', 9), ('#', 9), ('3', 9), ('=', 8),
15('in', 8), ('with', 8), ('Community', 7), ('The', 7), ('Docs', 6),
16('Software', 6), (':', 6), ('3:', 5), ('that', 5), ('sum', 5)]复制代码
天然而然地,因为这是Python主页,所以Python和(>>>)解释器符号是最多见的术语,这也展现了网站的第一感受。
一个更好而且更有效的方法是使用NLTK的FreqDist()函数。为了进行对比,咱们能够观察以前开发的执行相同任务的代码。
1>>>import nltk
2>>>Freq_dist_nltk=nltk.FreqDist(tokens)
3>>>print Freq_dist_nltk
4>>>for k,v in Freq_dist_nltk.items():
5>>> print str(k)+':'+str(v)
6>>': 23, 'and': 21, ',': 18, 'to': 18, 'the': 714, 'of': 13, 'for': 12, 'Events': 11, 'News': 11, ...> 8Python:55 9>>>:23 10and:21 11,:18 12to:18 13the:14 14of:13 15for:12 16Events:11 17News:11 18复制代码
如今,让咱们作一些更有趣的事情,画出这些频率分布。
1>>>Freq_dist_nltk.plot(50, cumulative=False)
2>>># below is the plot for the frequency distributions复制代码
能够看到,累积频率持续增加,总体上,曲线有一条长长的尾巴。一些噪声依然存在,一些单词(如the、of、for和=)是毫无用处的。对于这些单词(如the、a、an等),使用术语停用词(stop word)来称呼它们。因为在大部分文档中不定代词通常都会出现,所以这些词没有什么判别力,不能传达太多的信息。在大多数的NLP和信息检索任务中,人们一般会删除停用词。让咱们再次回到当前的示例中。
1>>>stopwords=[word.strip().lower() for word in open("PATH/english.stop. 2txt")]
3>>>clean_tokens=[tok for tok in tokens if len(tok.lower())>1 and (tok.
4lower() not in stopwords)]
5>>>Freq_dist_nltk=nltk.FreqDist(clean_tokens)
6>>>Freq_dist_nltk.plot(50, cumulative=False)复制代码
如今,这看起来干净多了!在完成了这么多任务后,能够访问Wordle,将频率分布转换成CSV格式。你应该可以获得如下词云。
书号:978-7-115-50334-3
推荐理由:NLTK是天然语言处理领域中很是受欢迎和普遍使用的Python库。NLTK的优势在于其简单性,其中大多数复杂的天然语言处理任务使用几行代码便可完成。本书旨在讲述如何用Python和NLTK解决各类天然语言处理任务并开发机器学习方面的应用。本书介绍了NLTK的基本模块,讲述了采用NLTK实现天然语言处理的大量技巧,讨论了一些文本处理方法和语言处理技术,展现了使用Python实现NLP项目的大量实践经验。本书主要内容包括文本挖掘/NLP任务中所需的全部预处理步骤,如何使用Python 3的NLTK 3进行文本处理,如何经过Python开展NLP项目。
本书适合NLP和机器学习领域的爱好者、Python程序员以及机器学习领域的研究人员阅读。
- END -