天天看点

李宏毅自然语言处理——成分句法分析

引言

上次我们介绍过了指代消歧,现在我们介绍句法分析。

句法分析(syntactic parsing)分为两大类:依存句法分析(Dependency Parsing)和成分句法分析(Constituency Parsing)。

本文我们主要介绍成分句法分析。

李宏毅自然语言处理——成分句法分析

成分句法分析

李宏毅自然语言处理——成分句法分析

成分句法分析假设在一个句子里面,某些span组成Constituency(成分),可以把成分想成一个单位。

比如“learing is very”就不是一个单位,但是“deep learning”就是一个单位,“very powerful”看起来也是一个单位,就是看起来放在一起比较通顺,不别扭。

那成分句法分析要做的是把句子里面,所有能组成成分的字符串找出来。

最简单是每个单词就是一个成分。

每个成分都有一个标签(label,或者是POS tag)。

比如“deep learning”的标签是名词短语;而“very powerful”的标签是形容词短语。

那有哪些标签呢

李宏毅自然语言处理——成分句法分析

那怎么做呢

李宏毅自然语言处理——成分句法分析

首先输入一个句子,这个句子中每个词汇都是一个成分,每个成分都有一个标签;

接下来相邻的成分可能可以组合起来变成一个更大的单位,比如“deep”和“learning”可以组合起来;“very”和“powerful”可以组合起来等等

所有成分组合起来,变成一个句子(S)。

把所有组合起来的成分放在一起,就形成了一个树状的结构。

李宏毅自然语言处理——成分句法分析

我们假设这个树是一个二叉树,叶子就是词汇。那如何解决成分句法分析的问题呢,有两大解法。

李宏毅自然语言处理——成分句法分析

第一个叫Chart-based方法。

李宏毅自然语言处理——成分句法分析

那要怎么做呢,我们要训练一个分类器,给它一个span,它判断这个span是否为一个成分(二分类器)。

除了判断一个span是否为成分之外,我们还要判断这个成分的标签(多分类器)。

李宏毅自然语言处理——成分句法分析

举例来说,把“deep learning”丢进去,它输出是成分,并且输出它所属的标签。

李宏毅自然语言处理——成分句法分析

对于不是成分的东西,比如“deep learning is”丢进去,它判断不是成分,此时标签的输出就不重要了。

李宏毅自然语言处理——成分句法分析

那这个分类器长什么样子呢?

我们输入一串文字,然后把这串文字丢到BERT里面,得到每个token的嵌入向量。然后把你在意的span,用span feature extraction抽出一个代表的向量,然后把这个向量,比如丢到一个多层的全连接网络中,输出就是YES/NO;

然后把这个向量丢到另外的多层全连接网络,输出这个成分所属的标签。

接下来就端到端的学习,就结束了。

李宏毅自然语言处理——成分句法分析

所以感觉整个过程还是挺简单的。

假设你有个token,只要跑次,就能知道所有的span是不是一个成分。

实际上这个问题没有这么简单,这里有一个严重的问题。

因为你的分类器并不是完美的,可能你跑完分类器后,你会发现输出了一些矛盾的结果。

可能把“deep learning is”丢到分类器中,它输出是YES。

然后把“is very powerful”丢进去,它也输出是YES。

这时候就矛盾了,因为如果这两者都是成分的话,就没有办法把它们两拼成一个树了。因为它们有重叠的部分。

那如何避免这种矛盾的情况发生呢。

其实实际上你训练好分类器后,你是这样使用的。

李宏毅自然语言处理——成分句法分析

给一个句子,你会先穷举处所有可能的树状结构。

可能把“I am”拼成一个成分,然后把“I am good”拼成一个更大的成分。

也可能把“am good”拼成一个成分,把“I am good”拼成一个更大的成分。

下面就用刚才训练出来的分类器,去看哪一个树状结构得到的分数更高,也就是说,你先找出合法的树状结构,再用分类器去判断哪个树状结构是最好的。避免单纯判断成分产生矛盾的情况。

如果你的句子很长,那么穷举所有的树状结构就需要CKY算法。

李宏毅自然语言处理——成分句法分析

另外的方法叫作Transition-based方法,是怎么做的呢,我们来看一个例子。

李宏毅自然语言处理——成分句法分析

首先要有一个Stack,它初始为空的。然后有一个Buffer,里面放的即使要来做分析的句子。

接着有三个可以采取的动作。

第一个是创建一个成分;第二个是从buffer里面移动一个token到stack;第三个是生成一个完整的成分。

然后我们看具体是如何做的。

李宏毅自然语言处理——成分句法分析

因为开始stack都是空的,所以第一个要采取的动作就是创建,首先是创建一个句子。

然后把创建句子这个动作​

​(S​

​放到Buffer里面,

李宏毅自然语言处理——成分句法分析

接下来要创造一个名词短语。

李宏毅自然语言处理——成分句法分析

然后我们决定要采取SHIFT这个动作,它要做的事情就是把Buffer里面的东西,移到Stack里面去。

李宏毅自然语言处理——成分句法分析

现在Stack里面有两个没有产生完毕的成分,因此需要继续执行SHIFT,把learning拿进去。

李宏毅自然语言处理——成分句法分析

接下来根据Stack和Buffer要采取Reduce这个动作。

李宏毅自然语言处理——成分句法分析

执行为Reduce后,我们就产生了一个成分,它是名词短语(NP)。接下来再决定下一个动作是什么。

李宏毅自然语言处理——成分句法分析

假设现在根据Stack和Buffer里面的值决定要创造一个动词短语,然后需要执行SHIFT把Buffer里面的token放到Stack里面去。

李宏毅自然语言处理——成分句法分析

假设接下来决定要创建一个形容词短语(ADJP,视频里面有误)

李宏毅自然语言处理——成分句法分析

并且下一步执行SHIFT把very放到stack里面去。然后再次执行SHIFT把buffer最后的token移到stack里面去。

李宏毅自然语言处理——成分句法分析

此时BUFFER里面已经空了,由于形容词短语还没有结束,所以就现关闭形容词短语,执行REDUCE动作。

李宏毅自然语言处理——成分句法分析

此时又看到动词短语没有结束,再次执行REDUCE。

李宏毅自然语言处理——成分句法分析

最后再执行一次REDUCE,结束掉整个句子的成分。

李宏毅自然语言处理——成分句法分析

就得到了最后的句法分析结果。

上面我们有一个重要步骤没有细讲,就是如何决定什么时候要采取什么动作。这里可以用深度学习模型来做这件事。但是在之前,有人尝试了用RNN来做。

李宏毅自然语言处理——成分句法分析

主要思想是根据stack里面和buffer里面的东西,来决定要采取什么动作。

所以可以拿两个RNN,分别读入stack和buffer里面的序列。也许之前已经采取过的动作,也读入另一个RNN。

然后每个RNN都把最后的输出拿出来,丢给某个网络,由它来决定要采取哪个动作。

李宏毅自然语言处理——成分句法分析

其实这就是一个分类问题,你可以知道上面的情况,应该要采取REDUCE。然后希望经过RNN后,最终的网络输出REDUCE。

李宏毅自然语言处理——成分句法分析

还有另一种方法,采取基于序列的方法,直接用一个seq2seq模型来做这件事情。

李宏毅自然语言处理——成分句法分析

我们今天要做的事情是,让机器看这段文字,然后产生一个树状结构。我们其实可以把这个树状结构表示成一个序列。比如采用由上而下,由做而右遍历的放。首先看到了根节点,然后输出“(S”。

李宏毅自然语言处理——成分句法分析

然后进入左节点,也是先看根节点,第一个是NP,然后序列就变成了“(S (NP”。然后又看它的左节点,此时为“deep”,由于它是叶子节点,接着看右边,是“learing”。因此,变成了“(S (NP deep learning”。

接下来由于NP的孩子节点都产生完了,然后需要放要一个符号代表这件事,这里放了一个“)”,整个序列变成了“(S (NP deep learning )”,以此类推,最终产生序列:“(S (NP deep learning ) (VP is (ADJP very powerful ) )”

李宏毅自然语言处理——成分句法分析

Seq2Seq的方法其实和RNN Grammar的方法没有太大的区别。比如你要放一个“(S”,就是“CREATE(S)”,你要放一个token进去,就是动作“SHIFT”,等等。

我们主要介绍了监督学习的句法分析,那有没有无监督的方法