【问题标题】:extract relationships using NLTK使用 NLTK 提取关系
【发布时间】:2011-10-21 15:46:10
【问题描述】:

这是follow-up of my question。我正在使用 nltk 来解析人员、组织及其关系。使用this example,我能够创建大量的人和组织;但是,我在 nltk.sem.extract_rel 命令中遇到错误:

AttributeError: 'Tree' object has no attribute 'text'

完整代码如下:

import nltk
import re
#billgatesbio from http://www.reuters.com/finance/stocks/officerProfile?symbol=MSFT.O&officerId=28066
with open('billgatesbio.txt', 'r') as f:
    sample = f.read()

sentences = nltk.sent_tokenize(sample)
tokenized_sentences = [nltk.word_tokenize(sentence) for sentence in sentences]
tagged_sentences = [nltk.pos_tag(sentence) for sentence in tokenized_sentences]
chunked_sentences = nltk.batch_ne_chunk(tagged_sentences)

# tried plain ne_chunk instead of batch_ne_chunk as given in the book
#chunked_sentences = [nltk.ne_chunk(sentence) for sentence in tagged_sentences]

# pattern to find <person> served as <title> in <org>
IN = re.compile(r'.+\s+as\s+')
for doc in chunked_sentences:
    for rel in nltk.sem.extract_rels('ORG', 'PERSON', doc,corpus='ieer', pattern=IN):
        print nltk.sem.show_raw_rtuple(rel)

此示例与given in the book 非常相似,但该示例使用准备好的“已解析文档”,它出现在任何地方,我不知道在哪里可以找到它的对象类型。我也浏览了 git 库。任何帮助表示赞赏。

我的最终目标是提取一些公司的人员、组织、头衔(日期);然后创建个人和组织的网络地图。

【问题讨论】:

  • 你有想过这个吗?我可以看看你想出了什么,因为我遇到了完全相同的问题。

标签: python nlp nltk


【解决方案1】:

它看起来像是一个“已解析文档”,一个对象需要有一个 headline 成员和一个 text 成员,这两个成员都是令牌列表,其中一些令牌被标记为树。例如,这个(hacky)示例有效:

import nltk
import re

IN = re.compile (r'.*\bin\b(?!\b.+ing)')

class doc():
  pass

doc.headline=['foo']
doc.text=[nltk.Tree('ORGANIZATION', ['WHYY']), 'in', nltk.Tree('LOCATION',['Philadelphia']), '.', 'Ms.', nltk.Tree('PERSON', ['Gross']), ',']

for rel in  nltk.sem.extract_rels('ORG','LOC',doc,corpus='ieer',pattern=IN):
   print nltk.sem.relextract.show_raw_rtuple(rel)

运行时提供输出:

[ORG: 'WHYY'] 'in' [LOC: 'Philadelphia']

显然您实际上不会像这样对其进行编码,但它提供了extract_rels 期望的数据格式的工作示例,您只需要确定如何执行预处理步骤以将您的数据按摩成该格式。

【讨论】:

  • 谢谢,bdk。我现在正在尝试将 chunked_sentences 中获得的树转换为解析的文档格式。使用您的方法没有错误,但它也没有给我任何结果。正则表达式模式可能不匹配。
  • hmm,不知道为什么您没有使用上面的脚本得到结果,我只是尝试将它粘贴到一个文件中(以确保我没有搞砸粘贴)并运行它并给出这里的预期结果。
  • 不,我的意思是,您的脚本工作正常,但是当我根据我的目的修改它(使用我的文本/树)时,它不会返回关系。我怀疑它与我的正则表达式模式或我的树有关。感谢您的帮助。
【解决方案2】:

这里是nltk.sem.extract_rels函数的源代码:

def extract_rels(subjclass, objclass, doc, corpus='ace', pattern=None, window=10):
"""
Filter the output of ``semi_rel2reldict`` according to specified NE classes and a filler pattern.

The parameters ``subjclass`` and ``objclass`` can be used to restrict the
Named Entities to particular types (any of 'LOCATION', 'ORGANIZATION',
'PERSON', 'DURATION', 'DATE', 'CARDINAL', 'PERCENT', 'MONEY', 'MEASURE').

:param subjclass: the class of the subject Named Entity.
:type subjclass: str
:param objclass: the class of the object Named Entity.
:type objclass: str
:param doc: input document
:type doc: ieer document or a list of chunk trees
:param corpus: name of the corpus to take as input; possible values are
    'ieer' and 'conll2002'
:type corpus: str
:param pattern: a regular expression for filtering the fillers of
    retrieved triples.
:type pattern: SRE_Pattern
:param window: filters out fillers which exceed this threshold
:type window: int
:return: see ``mk_reldicts``
:rtype: list(defaultdict)
"""
....

因此,如果您将语料库参数作为 ieer 传递,则 nltk.sem.extract_rels 函数期望 doc 参数是 IEERDocument 对象。您应该将语料库作为 ace 传递,或者只是不传递它(默认为 ace)。在这种情况下,它需要一个块树列表(这就是你想要的)。我修改了代码如下:

import nltk
import re
from nltk.sem import extract_rels,rtuple

#billgatesbio from http://www.reuters.com/finance/stocks/officerProfile?symbol=MSFT.O&officerId=28066
with open('billgatesbio.txt', 'r') as f:
    sample = f.read().decode('utf-8')

sentences = nltk.sent_tokenize(sample)
tokenized_sentences = [nltk.word_tokenize(sentence) for sentence in sentences]
tagged_sentences = [nltk.pos_tag(sentence) for sentence in tokenized_sentences]

# here i changed reg ex and below i exchanged subj and obj classes' places
OF = re.compile(r'.*\bof\b.*')

for i, sent in enumerate(tagged_sentences):
    sent = nltk.ne_chunk(sent) # ne_chunk method expects one tagged sentence
    rels = extract_rels('PER', 'ORG', sent, corpus='ace', pattern=OF, window=7) # extract_rels method expects one chunked sentence
    for rel in rels:
        print('{0:<5}{1}'.format(i, rtuple(rel)))

它给出了结果:

[PER: u'Chairman/NNP'] u'and/CC Chief/NNP Executive/NNP Officer/NNP of/IN the/DT' [ORG: u'Company/NNP']

【讨论】:

  • 当我复制并粘贴此示例代码时,我没有得到任何东西,正则表达式是否正确?...当我运行它时,它没有给我你的输出。
  • 我再次运行它并得到相同的结果。我认为正则表达式是正确的。我真的不知道可能是什么问题。
  • 我唯一的想法是删除.decode(),因为我在python3中,你认为这与这个问题有关吗?......
  • 是的,您应该在 python2 中运行此代码,因为 nltk 版本在 python2 和 python3 中也不同。
  • 我用 python2 运行它,结果还是一样...我没有得到相同的输出,实际上我什么也没得到...我的 nltk 版本是 3.2.1,不知道要做什么做什么?...
【解决方案3】:

这是 nltk 版本问题。您的代码应该在 nltk 2.x 中工作 但是对于 nltk 3,您应该像这样编写代码

IN = re.compile(r'.*\bin\b(?!\b.+ing)')
for doc in nltk.corpus.ieer.parsed_docs('NYT_19980315'):
    for rel in nltk.sem.relextract.extract_rels('ORG', 'LOC', doc,corpus='ieer', pattern = IN):
         print (nltk.sem.relextract.rtuple(rel))

NLTK Example for Relation Extraction Does not work

【讨论】:

  • 对缺少解释和指向具有不同错误上下文的问题的链接投反对票。
猜你喜欢
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
  • 2013-12-15
  • 1970-01-01
  • 2012-10-15
相关资源
最近更新 更多