热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【语言处理与Python】8.2文法有什么用?\8.3上下文无关文法\8.4上下文无关文法分析

8.2文法有什么用?超越n-grams用bigrams中的频率信息生成句子,短的时候可以接收,但是长的时候就显得无法接受。我们系统地可以用较短的序列替代较长的序列,并使其依然符合语法规则。

8.2文法有什么用?

超越n-grams

用bigrams中的频率信息生成句子,短的时候可以接收,但是长的时候就显得无法接受。

我们系统地可以用较短的序列替代较长的序列,并使其依然符合语法规则。

例如下面这句话:

image

我们可以为这幅图上添上文法类别标签。

NP为名词短语;VP为动词短语;PP为介词短语;

image

用树来表示:

image

句子可以有任意的长度。短语结构树可以有任意深度。

在下一节中,将看到一个指定的文法如何将句子细分成它的直接成分,以及如何将这些进一步细分,直到到达单独词汇层面。

8.3上下文无关文法

context-free grammar,CFG上下文无关文法(更多关于上下文无关文法请自行了解)

grammar1= nltk.parse_cfg("""
S -> NPVP
VP-> VNP| VNPPP
PP-> P NP
V-> "saw" | "ate" | "walked"
NP-> "John" | "Mary" | "Bob" | DetN| DetNPP
Det-> "a" | "an" | "the" | "my"
N-> "man" | "dog" | "cat" | "telescope" | "park"
P-> "in" | "on" | "by" | "with"
""")
>>>sent = "Mary saw Bob".split()
>>>rd_parser =nltk.RecursiveDescentParser(grammar1)
>>>for tree in rd_parser.nbest_parse(sent):
...
print tree
(S (NP Mary)(VP (V saw) (NP Bob)))

写自己的文法

我们可以写自己的文法,保存在cfg的文件中。

>>>grammar1= nltk.data.load('file:mygrammar.cfg')
>>>sent = "Mary saw Bob".split()
>>>rd_parser =nltk.RecursiveDescentParser(grammar1)
>>>for tree in rd_parser.nbest_parse(sent):
print tree

如果没有任何输出,可能是sent也就是句子不符合文法,可以打开追踪,进行调试和检查。

rd_parser =nltk.RecursiveDescentParser(grammar1, trace=2)

句法结构中的递归

句法递归请参考文法相关资料。

递归深度是没有限制的,我们可以尝试分析更深层次的嵌套结构的句子。

RecursiveDescentParser是无法处理形如X-> XY的左递归。

8.4上下文无关文法分析

在这里介绍两种简单的分析方法,一种自上而下的方法成为递归下降分析,一种自下而上的方法成为移近-归约分析。同样,也会看到更复杂的算法,一种带自下而上过滤的自上而下的方法称为左角落分析。

一种动态规划技术成为图表分析。

递归下降分析

我们可以使用图形化师范nltk.app.rdparser()中看到递归下降的过程。

image

 

从S节点开始匹配。

NLTK提供了一个递归下降分析器:

>>>rd_parser =nltk.RecursiveDescentParser(grammar1)
>>>sent = 'Mary saw a dog'.split()
>>>for t in rd_parser.nbest_parse(sent):
...
print t
(S (NP Mary)(VP (V saw) (NP (Det a) (N dog))))

递归下降是有缺点的:

1、左递归产生式会进入死循环。

2、分析器浪费了很多时间处理不符合输入句子的词和结构

3、回溯过程中可能丢弃分析过的成分,他们需要在之后重新建立

移进-归约分析(简单的自下而上分析)

移位:分析器反复将下一个输入词推到堆栈中,这是移位操作。

归约:如果堆栈上的前N项匹配一些产生式右侧的N个项目,那么就把他们弹出栈,并把产生式左边的项目压入栈。这种替换的操作就是归约操作。

同样,可以使用图形化示范nltk.app.srparser()

image

相关代码:

>>>sr_parse= nltk.ShiftReduceParser(grammar1)
>>>sent = 'Mary saw a dog'.split()
>>>print sr_parse.parse(sent)
(S (NP Mary)(VP (V saw) (NP (Det a) (N dog))))

左角落分析器

递归下降分析器的问题之一就是不能处理左递归,会进入无限循环。左角落分析器是我们已经看到的自下而上与自上而下的方法的混合体。

他不会陷入左递归产生式的陷阱。在开始工作之前,左角落分析器预处理上下文无关文法建立一个表,其中每行包括两个单元。第一个存放非终结符,第二个存放那个非终结符可能的左角落集合。

例如,grammar2的文法:

grammar2= nltk.parse_cfg("""
S -> NP VP
NP-> Det Nom| PropN
Nom-> Adj Nom| N
VP-> V Adj| VNP| VS| VNPPP
PP-> P NP
PropN-> 'Buster' | 'Chatterer' | 'Joe'
Det-> 'the' | 'a'
N-> 'bear' | 'squirrel' | 'tree' | 'fish' | 'log'
Adj -> 'angry' | 'frightened' | 'little' | 'tall'
V-> 'chased' | 'saw' | 'said' | 'thought' | 'was' | 'put'
P-> 'on'
""")

他的左角落为:

image

分析器每次考虑产生式时,他会检查下一个输入词是否与左角落表格中至少一种非终结符的类别相容。

符合语句规则的字串表

上面讨论的简单的分析器在完整性和效率上都有限制,为了弥补这些,我们将运用动态规划算法设计技术解决问题。

这里介绍图表分析。有一个表格需要我们注意,符合语法规则的字串表,简称为WFST。

以这句话为例子:

>>>text = ['I', 'shot', 'an', 'elephant', 'in', 'my', 'pajamas']

如何构建WFST:

image

def init_wfst(tokens, grammar):
numtokens
= len(tokens)
wfst
= [[None for i in range(numtokens+1)] for j in range(numtokens+1)]
for i in range(numtokens):
productions
= grammar.productions(rhs=tokens[i])
wfst[i][i
+1]= productions[0].lhs()
return wfst
def complete_wfst(wfst,tokens, grammar,trace=False):
index
= dict((p.rhs(),p.lhs()) for pin grammar.productions())
numtokens
= len(tokens)
for span in range(2, numtokens+1):
for start in range(numtokens+1-span):
end
= start + span
for midin range(start+1, end):
nt1,nt2
= wfst[start][mid],wfst[mid][end]
if nt1 and nt2 and (nt1,nt2) in index:
wfst[start][end]
= index[(nt1,nt2)]
if trace:
print "[%s] %3s[%s] %3s[%s] ==>[%s] %3s[%s]" %
\
(start, nt1, mid,nt2,end, start, index[(nt1,nt2)], end)
return wfst

def display(wfst,tokens):
print '\nWFST ' + ' '.join([("%-4d" %i) for i in range(1, len(wfst))])
for i in range(len(wfst)-1):
print "%d " %i,
for j in range(1, len(wfst)):
print "%-4s" %(wfst[i][j] or '.'),
print
>>>tokens = "I shot an elephant in mypajamas".split()
>>>wfst0= init_wfst(tokens, groucho_grammar)
>>>display(wfst0,tokens)
WFST1
2 3 4 5 6 7
0 NP . . . . . .
1 . V . . . . .
2 . . Det . . . .
3 . . . N . . .
4 . . . . P . .
5 . . . . . Det .
6 . . . . . . N
>>>wfst1= complete_wfst(wfst0, tokens, groucho_grammar)
>>>display(wfst1,tokens)
WFST1
2 3 4 5 6 7
0 NP . . S . . S
1 . V . VP . . VP
2 . . Det NP . . .
3 . . . N . . .
4 . . . . P . PP
5 . . . . . Det NP
6 . . . . . . N

在其中,要注意index的内容:

要构建index中的内容,需要有下面的步骤,这里把那段代码提取了出来,单独演示:

#对应的文法
>>> groucho_grammar= nltk.parse_cfg("""
S -> NP VP
PP -> P NP
NP -> Det N| DetN PP| 'I'
VP -> V NP| VP PP
Det -> 'an' | 'my'
N -> 'elephant' | 'pajamas'
V -> 'shot'
P ->'in'
""")
#文法的内容
>>> grammar,productions()
[S
-> NP VP, PP -> P NP, NP -> Det N, NP -> DetN PP, NP -> 'I', VP -> V NP, VP -> VP PP, Det -> 'an', Det -> 'my', N -> 'elephant', N -> 'pajamas', V -> 'shot', P -> 'in']
#index的内容
pprint.pprint(dict((p.rhs(),p.lhs()) for p in groucho_grammar.productions()))
{(Det, N): NP,
(DetN, PP): NP,
(NP, VP): S,
(P, NP): PP,
(V, NP): VP,
(VP, PP): VP,
(
'I',): NP,
(
'an',): Det,
(
'elephant',): N,
(
'in',): P,
(
'my',): Det,
(
'pajamas',): N,
(
'shot',): V}
>>>

相信,读完这个代码,如果懂得了,必然懂得了构建过程的核心思想。


推荐阅读
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • Opencv提供了几种分类器,例程里通过字符识别来进行说明的1、支持向量机(SVM):给定训练样本,支持向量机建立一个超平面作为决策平面,使得正例和反例之间的隔离边缘被最大化。函数原型:训练原型cv ... [详细]
  • 基于词向量计算文本相似度1.测试数据:链接:https:pan.baidu.coms1fXJjcujAmAwTfsuTg2CbWA提取码:f4vx2.实验代码:imp ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 本文介绍了一个Python函数same_set,用于判断两个相等长度的数组是否包含相同的元素。函数会忽略元素的顺序和重复次数,如果两个数组包含相同的元素,则返回1,否则返回0。文章还提供了函数的具体实现代码和样例输入输出。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • 颜色迁移(reinhard VS welsh)
    不要谈什么天分,运气,你需要的是一个截稿日,以及一个不交稿就能打爆你狗头的人,然后你就会被自己的才华吓到。------ ... [详细]
  • Explain如何助力SQL语句的优化及其分析方法
    本文介绍了Explain如何助力SQL语句的优化以及分析方法。Explain是一个数据库SQL语句的模拟器,通过对SQL语句的模拟返回一个性能分析表,从而帮助工程师了解程序运行缓慢的原因。文章还介绍了Explain运行方法以及如何分析Explain表格中各个字段的含义。MySQL 5.5开始支持Explain功能,但仅限于select语句,而MySQL 5.7逐渐支持对update、delete和insert语句的模拟和分析。 ... [详细]
  • mapreduce源码分析总结
    这篇文章总结的非常到位,故而转之一MapReduce概述MapReduce是一个用于大规模数据处理的分布式计算模型,它最初是由Google工程师设计并实现的ÿ ... [详细]
author-avatar
Cyndi_lidi_816
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有