【问题标题】:Improving the extraction of human names with nltk [closed]使用 nltk 改进人名的提取 [关闭]
【发布时间】:2013-12-15 22:50:45
【问题描述】:

我正在尝试从文本中提取人名。

有没有人推荐的方法?

这是我尝试过的(代码如下): 我正在使用nltk 查找标记为人的所有内容,然后生成该人所有 NNP 部分的列表。我跳过只有一个 NNP 的人,以避免抓住一个单独的姓氏。

我得到了不错的结果,但想知道是否有更好的方法来解决这个问题。

代码:

import nltk
from nameparser.parser import HumanName

def get_human_names(text):
    tokens = nltk.tokenize.word_tokenize(text)
    pos = nltk.pos_tag(tokens)
    sentt = nltk.ne_chunk(pos, binary = False)
    person_list = []
    person = []
    name = ""
    for subtree in sentt.subtrees(filter=lambda t: t.node == 'PERSON'):
        for leaf in subtree.leaves():
            person.append(leaf[0])
        if len(person) > 1: #avoid grabbing lone surnames
            for part in person:
                name += part + ' '
            if name[:-1] not in person_list:
                person_list.append(name[:-1])
            name = ''
        person = []

    return (person_list)

text = """
Some economists have responded positively to Bitcoin, including 
Francois R. Velde, senior economist of the Federal Reserve in Chicago 
who described it as "an elegant solution to the problem of creating a 
digital currency." In November 2013 Richard Branson announced that 
Virgin Galactic would accept Bitcoin as payment, saying that he had invested 
in Bitcoin and found it "fascinating how a whole new global currency 
has been created", encouraging others to also invest in Bitcoin.
Other economists commenting on Bitcoin have been critical. 
Economist Paul Krugman has suggested that the structure of the currency 
incentivizes hoarding and that its value derives from the expectation that 
others will accept it as payment. Economist Larry Summers has expressed 
a "wait and see" attitude when it comes to Bitcoin. Nick Colas, a market 
strategist for ConvergEx Group, has remarked on the effect of increasing 
use of Bitcoin and its restricted supply, noting, "When incremental 
adoption meets relatively fixed supply, it should be no surprise that 
prices go up. And that’s exactly what is happening to BTC prices."
"""

names = get_human_names(text)
print "LAST, FIRST"
for name in names: 
    last_first = HumanName(name).last + ', ' + HumanName(name).first
        print last_first

输出:

LAST, FIRST
Velde, Francois
Branson, Richard
Galactic, Virgin
Krugman, Paul
Summers, Larry
Colas, Nick

除了维珍银河,这都是有效的输出。当然,在本文的上下文中,知道维珍银河不是人名是困难的(也许是不可能的)部分。

【问题讨论】:

  • 虽然很有趣,但不清楚这里的实际问题是什么。 “让我的代码更好”的建议不太适合这个网站。
  • 谢谢,基本上我的问题是:我想从文本中提取名称。这是我尝试过的,它工作正常,但不是非常好。有没有人会推荐的解决这个问题的替代方法?我将编辑问题以改进它。
  • 感谢分享。我能够使用您的代码,但我遇到了两个需要修复的错误。首先我得到了错误:SyntaxError: Non-ASCII character.... no encoding declared,通过在第 1 行添加修复:# -- coding: UTF-8 -- 然后我得到错误:NotImplementedError("Use label() to access a node label.,通过从第 17 行删除“节点”修复如下:for subtree in sentt.subtrees(filter=lambda t: t.label() == 'PERSON'):
  • 如果您希望今天使用此代码。确保将这些放在 import 语句之后。 nltk.download('朋克'); nltk.download('averaged_perceptron_tagger'); nltk.download('maxent_ne_chunker'); nltk.download('单词');除此之外,请确保将 t.node 替换为 t.label()

标签: python nlp nltk


【解决方案1】:

必须同意“让我的代码更好”的建议不太适合这个网站,但我可以给你一些方法让你尝试深入了解

看看Stanford Named Entity Recognizer (NER)。它的绑定已包含在 NLTK v 2.0 中,但您必须下载一些核心文件。这是script,它可以为您完成所有这些工作。

我写了这个脚本:

import nltk
from nltk.tag.stanford import NERTagger
st = NERTagger('stanford-ner/all.3class.distsim.crf.ser.gz', 'stanford-ner/stanford-ner.jar')
text = """YOUR TEXT GOES HERE"""

for sent in nltk.sent_tokenize(text):
    tokens = nltk.tokenize.word_tokenize(sent)
    tags = st.tag(tokens)
    for tag in tags:
        if tag[1]=='PERSON': print tag

并得到了不错的输出:

('弗朗索瓦', '人') ('R.','人') ('Velde','人') (“理查德”,“人”) (“布兰森”,“人”) (“处女”,“人”) (“银河”,“人”) (“比特币”、“人”) (“比特币”、“人”) (“保罗”,“人”) (“克鲁格曼”,“人”) (“拉里”,“人”) (“夏天”,“人”) (“比特币”、“人”) (“尼克”,“人”) (“可乐”,“人”)

希望这有帮助。

【讨论】:

  • 他希望输出为名字和姓氏。 NER 只会给出 PERSON 标签。
  • 此解决方案分别给出名字和姓氏,而不是结合在一起。如果有中间名,您将遇到问题。更糟糕的是,如果你有一个包含四个单词的名字,那么如果我们只是组合 2 个连续的单词来找到一个名字,它就会被分成 2 个名字。因此不能回答这个问题。谢谢!
  • 这也适用于不同语言的名称吗?如果没有,那么如何做到这一点?我用的是印度名字。
  • 这部分没有经过:" from nltk.tag.stanford import NERTagger"
  • @tursunWali 很遗憾听到这个消息。这个答案大约有 7 年的历史。它肯定需要更新到更新的 Python 和 NLTK 版本。
【解决方案2】:

对于其他人来说,我发现这篇文章很有用:http://timmcnamara.co.nz/post/2650550090/extracting-names-with-6-lines-of-python-code

>>> import nltk
>>> 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())
...

【讨论】:

  • 如果一个名字有中间名怎么办?它不会承受
  • 我在较新版本的 NLTK 中收到此错误:notimplementederror use label() to access a node label。通过将最后两行更改为以下内容来解决它: if hasattr(chunk, 'label'): print(chunk.label(), ' '.join(c[0] for c in chunk.leaves()))
【解决方案3】:

我实际上只想提取人名,因此,我想检查所有作为 wordnet 输出的名称(一个大型的英语词汇数据库)。 更多关于 Wordnet 的信息可以在这里找到:http://www.nltk.org/howto/wordnet.html

import nltk
from nameparser.parser import HumanName
from nltk.corpus import wordnet


person_list = []
person_names=person_list
def get_human_names(text):
    tokens = nltk.tokenize.word_tokenize(text)
    pos = nltk.pos_tag(tokens)
    sentt = nltk.ne_chunk(pos, binary = False)

    person = []
    name = ""
    for subtree in sentt.subtrees(filter=lambda t: t.label() == 'PERSON'):
        for leaf in subtree.leaves():
            person.append(leaf[0])
        if len(person) > 1: #avoid grabbing lone surnames
            for part in person:
                name += part + ' '
            if name[:-1] not in person_list:
                person_list.append(name[:-1])
            name = ''
        person = []
#     print (person_list)

text = """

Some economists have responded positively to Bitcoin, including 
Francois R. Velde, senior economist of the Federal Reserve in Chicago 
who described it as "an elegant solution to the problem of creating a 
digital currency." In November 2013 Richard Branson announced that 
Virgin Galactic would accept Bitcoin as payment, saying that he had invested 
in Bitcoin and found it "fascinating how a whole new global currency 
has been created", encouraging others to also invest in Bitcoin.
Other economists commenting on Bitcoin have been critical. 
Economist Paul Krugman has suggested that the structure of the currency 
incentivizes hoarding and that its value derives from the expectation that 
others will accept it as payment. Economist Larry Summers has expressed 
a "wait and see" attitude when it comes to Bitcoin. Nick Colas, a market 
strategist for ConvergEx Group, has remarked on the effect of increasing 
use of Bitcoin and its restricted supply, noting, "When incremental 
adoption meets relatively fixed supply, it should be no surprise that 
prices go up. And that’s exactly what is happening to BTC prices."
"""

names = get_human_names(text)
for person in person_list:
    person_split = person.split(" ")
    for name in person_split:
        if wordnet.synsets(name):
            if(name in person):
                person_names.remove(person)
                break

print(person_names)

输出

['Francois R. Velde', 'Richard Branson', 'Economist Paul Krugman', 'Nick Colas']

除了拉里·萨默斯之外,所有的名字都是正确的,这是因为姓氏“萨默斯”。

【讨论】:

  • 看起来不错,但在代码中 person_list 未定义
  • 嘿@EdgarH,现在应该可以正常工作了。 person_names需要在person_list之后初始化
  • 使用 NLTK 处理 NER 时,此类导入是一个问题,并且“pip install XYZ”不起作用:from nameparser.parser import HumanName AND from nltk.tag.stanford import NERTagger
【解决方案4】:

@trojane 的回答对我来说不太奏效,但对我有很大帮助。

先决条件

创建一个文件夹stanford-ner,并将以下两个文件下载到其中:

脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import nltk
from nltk.tag.stanford import StanfordNERTagger

text = u"""
Some economists have responded positively to Bitcoin, including
Francois R. Velde, senior economist of the Federal Reserve in Chicago
who described it as "an elegant solution to the problem of creating a
digital currency." In November 2013 Richard Branson announced that
Virgin Galactic would accept Bitcoin as payment, saying that he had invested
in Bitcoin and found it "fascinating how a whole new global currency
has been created", encouraging others to also invest in Bitcoin.
Other economists commenting on Bitcoin have been critical.
Economist Paul Krugman has suggested that the structure of the currency
incentivizes hoarding and that its value derives from the expectation that
others will accept it as payment. Economist Larry Summers has expressed
a "wait and see" attitude when it comes to Bitcoin. Nick Colas, a market
strategist for ConvergEx Group, has remarked on the effect of increasing
use of Bitcoin and its restricted supply, noting, "When incremental
adoption meets relatively fixed supply, it should be no surprise that
prices go up. And that’s exactly what is happening to BTC prices.
"""

st = StanfordNERTagger('stanford-ner/english.all.3class.distsim.crf.ser.gz',
                       'stanford-ner/stanford-ner.jar')

for sent in nltk.sent_tokenize(text):
    tokens = nltk.tokenize.word_tokenize(sent)
    tags = st.tag(tokens)
    for tag in tags:
        if tag[1] in ["PERSON", "LOCATION", "ORGANIZATION"]:
            print(tag)

结果

('Bitcoin', 'LOCATION')       # wrong
('Francois', 'PERSON')
('R.', 'PERSON')
('Velde', 'PERSON')
('Federal', 'ORGANIZATION')
('Reserve', 'ORGANIZATION')
('Chicago', 'LOCATION')
('Richard', 'PERSON')
('Branson', 'PERSON')
('Virgin', 'PERSON')         # Wrong
('Galactic', 'PERSON')       # Wrong
('Bitcoin', 'PERSON')        # Wrong
('Bitcoin', 'LOCATION')      # Wrong
('Bitcoin', 'LOCATION')      # Wrong
('Paul', 'PERSON')
('Krugman', 'PERSON')
('Larry', 'PERSON')
('Summers', 'PERSON')
('Bitcoin', 'PERSON')        # Wrong
('Nick', 'PERSON')
('Colas', 'PERSON')
('ConvergEx', 'ORGANIZATION')
('Group', 'ORGANIZATION')     
('Bitcoin', 'LOCATION')       # Wrong
('BTC', 'ORGANIZATION')       # Wrong

【讨论】:

  • u"textString" 在字符串之前是什么意思,我知道r"text\String" -> 这是原始的。
  • 这是 Python 2 的遗留问题。我将其删除。见stackoverflow.com/a/2464968/562769
【解决方案5】:

您可以尝试对找到的名称进行解析,并检查是否可以在诸如 freebase.com 之类的数据库中找到它们。在本地获取数据并查询(在RDF中),或者使用google的api:https://developers.google.com/freebase/v1/getting-started。大多数大公司、地理位置等(会被你的 sn-p 捕获)可以根据 freebase 数据被丢弃。

【讨论】:

  • 此 api 已停用
【解决方案6】:

这对我来说效果很好。我只需要更改一行就可以运行。

    for subtree in sentt.subtrees(filter=lambda t: t.node == 'PERSON'):

需要

    for subtree in sentt.subtrees(filter=lambda t: t.label() == 'PERSON'):

输出中存在缺陷(例如,它将“洗钱”识别为一个人),但根据我的数据,名称数据库可能不可靠。

【讨论】:

    【解决方案7】:

    我想在这里发布一个残酷而贪婪的解决方案,以解决@Enthusiast提出的问题:如果可能,请获取一个人的全名。

    每个名称中第一个字符的大写用作识别Spacy 中的PERSON 的标准。例如,“吉姆霍夫曼”本身不会被识别为命名实体,而“吉姆霍夫曼”将被识别。

    因此,如果我们的任务只是从脚本中挑选人物,我们可以简单地先将每个单词的第一个字母大写,然后将其转储到spacy

    import spacy
    
    def capitalizeWords(text):
    
      newText = ''
    
      for sentence in text.split('.'):
        newSentence = ''
        for word in sentence.split():
          newSentence += word+' '
        newText += newSentence+'\n'
    
      return newText
    
    nlp = spacy.load('en_core_web_md')
    
    doc = nlp(capitalizeWords(rawText))
    
    #......
    
    

    请注意,这种方法以增加误报为代价覆盖全名。

    【讨论】:

    • OSError: [E050] 找不到模型“en_core_web_md”。它似乎不是快捷链接、Python 包或数据目录的有效路径。
    • 你必须通过 python -m spacy download en_core_web_md 安装这个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 2011-08-06
    • 2015-07-28
    相关资源
    最近更新 更多