(深度学习)with语句在python和深度学习的用法

(深度学习)with语句在python和深度学习的用法

2023年6月29日发(作者:)

(深度学习)with语句在python和深度学习的⽤法⽂章⽬录中的with语句⽤python打开⽂件时,⼀定要记得调⽤⽅法close()将⽂件关闭。要确保⽂件得以关闭,可使⽤⼀条try/finally语句,并在finally⼦句中调⽤close。#

在这⾥打开⽂件try: #

将数据写⼊到⽂件中finally: ()实际上,有⼀条专门为此设计的语句,那就是with语句。with open("") as somefile: do_something(somefile)with语句让你能够打开⽂件并将其赋给⼀个变量(这⾥是somefile)。在语句体中,你将数据写⼊⽂件(还可能做其他事情)。到达该语句末尾时,将⾃动关闭⽂件,即便出现异常亦如此。with语句适⽤于对资源进⾏访问的场合,确保不管使⽤过程中是否发⽣异常都会执⾏必要的“清理”操作,释放资源,⽐如⽂件使⽤后⾃动关闭、线程中锁的⾃动获取和释放等。1.1上下⽂管理器with语句实际上是⼀个⾮常通⽤的结构,允许你使⽤所谓的上下⽂管理器。上下⽂管理器是⽀持两个⽅法的对象:

__enter __ 和__exit ____enter __⽅法__enter__不接受任何参数,在进⼊with语句时被调⽤,其返回值被赋给关键字as后⾯的变量__exit __⽅法__exit__接受三个参数:异常类型、异常对象和异常跟踪。它在离开⽅法时被调⽤(通过前述参数将引发的异常提供给它)。如果__exit__返回False,将抑制所有的异常。⽂件可⽤作上下⽂管理器。它们的⽅法__enter__返回⽂件对象本⾝,⽽⽅法__exit__关闭⽂件1.2with语句执⾏过程with EXPR as VAR: BLOCK其中EXPR可以是任意表达式;as VAR是可选的。其⼀般的执⾏过程是这样的:1. 执⾏EXPR,⽣成上下⽂管理器context_manager;2. 获取上下⽂管理器的__exit()__⽅法,并保存起来⽤于之后的调⽤;3. 调⽤上下⽂管理器的__enter__()⽅法;如果使⽤了as⼦句,则将__enter__()⽅法的返回值赋值给as⼦句中的VAR;4. 执⾏BLOCK中的表达式;5. 不管是否执⾏过程中是否发⽣了异常,都要执⾏上下⽂管理器的__exit__()⽅法,__exit__()⽅法负责执⾏“清理”⼯作,如释放资源等。如果执⾏过程中没有出现异常,或者语句体中执⾏了语句break/continue/return,则以None作为参数调⽤__exit__(None, None,None)。如果执⾏过程中出现异常,则使⽤_info得到的异常信息为参数调⽤__exit__(exc_type, exc_value, exc_traceback)6. 出现异常时,如果__exit__(type, value, traceback)返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通⽤做法;如果返回True,则忽略异常,不再对异常进⾏处理。1.3⾃定义上下⽂管理器讲完了with语句的内在原理,接下来我们就可以按照这个原理,实现我们⾃⼰的上下⽂管理器。⾃定义的上下⽂管理器要实现上下⽂管理协议所需要的__enter__()和__exit__()两个⽅法:class Test(object) : def __init__(self): pass def __enter__(self): print("__enter__") return self def __exit__(self, exc_type, exc_val, exc_tb): print("__exit__") return Truedef testFun() : return Test()with testFun() as t :

print("with demo")#输出结果__enter__with demo__exit__ ntTape() as tapeclass GradientTape(object): def __init__(self, persistent=False, watch_accessed_variables=True): pass def __enter__(self): self._push_tape() return self def __exit__(self, typ, value, traceback): if self._recording: self._pop_tape() ...作⽤Tape在英⽂中是胶带,磁带的含义,⽤在这⾥是由于eager模式带来的影响。在TensorFlow 1.x静态图时代,我们知道每个静态图都有两部分,⼀部分是前向图,另⼀部分是反向图。反向图就是⽤来计算梯度的,⽤在整个训练过程中。⽽TensorFlow 2.0默认是eager模式,每⾏代码顺序执⾏,没有了构建图的过程(也取消了control_dependency的⽤法)。但也不能每⾏都计算⼀下梯度吧?计算量太⼤,也没必要。因此,需要⼀个上下⽂管理器(context manager)来连接需要计算梯度的函数和变量,⽅便求解同时也提升效率。tensorflow 提供ntTape api来实现⾃动求导功能。只要在ntTape()上下⽂中执⾏的操作,都会被记录在“tape”中,然后tensorflow使⽤反向⾃动微分来计算相关操作的梯度。⽽with结构在这⾥的⽤处是,只计算在with⾥变量的梯度,with结构到grads框起了梯度的计算过程举个例⼦:计算y=x^2在x = 3时的导数:x = nt(3.0)with ntTape() as g: (x) y = x * xdy_dx = nt(y, x) # y’ = 2*x = 2*3 = 6print(dy_dx) #(6.0, shape=(), dtype=float32)例⼦中的watch函数把需要计算梯度的变量x加进来了。GradientTape默认只监控由le创建的traiable=True属性(默认)的变量。上⾯例⼦中的x是constant,因此计算梯度需要增加(x)函数,⼿动监视张量,即watch的作⽤是确保tensor类型的数据能被梯度带检测到。参数persistent:布尔值,⽤于控制是否创建持久渐变磁带。默认情况下为False,这意味着最多可以在此对象上对gradient()⽅法进⾏⼀次调⽤,即GradientTape的资源在调⽤gradient函数后就被释放,再次调⽤就⽆法计算了。所以如果需要多次计算梯度,需要开启persistent=True属性,例如:x = nt(3.0)with ntTape(persistent=True) as g: (x) y = x * x z = y * ydz_dx = nt(z, x) # z = y^2 = x^4, z’ = 4*x^3 = 4*3^3dy_dx = nt(y, x) # y’ = 2*x = 2*3 = 6del g #

删除这个上下⽂胶带watch_accessed_variables:布尔值,控制watch在磁带处于活动状态时磁带是否将⾃动访问任何(可训练的)变量。默认值为True,可以从磁带中读取可训练的磁带得出的任何结果中请求梯度Variable。如果为False,则⽤户必须明确要求他们要从中请求渐变的watch任何Variable,⼀般⽤不到GradientTape也可以嵌套多层⽤来计算⾼阶导数,例如:x = nt(3.0)with ntTape() as g: (x) with ntTape() as gg: (x) y = x * x dy_dx = nt(y, x) # y’ = 2*x = 2*3 =6d2y_dx2 = nt(dy_dx, x) # y’’ = 2最后,⼀般在⽹络中使⽤时,不需要显式调⽤watch函数,使⽤默认设置,GradientTape会监控可训练变量,例如:w = le(nt(5, dtype=32))with ntTape() as tape: # with结构到grads框起了梯度的计算过程。 loss = (w + 1)grads = nt(loss, w) # .gradient函数告知谁对谁求导参考:

发布者:admin,转转请注明出处:http://www.yc00.com/web/1687977246a62836.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信