• 5.2 段落处理

    5.2 段落处理

    我们解释一句话时会使用丰富的上下文知识,一部分取决于前面的内容,一部分取决于我们的背景假设。DRT 提供了一个句子的含义如何集成到前面段落表示中的理论,但是在前面的讨论中明显缺少这两个部分。首先,一直没有尝试纳入任何一种推理;第二,我们只处理了个别句子。这些遗漏由模块nltk.inference.discourse纠正。

    段落是一个句子的序列 s<sub>1</sub>, … s<sub>n</sub>,段落线是读法的序列 s<sub>1</sub>-r<sub>i</sub>, … s<sub>n</sub>-r<sub>j</sub> ,每个序列对应段落中的一个句子。该模块按增量处理句子,当有歧义时保持追踪所有可能的线。为简单起见,下面的例子中忽略了范围歧义。

    1. >>> dt = nltk.DiscourseTester(['A student dances', 'Every student is a person'])
    2. >>> dt.readings()
    3. s0 readings:
    4. s0-r0: exists x.(student(x) & dance(x))
    5. s1 readings:
    6. s1-r0: all x.(student(x) -> person(x))

    一个新句子添加到当前的段落时,设置参数consistchk=True会通过每条线,即每个可接受的读法的序列的检查模块来检查一致性。在这种情况下,用户可以选择收回有问题的句子。

    1. >>> dt.add_sentence('No person dances', consistchk=True)
    2. Inconsistent discourse: d0 ['s0-r0', 's1-r0', 's2-r0']:
    3. s0-r0: exists x.(student(x) & dance(x))
    4. s1-r0: all x.(student(x) -> person(x))
    5. s2-r0: -exists x.(person(x) & dance(x))
    1. >>> dt.retract_sentence('No person dances', verbose=True)
    2. Current sentences are
    3. s0: A student dances
    4. s1: Every student is a person

    以类似的方式,我们使用informchk=True检查新的句子φ是否对当前的段落有信息量。定理证明器将段落线中现有的句子当做假设,尝试证明φ;如果没有发现这样的证据,那么它是有信息量的。

    1. >>> dt.add_sentence('A person dances', informchk=True)
    2. Sentence 'A person dances' under reading 'exists x.(person(x) & dance(x))':
    3. Not informative relative to thread 'd0'

    也可以传递另一套假设作为背景知识,并使用这些筛选出不一致的读法;详情请参阅http://nltk.org/howto上的段落 HOWTO。

    discourse模块可适应语义歧义,筛选出不可接受的读法。下面的例子调用 Glue 语义和 DRT。由于 Glue 语义模块被配置为使用的覆盖面广的 Malt 依存关系分析器,输入(Every dog chases a boy. He runs.)需要分词和标注。

    1. >>> from nltk.tag import RegexpTagger
    2. >>> tagger = RegexpTagger(
    3. ... [('^(chases|runs)$', 'VB'),
    4. ... ('^(a)$', 'ex_quant'),
    5. ... ('^(every)$', 'univ_quant'),
    6. ... ('^(dog|boy)$', 'NN'),
    7. ... ('^(He)$', 'PRP')
    8. ... ])
    9. >>> rc = nltk.DrtGlueReadingCommand(depparser=nltk.MaltParser(tagger=tagger))
    10. >>> dt = nltk.DiscourseTester(['Every dog chases a boy', 'He runs'], rc)
    11. >>> dt.readings()
    12. s0 readings:
    13. s0-r0: ([],[(([x],[dog(x)]) -> ([z3],[boy(z3), chases(x,z3)]))])
    14. s0-r1: ([z4],[boy(z4), (([x],[dog(x)]) -> ([],[chases(x,z4)]))])
    15. s1 readings:
    16. s1-r0: ([x],[PRO(x), runs(x)])

    段落的第一句有两种可能的读法,取决于量词的作用域。第二句的唯一的读法通过条件<cite>PRO(x)`</cite>表示代词 He。现在让我们看看段落线的结果:

    1. >>> dt.readings(show_thread_readings=True)
    2. d0: ['s0-r0', 's1-r0'] : INVALID: AnaphoraResolutionException
    3. d1: ['s0-r1', 's1-r0'] : ([z6,z10],[boy(z6), (([x],[dog(x)]) ->
    4. ([],[chases(x,z6)])), (z10 = z6), runs(z10)])

    当我们检查段落线d0d1时,我们看到读法s0-r0,其中 every dog 超出了a boy的范围,被认为是不可接受的,因为第二句的代词不能得到解释。相比之下,段落线d1中的代词(重写为z24 通过 等式(z24 = z20)绑定。

    不可接受的读法可以通过传递参数filter=True过滤掉。

    1. >>> dt.readings(show_thread_readings=True, filter=True)
    2. d1: ['s0-r1', 's1-r0'] : ([z12,z15],[boy(z12), (([x],[dog(x)]) ->
    3. ([],[chases(x,z12)])), (z17 = z12), runs(z15)])

    虽然这一小段是极其有限的,它应该能让你对于我们在超越单个句子后产生的语义处理问题,以及部署用来解决它们的技术有所了解。