打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Python NLTK自然语言处理:词干、词形与MaxMatch算法

限时干货下载:

回复【999】免费获取【Python视频教程,从基础到进阶】资料

CSDN:白马负金羁

自然语言处理是计算机科学领域与人工智能领域中的一个重要方向。自然语言工具箱(NLTK,Natural Language Toolkit)是一个基于Python (http://lib.csdn.net/base/11)语言的类库,它也是当前最为流行的自然语言编程与开发工具。在进行自然语言处理研究和应用时,恰当利用NLTK中提供的函数可以大幅度地提高效率。本文就将通过一些实例来向读者介绍NLTK的使用。


开发环境:我所使用的Python版本是最新的3.5.1,NLTK版本是3.2。Python的安装不在本文的讨论范围内,我们略去不表。你可以从NLTK的官网上http://www.nltk.org/ 获得最新版本的NLTK。Anyway,使用pip指令来完成NLTK包的下载和安装无疑是最简便的方法。

当然,当你完成这一步时,其实还不够。因为NLTK是由许多许多的包来构成的,此时运行Python,并输入下面的指令(当然,第一条指令还是要导入NLTK包)


[python] view plain copy

  1. >>> import nltk  

  2. >>> nltk.download()  



然后,Python Launcher会弹出下面这个界面,建议你选择安装所有的Packages,以免去日后一而再、再而三的进行安装,也为你的后续开发提供一个稳定的环境。某些包的Status显示“out of date”,你可以不必理会,它基本不影响你的使用与开发。


既然你已经安装成功,我们来小试牛刀一下。当然本文涉及的主要任务都是自然语言处理中最常用,最基础的pre-processing过程,结合机器学习的高级应用我们会在后续文章中再进行介绍。


1、 Sentences Segment(分句)

也就是说我们手头有一段文本,我们希望把它分成一个一个的句子。此时可以使用NLTK中的 punkt sentence segmenter。来看示例代码


[python] view plain copy 

  1. >>> sent_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')  

  2. >>> paragraph = 'The first time I heard that song was in Hawaii on radio.   

  3. ... I was just a kid, and loved it very much! What a fantastic song!'  

  4. >>> sentences = sent_tokenizer.tokenize(paragraph)  

  5. >>> sentences  

  6. ['The first time I heard that song was in Hawaii on radio.',   

  7.  'I was just a kid, and loved it very much!',   

  8.  'What a fantastic song!']  



由此,我们便把一段话成功分句了。


2、Tokenize sentences (分词)

接下来我们要把每个句话再切割成逐个单词。最简单的方法是使用NLTK 包中的 WordPunct tokenizer。来看示例代码


[python] view plain copy 

  1. >>> from nltk.tokenize import WordPunctTokenizer  

  2. >>> sentence = 'Are you old enough to remember Michael Jackson attending   

  3. ... the Grammys with Brooke Shields and Webster sat on his lap during the show?'  

  4. >>> words = WordPunctTokenizer().tokenize(sentence)  

  5. >>> words  

  6. ['Are''you''old''enough''to''remember''Michael''Jackson''attending',  

  7.  'the''Grammys''with''Brooke''Shields''and''Webster''sat''on''his',  

  8.  'lap''during''the''show''?']  



我们的分词任务仍然完成的很好。除了WordPunct tokenizer之外,NLTK中还提供有另外三个分词方法,

TreebankWordTokenizer,PunktWordTokenizer和WhitespaceTokenizer,而且他们的用法与WordPunct tokenizer也类似。然而,显然我们并不满足于此。对于比较复杂的词型,WordPunct tokenizer往往并不胜任。此时我们需要借助正则表达式的强大能力来完成分词任务,此时我所使用的函数是regexp_tokenize()。来看下面这段话


[python] view plain copy 

  1. >>> text = 'That U.S.A. poster-print costs $12.40...'  


目前市面上可以参考的在Python下进行自然语言处理的书籍是由Steven Bird、Ewan Klein、Edward Loper编写的《Python 自然语言处理》。但是该书的编写时间距今已有近十年的时间,由于软件包更新等语言,在新环境下进行开发时,书中的某些代码并不能很正常的运行。最后,我们举一个书中代码out of date的例子(对上面这就话进行分词),并给出相应的解决办法。首先来看书中的一段节录


[python] view plain copy 

  1. >>> text = 'That U.S.A. poster-print costs $12.40...'  

  2. >>> pattern = r'''''(?x)    # set flag to allow verbose regexps 

  3. ...     ([A-Z]\.)+        # abbreviations, e.g. U.S.A. 

  4. ...   | \w+(-\w+)*        # words with optional internal hyphens 

  5. ...   | \$?\d+(\.\d+)?%?  # currency and percentages, e.g. $12.40, 82% 

  6. ...   | \.\.\.            # ellipsis 

  7. ...   | [][.,;''?():-_`]  # these are separate tokens; includes ], [ 

  8. ... '''  

  9. >>> nltk.regexp_tokenize(text, pattern)  



我们预期得到输出应该是这样的


[python] view plain copy 

  1. ['That''U.S.A.''poster-print''costs''$12.40''...']  


但是我们实际得到的输出却是这样的(注意我们所使用的NLTK版本)



[python] view plain copy

  1. [(''''''),  

  2.  ('A.'''''),  

  3.  ('''-print'''),  

  4.  (''''''),  

  5.  ('''''.40'),  

  6.  ('''''')]  


会出现这样的问题是由于nltk.internals.compile_regexp_to_noncapturing()在V3.1版本的NLTK中已经被抛弃(尽管在更早的版本中它仍然可以运行),为此我们把之前定义的pattern稍作修改


[python] view plain copy 

  1. pattern = r'''(?x)                   # set flag to allow verbose regexps 

  2.               (?:[A-Z]\.)+           # abbreviations, e.g. U.S.A. 

  3.               |\d+(?:\.\d+)?%?       # numbers, incl. currency and percentages 

  4.               |\w+(?:[-']\w+)*       # words w/ optional internal hyphens/apostrophe 

  5.               |\.\.\.                # ellipsis 

  6.               |(?:[.,;''?():-_`])    # special characters with meanings 

  7.             '''  


再次执行前面的语句,便会得到


[python] view plain copy 

  1. >>> nltk.regexp_tokenize(text, pattern)  

  2. ['That''U.S.A.''poster-print''costs''12.40''...']  


 

Python自然语言处理:词干、词形与MaxMatch算法


自然语言处理中一个很重要的操作就是所谓的stemming 和 lemmatization,二者非常类似。它们是词形规范化的两类重要方式,都能够达到有效归并词形的目的,二者既有联系也有区别。


1、词干提取(stemming)

定义:Stemming is the process for reducing inflected (or sometimes derived) words to their stem, base or root form—generally a written word form.

解释一下,Stemming 是抽取词的词干或词根形式(不一定能够表达完整语义)。


NLTK中提供了三种最常用的词干提取器接口,即 Porter stemmer, Lancaster Stemmer 和 Snowball Stemmer。

Porter Stemmer基于Porter词干提取算法,来看例子

[python] view plain copy 

  1. >>> from nltk.stem.porter import PorterStemmer  

  2. >>> porter_stemmer = PorterStemmer()  

  3. >>> porter_stemmer.stem(‘maximum’)  

  4. u’maximum’  

  5. >>> porter_stemmer.stem(‘presumably’)  

  6. u’presum’  

  7. >>> porter_stemmer.stem(‘multiply’)  

  8. u’multipli’  

  9. >>> porter_stemmer.stem(‘provision’)  

  10. u’provis’  

  11. >>> porter_stemmer.stem(‘owed’)  

  12. u’owe’  


Lancaster Stemmer 基于Lancaster 词干提取算法,来看例子


[python] view plain copy 

  1. >>> from nltk.stem.lancaster import LancasterStemmer  

  2. >>> lancaster_stemmer = LancasterStemmer()  

  3. >>> lancaster_stemmer.stem(‘maximum’)  

  4. ‘maxim’  

  5. >>> lancaster_stemmer.stem(‘presumably’)  

  6. ‘presum’  

  7. >>> lancaster_stemmer.stem(‘presumably’)  

  8. ‘presum’  

  9. >>> lancaster_stemmer.stem(‘multiply’)  

  10. ‘multiply’  

  11. >>> lancaster_stemmer.stem(‘provision’)  

  12. u’provid’  

  13. >>> lancaster_stemmer.stem(‘owed’)  

  14. ‘ow’  


Snowball Stemmer基于Snowball 词干提取算法,来看例子


[python] view plain copy 

  1. >>> from nltk.stem import SnowballStemmer  

  2. >>> snowball_stemmer = SnowballStemmer(“english”)  

  3. >>> snowball_stemmer.stem(‘maximum’)  

  4. u’maximum’  

  5. >>> snowball_stemmer.stem(‘presumably’)  

  6. u’presum’  

  7. >>> snowball_stemmer.stem(‘multiply’)  

  8. u’multipli’  

  9. >>> snowball_stemmer.stem(‘provision’)  

  10. u’provis’  

  11. >>> snowball_stemmer.stem(‘owed’)  

  12. u’owe’  



2、词形还原(lemmatization)

定义:Lemmatisation (or lemmatization) in linguistics, is the process of grouping together the different inflected forms of a word so they can be analysed as a single item.


可见,Lemmatisation是把一个任何形式的语言词汇还原为一般形式(能表达完整语义)。相对而言,词干提取是简单的轻量级的词形归并方式,最后获得的结果为词干,并不一定具有实际意义。词形还原处理相对复杂,获得结果为词的原形,能够承载一定意义,与词干提取相比,更具有研究和应用价值。


我们会在后面给出一个同MaxMatch算法相结合的更为复杂的例子。


3、最大匹配算法(MaxMatch)

MaxMatch算法在中文自然语言处理中常常用来进行分词(或许从名字上你已经能想到它是基于贪婪策略设计的一种算法)。通常,英语中一句话里的各个词汇之间通过空格来分割,这是非常straightforward的,但是中文却没有这个遍历。例如“我爱中华人民共和国”,这句话被分词的结果可能是这样的{‘我’,‘爱’,‘中华’,‘人民’,‘共和国’},又或者是{‘我’,‘爱’,‘中华人民共和国’},显然我们更倾向于后者的分词结果。因为‘中华人民共和国’显然是一个专有名词(把这样一个词分割来看显然并不明智)。我们选择后者的策略就是所谓的MaxMatch,即最大匹配。因为‘中华人民共和国’这个词显然要比‘中华’,‘人民’,‘共和国’这些词都长。


我们可以通过一个英文的例子来演示MaxMatch算法(其实中文处理的道理也是一样的)。算法从右侧开始逐渐减少字符串长度,以此求得可能匹配的最大长度的字符串。考虑到我们所获得的词汇可能包含有某种词型的变化,所以其中使用了Lemmatisation,然后在词库里进行匹配查找。

[python] view plain copy 

  1. from nltk.stem import WordNetLemmatizer  

  2. from nltk.corpus import words  

  3.   

  4. wordlist = set(words.words())  

  5. wordnet_lemmatizer = WordNetLemmatizer()  

  6.   

  7. def max_match(text):  

  8.     pos2 = len(text)  

  9.     result = ''  

  10.     while len(text) > 0:         

  11.         word = wordnet_lemmatizer.lemmatize(text[0:pos2])  

  12.         if word in wordlist:  

  13.             result = result + text[0:pos2] + ' '  

  14.             text = text[pos2:]  

  15.             pos2 = len(text)  

  16.         else:  

  17.             pos2 = pos2-1                 

  18.     return result[0:-1]  


来看看算法的实现效果



[python] view plain copy 

  1. >>> string = 'theyarebirds'  

  2. >>> print(max_match(string))  

  3. they are birds  


当然,上述代码尚有一个不足,就是当字符串中存在非字母字符时(例如数字标点等),它可能会存在一些问题。有兴趣的读者不妨自己尝试完善改进这个版本的实现。


以上便是我们对NLTK这个自然语言处理工具包的初步探索,最后,我想说《Python 自然语言处理》仍然是当前非常值得推荐的一本讲述利用NLTK和Python进行自然语言处理技术的非常值得推荐的书籍。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Python文本预处理:步骤、使用工具及示例
Python自然语言工具包(NLTK)入门
ML之H-Clusters:基于H-Clusters算法利用电影数据集实现对top 100电影进行文档分类
英文文本挖掘预处理流程总结
用于文本数据分析的 Pandas:使用 str 访问器清理和操作文本数据
word_in_context | 查看某类词的上下文,更好的理解文本数据
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服