NLP基础学习笔记1-基于DFS搜索和规则的句子生成模型



本文和当前流行的NLP算法其实关系不大,是介绍一些历史上人们为了解决一些NLP问题提出的解决思路。


NLP自然语言处理经过了多年的发展,现在主流是采用机器学习和深度学习的方法进行NLP问题的解决,但是历史上,在机器学习还没有提出前,科学家还想出了很多解决自然语言问题的方法。可以基于搜索的方法去解决问题,其中一种就是基于规则的方法,这次学习老师采用了基于规则的方法解决句子生成的问题,下面对基于规则的方法进行总结。

待解决的问题,我们想生成一些合法的句子,生成句子由一个名词短语noun_phrase和动词短语verb_phrase组成,其具体的规则定义如下,其中规则部分的空格表示把两个部分合为一个,|号表示选择随机其中的某一个

grammar = “
sentence=>noun_phrase verb_phrase
noun_phrase=>Article Adj* noun
verb_phrase=>verb noun_phrase
Adj*=>null | Adj Adj*
Article=>一个 | 这个
noun=>女人 | 篮球 | 桌子 | 小猫
verb=>看着 | 坐在 | 听着 | 看见
Adj=>蓝色的 | 好看的 | 小小的
”

用python实现,最容易想到的实现方法就是把sentence,noun_phrase,verb_phrase,Adj*,Adj,noun,verb都封装为函数,然后通过解析grammar提取出关键字来,然后实现一系列的switch case或者if else,通过不同的关键字调用不同的函数实现具体功能。这样的实现有两个弊端,第一个是假如我们需要新增一个语法,那么必须新封装一个函数,然后在switch case中添加一个新的分支;第二个是若语法复杂后,必然导致过高的代码圈复杂度。

我们可以将语法解析流程画成树状图,如下所示,其实整个语法解析流程就是一个树搜索的过程,每个语法解析到每个父子节点可能有两种策略,一种就是将所有子节点的结果组合起来,另一种就是随机选取一种子节点的结果

NLP中文摘要生成 nlp标题生成_NLP中文摘要生成

NLP中文摘要生成 nlp标题生成_语法解析_02

看着上面的树形结构,可以想到使用BFS搜索的方法去实现树形结构的搜索,一次搜索结果就是一次语法解析的结果,这个DFS搜索和传统DFS搜索的唯一区别就是有些树形节点的子节点需要随机选择,所以并不是每个子节点都会被遍历到。

import random

grammar = """

sentence=>noun_phrase+verb_phrase

noun_phrase=>Article+Adj*+noun

verb_phrase=>verb+noun_phrase

Adj*=>null | Adj+Adj*

Article=>一个 | 这个

noun=>女人 | 篮球 | 桌子 | 小猫

verb=>看着 | 坐在 | 听着 | 看见

Adj=>蓝色的 | 好看的 | 小小的

"""
def create_grammar(grammar_str, split='=>', line_split='\n'):
    grammar = {}
    for line in grammar_str.split(line_split):
        if not line.strip(): 
            continue
        expression, statement = line.split(split)
        grammar[expression.strip()] = [s.strip() for s in statement.split('|')]
    return grammar

choice = random.choice

def generate(gram, target):
    """采用递归实现深度优先搜索"""
    if target not in gram:
        return target # means target is a terminal expression
    expaned = [generate(gram, t) for t in choice(gram[target])]
    return ''.join([e for e in expaned if e != 'null'])

grammar = create_grammar(grammar)

generate(gram=grammar, target='sentence')

生成结果为

'一个篮球坐在这个好看的小猫'

上述的朴素方法可以按照人们预先定义的语法规则生成出句子来,通过对问题解决方法的抽象,用BFS搜索的方法解决了问题,避免了传统面向过程的解决方法中大量if else代码的实现。但是,基于搜索方法决策问题,可能会面临巨大的搜索空间而导致无法解决。