nltk StanfordNERTagger:如何在没有大写的情况下获得专有名词
nltk StanfordNERTagger : How to get proper nouns without capitalization
我正在尝试使用 StanfordNERTagger 和 nltk 从一段文本中提取关键字。
docText="John Donk works for POI. Brian Jones wants to meet with Xyz Corp. for measuring POI's Short Term performance Metrics."
words = re.split("\W+",docText)
stops = set(stopwords.words("english"))
#remove stop words from the list
words = [w for w in words if w not in stops and len(w) > 2]
str = " ".join(words)
print str
stn = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz')
stp = StanfordPOSTagger('english-bidirectional-distsim.tagger')
stanfordPosTagList=[word for word,pos in stp.tag(str.split()) if pos == 'NNP']
print "Stanford POS Tagged"
print stanfordPosTagList
tagged = stn.tag(stanfordPosTagList)
print tagged
这给了我
John Donk works POI Brian Jones wants meet Xyz Corp measuring POI Short Term performance Metrics
Stanford POS Tagged
[u'John', u'Donk', u'POI', u'Brian', u'Jones', u'Xyz', u'Corp', u'POI', u'Short', u'Term']
[(u'John', u'PERSON'), (u'Donk', u'PERSON'), (u'POI', u'ORGANIZATION'), (u'Brian', u'ORGANIZATION'), (u'Jones', u'ORGANIZATION'), (u'Xyz', u'ORGANIZATION'), (u'Corp', u'ORGANIZATION'), (u'POI', u'O'), (u'Short', u'O'), (u'Term', u'O')]
很明显,Short
和 Term
之类的东西被标记为 NNP
。我拥有的数据包含许多这样的实例,其中 非 NNP
单词大写 。这可能是由于拼写错误,也可能是 headers。我对此没有太多控制权。
我如何解析或清理数据,以便我可以检测到非 NNP
字词,即使它可能被大写? 我不希望像 Short
和 Term
这样的术语被归类为 NNP
另外,不确定为什么 John Donk
被当成人抓获,而 Brian Jones
却没有。可能是因为我的数据中有其他大写的非 NNP
s?这会影响 StanfordNERTagger
对待其他一切的方式吗?
更新,一种可能的解决方案
这是我打算做的事情
- 取每个单词并转换为小写
- 标记小写单词
- 如果标签是
NNP
那么我们知道原来的词也一定是NNP
- 如果不是,那么原词是mis-capitalized
这是我尝试做的
str = " ".join(words)
print str
stp = StanfordPOSTagger('english-bidirectional-distsim.tagger')
for word in str.split():
wl = word.lower()
print wl
w,pos = stp.tag(wl)
print pos
if pos=="NNP":
print "Got NNP"
print w
但这给了我错误
John Donk works POI Jones wants meet Xyz Corp measuring POI short term performance metrics
john
Traceback (most recent call last):
File "X:\crp.py", line 37, in <module>
w,pos = stp.tag(wl)
ValueError: too many values to unpack
我尝试了多种方法,但总是出现一些错误。 如何标记单个单词?
我不想将整个字符串转换为小写然后标记。如果我这样做,StanfordPOSTagger
returns 一个空字符串
首先你不应该在你的程序中使用预定义的关键字作为变量名。避免使用 str
作为变量名。而是使用 newstring
或其他任何东西。
在您的更新中,您将 每个 小写单词传递给词性标注器。
tag()
方法拆分传递给它的每个字符串并为每个字符提供 POS 标记。
所以我建议您将 list
而不是单词传递给 tag()
方法。
该列表一次只包含一个词。
您可以这样尝试:w = stp.tag([wl])
w
将是一个包含两项的列表 [w1,POS]
这样你可以标记一个单词
但在这种情况下,它将 john
的 POS 标记作为 NN
首先,请参阅您的其他问题以设置从命令行或 python 调用 Stanford CoreNLP:nltk : How to prevent stemming of proper nouns。
对于正确的大小写句子,我们看到 NER 工作正常:
>>> from corenlp import StanfordCoreNLP
>>> nlp = StanfordCoreNLP('http://localhost:9000')
>>> text = ('John Donk works POI Jones wants meet Xyz Corp measuring POI short term performance metrics. '
... 'john donk works poi jones wants meet xyz corp measuring poi short term performance metrics')
>>> output = nlp.annotate(text, properties={'annotators': 'tokenize,ssplit,pos,ner', 'outputFormat': 'json'})
>>> annotated_sent0 = output['sentences'][0]
>>> annotated_sent1 = output['sentences'][1]
>>> for token in annotated_sent0['tokens']:
... print token['word'], token['lemma'], token['pos'], token['ner']
...
John John NNP PERSON
Donk Donk NNP PERSON
works work VBZ O
POI POI NNP ORGANIZATION
Jones Jones NNP ORGANIZATION
wants want VBZ O
meet meet VB O
Xyz Xyz NNP ORGANIZATION
Corp Corp NNP ORGANIZATION
measuring measure VBG O
POI poi NN O
short short JJ O
term term NN O
performance performance NN O
metrics metric NNS O
. . . O
对于小写的句子,POS 标签和任何 NER 标签都不会得到 NNP
:
>>> for token in annotated_sent1['tokens']:
... print token['word'], token['lemma'], token['pos'], token['ner']
...
john john NN O
donk donk JJ O
works work NNS O
poi poi VBP O
jones jone NNS O
wants want VBZ O
meet meet VB O
xyz xyz NN O
corp corp NN O
measuring measure VBG O
poi poi NN O
short short JJ O
term term NN O
performance performance NN O
metrics metric NNS O
所以你的问题应该是:
- 你的NLP应用的最终目标是什么?
- 为什么你的输入是小写的?是您的行为还是数据的提供方式?
回答完这些问题后,您可以继续决定您真正想用 NER 标签做什么,即
如果输入是小写的,这是因为您构建 NLP 工具链的方式,那么
- 不要那样做!!! 对正常文本执行 NER,而不会造成您创建的扭曲。这是因为 NER 是在普通文本上训练的,所以它不会真正脱离普通文本的上下文。
- 另外尽量不要混合使用来自不同套件的 NLP 工具,它们通常不会很好地发挥作用,尤其是在 NLP 工具链的末端
如果输入是小写的,因为原始数据是小写的,那么:
- 注释一小部分数据,或找到小写的注释数据,然后重新训练模型。
- 解决它并使用普通文本训练一个 truecaser,然后将 truecasing 模型应用于小写文本。参见 https://www.cs.cmu.edu/~llita/papers/lita.truecasing-acl2003.pdf
如果输入有错误的大小写,例如`Some big Some Small but not all are Proper Noun, then
- 也试试 truecasing 解决方案。
我正在尝试使用 StanfordNERTagger 和 nltk 从一段文本中提取关键字。
docText="John Donk works for POI. Brian Jones wants to meet with Xyz Corp. for measuring POI's Short Term performance Metrics."
words = re.split("\W+",docText)
stops = set(stopwords.words("english"))
#remove stop words from the list
words = [w for w in words if w not in stops and len(w) > 2]
str = " ".join(words)
print str
stn = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz')
stp = StanfordPOSTagger('english-bidirectional-distsim.tagger')
stanfordPosTagList=[word for word,pos in stp.tag(str.split()) if pos == 'NNP']
print "Stanford POS Tagged"
print stanfordPosTagList
tagged = stn.tag(stanfordPosTagList)
print tagged
这给了我
John Donk works POI Brian Jones wants meet Xyz Corp measuring POI Short Term performance Metrics
Stanford POS Tagged
[u'John', u'Donk', u'POI', u'Brian', u'Jones', u'Xyz', u'Corp', u'POI', u'Short', u'Term']
[(u'John', u'PERSON'), (u'Donk', u'PERSON'), (u'POI', u'ORGANIZATION'), (u'Brian', u'ORGANIZATION'), (u'Jones', u'ORGANIZATION'), (u'Xyz', u'ORGANIZATION'), (u'Corp', u'ORGANIZATION'), (u'POI', u'O'), (u'Short', u'O'), (u'Term', u'O')]
很明显,Short
和 Term
之类的东西被标记为 NNP
。我拥有的数据包含许多这样的实例,其中 非 NNP
单词大写 。这可能是由于拼写错误,也可能是 headers。我对此没有太多控制权。
我如何解析或清理数据,以便我可以检测到非 NNP
字词,即使它可能被大写? 我不希望像 Short
和 Term
这样的术语被归类为 NNP
另外,不确定为什么 John Donk
被当成人抓获,而 Brian Jones
却没有。可能是因为我的数据中有其他大写的非 NNP
s?这会影响 StanfordNERTagger
对待其他一切的方式吗?
更新,一种可能的解决方案
这是我打算做的事情
- 取每个单词并转换为小写
- 标记小写单词
- 如果标签是
NNP
那么我们知道原来的词也一定是NNP
- 如果不是,那么原词是mis-capitalized
这是我尝试做的
str = " ".join(words)
print str
stp = StanfordPOSTagger('english-bidirectional-distsim.tagger')
for word in str.split():
wl = word.lower()
print wl
w,pos = stp.tag(wl)
print pos
if pos=="NNP":
print "Got NNP"
print w
但这给了我错误
John Donk works POI Jones wants meet Xyz Corp measuring POI short term performance metrics
john
Traceback (most recent call last):
File "X:\crp.py", line 37, in <module>
w,pos = stp.tag(wl)
ValueError: too many values to unpack
我尝试了多种方法,但总是出现一些错误。 如何标记单个单词?
我不想将整个字符串转换为小写然后标记。如果我这样做,StanfordPOSTagger
returns 一个空字符串
首先你不应该在你的程序中使用预定义的关键字作为变量名。避免使用 str
作为变量名。而是使用 newstring
或其他任何东西。
在您的更新中,您将 每个 小写单词传递给词性标注器。
tag()
方法拆分传递给它的每个字符串并为每个字符提供 POS 标记。
所以我建议您将 list
而不是单词传递给 tag()
方法。
该列表一次只包含一个词。
您可以这样尝试:w = stp.tag([wl])
w
将是一个包含两项的列表 [w1,POS]
这样你可以标记一个单词
但在这种情况下,它将 john
的 POS 标记作为 NN
首先,请参阅您的其他问题以设置从命令行或 python 调用 Stanford CoreNLP:nltk : How to prevent stemming of proper nouns。
对于正确的大小写句子,我们看到 NER 工作正常:
>>> from corenlp import StanfordCoreNLP
>>> nlp = StanfordCoreNLP('http://localhost:9000')
>>> text = ('John Donk works POI Jones wants meet Xyz Corp measuring POI short term performance metrics. '
... 'john donk works poi jones wants meet xyz corp measuring poi short term performance metrics')
>>> output = nlp.annotate(text, properties={'annotators': 'tokenize,ssplit,pos,ner', 'outputFormat': 'json'})
>>> annotated_sent0 = output['sentences'][0]
>>> annotated_sent1 = output['sentences'][1]
>>> for token in annotated_sent0['tokens']:
... print token['word'], token['lemma'], token['pos'], token['ner']
...
John John NNP PERSON
Donk Donk NNP PERSON
works work VBZ O
POI POI NNP ORGANIZATION
Jones Jones NNP ORGANIZATION
wants want VBZ O
meet meet VB O
Xyz Xyz NNP ORGANIZATION
Corp Corp NNP ORGANIZATION
measuring measure VBG O
POI poi NN O
short short JJ O
term term NN O
performance performance NN O
metrics metric NNS O
. . . O
对于小写的句子,POS 标签和任何 NER 标签都不会得到 NNP
:
>>> for token in annotated_sent1['tokens']:
... print token['word'], token['lemma'], token['pos'], token['ner']
...
john john NN O
donk donk JJ O
works work NNS O
poi poi VBP O
jones jone NNS O
wants want VBZ O
meet meet VB O
xyz xyz NN O
corp corp NN O
measuring measure VBG O
poi poi NN O
short short JJ O
term term NN O
performance performance NN O
metrics metric NNS O
所以你的问题应该是:
- 你的NLP应用的最终目标是什么?
- 为什么你的输入是小写的?是您的行为还是数据的提供方式?
回答完这些问题后,您可以继续决定您真正想用 NER 标签做什么,即
如果输入是小写的,这是因为您构建 NLP 工具链的方式,那么
- 不要那样做!!! 对正常文本执行 NER,而不会造成您创建的扭曲。这是因为 NER 是在普通文本上训练的,所以它不会真正脱离普通文本的上下文。
- 另外尽量不要混合使用来自不同套件的 NLP 工具,它们通常不会很好地发挥作用,尤其是在 NLP 工具链的末端
如果输入是小写的,因为原始数据是小写的,那么:
- 注释一小部分数据,或找到小写的注释数据,然后重新训练模型。
- 解决它并使用普通文本训练一个 truecaser,然后将 truecasing 模型应用于小写文本。参见 https://www.cs.cmu.edu/~llita/papers/lita.truecasing-acl2003.pdf
如果输入有错误的大小写,例如`Some big Some Small but not all are Proper Noun, then
- 也试试 truecasing 解决方案。