《NLTK基础教程——用NLTK和Python库构建机器学习应用》——1.3 向NLTK迈进

    xiaoxiao2024-05-10  6

    本节书摘来异步社区《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书中的第1章,第1.3节,作者:Nitin Hardeniya,更多章节内容可以访问云栖社区“异步社区”公众号查看。

    1.3 向NLTK迈进

    尽管在这里,我们并不打算深入探讨自然语言处理理论,但也会尽快让你实际接触一下NLTK。因此,我打算先介绍一些NLTK的基本用例,这是一个很好的机会,你可以先为今后做类似事情做一些准备。下面,我们会从一个Python程序员习惯的处理方式切入,演示如何用NLTK将该方式转换成一个更为高效、可靠、简洁的解决方案。

    我们先来看一个纯文本分析的例子。这个例子是我们要从Python官方主页上摘取部分内容。

    >>>import urllib2 >>># urllib2 is use to download the html content of the web link >>>response = urllib2.urlopen('http://python.org/') >>># You can read the entire content of a file using read() method >>>html = response.read() >>>print len(html) 47020

    目前,我们还没有得到任何关于该URL所讨论话题的线索,所以接下来,我们要先做一次探索性数据分析(EDA)。通常对于一段文本域而言,EDA可能包含了多重含义,但这里只会涉及其中的一个简单用例,即该文档的主体术语类型。主题是什么?它们的出现频率如何?整个分析过程还会或多或少地涉及一些预处理层面的步骤。我们会试着先用纯Python的方式来实现它,然后用NLTK再将其实现一次。

    我们先要清理掉其中的html标签。一种可行的做法是只选取其中的标记,包括数字和字符。如果之前有在工作中使用过正则表达式,你应该可以轻松地将这些html字符串转换成一个标记列表:

    >>># Regular expression based split the string >>>tokens = [tok for tok in html.split()] >>>print "Total no of tokens :"+ str(len(tokens)) >>># First 100 tokens >>>print tokens[0:100] Total no of tokens :2860 ['<!doctype', 'html>', '<!--[if', 'lt', 'IE', '7]>', '<html', 'class="no- js', 'ie6', 'lt-ie7', 'lt-ie8', 'lt-ie9">', '<![endif]-->', '<!--[if', 'IE', '7]>', '<html', 'class="no-js', 'ie7', 'lt-ie8', 'lt-ie9">', '<![endif]-->', ''type="text/css"', 'media="not', 'print,', 'braille,' ...]

    如你所见,上面列出了我们在处理文本内容时用不到的HTML标签和其他多余字符。当然,这个任务还有个更为简洁的版本:

    >>>import re >>># using the split function >>>#https://docs.python.org/2/library/re.html >>>tokens = re.split('\W+',html) >>>print len(tokens) >>>print tokens[0:100] 5787 ['', 'doctype', 'html', 'if', 'lt', 'IE', '7', 'html', 'class', 'no', 'js', 'ie6', 'lt', 'ie7', 'lt', 'ie8', 'lt', 'ie9', 'endif', 'if', 'IE', '7', 'html', 'class', 'no', 'js', 'ie7', 'lt', 'ie8', 'lt', 'ie9', 'endif', 'if', 'IE', '8', 'msapplication', 'tooltip', 'content', 'The', 'official', 'home', 'of', 'the', 'Python', 'Programming', 'Language', 'meta', 'name', 'apple' ...]

    这样看上去已经简洁多了吧?但其实它还可以更简洁一点。在这里,我们所做的努力是尽可能地去除干扰,但那些被清理的HTML标记还是会如雨后春笋般地冒出来,而且我们可能也想以单词长度为标准,删除某一特定长度的单词——如说移除像7、8这样的元素,因为在目前情况下,这些都只是干扰词。现在,我们要做的不是用NLTK来重复相同的任务,完成这些预处理步骤。因为所有的清理工作都可以通过调用clean_html()函数[3]来完成:

    >>>import nltk >>># http://www.nltk.org/api/nltk.html#nltk.util.clean_html >>>clean = nltk.clean_html(html) >>># clean will have entire string removing all the html noise >>>tokens = [tok for tok in clean.split()] >>>print tokens[:100] ['Welcome', 'to', 'Python.org', 'Skip', 'to', 'content', '& #9660;', 'Close', 'Python', 'PSF', 'Docs', 'PyPI', 'Jobs', 'Community', '& #9650;', 'The', 'Python', 'Network', '≡', 'Menu', 'Arts', 'Business' ...]

    很酷吧?而且,这无疑让我们的代码更简洁易行了。

    下面再来看看如何获得这些术语的频率分布。当然,我们还是要从纯Python的方式做起,之后再告诉你NLTK的方式。

    >>>import operator >>>freq_dis={} >>>for tok in tokens: >>> if tok in freq_dis: >>> freq_dis[tok]+=1 >>> else: >>> freq_dis[tok]=1 >>># We want to sort this dictionary on values ( freq in this case ) >>>sorted_freq_dist= sorted(freq_dis.items(), key=operator.itemgetter(1), reverse=True) >>>print sorted_freq_dist[:25] [('Python', 55), ('>>>', 23), ('and', 21), ('to', 18), (',', 18), ('the', 14), ('of', 13), ('for', 12), ('a', 11), ('Events', 11), ('News', 11), ('is', 10), ('2014-', 10), ('More', 9), ('#', 9), ('3', 9), ('=', 8), ('in', 8), ('with', 8), ('Community', 7), ('The', 7), ('Docs', 6), ('Software', 6), (':', 6), ('3:', 5), ('that', 5), ('sum', 5)]

    由于目标是Python的官方主页,Python和(>>>)解释器符号自然就成了最常用的术语,这也符合该网站给人的感觉。

    当然,这个任务还有一个更好用、也更有效的方法,即调用NLTK中的FreqDist()函数。在此,我们可以来看看调用后前相同代码的比对:

    >>>import nltk >>>Freq_dist_nltk=nltk.FreqDist(tokens) >>>print Freq_dist_nltk >>>for k,v in Freq_dist_nltk.items(): >>> print str(k)+':'+str(v) < FreqDist: 'Python': 55, '>>>': 23, 'and': 21, ',': 18, 'to': 18, 'the': 14, 'of': 13, 'for': 12, 'Events': 11, 'News': 11, ...> Python:55 >>>:23 and:21 ,:18 to:18 the:14 of:13 for:12 Events:11 News:11

    注意 小技巧:  

    下载示例代码 

    你在http://www.packtpub.com中登录你的账户,从中可以下载你所购买的、由Packt出版的所有书籍的示例代码。如果你在别处购得此书,也可以在http://www. packtpub.com/support上注册相关文件,我们会用E-mail将其直接发送给你。现在,让我们来做一些更时髦的事。我们来绘制这样的一张图,如图1-2所示。

    >>>Freq_dist_nltk.plot(50, cumulative=False) >>># below is the plot for the frequency distributions

    在图1-2中,我们可以看到累积频率的即时增长,在某些点上曲线会进入一条长长的尾巴。其中依然存在着一些干扰,有些类似于the、of、for以及=这样的词都是属于无用词,这些词有一个专用术语:停用词。如the、a、an这样的词也都属于停用词。由于冠词、代词在大多数文档中都是普遍存在的,因而对信息的识别没有帮助。在大多数NLP及信息检索任务中,人们通常都会先删除掉这些停用词。下面,让我们再次回到之前运行的那个例子中,绘制结果如图1-3所示。

    >>>stopwords=[word.strip().lower() for word in open("PATH/english.stop. txt")] >>>clean_tokens=[tok for tok in tokens if len(tok.lower())>1 and (tok. lower() not in stopwords)] >>>Freq_dist_nltk=nltk.FreqDist(clean_tokens) >>>Freq_dist_nltk.plot(50, cumulative=False)

    注意 提示: 

    如果想知道关于词云的更多信息,请访问http://www. wordle.net/advanced。

    现在,代码看起来简洁多了吧!在完成这么多事后,你可以去Wordle网站上将其频率分布以CSV形式显示出来,可以得到如图1-4所示词云图。

    最新回复(0)