【问题标题】:Handling information from a prolog sentence parser处理来自序言句解析器的信息
【发布时间】:2017-12-09 18:22:18
【问题描述】:

我在 prolog 中创建了一个句子解析器。它成功地解析了输入的句子...... ?- sentence([input,sentence,here],Parse).

这是我用来解析句子的代码:

np([X|T],np(det(X),NP2),Rem):- /* Det NP2 */
    det(X),
    np2(T,NP2,Rem).
np(Sentence,Parse,Rem):- np2(Sentence,Parse,Rem). /* NP2 */
np(Sentence,np(NP,PP),Rem):- /* NP PP */
    np(Sentence,NP,Rem1),
    pp(Rem1,PP,Rem).

np2([H|T],np2(noun(H)),T):- noun(H). /* Noun */
np2([H|T],np2(adj(H),Rest),Rem):- adj(H),np2(T,Rest,Rem).

pp([H|T],pp(prep(H),Parse),Rem):- /* PP NP */
    prep(H),
    np(T,Parse,Rem).

vp([H| []], vp(verb(H))):- /* Verb */
    verb(H).

vp([H|T], vp(verb(H), Rem)):- /* VP PP */
    vp(H, Rem),
    pp(T, Rem, _).

vp([H|T], vp(verb(H), Rem)):- /* Verb NP */
    verb(H),
    np(T, Rem, _).

我应该提到输出是:sentence(np(det(a), np2(adj(very), np2(adj(young), np2(noun(boy))))), vp(verb(loves), np(det(a), np2(adj(manual), np2(noun(problem)))))).

使用预定义的词汇表:det(a), adj(very), adj(young), noun(boy), verb(loves), det(a), adj(manual), noun(problem)

我想要做的是将解析后的输出传递给谓词,将单词分成三个不同的类别,即“主语、动词和宾语”。

(1) 主语将包含前两个形容词,然后是名词。

(2) 动词将包含“动词短语”中的动词。

(3) 宾语将包含“动词短语”中的形容词和名词。

所有的限定符都应该被忽略。

例如,我想要一个在输出中查找形容词的谓词。

我已经尝试了很多方法来尝试使其正常工作,但没有任何工作。任何帮助将不胜感激。

【问题讨论】:

  • 好的。我已经添加了用于解析句子的代码。

标签: parsing prolog


【解决方案1】:

那么,我正在做第二次尝试。

输出将是:sentence(np(det(a), np2(adj(very), np2(adj(young), np2(noun(boy))))), vp(verb(loves), np(det(a), np2(adj(manual), np2(noun(problem))))))。 [...] 我想做的是 将解析后的输出传递给将单词分开的谓词 分为三个不同的类别,即“主语、动词和 对象”。

您可以编写这样的程序,将您的结构映射到单词列表。

handle_sent(sentence(NP1,vp(V,NP2)),Subj,Verb,Obj) :-
  handle_np(NP1,Subj), handle_verb(V,Verb), handle_np(NP2,Obj).

handle_verb(verb(V),[V]).

handle_np(np(_,np2(adj(A),np2(noun(N)))),[A,N]).
handle_np(np(_,np2(adj(A1),np2(adj(A2),np2(noun(N))))),[A1,A2,N]).

这会产生:

?- handle_sent(...,Subj,Verb,Obj).
Subj = [very,young,boy]
Verb = [loves]
Obj = [manual,problem]

【讨论】:

    【解决方案2】:

    下面的 DCG 会产生这种行为:

    ?- s(Sem,[a,young,boy,loves,a,manual,problem],[]).
    Sem = [noun(boy),verb(loves),noun(problem)]
    

    你的语法有一些问题。您的第三个 np 子句直接调用自身(不消耗其间的输入),这意味着无限循环。您发布的语法似乎无法产生您的输出(非常年轻)。不管怎样,这里是 DCG:

    s(Sem) -->
      np(Sem1), vp(Sem2), { append(Sem1,Sem2,Sem) }.
    
    np(Sem) -->
      [W], { det(W) },
      np2(Sem).
    np(Sem) -->
      np2(Sem).
    np(Sem) -->
      np2(Sem1),
      pp(Sem2), { append(Sem1,Sem2,Sem) }.
    
    np2([noun(W)]) -->
      [W], { noun(W) }.
    np2(Sem) -->
      [W], { adj(W) },
      np2(Sem).
    
    pp(Sem) -->
      [W], { prep(W) },
      np(Sem).
    
    vp([verb(W)]) -->
      [W], { verb(W) }.
    vp(Sem) -->
      [W], { verb(W) },
      np(Sem0), { Sem = [verb(W)|Sem0] }.
    vp(Sem) -->
      [W], { verb(W) },
      pp(Sem0), { Sem = [verb(W)|Sem0] }.
    

    加法:如果你想处理修饰(例如形容词),那么有一些简单明显的解决方案很快就会变得不切实际,然后还有更通用的技术,比如在np 中添加一个逻辑变量。

    np(X,Sem) -->
      [W], { det(W) },
      np2(X,Sem).
    np(X,Sem) -->
      np2(X,Sem).
    np(X,Sem) -->
      np2(X,Sem1),
      pp(Sem2), { append(Sem1,Sem2,Sem) }.
    
    np2(X,[noun(X,W)]) -->
      [W], { noun(W) }.
    np2(X,[adj(X,W)|Sem]) -->
      [W], { adj(W) },
      np2(X,Sem).
    

    此变量 (X) 从未实例化,它仅用于将名词短语含义的各个部分链接在一起。

    ?- s(Sem,[a,young,boy,loves,a,manual,problem],[]).
    Sem = [adj(_A,young),noun(_A,boy),verb(loves),adj(_B,manual),noun(_B,problem)]
    

    还有各种额外的可能性。好书是 Gazdar 和 Mellish,Prolog 中的 NLP,和 Norvig,AI 编程范式(如果你说 Lisp),以及 Pereira 和 Shieber,Prolog和自然语言分析

    补充 #2:再次阅读您的问题和this other question 后,我意识到您实际上想要三个单独的列表。没问题。

    s(L1,L2,L3) -->
      np(_,L1), vp(L2,L3).
    
    np(X,L) -->
      [W], { det(W) },
      np2(X,L).
    np(X,L) -->
      np2(X,L).
    np(X,L) -->
      np2(X,L),
      pp(_).
    
    np2(X,[noun(X,W)]) -->
      [W], { noun(W) }.
    np2(X,[adj(X,W)|L]) -->
      [W], { adj(W) },
      np2(X,L).
    
    pp(L) -->
      [W], { prep(W) },
      np(_,L).
    
    vp([verb(W)],[]) -->
      [W], { verb(W) }.
    vp([verb(W)],L) -->
      [W], { verb(W) },
      np(_,L).
    vp([verb(W)],L) -->
      [W], { verb(W) },
      pp(L).
    

    输出:

    | ?- s(L1,L2,L3,[a,young,boy,loves,a,manual,problem],[]).
    L1 = [adj(_A,young),noun(_A,boy)],
    L2 = [verb(loves)],
    L3 = [adj(_B,manual),noun(_B,problem)] ? 
    

    现在也许您不需要逻辑变量,但另一方面,您可以使用更复杂的修饰符,例如“一个小男孩喜欢涉及红色螺栓和白色立方体的手工问题”。然后变量将跟踪哪个形容词修饰哪个名词。

    【讨论】:

    • 我是否可以通过使用单独的谓词来做到这一点,例如 'extractnounphrase(np(det(A),_)):-' 将解析后的值传递给它们?而不是随着我们一起做。
    • 好吧,这就像拥有两个解析器,因为您当前生成的输出与您的语法规则同构。 DCG 要好得多。
    • 我知道 DSG 更好(因为人们一直告诉我),但我仍然要学习这一点。我想知道您是否可以按照我一直在做的方式告诉我如何做。
    猜你喜欢
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 2023-04-03
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    相关资源
    最近更新 更多