tf.function
参考:
-
YouTube - tf.function and Autograph (TF Dev Summit ‘19)
-
tensorflow.org - tf.function
-
CSDN【Tensorflow教程笔记】常用模块 tf.function :图执行模式
tf.function
修饰的函数会将其中的操作转化为Graph execution(图执行),效率会高于Eagerly execution(直接计算,step by step)
Speed: Graph execution > Eagerly execution
计算图的重复利用与重建
通过@tf.function
修饰的函数被称为泛型函数(GenericFunction),而每次调用该函数就会进行实例化,会基于传入参数的属性得到对应的具象函数(ConcreteFunction),通过fn.get_concrete_function()
可以将GenericFunction
转化为ConcreteFunction
,对于ConcreteFunction
就存在计算图可以修改(修改方式应该和TF1.x类似):
fn.get_concrete_function(实参/tf.TensorSpec())
:向函数具象化里传入实参或者指定传入的Tensor
类型。
并且要避免向tf.function
传递Python中的标量或者列表,这会导致计算图的重复构建,降低效率。
当多次创建计算图时(大于5次),TF就会发出警告
计算图的输入限制
可以在两个位置对计算图的输入参数进行限制
fn.get_concrete_function(tf.TensorSpec(), tf.TensorSpec(), ...)
:在函数具象化时加入限制,得到结果是ConcreteFunction
@tf.function(input_signature=[tf.TensorSpec(), tf.TensorSpec(), ...])
:在tf.function
构建时候就通过input_signature
属性对输入进行限制,得到的函数是GenericFunction
上述两个方法都是有多少个输入变量就写多少个tf.TensorSpec()
在保持原有代码逻辑的前提下,尽可能使用并行计算提高速度
tf.Variable 的创建和删除?
下面这样写会报错,因为tf.function不清楚内部定义的变量v
究竟是每次要为其创建一个新的计算图,还是利用之前的已经创建过的变量v
:
- 如果是
tf 1.x
,那么就只会创建一次(graph execution)
- 如果是eagerly execution,那么会每次创建出
v
然后在函数结束时删除v
,不断删除再创建
解决方法:
- 在图执行函数外创建变量
- 通过编写类,并在第一次调用该类的时候创建变量,类似Layer中的
build()
函数
自动生成计算图的函数限制
tf.function
支持Python原生函数:if, while
,其中 if
会自动转化为 tf.cond
,while
会自动转化为 tf.while_loop
;
并且有类似C++中的数组 tf.TensorArray(dtype, size)
(在tf.function
中对tf.TensorArray
进行初始化,作为计算图中的一个数组,最后需要将其通过ta.stack()
返回出来):
- 动态:
ta = tf.TensorArray(dtype, size, dynamic_size=True)
- 静态:
dynamic_size
默认为False
,size
就是当前数组的固定大小
- 加入元素:
ta = ta.write(pos, val)
类似于ta[pos] = val
,如果是静态数组,则要求有pos < ta.size()
- 重置数组:
ta = ta.unstack([...])
将ta
重置为列表[...]
,如果是静态数组,则需要保证len([...]) <= ta.size()
- 数组转化:
ta.stack()
将ta
转化为tf.Tensor
的形式
计算图中 Python 内置函数只会被执行一次
在梯度下降中应用的例子