说我有这句话: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?以及我该如何解决?
答案 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')]