Nlp 词性标注后对单词进行柠檬化会产生意想不到的结果
我正在使用python3.5和nltk pos_标记函数以及WordNetLemmatizer。我的目标是将数据库中的单词展平,以便对文本进行分类。我正在尝试使用lemmatizer进行测试,在相同的令牌上使用POS标记器时,我遇到了奇怪的行为。在下面的示例中,我有一个包含三个字符串的列表,当在POS标记器中运行它们时,每个其他元素都作为名词(NN)返回,其余元素作为动词(VBG)返回 这会影响柠檬化。输出如下所示:Nlp 词性标注后对单词进行柠檬化会产生意想不到的结果,nlp,nltk,pos-tagger,lemmatization,python-3.5,Nlp,Nltk,Pos Tagger,Lemmatization,Python 3.5,我正在使用python3.5和nltk pos_标记函数以及WordNetLemmatizer。我的目标是将数据库中的单词展平,以便对文本进行分类。我正在尝试使用lemmatizer进行测试,在相同的令牌上使用POS标记器时,我遇到了奇怪的行为。在下面的示例中,我有一个包含三个字符串的列表,当在POS标记器中运行它们时,每个其他元素都作为名词(NN)返回,其余元素作为动词(VBG)返回 这会影响柠檬化。输出如下所示: pos Of token: v lemmatized token: skydi
pos Of token: v
lemmatized token: skydive
pos Of token: n
lemmatized token: skydiving
pos Of token: v
lemmatized token: skydive
如果我向相同字符串列表中添加更多元素,则相同的模式将继续。我使用的完整代码如下:
tokens = ['skydiving', 'skydiving', 'skydiving']
lmtzr=WordNetLemmatizer()
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return 'a'
elif treebank_tag.startswith('V'):
return 'v'
elif treebank_tag.startswith('N'):
return 'n'
elif treebank_tag.startswith('R'):
return 'r'
elif treebank_tag.startswith('S'):
return ''
else:
return ''
numTokens = (len(tokens))
for i in range(0,numTokens):
tokens[i]=tokens[i].replace(" ","")
noSpaceTokens = pos_tag(tokens)
for token in noSpaceTokens:
tokenStr = str(token[1])
noWhiteSpace = token[0].replace(" ", "")
preLemmed = get_wordnet_pos(tokenStr)
print("pos Of token: " + preLemmed)
lemmed = lmtzr.lemmatize(noWhiteSpace,preLemmed)
print("lemmatized token: " + lemmed)
简而言之: 当词性标注时,你需要一个上下文句子,而不是一系列不合语法的标记
- 例如,要使一个语法的句子语法化,你可以看看
- 例如,从,我们必须为lemmatize函数指定
参数李>pos
- 否则将始终假定
POS,另请参见n
长: POS-tagger通常用于整个句子,而不是单个单词。当你试图在上下文之外标记一个单词时,你得到的是最频繁的标记 要验证在标记单个单词(即只有一个单词的句子)时,它始终给出相同的标记:
>>> from nltk.stem import WordNetLemmatizer
>>> from nltk import pos_tag
>>> ptb2wn_pos = {'J':'a', 'V':'v', 'N':'n', 'R':'r'}
>>> sent = ['skydive']
>>> most_frequent_tag = pos_tag(sent)[0][1]
>>> most_frequent_tag
'JJ'
>>> most_frequent_tag = ptb2wn_pos[most_frequent_tag[0]]
>>> most_frequent_tag
'a'
>>> for _ in range(1000): assert ptb2wn_pos[pos_tag(sent)[0][1][0]] == most_frequent_tag;
...
>>>
现在,由于如果句子只有一个单词,则默认情况下标记始终为“a”,因此WordNetLemmatizer
将始终返回skydove
:
>>> wnl = WordNetLemmatizer()
>>> wnl.lemmatize(sent[0], pos=most_frequent_tag)
'skydive'
让我们来看看句子上下文中单词的引理:
>>> sent2 = 'They skydrive from the tower yesterday'
>>> pos_tag(sent2.split())
[('They', 'PRP'), ('skydrive', 'VBP'), ('from', 'IN'), ('the', 'DT'), ('tower', 'NN'), ('yesterday', 'NN')]
>>> pos_tag(sent2.split())[1]
('skydrive', 'VBP')
>>> pos_tag(sent2.split())[1][1]
'VBP'
>>> ptb2wn_pos[pos_tag(sent2.split())[1][1][0]]
'v'
因此,当您执行pos\u标记时,令牌输入列表的上下文很重要
在您的示例中,您有一个列表['skydiving','skydiving','skydiving','skydiving']
,这意味着您正在进行词性标记的句子是一个不合语法的句子:
>>> sent2 = 'They skydrive from the tower yesterday'
>>> pos_tag(sent2.split())
[('They', 'PRP'), ('skydrive', 'VBP'), ('from', 'IN'), ('the', 'DT'), ('tower', 'NN'), ('yesterday', 'NN')]
>>> pos_tag(sent2.split())[1]
('skydrive', 'VBP')
>>> pos_tag(sent2.split())[1][1]
'VBP'
>>> ptb2wn_pos[pos_tag(sent2.split())[1][1][0]]
'v'
跳伞跳伞
而pos_tag
函数认为这是一个正常的句子,因此给出了标记:
>>> sent3 = 'skydiving skydiving skydiving'.split()
>>> pos_tag(sent3)
[('skydiving', 'VBG'), ('skydiving', 'NN'), ('skydiving', 'VBG')]
在这种情况下,第一个词是动词,第二个词是名词,第三个词是动词,这将返回以下引理(您不希望):
因此,如果我们在您的标记列表中有一个有效的语法句子,那么输出可能会非常不同
>>> sent3 = 'The skydiving sport is an exercise that promotes diving from the sky , ergo when you are skydiving , you feel like you are descending to earth .'
>>> pos_tag(sent3.split())
[('The', 'DT'), ('skydiving', 'NN'), ('sport', 'NN'), ('is', 'VBZ'), ('an', 'DT'), ('exercise', 'NN'), ('that', 'IN'), ('promotes', 'NNS'), ('diving', 'VBG'), ('from', 'IN'), ('the', 'DT'), ('sky', 'NN'), (',', ','), ('ergo', 'RB'), ('when', 'WRB'), ('you', 'PRP'), ('are', 'VBP'), ('skydiving', 'VBG'), (',', ','), ('you', 'PRP'), ('feel', 'VBP'), ('like', 'IN'), ('you', 'PRP'), ('are', 'VBP'), ('descending', 'VBG'), ('to', 'TO'), ('earth', 'JJ'), ('.', '.')]
是的,我担心缺乏背景是问题所在。我想我试图在没有适当背景的情况下潜入nltk。现在从第一章开始读这本书。我们必须找到另一种方法来解决这个问题。