最近我一直在阅读关于自然语言处理(NLP)的资料,到目前为止,我对从句子分割到词性标注(POS-tagging),以及知识表示等各个方面的基本工作原理有了一个(非常)初步的了解。
我知道市面上有各种各样的NLP库(主要是Java或Python),我还找到了一个.NET实现(SharpNLP)。实际上,它非常出色。无需编写任何自定义处理逻辑;只需使用它们的函数,瞧!用户输入就被很好地分离并进行了词性标注。
我不明白的是,如果我的主要动机是构建一个问答系统(类似于聊天机器人),接下来该怎么做?我可以使用哪些库(最好是.NET)?如果我想构建自己的知识库(KB),我应该如何表示我的知识?我是否需要将词性标注的输入解析成我的数据库可以理解的其他形式?如果我使用的是MS SQL,有没有哪个库可以帮助将词性标注的输入映射到数据库查询?还是我需要根据程序语义(我读到过)来编写自己的数据库查询逻辑?
当然,下一步是制定一个结构良好的回复,但我认为我可以稍后再处理。现在困扰我的是在这个领域(知识表示,NLP到KB/DB检索)缺乏资源,如果你们中的任何人能提供专业意见,我将不胜感激 🙂
回答:
这是一个非常广泛的问题,因此它几乎不符合StackOverflow的格式,不过我还是想尝试回答一下。
首先,谈谈NLP
在NLP领域,成熟工具的广泛可用性本身就有些误导性。当然,所有/大多数NLP功能,从例如词性标注或分块到例如自动摘要或命名实体识别,都由各种库的逻辑和支持数据很好地覆盖和服务。然而,从这些构建块构建现实世界的解决方案绝非易事。需要做到以下几点:
- 沿着某种管道或链构建解决方案,使特定转换的结果输入到后续过程的输入中。
- 配置各个过程:这些过程的计算框架已经很成熟,但它们对基础数据(如训练/参考语料库、可选调优参数等)极为敏感。
- 选择和验证适当的功能/过程。
上述内容对于解决方案中与从文本中提取和处理语义元素相关的部分尤其困难(广义上的信息提取,但也包括共指消歧、关系提取或情感分析等)。这些NLP功能及其在各种库中的相应实现往往更难配置,对领域依赖模式或语音水平的变化甚至支持语料库的“格式”更为敏感。
简而言之,NLP库为诸如问题中提到的“问答系统”等应用提供了必要的构建块,但需要大量的“粘合剂”以及如何以及在哪里应用这些粘合剂的谨慎判断(还需要大量非NLP技术,如下文讨论的知识表示问题)。
关于知识表示
如上所述,仅词性标注不足以成为NLP管道的一部分。基本上,词性标注会为文本中的每个单词添加信息,指示该单词的[可能]语法角色(如名词与形容词、动词与代词等)。这种词性信息非常有用,因为它允许例如后续将文本分块成逻辑相关的单词组和/或更精确地在字典、分类法或本体中查找单个单词。
为了说明某些“问答系统”可能需要的信息提取和底层知识表示,我将讨论各种语义搜索引擎中使用的常见格式。然而,请注意,这种格式对于语义搜索可能更多是概念性的而非规定性的,其他应用如专家系统或翻译机器需要其他形式的知识表示。
这个想法是使用NLP技术以及支持数据(从简单的“查找表”用于简单词汇,到用于分类的树状结构,再到用专门语言表达的本体)来从文本中提取三元组实体,具有以下结构:
- 一个代理:做某事的人或物
- 一个动词:正在做的事情
- 一个对象:被“做”的人或物(或更广泛地说,关于“做”的某些补充信息)
示例:
猫/代理 吃/动词 老鼠/对象。
John-Grisham/代理 写/动词 The-Pelican-Brief/对象
牛/代理 生产/动词 牛奶/对象
此外,这种三元组,有时称为“事实”,可以根据动词的语义模式分类为各种类型。例如,“因果”事实有一个表示某种因果关系的动词,“包含”事实有一个暗示容器与被包含物关系的动词,“定义”事实是指代理/主体通过对象定义的模式(例如,“猫是哺乳动物”),等等。
人们很容易想象如何查询这种事实数据库以提供问题的答案,并提供各种智能和服务,如同义词替换或提高答案与问题的相关性(与简单的关键词匹配相比)。
从文本中提取事实的真正难点。为此目的,许多NLP功能被投入使用。例如,NLP管道中的一个步骤是用它们所指的代词替换名词(NLP术语中的指代消解或更广泛的共指消解)。另一个步骤是识别命名实体:人的名字、地理位置、书籍等(NLP术语中的NER)。另一个步骤可能是重写由“AND”连接的从句,以便通过重复隐含的语法元素来创建事实。
例如,上面的John Grisham示例可能来自于类似以下文本摘录:作者J. Grisham出生在阿肯色州。他在1989年写了《杀死一只知更鸟》,在1992年写了《鹈鹕案》
得到John-Grisham/代理 写/动词 The-Pelican-Brief/对象
意味着(除其他外):
- 识别“J. Grisham”和“The Pelican Brief”为特定实体。
- 在第二句话中用“John-Grisham”替换“He”。
- 将第二句话重写为两个事实:“John-Grisham写了A-time-to-kill在1989年”和“John-Grisham写了The-Pelican-brief在1992年”
- 删除“在1992年”部分(或者更好的是,创建另一个事实,一个“时间事实”:“The-Pelican-brief/代理 与时间相关/动词 年-1992/对象”)(顺便说一下,这也意味着识别
1992
为类型为“年”的时间实体。)
简而言之:信息提取即使应用于相对有限的领域,并且利用库中现有的NLP功能,也是一项复杂的任务。它的确比仅仅识别名词与形容词和动词要“混乱”得多 😉