搜索自然语言句子结构
Posted
技术标签:
【中文标题】搜索自然语言句子结构【英文标题】:Searching Natural Language Sentence Structure 【发布时间】:2011-06-24 23:43:15 【问题描述】:存储和树数据库的最佳方法是什么?
使用OpenNLP'sEnglish Treebank Parser,我可以获得相当可靠的任意句子的句子结构解析。我想做的是创建一个工具,可以从我的源代码中提取所有文档字符串,为文档字符串中的所有句子生成这些树,将这些树及其关联的函数名存储在数据库中,然后允许用户使用自然语言查询来搜索数据库。
所以,给定函数upload_files()
的句子"This uploads files to a remote machine."
,我会得到树:
(TOP
(S
(NP (DT This))
(VP
(VBZ uploads)
(NP (NNS files))
(PP (TO to) (NP (DT a) (JJ remote) (NN machine))))
(. .)))
如果有人输入查询“我如何上传文件?”,相当于树:
(TOP
(SBARQ
(WHADVP (WRB How))
(SQ (MD can) (NP (PRP I)) (VP (VB upload) (NP (NNS files))))
(. ?)))
如何在 SQL 数据库中存储和查询这些树?
我编写了一个简单的概念验证脚本,它可以使用正则表达式和网络图解析的组合来执行此搜索,但我不确定如何以可扩展的方式实现它。
是的,我意识到使用简单的关键字搜索来检索我的示例是微不足道的。我试图测试的想法是如何利用语法结构,这样我就可以剔除具有相似关键字但句子结构不同的条目。例如,对于上面的查询,我不想检索与句子 "Checks a remote machine to find a user that uploads files."
关联的条目,它具有相似的关键字,但显然描述的是完全不同的行为。
【问题讨论】:
【参考方案1】:我同意ffriend 的观点,即您需要在现有知识库和自然语言搜索工作的基础上采取不同的方法。在关系数据库中存储上下文无关的解析树不是问题,但是作为搜索的一部分,对解析树进行有意义的比较将是非常困难的。当您只是对利用一点语法关系知识感兴趣时,解析树真的太复杂了。如果将解析简化为依赖三元组,则可以使搜索问题更容易,并首先获得您感兴趣的语法关系。例如,您可以使用Stanford dependency parser,它会生成一个上下文无关的解析,然后从中提取依赖三元组。它为“此函数将文件上传到远程机器”产生如下输出:
det(function-2, This-1)
nsubj(uploads-3, function-2)
dobj(uploads-3, files-4)
det(machine-8, a-6)
amod(machine-8, remote-7)
prep_to(uploads-3, machine-8)
在您的数据库中,您可以存储与函数关联的这些三元组的简化子集,例如:
upload_file(): subj(uploads, function)
upload_file(): obj(uploads, file)
upload_file(): prep(uploads, machine)
当人们搜索时,您可以找到具有最多重叠三元组或类似内容的函数,您可能还想加权不同的依赖关系或允许部分匹配等。您可能还想减少单词在引理的三元组中,可能是 POS,具体取决于您的需要。
有很多人从事过自然语言搜索(如 Powerset),所以一定要搜索现有的方法。我在这里提出的方法确实很少,我可以想到大量可能会出现问题的示例,但我认为沿着这些思路的一些方法对于受限制的域可以相当有效。
【讨论】:
【参考方案2】:这不是一个完整的答案,但如果您想对您的树执行语言复杂的查询,最好的办法是预处理您的解析器输出并使用 tgrep2 进行搜索:
http://www.stanford.edu/dept/linguistics/corpora/cas-tut-tgrep.html
据我所知,Trgrep/tgrep2 是用于搜索解析树的最灵活、功能最齐全的包。这不是您要求的基于 mysql 的解决方案,但我认为您可能有兴趣了解此选项。
Tgrep2 允许您询问有关父母、后代和兄弟姐妹的问题,而其他解决方案不会保留解析的完整树结构或允许此类复杂查询。
【讨论】:
【参考方案3】:关系数据库不能以自然的方式存储知识,您真正需要的是知识库或本体(尽管它可能构建在关系数据库之上)。它以三元组<subject, predicate, object>
保存数据,因此您的短语将存储为<upload_file(), upload, file>
。有很多工具和方法可以在这样的 KB 中进行搜索(例如,Prolog 就是一种专门为此而设计的语言)。所以,您所要做的就是将句子从自然语言翻译成KB 三元组/本体图,将用户查询翻译成不完整的三元组(你的问题看起来像<?, upload, file>
) 或连接查询,然后搜索您的知识库。 OpenNLP 将帮助您进行翻译,其余的取决于您决定使用的具体技术和技术。
【讨论】:
这是一个有趣的想法,尽管我认为使用语义网络本体会比您所说的要复杂一些。它不会像一个扁平的三元组那么简单。主语、谓语和宾语可能每个都是嵌套的三元组,仍然需要用词性标记。 @Cerin:在本体中,您已经使用“清理过的”数据,即使用事实,而不是文字本身。本体中的三元组也不能嵌套,但它们可以组成相当大的子图,这是真的。最困难的事情是将句子翻译成事实,但无论如何您都需要将它们翻译成某种东西来执行有效的搜索,那么为什么不将它们翻译成结构,这是众所周知的并在数千篇论文中有所描述呢?您可以使用领域区域中非常基本的三元组手动创建一些初始本体,然后使用它来映射新事实并扩大自身。 我明白你的意思,但这可能不切实际。数据永远不会完全“干净”。 OpenNLP 输出几个带有确定性度量标记的解析,因此本体中的每个子图都必须存储和推理这种不确定性。我也永远不会在事实和单词/句子之间有明确的区别。我只想利用语法结构来改进搜索。尝试解释语义也有点超出范围。 顺便说一句,当我说嵌套时,我指的是子图。 N3/Turtle/RDF 支持匿名节点,您可以使用匿名节点将任意数量的三元组“组合”成更高级别三元组中的单个参数。以上是关于搜索自然语言句子结构的主要内容,如果未能解决你的问题,请参考以下文章