Knowledge 7一阶谓词逻辑-Generalized Modus Ponens规则

1.写在前面

         propositionalize虽然可以做到我们想做的事,但是它没效率。怎么做更有效率点呢?我们首先来介绍一个,我们叫Generalized Modus Ponens

2.Generalized Modus Ponens

        Generalized Modus Ponens,它其实就是Modus Ponens,Modus Ponens是如果知道一个前提,就可以imply这个结论(A=>B),如果我知道前提,那得到的结果就是结论。generalized Modus Ponens是我知道这个前提,可是这个前提跟A不太一样,它长的有点像,又有点不像,就是一个A‘,它长的很像A,但是不太一样,但是我还是某种程度上可以得到这个结论,只要我能找到正确的替换,使得A跟A‘一样,那我就可以得到B的结论。

        如果我知道这些前提,P1到Pn,这是我的前提,我要导到q的结论,可是我知道的不是真正的 p1,我知道的是p1‘,它们长的很像,但是不一样,然后p2也是跟p2‘一样有点像,如果您能找到一个substitution替代,也就是说你把p1‘和p1两个,你都用一种substitution θ,这个substitution带进去,这个θ可以是任意东西,比如说我们常写的就是,你把x换成John,假设这个样子substitution替代,会使得左右两边看起来一样。如果对每一个Pi前提都成立的话,那结果你就会可以得到 q ,当然你也不是直接拿到q ,这个 q 你也要用同样的θ去替换。

        其实刚刚那个例子,我们知道P1,P2,Q,还有和P1,P2相像的两个。如果我们能找到一个substitution使得这两个长的一样的话,那Q就可以得到。

        我们对应上面这个KB,如果我刚刚写的p1‘  是这一个King(John),p1是这个King(x),你要找到substitution,就是x换成John,左右两边就长得一模一样,同样,这边是p2,你只要把x换成y,就长的一模一样,我们刚刚说了,x是John,你要再把x换成y,所以是y换成John,这是你的结论。如果你用这个substitution的话,你就会发现,第一行和第二行左右是一模一样的,就得到这个结论q is Evil(x),结论不是直接得到的,你要把这个substitution  apply过来,也就是说把里面的x换成John就可以搞定。

        Modus Ponens 应用在KB上,基本指的是definite clause受限制子句,你用CNF的讲法,就是一堆东西的 or  ,里面只有一个是正的,其他都是负的。另外一种讲法,第一幅图GMP中,这边就是全部都是正的,imply一个正的,也是definite clause(准确讲应该是horn clause ,definite clause是只有一个正子句,horn clause 是至多有一个正子句)。只要是definite clause的话,你可以用generalized Modus Ponens去做。

3.Generalized Modus Ponens的可靠性和完备性

3.1 GMP的可靠性soundness

        我们在证明GMP的可靠性之前,我们假设已知一个引理:对于任意的 definite clause p,我们可以通过UI得到 p  entaiment  SUBST(θ,p)。即一个p做一个substitution,这个p里面有for all,把这个东西去替换成一个常数,那么原句就会entail 替换后的句子,这个就是UI 的soundness,这个当做我们的已知。

        接下来我们看怎么证明GMP的soundness,我们可以看到上图中右侧部分,看下面proof,换一个θ ,原句entailment 替换之后的句子。θ 代入之后得到下面那个式子,两个是等价的。我们可以得到:原句entailment后面一整串东西

        第二步,我们已知p1'和 p2'等,我们可以entail 他们的and 合取,然后我们再用UI的那个已知引理,得到entailment后面的一长串。我们仔细看第二步骤的后面经过SUBST之后,其实就是第一步骤的前提条件,那么我们就可以推出第一步的SUBST(θ , q)。这就是GMP的soundness证明。

3.2 Unification统一和standardization(标准化)

        我们刚看到要应用GMP,有一个重要步骤,就是找一个substitution替换,使得替换完之后,p1'= p1,然后对每一个前提都可以找到这样一个substitution,这个概念我们称为Unification统一Unification就是众多substitution替换,其中一种可以使得左边等于右边。通过UNIFY(p,q) 函数会return一个θ,我们用这个θ 替换p,和我们用θ替换q,是相等的。下面是例子展示:

        最后一个我们直接看式子,应该是得不到正确的结论,x必须既是John又是Eliza,John是同一个人。可是应该让它unify出来,为什么呢,因为这边的x是不代表同一个东西。因为我们省略了东西,但这东西可以是for all x,可以是存在x,这是变数来源。在这种情况下我们已知这一个就是从all x跟存在x这两个x不需要是同一个。就是说我们在做unification的时候其实前面之前要先做一件事情叫standardization。

          像我们刚那个例子,这是p,这是q,你应该先把p,q的变数先standardize,使得它们不一样,就像这个x跟这个x是不需要一样的,那通常做法:这是x1,看到x2,再看到x3等等。如果把这两个变数定为不一样的,那你unify结果当然可以是x是Eliza,x17是John。在一些case里面,unifier会不止一个。譬如说我们看一下上面中间那个例子。如果我们要unify这两个,这个是我的p,这个是我的q,你当然可以x,y,z它都是John,这样的话左边会等于右边,就左右都长得一模一样,但是这不是一个最generalize的unifier,一般来说我们希望unifier这个function能return,我们指的是most general unifier。我们简称MGU,这个例子它的MGU应该是y是John,x是z就可以了。

          不过多的去绑定这个sentence,在术语来说,我们一个sentence里面只要是变数,我们喜欢叫ground truth,ground就是地底,在逻辑上我们常常讲说如果是一个变数的话我们就float,或说lift,就是把一个ground举起来,一个变数叫lifted,这是我们常用的讲法。反正你在一个unifier中,不要把一个sentence绑的太死,就不要把它代的,尽量不要去ground它。这样return就是我们most general的unifier。

         那你要怎么得到most general unifier ,用的技巧跟我们前几讲讲的search类似,它是一个树状结构,然后两边就是等于p and q,两边同时用树状结构去展开,然后展到直到某一层两边是长一样的,那我们就把它们match在一起。这时候就是如果用那种prefer search就是尽量不要往下伸,return的最短层数那一个话通常那一个就是most general的unifier。

         另外一个我们提到,因为这个search unifier的过程就是一个搜寻的过程,搜寻的过程我们提到一个名词叫occur check,这个occur check做事情其实是说某个东西,某个term出现多少次,这个地方我们要讲的过于详细,有同学对这个有兴趣的同学可能要查,要接触一下比较advance的进阶的人工智慧的课程,进阶的搜寻技巧,但是一般而言我们假设说这是p,这是q,这两个sentence,基本上这两个sentence是不存在unifier,也就说这两个sentence你不管x带什么东西,它都应该左边不会等于右边因为右边的式子永远多一个s,但是如果你做occur check的话,你就可以了解p不能跟q unify,occur check要做其实不是一件简单的事情,它类似于在搜寻的过程中要去check某两个space是不是repeat,是不是已经重复了。那这件事情我们之前在搜寻的时候就讲过,你如果没有足够的记忆体不见得能够做好这件事,而且写起来,就算你有足够的记忆体写起来你效率会比较慢一点。会讲到prolog这个system,大部分逻辑演绎的system其实很多时候是略过occur check的,很多system我们在实际做的时候,会使得这个p和这个q这样的会使他们unify,会成立。当然结果不是正确的,但是为了一些现实的resource的问题我们不得不这样做。

        接下来我们可以定义一个definite clause,就是first-order definite clause,希望我们的inference效率一些,也就是我们之前提的generalize的Modus Ponens的一个KB,原则上我们提醒大家就是只有一个正子句。你可以有variable,我们看一下怎么用definite clause和generalize Modus Ponens来演绎这个问题。

       这句话蛮长的,大家可以看一下,我们想要用这一段话证明Colonel West是有罪的。

3.3 first-order logic的例子

         我们看一下用first-order logic怎么做。首先第一件事情当然是我们要把这一句话把它先把他transfer成first-order logic的sentence。

         你对任何一个人,只要是American,我前面其实省略for all了。习惯是这样,接下来我们要做的例子是对一个first-order logic KB,如果有existence的时候我们都会把它用EI搞定,那for all的情况下呢,一样可以用UI全部弄完,不过那样就回到propositionalize的过程,所以基本上对for all我们是保留。existence我们就用EI把变数换成常数,接下来我们的first-order logic KB里面所有的变数都是for all,那既然说所有变数都是for all我们就不再写for all这个东西,大家记得一件事,现在只要看到变数,就是for all的意思。对任何一个x,只要是x是American,然后对任何一个y,只要y是weapon,然后x是American sell了weapon  to z,而且z是跟美国是敌对的,则x就criminal。x就是有罪的。基本上你可以看一下就差不多是上面这一句英文的翻译,写成逻辑式。

         我们接下来有一句senten说Nono这个country有一些missiles导弹,那也就说存在,你直接写的话是这样,存在某一个x,nono有x,而且x是missiles,那还是注意,existence我们对应的是and,这我们之前前面有提过。到这边你是第一次转换,但到这边时候我们就立刻apply EI,换成M1,把x换成M1,接下来这个就是真正到我们KB里面的东西。就把它换成Skolen的constant。

        那接下来是对所有的missile卖给他的都是,nono所有的missile全都是West卖给他的,所以只要对for all,所有的x,missile,然后 nono又拥有这个x,则就是West卖x给nono的。

        然后这是我们基本上的knowledge,就是missile是weapon,是一种武器,所以只要for all x,对任何的x,只要x是missile,他就是weapon,大家还是可以注意下我们这边用的for all 对应的是imply。

        接下来就是任何跟美国敌对的country我们都认为它有敌意hostile的,所以任何x,只要x是跟American是enemy,就imply它是hostile。

        然后,West是American,这是我们已知的事实。

        接下来,country nono是美国的敌人,这个也是已知的事实。

        到这边我们就把上面那一段话以及我们所有知道的knowledge换成first-order logic的一个过程,那接下来就上我们就可以apply forward chaining,然后用generalized 的Modus Ponens去做forward chaining。

        你可以看到其实就是Modus Ponens过程。就是你只要找到一个substitution使得它的前提都可以对上,我就直接得到结论。我们就一直试着去做这件事,然后在过程中我们要会unify,去整合那个substitution,只要找得到substitution我们就可以试试看。

3.4 证明forward chaining

        那接下来我们可以看一下这个forward chaining怎么证明,我们刚转换完了以后我们最后目的是要证明Colonel West是criminal的嘛,那我们把我们刚才所有的这几个式子,有8个式子,好那我们把它换成就写在这边,写在我们的knowledge base,好那我们是一样,,就是在forward chaining常常会这样说有implication,他们都,这些列的8个全都是horn clause,那或者你要讲definite clause也可以。就把红笔写的这true拿掉,那这一类形式我们通常把它称为fact,通常你里面还有implication的,这个东西我们称为,就里面写成implication那有时候也把它称为rules都可以。好,那基本上我们就回到那forward chaining分为已知的事实还有我们的规则。好那接下来我们要做forward chaining要做的事情就是把所有可能的事实都导出来,那基本上我们会看一下,譬如说,如果大家还记得,propositional那边的时候,我们就是看前提有多少没有被满足,譬如说第一个generation可以看,就是R5一个check,这边还有没满足的,premise,OK,这边是就这一个,这个,这个,这个,然后你去看一下然后发现,你可以找得到一些,可是你没法全部同时找到,所以这个我们就等到下一个iteration来做,但现在好像R6还蛮简单的,R6这是一个p1,p2,这是前提,然后下面得到结论就是Q,那我们看一下,我们已知的事实你会发现这个p1‘,然后你看nono and1,所以这边是p2’,然后接下来你就找unifier,然后call unifier就会得到这件事,就是x就是M1,好,x是M1,这个x就一样,可以套到,就是M1,好,那这个结论一旦得到以后,你就把它加入已知的事实。就是把这个加到已知的事实里面。然后继续,接下来你看啊,R7也很简单,R7这个missile跟这个很像,missile跟这个很像,就直接把他换成M1,好你就得到这个结论,M1是个weapon。好,那类似我们可以做R8,R8这个enemy跟这个enemy很像,你要替换的就是nono,所以你会得到nono是hostile的。

        那接下来第二个generation。第二个generation这个演绎蛮简单的,因为你得到了这三个,就会发现你得到这一个然后你会发现这个跟这个很像。好,就去call unifier,看能不能找到合适的substitution,那实际上是可以找到,你找到的结果就是x换成West,然后y换成M1,z换成nono就可以搞定。那你这些前提都知道以后你就把这个substitution一样套到它的结论,那这个结论也就说把x换成West。所以就得到了criminal west。

        好,我们来看一下图。那其实这是我们刚刚有讲,只是用图像来表达一下。

3.5 Forward Chaining的特性

        第一个它是既sound又complete,那当然只有在first-order的definite clause,first-order definite clauses当然不是全部的first-order logic,但他是一个子集

        sound的部分我们就基本上证过了,就是generalized Modus Ponens,我们有GMP可以证明。那它complete的证明我们这边省略。但是它如果真的要去证明的话同学可以看一下课本的部分,其实跟我们上一讲在证明proposition logic里面证明forward  chaining证明法很接近,那时候我们有完整的讲清楚,这边的话一样类似,就是我们一样利用fixed point概念来证明,你还是想说说当你forward chaining到一步的时候它不会再导出新的结论的时候,把那地方称为fixed point,然后我们要证明,就是在这个时间点,我看过的结论,所有能导出来的东西我们全都把它设为true,其它设为false,然后这是一个model,这是一个原来你想证的sentence的model,这部分其实跟之前一样,那有些比较detail的部分我们省略不讲的原因。是因为这边因为有新的,有introduce变出的东西iii,那个地方其实我们的证明会变得稍微复杂一点。其实有点类似,如果是Modus Ponens的证明它soundness我们truth table就可以。它的generalized的版本,我们要稍微花费一些唇舌,讲述这些是怎么被扮演进来的。差别就在这边,概念是一样的。

        我们在First-Order的define clause的里面有一种比较,再小一点,范围再小一点的情况,就是如果我们没有function,整个KB没有function,这样的一个特别的KB我们称为Datalog。我们刚刚证明那个conenel west是criminal那个KB本身没有function,大家可以回想一下,我们在里面没有定义任何function,在这种情况下,forward chaining的时间基本上是polynomial time,也就说最多有k个变数,然后每一个你最多有n个ground term ,因为你没有function,所以你ground term就这么多,就只能代换这么多次,然后你有p个这样的sentence,那你最多换这么多次,forward chaining一定在time时间内结束,一般而言会比这个效率再快一些。通常你可能还没到这个时间点你已经想要,已经得到。但你如果不设定这个,就是你并没有一定的query,你没有事先提一定要问什么问题,你就让forward chaining一直跑,把所有可能能导出来的全部导出来的话,基本上你时间就这么多,跟你去proposition来这个KB,然后用proposition的方法来做结果是一样的。我们有讲过forward chaining就把所有的function都会拿出来。所以可以正式证出来。它有个问题,就是原本要证的某个sentence它如果没有没有被entail,没有被KB entail的话那它可能根本不会turn了,如果有function的情况下,这个我们刚刚有提过。这一个我们也讲过,这是不可能避免的事情,因为基本上entailment是first-order semi-decidable。

         这是forward chaining的一些特性。那它的efficiency呢?

        它效能来说,基本上我们刚刚那个做法还可以稍微改进一下,因为一般来说你如果在第k个,你如果没有任何的前提,在前一个iteration知道的情况下,你在第k个generation你也不可能得到结论。这个想法我们类似在proposition和logic和forward chaining的时候我们contour来做这件事情,就是你不用重复的去做unifier的动作。在propositionallogic那边的forward chaining我们是用contour,就你未知的前提我们先定义一个k,然后,你知道一个你就减,知道一个就减,那现在这边是因为有变数,因为你知道是一个p1,那你真正match的是p1,那你如果没事的话去unify p1,其实很浪费时间。

        要讲的就是它的前提没有任何的增加的情况下,你不要去做额外的unification。那可是matching本身就是我们去match,说你哪些有,就是unify这件动作,本身其实很麻烦。如果你用Database indexing的一些技术我们是可以蛮快,譬如说你要问Missile(x),你可以蛮快的时间内,由它的database里面有Missile(M1)你可以很快的知道,x是M1。可是这是单一一个,就是你一个predicate的unify的,很快你可以做到,就是你用hashing的方式去做indexing。但是如果你要去match多个的时候,譬如说像我们下面这个式子,有两个term要去match,就蛮困难的,因为如果你先match这个,因为答案不止,你如果match x它有可能M1,有可能M2、M3,接下来如果M1的话你去match这个可能会match失败。可能nono没有M1,但是可能nono有M3,也就说这个东西是一个搜寻的过程,你不知道哪一个return的值会使得你在下一个的matching会比较快。你要找到一个有效率的matching,这个问题本身是一个NP-hard,就是你要得到最有效率的一群不是一个很简单的问题。

        即使我们知道我们刚刚提的是forward chaining有这些困难,有些时候在做matching,就是你先unify A,还是先unify B,这件事情弄不好,就很没效率,但是,它即使如此还是非常常用,forward chaining常常用在deductive的Database里面。

3.6 Backward Chaining Example

        接下来我们讲一下backward chaining,因为forward chaining我们讲的比较细一点,那backward chaining概念其实一样,还是一个and or grave search所以我们基本上就在我们刚刚例子看一下它实际上怎么做就好了。

        因为backward chaining基本上我们就是有目标,我们要证明west是设法证明west是criminal,接下来你就去Database里面录入它需要的前提。你有唯一有match的,你去看它的结论,结论是criminal(x),如果还记得那个knowledge base的话,就是你如果你有一个criminal(x),则下面这四个前提。那到这个时间也就是x必须要unify的是west。然后这样的话你就可以,然后我们在backward chaining的时候未来记忆体的效率,所以我们都是用dfs,definite search所以你先优先走这一支,走这一支的时候你就看一下,American这边我知道x要换成west,就把上面的这一个unify必须往下派过来,所以这边的American的x会变成American(west),然后你要看一下这个American(west),American(west)是不是可以知道的事实。在我们的case是可以知道,American(west)是已知的事实。所以我们就不再需要新的unify了,就可以return回去。

        到下一步如果说是DFS接下来我们走上面第二支,好这一支是weapon(y),那weapon(y)的前提就是Missile(y),好了Missile(y)的时候你再去match一下,那Missile(y)我们在我们knowledgebase里面有一个Missile(M1),所以我们就知道我们的y是M1。所以这是我们新加的unify,那这个新加的unify就必须要return回去的时候,整体的unify就增加了一个说x是west,y是M1这件事情。

        接下来再走下面第三支。走到这边的时候其实你sale的时候其实你这边的x,y我们刚刚已经都知道了。在上一张图片中知道到这边,所以要替换x换成west,y换成M1。接下来z你去看一下你的knowledgebase里面你就可以知道z必须要换成nono。

        这knowledgebase里面有了一个fact,这时候我们注意在这个时间点可以知道z是normal,然后一样,要把它加入你整个的unify。那这个前提呢是M1是Missile,而且nono owns M1,那这两个前提就check下knowledgebase里面,其实都有,所以这条路走通了。接着再return再走最后一条路。

        那最后一条路是hostile(x),hostile(z)的前提就是我们这边z的时候我们已经在上一步已经知道z是nono了,所以这边会换成nono,好,然后接下来你会,它的前提是enemy,enemy(z,america),那你知道z是nono所以我们要的是enemy(normal,America),好那你check一下你的knowledgebase有这条路,所以就走通了。好这边,所以这边额外需要的unify就不需要了。到这边其实到这边已经做完了,那就return回去,所以这就是整个backward chaining的过程,然后可以得到的unify就是这种东西。

3.7 Backward Chaining 的特性

        Backward chaining是DF search深度搜索的,space空间是线性的。但是整个过程,整个search的过程是在and or search。那你所有的前提,所有的premise全都要成立,所以每一支都要search,那如果,我们刚才的例子里面unify都很单纯,只有一个,我们一次就可以知道x就是M1,有些比较复杂,你可能unify不止一个,即使你是most general unify,你可能还是有若干个,譬如说我们刚举得例子x可能是M2啊,等等等等,那这样的话你就要做很多次,那在这个例子里面的话这都是OR search,因为这里面只要有一支成立就可以了。你不管是M2或M1或M2或M3,那只要有一个T,有一个substitution可以成立,就可以。

        既然我们看一下它的completeness则写东西,那既然它是DFS,我们知道DFS永远都是这样的问题,虽然它很有效率,它的记忆体用的很少,但是它可以造成一种,就是你从左边这一直通下去可能就是一个无穷回旋。好,那你可以有一些fix的方法,你可以有一些改进,其实这都,我们除了这边写这一句话,这句话很单纯,但其实还有很多技术去避掉这个问题,但是这些避掉这些问题的技术有时候同时带来新的问题,简单讲这是一个DFS本身的缺陷,但是它有些设法把这个缺陷弥补,弥补到一个地步的技巧,但是这些技巧不能说100%避掉这个问题。好,那同样一样就是你也可能蛮没效率的因为down下来了,之间讨论,解决过的问题,譬如说我要substitute一个,譬如说missile(x),这边我要问x是谁,可是你在展的过程中你可能又在别的,展到别的地方以后,下面可能又要再一次前题需要又要必须missile(x)。你可能这边又再问一次missile(x)是谁。即使你知道刚已经问过了。好这种情况下你可能就是比较没效率,但是我们可以记一下之前的方法,这有点像programming里面的Memorization的技巧。Memorization的技巧。就是你之前已经解过solve problem了,结果你到时候不要再解一次,就用的方法把它记起来。可你要记起来时要花额外的space,有在某些case上不代表,也不能保证一定能解决。因为有些时候你要记的东西实在太多了。

        但是我们今天讲了很多backward chaining的一些困难点,它有时候没效率,有时候incomplete等,但是即使如此,很多logic programming仍然使用,像我们等下要讲的prolog,这个在人工智慧里面常常使用的语言,它其实根本就没有任何improvement,就是它infinite loop就是infinite loop,即使这样,它还是在logic programming backward chaining常常被使用的一个技巧。

发布了289 篇原创文章 · 获赞 163 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/Suyebiubiu/article/details/103465648
今日推荐