【问题标题】:Python (NLTK) - more efficient way to extract noun phrases?Python (NLTK) - 提取名词短语的更有效方法?
【发布时间】:2018-03-29 20:04:05
【问题描述】:

我有一个涉及大量文本数据的机器学习任务。我想在训练文本中识别和提取名词短语,以便稍后在管道中将它们用于特征构建。 我已经从文本中提取了我想要的名词短语类型,但我对 NLTK 还很陌生,所以我以一种可以分解列表推导中的每个步骤的方式来解决这个问题,如下所示。

但我真正的问题是,我是否在这里重新发明轮子?有没有我没有看到的更快的方法来做到这一点?

import nltk
import pandas as pd

myData = pd.read_excel("\User\train_.xlsx")
texts = myData['message']

# Defining a grammar & Parser
NP = "NP: {(<V\w+>|<NN\w?>)+.*<NN\w?>}"
chunkr = nltk.RegexpParser(NP)

tokens = [nltk.word_tokenize(i) for i in texts]

tag_list = [nltk.pos_tag(w) for w in tokens]

phrases = [chunkr.parse(sublist) for sublist in tag_list]

leaves = [[subtree.leaves() for subtree in tree.subtrees(filter = lambda t: t.label == 'NP')] for tree in phrases]

将我们最终得到的元组列表的列表扁平化为 只是元组列表的列表

leaves = [tupls for sublists in leaves for tupls in sublists]

将提取的术语加入一个二元组

nounphrases = [unigram[0][1]+' '+unigram[1][0] in leaves]

【问题讨论】:

    标签: python-3.x pandas nlp nltk text-chunking


    【解决方案1】:

    看看Why is my NLTK function slow when processing the DataFrame?,如果您不需要中间步骤,则无需多次遍历所有行。

    ne_chunk 和来自

    的解决方案

    [代码]:

    from nltk import word_tokenize, pos_tag, ne_chunk
    from nltk import RegexpParser
    from nltk import Tree
    import pandas as pd
    
    def get_continuous_chunks(text, chunk_func=ne_chunk):
        chunked = chunk_func(pos_tag(word_tokenize(text)))
        continuous_chunk = []
        current_chunk = []
    
        for subtree in chunked:
            if type(subtree) == Tree:
                current_chunk.append(" ".join([token for token, pos in subtree.leaves()]))
            elif current_chunk:
                named_entity = " ".join(current_chunk)
                if named_entity not in continuous_chunk:
                    continuous_chunk.append(named_entity)
                    current_chunk = []
            else:
                continue
    
        return continuous_chunk
    
    df = pd.DataFrame({'text':['This is a foo, bar sentence with New York city.', 
                               'Another bar foo Washington DC thingy with Bruce Wayne.']})
    
    df['text'].apply(lambda sent: get_continuous_chunks((sent)))
    

    [出]:

    0                   [New York]
    1    [Washington, Bruce Wayne]
    Name: text, dtype: object
    

    使用自定义RegexpParser

    from nltk import word_tokenize, pos_tag, ne_chunk
    from nltk import RegexpParser
    from nltk import Tree
    import pandas as pd
    
    # Defining a grammar & Parser
    NP = "NP: {(<V\w+>|<NN\w?>)+.*<NN\w?>}"
    chunker = RegexpParser(NP)
    
    def get_continuous_chunks(text, chunk_func=ne_chunk):
        chunked = chunk_func(pos_tag(word_tokenize(text)))
        continuous_chunk = []
        current_chunk = []
    
        for subtree in chunked:
            if type(subtree) == Tree:
                current_chunk.append(" ".join([token for token, pos in subtree.leaves()]))
            elif current_chunk:
                named_entity = " ".join(current_chunk)
                if named_entity not in continuous_chunk:
                    continuous_chunk.append(named_entity)
                    current_chunk = []
            else:
                continue
    
        return continuous_chunk
    
    
    df = pd.DataFrame({'text':['This is a foo, bar sentence with New York city.', 
                               'Another bar foo Washington DC thingy with Bruce Wayne.']})
    
    
    df['text'].apply(lambda sent: get_continuous_chunks(sent, chunker.parse))
    

    [出]:

    0                  [bar sentence, New York city]
    1    [bar foo Washington DC thingy, Bruce Wayne]
    Name: text, dtype: object
    

    【讨论】:

    • 绝妙的答案!这些链接也非常有用。谢谢@alvas!问题,你为什么写 'prev = None' ?定义“get_continuous_chunks”时?
    • 哦,那是个错误,没必要。我想我正在使用 prev 检查历史记录,但实际上只需要 current_chunk 来检查历史记录。感谢您接听!
    • 嘿@alvas,你从哪里来的那个正则表达式 (NP = "NP: {(|)+.*} ") - 这是一个标准的名词短语检测标准吗?
    【解决方案2】:

    我建议参考之前的帖子: Extracting all Nouns from a text file using nltk

    他们建议使用 TextBlob 作为实现这一目标的最简单方法(如果不是在处理方面最有效的方法),并且那里的讨论解决了您的问题。

    from textblob import TextBlob
    txt = """Natural language processing (NLP) is a field of computer science, artificial intelligence, and computational linguistics concerned with the interactions between computers and human (natural) languages."""
    blob = TextBlob(txt)
    print(blob.noun_phrases)
    

    【讨论】:

    • 感谢您参与有关此问题的讨论! Textblob 绝对比有时笨重的 NLTK 更有优势。但是,您提供的解决方案不允许发生自定义解析 - 这最终可能是 NLTK 的更强大的专业人士。
    【解决方案3】:

    上述方法没有给我所需的结果。以下是我建议的功能

    from nltk import word_tokenize, pos_tag, ne_chunk
    from nltk import RegexpParser
    from nltk import Tree
    import re
    
    
    def get_noun_phrases(text):
        pos = pos_tag(word_tokenize(text))
        count = 0
        half_chunk = ""
        for word, tag in pos:
            if re.match(r"NN.*", tag):
                count+=1
                if count>=1:
                    half_chunk = half_chunk + word + " "
            else:
                half_chunk = half_chunk+"---"
                count = 0
        half_chunk = re.sub(r"-+","?",half_chunk).split("?")
        half_chunk = [x.strip() for x in half_chunk if x!=""]
        return half_chunk
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-31
      • 1970-01-01
      • 2017-11-23
      • 2013-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多