python中的修饰符以及@tf.custom_gradient用法

1. 修饰符

首先说一下修饰符“@”,其功能是在不改变原有函数内部代码的基础上,拓展原函数的功能。由于python里一切皆是对象,所以一个函数的形式参数可以是另一个函数,同时也可以返回一个函数。如这篇文章中的例子,我们定义了一个函数get_text,再将其作为p_decorate的参数输入,最后返回函数func_wrapper。

def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)


def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

my_get_text = p_decorate(get_text)

print(my_get_text("John"))

# <p>Outputs lorem ipsum, John dolor sit amet</p>

我们想将get_text的输出放在<p>“ ”</p>之间,于是我们定义了一个新的函数p_decorate来完成这件事,新函数p_decorate起到的就是修饰作用,我们可以称之为修饰函数。如果将“my_get_text = p_decorate(get_text)”改为“get_text = p_decorate(get_text)”,那么我们就在不改变原函数内部代码的基础上,拓展了原函数的内涵。为了简化代码,我们便用之前提到的修饰符“@”来替代上面那句代码,于是,上述代码可以改写为:

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)

print(get_text("John"))

# Outputs <p>lorem ipsum, John dolor sit amet</p>

 修饰函数中一定要return一个函数,当重新调用gei_text函数的时候,由于修饰符的添加,其返回的是,修饰符中return的函数func_wrpper。

2. tf.custom_gradient函数

tf.custom_gradient(func)用自定义的梯度来修饰函数func,在深度学习中比较常用,可以修改梯度在正向传播与反向传播的过程中的值。

其中func(*x)的返回值为一个元组(y,grad_fn)

  • x为一个Tensor的列表
  • y是一个Tensor或者Tensor的列表,可以看做函数正向传播过程中的输出,即func(x)。
  • grad_fn是一个Tensor的列表,是反向传播过程中的返回值,由自己定义。可以看做是func(x)对于x的“偏导”,但这个偏导值与正常数学中的函数的偏导不一样,它是一个你自己定义的函数。可以通过如下例子来理解:
import tensorflow as tf

input = tf.Variable([1.0], dtype=tf.float32)

@tf.custom_gradient
def clip_grad_layer(x):
  def grad(dy):
    return tf.clip_by_value(dy, -0.1, 0.1)
  return 3*tf.identity(x), grad

output_clip = clip_grad_layer(input)
grad_clip = tf.gradients(output_clip, input)

# output without gradient clipping in the backwards pass for comparison:
output_normal = tf.identity(input)
grad_normal = tf.gradients(output, input)

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  print("input:", sess.run(input))
  print("output_clipping:", sess.run(output_clip))
  print("output_no_clipping:", sess.run(output_normal))
  print("with clipping:", sess.run(grad_clip)[0])
  print("without clipping:", sess.run(grad_normal)[0])

其输出为:

#    input: [1.]
#    output_clipping: [3.]
#    output_no_clipping: [1.]
#    with clipping: [0.1]
#    without clipping: [1.]

 由于tf.custom_gradient有两个返回值,所以在定义函数clip_grad_layer的时候也得有两个返回值,一个是正向传播过程中函数的输出值,另一个是反向传播过程中的梯度值。

 

 

 

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值