tensorflow2.x学习笔记十一:@tf.function(AutoGraph)的使用规范

本文介绍了TensorFlow 2.0中的Autograph机制,它能将动态图转换为静态计算图,提升执行效率。文章总结并解析了使用Autograph时应遵循的编码规范,包括优先使用tf函数、避免在函数内部定义变量以及不得修改外部数据结构等要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

有三种计算图的构建方式:静态计算图,动态计算图,以及Autograph。

TensorFlow 2.0主要使用的是动态计算图和Autograph。

动态计算图易于调试,编码效率较高,但执行效率偏低。

静态计算图执行效率很高,但较难调试。

而Autograph机制可以将动态图转换成静态计算图,兼收执行效率和编码效率之利。

当然Autograph机制能够转换的代码并不是没有任何约束的,有一些编码规范需要遵循,否则可能会转换失败或者不符合预期。下面就来介绍一下使用Autograph的编码规范。

二、Autograph编码规范总结

1,被@tf.function修饰的函数应尽可能使用TensorFlow中的函数而不是Python中的其他函数。例如使用tf.print而不是print,使用tf.range而不是range,使用tf.constant(True)而不是True.

2,避免在@tf.function修饰的函数内部定义tf.Variable.

3,被@tf.function修饰的函数不可修改该函数外部的Python列表或字典等数据结构变量。

三、Autograph编码规范解析

1,被@tf.function修饰的函数应尽可能使用TensorFlow中的函数而不是Python中的其他函数。

import numpy as np
import tensorflow as tf

@tf.function
def np_random():
    a = np.random.randn(3,3)
    tf.print(a)
    
@tf.function
def tf_random():
    a = tf.random.normal((3,3))
    tf.print(a)
#np_random每次执行都是一样的结果。
np_random()
np_random()

array([[ 0.22619201, -0.4550123 , -0.42587565],
       [ 0.05429906,  0.2312667 , -1.44819738],
       [ 0.36571796,  1.45578986, -1.05348983]])
array([[ 0.22619201, -0.4550123 , -0.42587565],
       [ 0.05429906,  0.2312667 , -1.44819738],
       [ 0.36571796,  1.45578986, -1.05348983]])
#tf_random每次执行都会有重新生成随机数。
tf_random()
tf_random()

[[-1.38956189 -0.394843668 0.420657277]
 [2.87235498 -1.33740318 -0.533843279]
 [0.918233037 0.118598573 -0.399486482]]
[[-0.858178258 1.67509317 0.511889517]
 [-0.545829177 -2.20118237 -0.968222201]
 [0.733958483 -0.61904633 0.77440238]]

2,避免在@tf.function修饰的函数内部定义tf.Variable.

# 避免在@tf.function修饰的函数内部定义tf.Variable.

x = tf.Variable(1.0,dtype=tf.float32)
@tf.function
def outer_var():
    x.assign_add(1.0)
    tf.print(x)
    return(x)

outer_var() 
outer_var()
@tf.function
def inner_var():
    x = tf.Variable(1.0,dtype = tf.float32)
    x.assign_add(1.0)
    tf.print(x)
    return(x)

#在第二次执行该函数的时候将报错
#inner_var()
#inner_var()

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-12-c95a7c3c1ddd> in <module>
      7 
      8 #执行将报错
----> 9 inner_var()
     10 inner_var()

~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py 

in __call__(self, *args, **kwds)

    566         xla_context.Exit()
    567     else:
--> 568       result = self._call(*args, **kwds)
    569 
    570     if tracing_count == self._get_tracing_count():
......
ValueError: tf.function-decorated function tried to create variables on non-first call.

3,被@tf.function修饰的函数不可修改该函数外部的Python列表或字典等数据结构变量。

tensor_list = []

def append_tensor(x):
    tensor_list.append(x)
    return tensor_list

append_tensor(tf.constant(5.0))
append_tensor(tf.constant(6.0))
print(tensor_list)

[<tf.Tensor: shape=(), dtype=float32, numpy=5.0>, 
			<tf.Tensor: shape=(), dtype=float32, numpy=6.0>]
tensor_list = []

@tf.function #加上这一行切换成Autograph结果将不符合预期!!!
def append_tensor(x):
    tensor_list.append(x)
    return tensor_list


append_tensor(tf.constant(5.0))
append_tensor(tf.constant(6.0))
print(tensor_list)

[<tf.Tensor 'x:0' shape=() dtype=float32>]

参考链接https://github.com/lyhue1991/eat_tensorflow2_in_30_days

<think>嗯,用户想了解TensorFlow 1.x和2.x之间的转换差异。我需要先回忆一下这两个版本的主要区别。记得TensorFlow 2.0做了很多重大改变,比如默认启用Eager Execution,删除了很多旧的API,比如tf.Session和tf.placeholders。用户可能需要知道迁移过程中会遇到哪些问题,比如代码结构的调整,控制流的变化,还有变量管理方式的同。 首先,用户可能在使用1.x代码时依赖了Session和placeholder,这在2.x里需要怎么处理呢?应该建议使用tf.function来替代,或者用Keras的API简化模型构建。然后,控制流的改变,比如tf.cond和tf.while_loop在2.x中可能有同的实现,需要注意兼容性问题。引用中的[^1]提到控制流实现简化了,可能产生同的图表示,需要检查是否有bug。 另外,变量管理方面,2.x的变量名可能和1.x同,这会影响加载旧检查点。引用[^2]提到这一点,需要用户注意可能的兼容问题。用户可能还需要了解SavedModels的兼容性,虽然1.x的模型可以加载到2.x,但变量名变化可能导致问题。 然后,用户可能关心迁移工具,比如tf_upgrade_v2,这个工具能自动转换部分代码,但可能处理所有情况,需要手动调整。比如contrib模块被移除了,用户需要替换成其他库如TensorFlow Addons。 还要提到性能优化方面的差异,比如使用tf.data处理输入管道,避免使用feed_dict。此外,Keras作为高级API的整合,可能简化模型构建和训练流程。 最后,用户可能需要了解迁移步骤,比如检查代码依赖,使用迁移工具,替换废弃的API,测试转换后的代码。同时,引用中提到的Effective TensorFlow 2.0指南也是重要的参考资料,应该推荐给用户。 总结一下,回答需要涵盖API变化、控制流、变量管理、迁移工具、性能优化和迁移步骤等方面,并引用提供的资料来支持每个点。确保回答结构清晰,分点说明,帮助用户逐步理解迁移过程中的关键差异和解决方法。</think>### TensorFlow 1.x与2.x的转换差异解析 #### 1. **核心设计理念的差异** - **Eager Execution模式**:TensorFlow 2.x默认启用Eager Execution,无需手动构建计算图即可直接运行代码,调试更直观。而1.x需通过`tf.Session`和`tf.placeholder`显式管理计算图。 - **API简化**:2.x移除了冗余API(如`tf.contrib`),将高频操作整合到`tf.keras`中,例如`tf.layers`被`tf.keras.layers`取代。 #### 2. **控制流实现的变更** - 在1.x中,控制流(如`tf.cond`、`tf.while_loop`)基于静态图构建,而2.x通过`tf.function`和`Autograph`动态转换Python代码为图结构。例如: ```python # 1.x的静态控制流 output = tf.cond(tf.greater(a, b), lambda: tf.add(a, b), lambda: tf.subtract(a, b)) # 2.x的动态控制流(需用@tf.function装饰器) @tf.function def conditional_op(a, b): return a + b if a > b else a - b ``` 这种变更可能导致旧代码生成的图结构与2.x兼容[^1]。 #### 3. **变量与检查点的兼容性** - **变量命名规则**:2.x优化了变量管理逻辑,可能导致从1.x加载的检查点变量名匹配。例如,1.x中通过`tf.get_variable`生成的变量在2.x中可能需通过`tf.Variable`重构。 - **迁移工具**:可使用`tf.compat.v1`模块暂时保留1.x特性,但需逐步替换为2.x原生API。 #### 4. **模型保存与加载的调整** - **SavedModels兼容性**:1.x保存的模型仍可在2.x中加载,但涉及动态控制流或自定义层的代码可能需要调整。 - **Keras模型优先**:推荐使用`tf.keras.Model.save()`保存模型,而非1.x的`tf.saved_model`。 #### 5. **性能优化实践** - **输入管道优化**:2.x推荐使用`tf.data.Dataset`替代`feed_dict`,例如: ```python # 2.x的输入管道 dataset = tf.data.Dataset.from_tensor_slices((inputs, labels)).batch(32).prefetch(1) ``` - **混合精度训练**:2.x支持`tf.keras.mixed_precision`,可加速计算并减少显存占用。 #### 迁移步骤建议 1. **代码兼容性检查**:运行`tf_upgrade_v2 --infile=your_script.py --outfile=upgraded.py`自动转换代码。 2. **替换废弃API**:例如将`tf.Session.run()`替换为直接调用函数,移除`tf.variable_scope`。 3. **测试与验证**:使用`tf.debugging.enable_check_numerics()`捕捉数值异常,逐步验证功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值