将python函数转化为tensorflow图函数

tensorflow基础之——将python函数转化为tensorflow图函数_tensorflow中的concretefunction类型的concrete是干什么的-CSDN博客

目录

1. 使用tf.function转化成tensorflow函数

2.使用装饰器将python函数转化为tensorflow中的函数

3. 展示tensorflow的函数结构

4.python函数中有变量的处理方法 

5.对函数的输入类型作限定

5.1 为什么要对函数的入参做类型的限定?

5.2 使用tf.function中的input_signature对入参类型进行限定

5.3 使用get_concrete_function对入参类型进行限定,并将function转化为带有图定义的concreteFunction

6.查看图

6.1 查看有图定义的concrete function 的图

6.2 查看图的operations

 6.2.1 查看某个operation的输入和输出

6.2.2 通过name查看图的某个operation

6.3 通过name查看tensor

6.4 查看图的定义

7. 总结:将python函数转化为tensorflow图函数的意义

在tensorflow库函数中,做了各种各样的优化,比如针对编译器等
通过某种方法将python函数变成tensorflow库函数是不是更好呢?

1. 使用tf.function转化成tensorflow函数
首先,编写python函数

# 编写python函数
def scaled_elu(z, scale=1.0, alpha=1.0):
    # z >= 0 ? scale * z: scale * alpha * tf.nn.elu(z) 三目运算符
    is_positive = tf.greater_equal(z, 0.0)
    # tf.where 表示三目运算符
    return scale * tf.where(is_positive, z, alpha * tf.nn.elu(z))
 
print(scaled_elu(-3.))
print(scaled_elu([-3., 0., 3]))
使用tf.function转化成tensorflow函数

scaled_elu_tf = tf.function(scaled_elu)
print(scaled_elu_tf(-3.))
print(scaled_elu_tf([-3., 0., 3]))
scaled_elu_tf 和 scaled_elu是什么关系呢?

print(scaled_elu_tf.python_function is scaled_elu)
上述的输出为True。即scaled_elu_tf 的 python function 为 scaled_elu

scaled_elu_tf 和 scaled_elu有什么不同,是否想我们之前预言的那样,会有性能的提升呢?

%timeit scaled_elu(tf.random.normal((10000, 10000)))
%timeit scaled_elu_tf(tf.random.normal((10000, 10000)))
输出结果为:

可见 scaled_elu_tf 比 scaled_elu运行的稍快一些。可以看出,tensorflow函数比python函数的时间性能上有所提升。

2.使用装饰器将python函数转化为tensorflow中的函数
@tf.function
def scaled_elu_tf_2(z, scale=1.0, alpha=1.0):
    # z >= 0 ? scale * z: scale * alpha * tf.nn.elu(z) 三目运算符
    is_positive = tf.greater_equal(z, 0.0)
    # tf.where 表示三目运算符
    return scale * tf.where(is_positive, z, alpha * tf.nn.elu(z))
 
print(scaled_elu_tf_2(-3.))
print(scaled_elu_tf_2([-3., 0., 3]))
测试时间性能的提升

scaled_elu_2 = scaled_elu_tf_2.python_function
%timeit scaled_elu_2(tf.random.normal((10000, 10000)))
%timeit scaled_elu_tf_2(tf.random.normal((10000, 10000)))
3. 展示tensorflow的函数结构
from IPython.display import display, Markdown
 
def display_tf_code(func):
    code = tf.autograph.to_code(func)
    display(Markdown('```python\n{}\n```'.format(code)))
 
display_tf_code(scaled_elu)
结构如下所示

4.python函数中有变量的处理方法 
note: 变量必须在tf.function的外面进行初始化

var = tf.Variable(0.)
 
@tf.function
def add_21():
    return var.assign_add(21)
 
print(add_21())
Q: 如果把variable定义在里面呢?

A:会抛出异常

在定义神经网络的过程中,用的更多的是variable。
故定义神经网络的时候,在转成tensorflow函数之前,需要先对变量进行初始化。

5.对函数的输入类型作限定
# 如下是一个有入参的tensorflow图
 
@tf.function
def cube(z):
    return tf.pow(z, 3)
 
print(cube(tf.constant([1., 2., 3.]))) # 输入为float类型
print(cube(tf.constant([1, 2, 3]))) # 输入为int类型
如上所示,若不对函数的输入作限定,不管是传入float类型的数还是int类型的数都是可以的。

5.1 为什么要对函数的入参做类型的限定?

首先,对入参的类型作限定,会让输入的类型更加明确,
其次,由于python中没有类型信息,容易导致传惨错误。若对入参类型加以限定,就会减少传参错误的情况。

5.2 使用tf.function中的input_signature对入参类型进行限定
@tf.function(input_signature=[tf.TensorSpec([None], tf.int32, name='x')])
def cube(z):
    return tf.pow(z, 3)
 
try:
    print(cube(tf.constant([1., 2., 3.]))) # 输入为float类型
except ValueError as ex:
    print(ex)
 
print(cube)
print(cube(tf.constant([1, 2, 3]))) # 输入为int类型
如上述代码所示:对函数的入参做了类型限制,为int类型。故传入float类型的数据时,就会触发异常。

5.3 使用get_concrete_function对入参类型进行限定,并将function转化为带有图定义的concreteFunction
函数有了input_signature特性之后,才能使用save_model 保存模型。

在savedModel的过程中,也可以使用get_concrete_function 函数来把一个 tf.function标注的普通python函数转化为带有图定义的函数。

 @tf.function py func ——> tf.graph
  get_concrete_function ——> add input signature ——>savedModel
# @tf.function py func ——> tf.graph
# get_concrete_function ——> add input signature ——>savedModel
 
@tf.function()
def cube_2(z):
    return tf.pow(z, 3)
 
cube_2_func_int32 = cube_2.get_concrete_function(
    tf.TensorSpec([None], tf.int32))
 
print(cube_2_func_int32)
print(cube_2_func_int32(tf.constant([1, 2, 3]))) # 输入为int类型
除了使用类型,也可以使用具体的数值,对入参的类型进行限定。

cube_2_func_int32_2 = cube_2.get_concrete_function(
    tf.TensorSpec([5], tf.int32))
 
cube_2_func_int32_3 = cube_2.get_concrete_function(
    tf.constant([5]))
 
cube_2_func_int32_4 = cube_2.get_concrete_function(
    tf.constant([1, 2, 5]))
 
print(cube_2_func_int32_2)
print(cube_2_func_int32_2(tf.constant([1, 2, 3, 5, 6, 7]))) # 输入为int类型
 
print(cube_2_func_int32_3)
print(cube_2_func_int32_3(tf.constant([1, 2, 3, 5, 6, 7]))) # 输入为int类型
 
print(cube_2_func_int32_4)
print(cube_2_func_int32_4(tf.constant(10))) # 输入为int类型

note:这里只是对类型敏感,对shape不敏感

如下所示:

输出为:

定义入参的名字。

tf.function中的 input_signature中同样也是使用tf.TensorSpec,也可以定义入参的名字。

# tf.function中的 input_signature中同样也是使用tf.TensorSpec
cube_2_func_int32_name = cube_2.get_concrete_function(
    tf.TensorSpec([None], tf.int32, name='t'))
 
print(cube_2_func_int32_name)
6.查看图
note:虽然tf.function 中也可以对函数加input_signature。但是必须通过get_concrete_function才能将tf.function转化成带有图定义的对象。

6.1 查看有图定义的concrete function 的图
cube_2_func_int32_name.graph
6.2 查看图的operations
cube_2_func_int32_name.graph.get_operations()


pow_op = cube_2_func_int32_name.graph.get_operations()[2]
print(pow_op)
 

 6.2.1 查看某个operation的输入和输出
print(pow_op.inputs)
print(pow_op.outputs)
6.2.2 通过name查看图的某个operation
cube_2_func_int32_name.graph.get_operation_by_name('Identity')
6.3 通过name查看tensor
cube_2_func_int32_name.graph.get_tensor_by_name('t:0')
cube_2_func_int32_name.graph.get_tensor_by_name('Pow/y:0')
cube_2_func_int32_name.graph.get_tensor_by_name('Pow:0')
cube_2_func_int32_name.graph.get_tensor_by_name('Identity:0')
6.4 查看图的定义
cube_2_func_int32_name.graph.as_graph_def()
7. 总结:将python函数转化为tensorflow图函数的意义
(1) 如何保存一个模型

(2) 保存了模型之后如果把它载入进来?

(3) 在载入模型作inference的时候,如果使用c++或其它语言,经常会用到get_operation_by_name, get_tensor_by_name等这些函数.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值