0

我想用 Prolog 做一些信息检索任务。目前,我有一组(大量)不同的 Prolog 理论,它们表示句子中的依赖关系(顺便说一下,我将这些 Prolog 代码存储在一个文本文件中)——我只想找到那些与用户定义的目标子句匹配的理论。

例如,我有这样的 Prolog 代码:

rel("nsubjpass","seen","It",S):-S is 1.
rel("aux","seen","can",S):-S is 1.
rel("auxpass","seen","be",S):-S is 1.
...
rel("prep", X, Y, S):-rel("dobj", Z, X, SCORE1), rel("prep", Z, Y, SCORE2), S is SCORE1*SCORE2.
...
rel(_,_,_, S):-S is 0.0001.

我想搜索这样的目标子句:

?- rel("nsubj", WRONG, "Russell", SCORE1), 
   rel("nsubj", WRONG, "Russell", SCORE2), 
   ... , 
   rel("dobj",DOING,SOMETHING, SCORE9).

如果我对理论进行简单的类似foreach循环,搜索时间会随着理论数量的增加而变慢,所以我必须引入一些优化。

我的想法是创建一个倒排索引,我可以在其中维护每个术语的频率,以及它们发生的理论的 ID。然后在搜索时,我会首先过滤掉那些不会包含在结果中的不必要的理论。

信息检索领域有没有其他行之有效的方法或好的模式和算法可以很好地处理这个问题?

4

2 回答 2

1

我将其写为答案而不是评论,只是因为评论非常有限。

首先,如果你确实打算使用 Prolog,那么做一些研究是值得的

  1. 语言本身:
    • 它的优点和缺点是什么?
    • 我可以在惯用的 Prolog 中实现我的目标吗(已经解决了类似的问题)
  2. 不同的实现:
    • 特定实现比其他实现提供什么
    • 将实现与其他语言接口起来有多容易

在开始的短暂挣扎之后,我一直在专门使用 SWI-Prolog,所以我有偏见。但是 SWI 提供了一个非常完整、通用、相当高效的实现、优秀的文档,并且是完全开源的。

继续前进,您似乎正在使用 Prolog 事实来表示您的数据。Prolog 事实的形式:

foo(a,b,1).
foo(a,d,10).
...

建立Prolog 数据库。大多数实现都提供了某种事实索引,因此像“给我 'foo's 和 'a' 作为第一个参数”这样的查询:

?- foo(a,B,X).
B = b, X = 3;
B = d, X = 10.

通过所有可用的事实进行非常有效的搜索并返回与您的查询匹配的事实。您绝对不需要使用 for 循环搜索事实,或编写事实搜索算法。但是请注意,事实索引可能因实现而异。

此外,根据您的用例,将字符串表示为 Prolog 原子可能是最佳解决方案,高效且易于实现。看这里,特别是接近尾声的时候,一些非常有用的关于原子的“字符串操作”谓词。

继续前进,在 Prolog 中编写自上而下、从左到右的解析器是该语言的一个特性,使用 DCG(定句语法)。

最后,如果您对 Java 很熟悉并且只需要添加一个高效的(动态)数据存储,那么 Java + SQL 可能是更好的选择。

于 2013-04-20T07:39:31.627 回答
0

从 Prolog 开发人员的角度来看,我认为 Boris 的回答是合理的,但我不想花太多时间来研究如何从 Prolog 调用 Java 函数,反之亦然,更不用说从Prolog 脚本,这对我来说是必需的。

所以我有点固执,我试图实现我最初的想法,即从 Prolog 术语创建倒排索引,它完美地工作。所以现在当我想搜索某个 Prolog 目标时,第一步我可以过滤相关理论的“数据库”:我计算术语出现的交集,然后只使用这些理论运行 Prolog 引擎. 另一个大的性能优化是在各个搜索之间共享一个单例 TuProlog 引擎,它还减少了内存开销。哦,我也重构了规则,例如现在我写这个:

rel(nsubjpass, "seen","It", 1).

而不是这个:

rel("nsubjpass","seen","It",S):-S is 1.

我没有注意到这种变化对性能有任何显着提升,但至少它并没有变慢 :)

有了这些改动,现在可以看出真正的性能瓶颈不是运行 Prolog 引擎,而是使用 NLP 库……但这是另一个问题。:)

于 2013-04-25T10:00:59.540 回答