【问题标题】:Search for particular parts of speech (e.g. nouns) and print them along with a preceding word搜索特定的词性(例如名词)并将它们与前面的单词一起打印
【发布时间】:2022-01-01 02:17:37
【问题描述】:

我的文本由一系列基本句子组成,例如 “她是医生”“他是个好人”,以及等等。我正在尝试编写一个只返回名词和前面的代词(例如她、他、它)的程序。我需要它们成对打印,例如(she, doctor)(he, person)。我正在使用SpaCy,因为这样我也可以处理类似的法语和德语文本。

This 是我在本网站其他地方找到的最接近我需要的东西。到目前为止,我一直在尝试的是在文本中生成一个名词列表,然后在文本中搜索列表中的名词,并在其前面打印名词和单词 3 个位置(因为这是大多数的模式句子,大多数对我的目的来说已经足够好了)。这就是我创建列表所需要的:

def spacy_tag(text):
  text_open = codecs.open(text, encoding='latin1').read()
  parsed_text = nlp_en(text_open)
  tokens = list([(token, token.tag_) for token in parsed_text])
  list1 = []
  for token, token.tag_ in tokens:
    if token.tag_ == 'NN':
      list1.append(token)
  return(list1)

但是,当我尝试对其进行任何操作时,我会收到一条错误消息。我试过使用枚举,但我也无法让它工作。这是我在文本中搜索列表中单词的当前代码(我还没有开始添加应该预先在几个地方打印单词的部分,因为我仍然停留在搜索部分):

def spacy_search(text, list):
  text_open = codecs.open(text, encoding='latin1').read()
  for word in text_open:
   if word in list:
     print(word)

我得到的错误是在第 4 行,"if word in list:", and it says "TypeError: Argument 'other' has incorrect type (expected spacy.tokens.token.Token, got str)"

有没有更有效的方法来使用SpaCy 打印PRPNN pair?或者,如何修改我的代码以使其在文本中搜索列表中的名词? (它不需要是一个特别优雅的解决方案,它只需要产生一个结果)。

【问题讨论】:

    标签: python spacy pos-tagger


    【解决方案1】:

    你采取了错误的方法:

    先追加句子中的所有token属性:

    tokonized=[]
    for token in doc:
     tokonized.append((token.text ,token.lemma_, token.pos_, token.tag_, token.dep_,
                        token.shape_, token.is_alpha, token.is_stop,token.head,token.left_edge,token.right_edge,token.ent_type_))
    

    编写一个接收令牌并返回相关头的函数 并检查if Token pos == 'NOUN' and tag== 'NN'

    Head=''
    if token[2]=='NOUN' and token[3]=='NN': 
     return token[8]
    

    现在,如果返回头是一个 PRON,那么您找到了您正在寻找的东西,如果没有,则再次将头令牌发送到函数。

    您可以在下面看到运行示例:

    sentences=["she is a doctor", "he is a good person"]
    
    ('she', 'she', 'PRON', 'PRP', 'nsubj', 'xxx', True, True, is, she, she, '')
    ('is', 'be', 'AUX', 'VBZ', 'ROOT', 'xx', True, True, is, she, doctor, '')
    ('a', 'a', 'DET', 'DT', 'det', 'x', True, True, doctor, a, a, '')
    ('doctor', 'doctor', 'NOUN', 'NN', 'attr', 'xxxx', True, False, is, a, doctor, '')
    

    所以第一次调用将返回 Is,第二次调用将返回 she,然后您停止。

    同样的:

    ('he', 'he', 'PRON', 'PRP', 'nsubj', 'xx', True, True, is, he, he, '')
    ('is', 'be', 'AUX', 'VBZ', 'ROOT', 'xx', True, True, is, he, person, '')
    ('a', 'a', 'DET', 'DT', 'det', 'x', True, True, person, a, a, '')
    ('good', 'good', 'ADJ', 'JJ', 'amod', 'xxxx', True, False, person, good, good, '')
    ('person', 'person', 'NOUN', 'NN', 'attr', 'xxxx', True, False, is, a, person, '')
    

    所以第一次调用将返回 Is,第二次调用将返回 he,然后您停止。

    【讨论】:

      【解决方案2】:

      这是实现您的预​​期方法的一种简洁方法。

      # put your nouns of interest here
      NOUN_LIST = ["doctor", ...]
      
      def find_stuff(text):
          doc = nlp(text)
          if len(doc) < 4: return None # too short
          
          for tok in doc[3:]:
              if tok.pos_ == "NOUN" and tok.text in NOUN_LIST and doc[tok.i-3].pos_ == "PRON":
                  return (doc[tok.i-3].text, tok.text)
      

      正如提到的另一个答案,您在这里的方法是错误的。你想要句子的主语和宾语(或谓语主格)。您应该为此使用DependencyMatcher。这是一个例子:

      from spacy.matcher import DependencyMatcher
      import spacy
      
      nlp = spacy.load("en_core_web_sm")
      doc = nlp("she is a good person")
      
      pattern = [
        # anchor token: verb, usually "is"
        {
          "RIGHT_ID": "verb",
          "RIGHT_ATTRS": {"POS": "AUX"}
        },
        # verb -> pronoun
        {
          "LEFT_ID": "verb",
          "REL_OP": ">",
          "RIGHT_ID": "pronoun",
          "RIGHT_ATTRS": {"DEP": "nsubj", "POS": "PRON"}
        },
        # predicate nominatives have "attr" relation
        {
          "LEFT_ID": "verb",
          "REL_OP": ">",
          "RIGHT_ID": "target",
          "RIGHT_ATTRS": {"DEP": "attr", "POS": "NOUN"}
        }
      ]
      
      matcher = DependencyMatcher(nlp.vocab)
      matcher.add("PREDNOM", [pattern])
      matches = matcher(doc)
      
      for match_id, (verb, pron, target) in matches:
          print(doc[pron], doc[verb], doc[target])
      

      您可以使用displacy 检查依赖关系。您可以在Jurafsky and Martin book 中了解更多关于它们的信息。

      【讨论】:

      • 谢谢!据我所知,我能够运行的 SpaCy 版本是早期版本并且没有依赖匹配器,但第一种方法有效并且适合我的需要。除了一个问题 - 我的文本由换行符分隔的句子列表组成,SpaCy 不会将其解析为单独的句子,因此它适用于第一句而不是文本的其余部分。你知道我如何告诉它分别读取文本文件的每一行吗?
      • DependencyMatcher 已经存在了一段时间 - 出于好奇,您使用的是什么版本的 spaCy,为什么不能升级?
      • 另外,对于句子,如果您有单独的问题,请提出一个新问题,而不是在 cmets 中提问。
      • 我不确定我正在运行什么版本,但我收到了一个错误,这显然是旧版本的 SpaCy 特有的,解决方案是升级它。我正在使用谷歌合作实验室。无法升级可能是我的错误,但我的印象是我需要在本地下载它。我需要与其他人共享 Google Colab 文件,并且不能依赖他们能够在本地下载内容。不过我的时间很短,所以老实说,我不太担心解决这个问题。
      • 嗯,好的。我绝对确定您可以在 colab 中轻松使用最新版本的 spaCy,而且您无需在本地下载任何内容,因此您可能需要考虑这样做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 2016-05-20
      相关资源
      最近更新 更多