【问题标题】:Lemmatizing words after POS tagging produces unexpected results词性标注后词元化会产生意想不到的结果
【发布时间】:2016-01-14 11:03:48
【问题描述】:

我正在使用带有 nltk pos_tag 函数和 WordNetLemmatizer 的 python3.5。我的目标是展平我们数据库中的单词以对文本进行分类。我正在尝试使用 lemmatizer 进行测试,在相同的令牌上使用 POS 标记器时遇到了奇怪的行为。在下面的示例中,我有一个包含三个字符串的列表,当在 POS 标记器中运行它们时,每个其他元素都作为名词(NN)返回,其余元素作为动词(VBG)返回。

这会影响词形还原。输出如下所示:

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)

【问题讨论】:

    标签: nlp nltk pos-tagger lemmatization python-3.5


    【解决方案1】:

    简而言之:

    当 POS 标记时,您需要上下文句子而不是不合语法标记的列表。

    当对上下文句子进行词元化时,获得正确词元的唯一方法是手动指定 pos 标签。


    长篇大论:

    词性标注器通常适用于整个句子,而不是单个单词。当您尝试在上下文中标记单个单词时,您得到的是最常见的标记。

    验证在标记单个单词(即只有 1 个单词的句子)时,它总是给出相同的标记:

    >>> 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;
    ... 
    >>>
    

    现在,如果句子只有 1 个单词,则默认情况下标签始终为 'a',因此 WordNetLemmatizer 将始终返回 skydive

    >>> 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_tag 时,输入标记列表的上下文很重要。

    在您的示例中,您有一个列表 ['skydiving', 'skydiving', 'skydiving'],这意味着您要添加标签的句子是一个不合语法的句子:

    跳伞跳伞

    pos_tag 函数认为是一个正常的句子,因此给出了标签:

    >>> sent3 = 'skydiving skydiving skydiving'.split()
    >>> pos_tag(sent3)
    [('skydiving', 'VBG'), ('skydiving', 'NN'), ('skydiving', 'VBG')]
    

    在这种情况下,第一个词是动词,第二个词是名词,第三个词是动词,这将返回以下引理(您不需要):

    >>> wnl.lemmatize('skydiving', 'v')
    'skydive'
    >>> wnl.lemmatize('skydiving', 'n')
    'skydiving'
    >>> wnl.lemmatize('skydiving', 'v')
    'skydive'
    

    因此,如果我们在您的标记列表中有一个有效的语法句子,输出可能看起来非常不同

    >>> 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。现在从第 1 章开始。必须找到另一种方法来尝试解决这个问题。
    猜你喜欢
    • 2021-02-05
    • 1970-01-01
    • 2023-01-18
    • 2019-04-05
    • 1970-01-01
    • 2022-12-05
    相关资源
    最近更新 更多