【问题标题】:Python NLTK interpret a fixed pattern of sentence and tokenize itPython NLTK 解释句子的固定模式并将其标记化
【发布时间】:2014-11-10 08:20:41
【问题描述】:

我有一个应用程序,NLTK 需要解释人类发出的语音,并从中找到有意义的块。需要解释的句子格式为from <somewhere>, to <somewhere> on <some_date>, <class_of_travel,like AC_CHAIR_CAR>。如您所知,这可以通过多种方式表达,例如,

  1. 我想从亚特兰大去纽约,商务舱,2014 年 7 月 25 日。

  2. 我想乘坐商务舱,于 7 月 25 日从纽约前往亚特兰大。

  3. 我有一个梦想,有一天我会登上飞机,乘坐商务舱,然后降落在纽约,源头在亚特兰大,最好是 7 月 25 日。

  4. 7 月 25 日亚特兰大至纽约,商务舱。

你明白了。我想提取的是一些信息——来源、目的地、类别、日期。有些可能会丢失,必须加以识别或适当假设。就像发现源丢失一样,找出它。或者,如果缺少年份,请将其记入当前年份。并且一直忽略无用的信息(比如我有一个梦想部分,就像我崇拜马丁路德一样)。

有什么方法可以在 NLTK 中实现这一点?我知道有可用的标记器,并且有一些方法可以训练标记器,但我对此没有足够的知识。是否可以或多或少地涵盖所有可能意味着这样一个句子的情况,并提取这样的信息?如果是这样,我们将不胜感激。

【问题讨论】:

    标签: python nlp speech-recognition nltk


    【解决方案1】:

    在计算语言学中,这被称为“Named Entity Recognition”,它是从文本中识别组织、人员和位置等事物的过程。

    这里的挑战是 nltk 中的默认 NE 分块器是在 ACE corpus 上训练的最大熵分块器。它尚未经过训练以识别日期和时间,因此您需要对其进行调整并找到一种检测时间的方法。

    有一些包可以帮助提取命名实体,Stanford NER(命名实体识别器)是最流行的命名实体识别工具之一,由 Java 实现。但是你可以通过下载包来使用它,并通过提供斯坦福NER接口的NLTK进行交互。

    您可以下载Stanford Named Entity Recognizer version 3.4 在哪里可以找到 stanford-ner.jar 和分类器模型“all.3class.dissim.crf.ser.gz”

    from nltk.tag.stanford import NERTagger
    def stanfordNERExtractor(sentence):
        st =  NERTagger('/usr/share/stanford-ner/classifiers/all.3class.distsim.crf.ser.gz',
                   '/usr/share/stanford-ner/stanford-ner.jar')
        return st.tag(sentence.split()) 
    
    stanfordNERExtractedLines = stanfordNERExtractor("New York")
    print stanfordNERExtractedLines #[('New-York', 'LOCATION')]
    

    您也可以使用 NTLK,您可以在 official document 上找到更多详细信息,请查看此要点 from Gavin

    def extract_entities(text):
        for sent in nltk.sent_tokenize(text):
            for chunk in nltk.ne_chunk(nltk.pos_tag(nltk.word_tokenize(sent))):
                if hasattr(chunk, 'node'):
                    print chunk.node, ' '.join(c[0] for c in chunk.leaves())
    
    extract_entities("to play to Atlanta")
    
    #Output: [('to', 'TO'),('play', 'VB'),('to', 'TO'),('play', 'NN')],
    
    • 我们如何识别目的地? 区分位置后,您可能会遇到识别由空格分隔的单词或区分来源和区别的问题。

    最好编写一个正则表达式模式来识别源和目标。您可能无法获得像"to get" 这样的其他词,但您有从st.tag(“LOCATION”)确定要验证的位置列表,或者如果您使用 NTLK,您可以验证它是否是动词(“VB "/"NN")。您还可以通过使用 NLTK 的 UnigramTagger() 和 BigramTagger() 来检查可能性,以获取“FROM”和“TO”之后可以识别为位置的名称

    import re
    text= "I want to go to New York from Atlanta, business class, on 25th July."
    destination= re.findall(r'.to.([A-Z][a-zA-Z]+?[\s-]*[A-Z]*[a-zA-Z]*)',text)
    source= re.findall(r'.from.([A-Z][a-zA-Z]+?[\s-]*[A-Z]*[a-zA-Z]*)',text)
    
    print source,destination
    
    • 我们如何识别时间/日期?

    如上所述,这是我们可以面对的问题之一,但是我们可以使用正则表达式,如thread 中所述。

    print re.findall(
        r"""(?ix)             # case-insensitive, verbose regex
        \b                    # match a word boundary
        (?:                   # match the following three times:
         (?:                  # either
          \d+                 # a number,
          (?:\.|st|nd|rd|th)* # followed by a dot, st, nd, rd, or th (optional)
          |                   # or a month name
          (?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*)
         )
         [\s./-]*             # followed by a date separator or whitespace (optional)
        ){3}                  # do this three times
        \b """, 
        text)
    

    输出:

    25th July 2014.
    

    我们也可以使用python-dateutilthis 来代替正则表达式。

    如果缺少部分,例如年份或月份。我们可以使用 parsedatetime 包进行调整。

    查看这个快速示例(您可以根据不同的场景进行调整)

    >>> import parsedatetime
    >>> p = parsedatetime.Calendar()
    >>> print p.parse("25th this month")
    (time.struct_time(tm_year=2014, tm_mon=11, tm_mday=10, tm_hour=1, tm_min=5, tm_sec=31, tm_wday=0, tm_yday=314, tm_isdst=0), 0)
    >>> print p.parse("25th July")
    ((2015, 7, 25, 1, 5, 50, 0, 314, 0), 1)
    >>> print p.parse("25th July 2014")
    ((2014, 7, 25, 1, 6, 3, 0, 314, 0), 1)
    

    最后一件事是,您可以使用此dataset 提取机场,并验证所提及位置的正确性,以防您回答可用性(有些地方没有机场)。

    对于类,你可以通过查看句子中的“经济类”、“商务类”等词来验证(你可以选择in或正则表达式)。

    有关本主题的更多详细信息,请查看:NTLK - Extracting Information from Text

    【讨论】:

    • 如果从只有一个案例,我可以做到这一点。问题是相同的,可以用多种方式表达,例如 我的来源是亚特兰大,目的地是纽约,或 我将从西雅图开始,在波士顿结束(请注意,两者目标和目的地在此处以 at 开头)。两者的意思都与我想从这里到那里相同。有没有办法适应所有这些可能性,或者至少是其中的一个大子集?
    • 很难找到,但通常他们训练算法来理解所有这些场景,并使用分类器来提取源和扩展。这里的问题是,您必须找到一个数据集(或构建一个数据集,您可以考虑从旅行者的推文中收集类似的场景,#Tourism、#Flight、#Vacation .. 并过滤这些推文以构建您的数据集),查看本文作为构建分类器以提取命名实体的示例:researchgate.net/publication/…
    【解决方案2】:

    这个问题被称为“命名实体识别”(或简称“ner”)。谷歌搜索这些短语应该会指向许多库、在线 api、特定类型数据的巧妙经验法则等。

    http://nlp.stanford.edu:8080/ner/ 处查看演示 NER 系统

    检测对日期和时间的引用可能是目前基于启发式解决方案最多的情况。

    如果您正在使用的文本域特定且非常有限,那么设置手动精选的实体列表可能会非常有用。
    例如只需列出所有拥有商业机场的城市的所有机场代码/名称,并尝试将这些名称与任何输入文本进行精确的字符串匹配。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      • 2022-09-30
      • 1970-01-01
      • 2015-05-16
      • 2018-01-02
      相关资源
      最近更新 更多