Python3自然语言处理——词性标注
词性标注是对给定句子中的单词进行词性(Parts of Speech,POS)分类的过程。实现标注目的的软件称为词性标注器(tagger)。NLTK支持多种标注器。
1.内置的词性标注器
创建一个新文件,命名为Exploring.py,输入以下代码:
import nltk
simpleSentence="Beijing is the capital of China."
wordsInSentence=nltk.word_tokenize(simpleSentence)
print(wordsInSentence)
partsOfSpeechTags=nltk.pos_tag(wordsInSentence)
print(partsOfSpeechTags)
第1行代码指示Python解释器将NLTK模块从磁盘加载到内存,并使NLTK库在程序中可用。第2行创建了一个名为simpleSentence的变量,并定义为一个字符串。第3行代码调用了NLTK内置的word_tokenize()函数,它将给定的句子分解成单词并返回一个Python列表数据类型。一旦得到由函数计算的结果,我们就将其分配给wordsInSentence变量。第4行代码调用了Python内置的print()函数,它显示了如屏幕所示的数据结构。在本例中,我们显示了所有标注的单词列表。仔细观察这些输出,屏幕上显示了一个Python列表的数据结构,它由以逗号分隔的所有字符串组成,所有的列表元素都括在方括号内。第5行代码调用了内置的标注器pos_tag(),通过wordsInsentence变量生成一个单词列表,同时也标注了词性。一旦标注完成,就会生成完整的元组列表,每个元组都有标记的单词和相应的词性标注,最后通过第6行代码在屏幕上打印出给定的参数,结果如下:
["Beijing", "is", "the", "capital", "of", "China", "."]
[("Beijing", "NNP"), ("is", "VBZ"), ("the", "DT"), ("capital", "NN"), ("of", "IN"), ("China", "NNP"), (".", ".")]
在这个实例中,我们可以看到元组列表中的每个元组都由原始单词和POS标注组成。
2.编写自己的词性标注器
创建一个新文件,命名为OwnTagger.py输入以下源代码:
import nltk
def learnDefaultTagger(simpleSentence):
wordsInSentence=nltk.word_tokenize(simpleSentence)
tagger=nltk.DefaultTagger("NN")
posEnabledTags=tagger.tag(wordsInSentence)
print(posEnabledTags)
def learnRETagger(simpleSentence):
customPatterns=[
(r".*ing$","ADJECTIVE"),
(r".*ly$","ADVERB"),
(r".*ion$","NOUN"),
(r"(.*ate|.*en|is)$","VERB"),
(r"^an$","INDEFINITE-ARTICLE"),
(r"^(with|on|at)$","PREPOSITION"),
(r"^\-?[0-9]+(\.[0-9]+)$","NUMBER"),
(r">*$","None")
]
tagger=nltk.RegexpTagger(customPatterns)
wordsInSentence=nltk.word_tokenize(simpleSentence)
posEnabledTags=tagger.tag(wordsInSentence)
print(posEnabledTags)
def learnLookupTagger(simpleSentence):
mapping={
".":".","place":"NN","on":"IN","earth":"NN",
"Mysore":"NNP","is":"VBZ","an":"DT","amazing":"JJ"
}
tagger=nltk.UnigramTagger(model=mapping)
wordsInSentence=nltk.word_tokenize(simpleSentence)
posEnabledTags=tagger.tag(wordsInSentence)
print(posEnabledTags)
if __name__=="__main__":
testSentence="Mysore is an amazing place on earth. I have visited Mysore 10 times."
learnDefaultTagger(testSentence)
learnRETagger(testSentence)
learnLookupTagger(testSentence)
结果如下:
[("Mysore", "NN"), ("is", "NN"), ("an", "NN"), ("amazing", "NN"), ("place", "NN"), ("on", "NN"), ("earth", "NN"), (".", "NN"), ("I", "NN"), ("have", "NN"), ("visited", "NN"), ("Mysore", "NN"), ("10", "NN"), ("times", "NN"), (".", "NN")]
[("Mysore", None), ("is", "VERB"), ("an", "INDEFINITE-ARTICLE"), ("amazing", "ADJECTIVE"), ("place", None), ("on", "PREPOSITION"), ("earth", None), (".", None), ("I", None), ("have", None), ("visited", None), ("Mysore", None), ("10", None), ("times", None), (".", None)]
[("Mysore", "NNP"), ("is", "VBZ"), ("an", "DT"), ("amazing", "JJ"), ("place", "NN"), ("on", "IN"), ("earth", "NN"), (".", "."), ("I", None), ("have", None), ("visited", None), ("Mysore", "NNP"), ("10", None), ("times", None), (".", ".")]
第一个(3-7行)函数名为learnDefaultTagger,它接收一个名为simpleSentence的参数。第4行从NLTK库调用word_tokenize函数,将simpleSentence作为第一个参数传递给这个函数。调用这个函数处理数据后,返回值是一个单词列表,并存储在InSentence变量中。第5行代码在Python NLTK库中将参数NN传递给DefaultTagger()类来创建一个tagger对象。第6行调用了tagger对象的tag()函数,从wordsInSentence变量中得到了单词序列,然后返回了标注后的单词列表,并保存在posEnabledTags中。值得注意的是,句子中的所有单词都标注为NN,这是标注器之前设置好的,用于不知道词性信息时的基本标注。第七行调用Python内置的print()函数来检查posEnabledTags变量的内容。我们可以看到句子中的所有单词都会被标注为NN。
9-23行代码创建了一个名为learnRETagger()的新函数,它的输入是一个字符串,输出是这个字符串包含的所有单词的列表,以及根据正则表达式标注器识别出的词性。10-19行代码看起来很多,但是每条代码可以完成很多事情:创建一个名为customPatterns的变量,定义一个新的Python列表数据类型,将八个元素添加到这个列表中·这个列表中的每个元素都是一个元组,每个元组都有两项,元组中的第一项是一个正则表达式,元组中的第二项是一个字符串。我们通过模式的识别将英语单词标注为某一类给定的词性。在前面的例子中,我们使用以下特征标注英文单词的词性:以ing结尾的单词可以被标注为形容词,例如,running;以ly结尾的单词可以被标注为副词,例如,willingly;以ion结尾的单词可以被标注为名词,例如,intimation;以ate或en结尾的单词可以被标注为动词,例如,terminate、darken或lighten;以an结尾的单词可以被标注为不定冠词;with、on或者at这类词被标注为介词;-123.0、984这样的词可以被标注为数词;我们将其他单词都标注为none,这个Python内置的数据类型表示无意义。第20行代码创建了NLTK的内置正则表达式标记器RegexpTagger的一个对象。我们将元组列表传递给该类的第一个参数customPatterns变量来初始化对象。该对象在将来可以被名为Tagger的变量引用。之后的处理过程,我们首先尝试使用NLTK内置的word_tokenize()函数来对字符串simpleSentence进行分词,并将单词列表存储在wordsInSentence变量中。然后我们调用正则表达式词性标注器的tag()函数来标注存储在wordsInSentence变量中的所有单词。这个标注过程的结果存储在posEnabledTags变量中。
25-33行定义一个新的函数learnLookupTagger,它将一个字符串作为参数传递给simpleSentence变量。33行代码从NLTK库调用UnigramTagger。这是一个查询词性标注器,它的输入是我们已经创建的定义为mapping变量的Python字典。创建的tagger对象用于将来调用。我们使用NLTK内置的word_tokenize()函数来标注句子并将结果保存在wordsInSentence变量中。当标注句子时,我们调用tagger的tag()函数,输入是传递给wordsInSentence变量的单词列表,并将标注的结果保存在posEnabledTags变量中。
3.训练自己的词性标注器
创建一个新文件,命名为Train.py。3.输入以下源代码:
import nltk
import pickle
def sampleData():
return[
"Beijing is the capital of China.",
"Steven Jobs was the CEO of Apple",
"iphone was Invented by Apple.",
"Books can be purchased in Market."
]
def buildDictionary():
dictionary={}
for sent in sampleData():
partsOfSpeechTags=nltk.pos_tag(nltk.word_tokenize(sent))
for tag in partsOfSpeechTags:
value=tag[0]
pos=tag[1]
dictionary[value]=pos
return dictionary
def saveMyTagger(tagger,fileName):
fileHandle=open(fileName,"wb")
pickle.dump(tagger,fileHandle)
fileHandle.close()
def saveMyTraining(fileName):
tagger=nltk.UnigramTagger(model=buildDictionary())
saveMyTagger(tagger,fileName)
def loadMyTagger(fileName):
return pickle.load(open(fileName,"rb"))
sentence="Iphone is purchased by Steven Jobs in Beijing Market."
fileName="myTagger.pickle"
saveMyTraining(fileName)
myTagger=loadMyTagger(fileName)
print(myTagger.tag(nltk.word_tokenize(sentence)))
结果如下:
[("Iphone", None), ("is", "VBZ"), ("purchased", "VBN"), ("by", "IN"), ("Steven", "NNP"), ("Jobs", "NNP"), ("in", "IN"), ("Beijing", "NNP"), ("Market", "NNP"), (".", ".")]
通过前两行代码,我们将NLTK和pickle模块加载到程序中。pickle模块实现了强大的序列化和反序列化算法,可用于处理非常复杂的Python对象。
4-10行定义了一个名为sampleData()的函数,它返回一个Python列表。本例中,我们返回四个示例字符串。
12-20定义一个名为buildDictionary()的函数,它每次从sampleData()函数生成的列表中读取一条字符串。每条字符串都用nltk.word_tokenize()函数进行分词。分词结果被添加到一个Python字典中,其中字典的键(key)是句子中的单词,字典的值(value)是词性。当字典生成完毕,返回给调用者。
22-25行定义一个名为saveMyTagger()的函数,它需要两个参数:tagger:词性标注器的一个对象;fileName:存储tagger对象的文件名称。我们首先以写入二进制(Write Binary,WB)的模式打开文件。然后使用pickle模块的dump()方法,将整个标注器存储在文件中,并在fileHandle上调用close()函数。
27-29行定义一个名为saveMyTraining的新函数,它接收名为fileName的单个参数。我们构建一个nltk.UnigramTagger()对象,它的输入是buildDictionary()函数的输出模型(根据我们之前定义的字符串示例集合建立),当生成tagger对象时,调用saveMyTagger()函数将其保存到磁盘。
31-32行定义一个新的函数loadMyTagger(),它接收名为fileName的单个参数。该函数从磁盘读取文件并将其传递给pickle.load()函数,该函数从磁盘反序列化tagger对象并返回它的引用。
34和35行定义了两个变量,一个是sentence,一个是fileName,它们分别是我们需要分析的字符串和我们存储词性标注器的文件路径。
37行调用了saveMyTraining()函数,myTagger.pickle为其参数。所以,我们基本上完成了将训练好的标注器存储在这个文件中。
39行将myTagger.pickle作为loadMyTagger()函数的参数,它从磁盘加载这个标注器,对其进行反序列化并创建一个对象。该对象进一步赋给myTagger变量。
41行调用刚从磁盘加载的tagger对象的tag()函数。我们用它来标注我们创建的字符串样本。处理完成后,屏幕上显示输出结果。
附:词性标注的标签对应的含义
Number | Tag | Discription |
1 | CC |
Coordinating conjunction 连接词 |
2 | CD | Cardinal number 基数词 |
3 | DT |
Determiner 限定词(如this,that,these,those,such,不定限定词:no,some,any,each,every,enough,either,neither,all,both,half,several,many,much,(a) few,(a) little,other,another. |
4 | EX | Existential there 存在句 |
5 | FW | Foreign word 外来词 |
6 | IN | Preposition or subordinating conjunction 介词或从属连词 |
7 | JJ | Adjective 形容词或序数词 |
8 | JJR |
Adjective,comparative 形容词比较级 |
9 | JJS |
Adjective,superlative 形容词最高级 |
10 | LS |
List item marker 列表标示 |
11 | MD | Modal 情态助动词 |
12 | NN | Noun, singular or mass 常用名词 单数形式 |
13 | NNS | Noun, plural 常用名词 复数形式 |
14 | NNP | Proper noun, singular 专有名词,单数形式 |
15 | NNPS | Proper noun, plural 专有名词,复数形式 |
16 | PDT | Predeterminer 前位限定词 |
17 | POS | Possessive ending 所有格结束词 |
18 | PRP | Personal pronoun 人称代词 |
19 | PRP$ | Possessive pronoun 所有格代名词 |
20 | RB | Adverb 副词 |
21 | RBR | Adverb, comparative 副词比较级 |
22 | RBS | Adverb, superlative 副词最高级 |
23 | RP | Particle 小品词 |
24 | SYM | Symbol 符号 |
25 | TO | to 作为介词或不定式格式 |
26 | UH | Interjection 感叹词 |
27 | VB | Verb, base form 动词基本形式 |
28 | VBD | Verb, past tense 动词过去式 |
29 | VBG | Verb, gerund or present participle 动名词和现在分词 |
30 | VBN | Verb, past participle 过去分词 |
31 | VBP | Verb, non-3rd person singular present 动词非第三人称单数 |
32 | VBZ | Verb, 3rd person singular present 动词第三人称单数 |
33 | WDT | Wh-determiner 限定词(如关系限定词:whose,which.疑问限定词:what,which,whose.) |
34 | WP | Wh-pronoun 代词(who whose which) |
35 | WP$ | Possessive wh-pronoun 所有格代词 |
36 | WRB | Wh-adverb 疑问代词(how where when) |
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。