为什么用NLTK的PoS标记器标记单词中的每个字母,而不是标记每个单词?

时间:2018-07-09 06:37:38

标签: python string nlp nltk part-of-speech

说我有这句话:I am a boy。我想找出句子中每个单词的词性。这是我的代码:

import nltk
sentence = 'I am a good boy'
for word in sentence:
    print(word)
    print(nltk.pos_tag(word))

但这会产生以下输出:

I
[('I', 'PRP')]

[(' ', 'NN')]
a
[('a', 'DT')]
m
[('m', 'NN')]

[(' ', 'NN')]
a
[('a', 'DT')]

[(' ', 'NN')]
g
[('g', 'NN')]
o
[('o', 'NN')]
o
[('o', 'NN')]
d
[('d', 'NN')]

[(' ', 'NN')]
b
[('b', 'NN')]
o
[('o', 'NN')]
y
[('y', 'NN')]

所以,我尝试改为这样做:

sentence = 'I am a good boy'
for word in sentence.split(' '):
    print(word)
    print(nltk.pos_tag(word))

这将产生以下输出:

I
[('I', 'PRP')]
am
[('a', 'DT'), ('m', 'NN')]
a
[('a', 'DT')]
good
[('g', 'NN'), ('o', 'MD'), ('o', 'VB'), ('d', 'NN')]
boy
[('b', 'NN'), ('o', 'NN'), ('y', 'NN')]

为什么要为每个字母而不是每个单词找到PoS?以及我该如何解决?

2 个答案:

答案 0 :(得分:2)

nltk.pos_tag处理列表或类似列表的东西作为参数,并标记该元素的每个元素。因此,在您的第二个示例中,它将每个字符串(即每个单词)拆分为字母,就像在第一个示例中将句子拆分为字母一样。当您传递从拆分句子中得到的整个列表时,它会起作用:

>>> nltk.pos_tag(sentence.split(" "))
[('I', 'PRP'), ('am', 'VBP'), ('a', 'DT'), ('good', 'JJ'), ('boy', 'NN')]

Per documentation,您通常会传递NLTK的令牌化返回的内容(这是单词/令牌的列表)。

答案 1 :(得分:1)

在两种情况下,您拆分数据的方式都不同。但是pos_tag需要一个可迭代的输入。
在第一种情况下,您是逐字母拆分句子。
对于前

sentence = "cat"
for word in sentence:
    print(word)
# 'c' , 'a', 't'

然后,您要pos_tagger查找每个字母的词性。

print(nltk.pos_tag(word))

很显然,由于每次将字母作为pos_tag()的输入时,您都在这里获得了每个字母的语音标签的一部分。


在第二个示例中,您正在按单词拆分句子。 例如:

sentence = 'I am a good boy'
splitted_words = sentence.split() # you can use split() instead of split(' ') 
for word in splitted_words: 
    print(word)
# 'I', 'am', 'a', 'good', 'boy'

现在要注意的是,每个单词都是可迭代的。 “ am”是可迭代的,我们可以通过“ am”进行迭代,然后得到“ a”和“ m”。 因此,很明显pos_tagger给出了单词中字母的结果。

如何解决此问题:

pos_tag()需要一个可迭代的参数(列表,元组等)。我建议您使用NLTK附带的tokenizer(),而不要用空格手动分割句子。 因此,您的代码应如下所示:

sentence = "I am a good boy"
tokenised_words = word_tokenize(sentence) # ['I', 'am', 'a', 'good', 'boy']
print(nltk.pos_tag(text))

输出

[('I', 'PRP'), ('am', 'VBP'), ('a', 'DT'), ('good', 'JJ'), ('boy', 'NN')]