如何避免从大写的文本标题中提取非专有名词?

Posted

技术标签:

【中文标题】如何避免从大写的文本标题中提取非专有名词?【英文标题】:How to avoid extracing non-proper nouns from headings in text with capitalization? 【发布时间】:2016-04-24 23:35:33 【问题描述】:

我正在尝试使用nltkStanford NLP 工具从一段文本中提取关键字。运行代码后,我可以得到这样的列表

companyA
companyB
companyC
Trend Analysis For companyA

这一切都很好,但请注意最后一项。这实际上是出现在文本中的标题。由于标题的所有单词都是大写的,我的程序认为这些都是专有名词,因此将它们组合在一起,就好像它们是一个大公司名称一样。

好消息是,只要文中某处提到了一家公司,我的程序就会选择它,因此我也会得到像 companyA 这样的单个项目。这些来自关于该公司的实际文本。

这就是我想做的。

在我上面得到的列表中,有没有办法查看一个项目并确定任何以前的项目是否是当前项目的子字符串?比如这种情况当我遇到

Trend Analysis For companyA

我可以检查我以前是否看过这部分内容。所以我可以确定我已经拥有companyA,因此我将忽略Trend Analysis For companyA我相信本文会提到任何公司,足以让 StanfordNER 接受它。因此我不必依赖标题来获得我需要的东西。

这有意义吗?这是正确的方法吗?恐怕这不会很有效,但我想不出别的。

编辑

这是我使用的代码

sentences = nltk.sent_tokenize(document) 
sentences = [nltk.word_tokenize(sent) for sent in sentences] 
sentences = [nltk.pos_tag(sent) for sent in sentences] 

之后我只是在每个句子上使用StanfordNERTagger

result = []
stn = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz') 
for s in sentences:
    taggedwords = stn.tag(s)
    for tag, chunk in groupby(taggedWords, lambda x:x[1]):

        if tag == "ORGANIZATION":

            result.append((tag, " ".join(w for w, t in chunk)))

return result

这样我可以得到所有的ORGANIZATIONs。

@Alvas 关于 Truecasing 的观点,你不觉得这有点矫枉过正吗?当我研究算法时,在我看来,他们试图为每个单词想出最有可能的拼写。可能性将基于语料库。我不认为我需要建立一个语料库,因为我可以使用像wordnet 或类似pyenchant 这样的字典来找出适当的拼写。另外,在这里我已经有了我需要的所有信息,即我正在挑选所有提到的公司。

还有一个问题。考虑公司名称

American Eagle Outfitters

注意Americanamerican 都是正确的拼写。 Eagleeagle 的类似物。恐怕即使我在我的算法中使用 Truecasing,它最终也会小写不应该小写的术语。

再次,我现在的问题是我提取了所有公司名称,但我也在提取标题。蛮力方式是对结果列表执行子字符串检查。我只是想知道是否有更有效的方法来做到这一点。此外,我认为我所做的任何调整都不会改善标记。我不认为我能超越StanfordNERTagger

【问题讨论】:

再一次,有趣但不适合 ***。你是如何使用NLTK + Stanford NLP 提取文本的?您可以发布代码链接或提供代码 sn-p 吗?根据您提取短语的方式,您可能无法提取您真正想要的内容。 你有没有尝试过***.com/questions/34439208/… 的truecasing 建议?我很确定 truecasing 总体上会减少你对 NER 的痛苦。我将把它作为重复投票,因为现在你遇到了带有大写字母的“假阳性”而不是没有大写字母的“假阴性”的相反问题。可能的解决方案保持不变,例如做truecasing 从cs.cmu.edu/~llita/papers/lita.truecasing-acl2003.pdf阅读第3.4.1节 @GaborAngeli,他使用的是无壳模型和***.com/questions/34439208/…。我认为更重要的是了解问题,了解现有技术,然后再着手实施或执行一项技术。 urbandictionary.com/define.php?term=the+proof+is+in+the+pudding 【参考方案1】:

我确实遇到了类似的问题,但整个文本没有大写(ASR 输出)。在那种情况下,我确实在未大写的注释数据上重新训练 NER 模型以获得更好的性能。

按照偏好(和复杂性)的顺序,我会考虑以下几个选项:

Uncapitalize text:在标记化/句子拆分之后,尝试猜测哪些句子都是大写的,并使用基于字典的方法来取消大写明确的标记(这可能被视为序列标记问题,并且可能涉及机器学习...但是可以很容易地为这个问题生成数据)。 学习具有大写特征的模型您可以在机器学习中添加一个特征来重建 POS 和 NER 模型,但这需要有语料库来重新训练模型。 后处理数据 鉴于标记容易出错,您可以应用一些后处理,这可能会考虑到先前发现的具有子字符串匹配的实体。但是这个过程会很危险,因为如果你找到“America”和“Bank Of America”,更正可能无法知道“Bank Of America”实际上是一个实体。

我个人会考虑第一个选项,因为您可以轻松地人工创建全大写语料库(从正确大写的文本)并训练序列标注器模型(例如 CRF)模型来检测应该删除大写字母的位置。

无论您使用哪种方法,您确实永远不会获得与正确大写的 texte 一样好的性能。您的输入可被视为部分嘈杂,因为 POS 标记和 NER 都缺少线索。

【讨论】:

感谢您的建议。顺便说一句,America 将被标记为 LOCATION 而不是 ORGANIZATION ;) 我确实尝试过很多这样的场景,因此我认为后期处理可能不是一个坏主意。 你提出了一个有趣的观点。如果整个句子都是大写的,那么它可能是一个标题,也许我一找到它就可以做点什么。但是,如果我尝试使用字典将明确的文本取消大写,那么Bank Of America 可能会变成bank of America。这对于句子/标题本身可能不正确,但只要Bank Of America 在文本的其他地方至少出现一次,我仍然可以忍受。 另外,我如何为这个问题生成数据?您是指一般数据还是仅查看手头的文档? 是的,美国很可能是一个位置——不过取决于上下文 :) 至于生成数据,您可以使用一般数据:获取任何(正确大写的)文本,然后将每个标记大写:同时使用序列(原始与全部大写)你可以训练一个序列标注器来学习哪些标记是非大写的。不确定该算法的效率如何,但它肯定是可行的并且可能非常有趣!

以上是关于如何避免从大写的文本标题中提取非专有名词?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 scikit TfidfVectorizer 中赋予专有名词更多的权重

名词1

金融文本挖掘的业务领域建模

在线文本实体抽取能力,助力应用解析海量文本数据

从短文本中提取和排名关键字

同步与异步阻塞与非阻塞理解