Session.run的调用
每一个Session.run调用都可以被Python函数替换。
(1)feed_dict和
v1.placeholder
s 成为函数参数;
(2)fetches成为函数的返回值;
之后,添加tf.function装饰器使其在图形中高效运行。
注意:(1)不像v1.Session.run,tf.function有固定的返回签名,总是返回所有的输出。如果这个导致性能问题,则创建两个单独的函数;
(2)tf.control_dependencies
和类似的操作没有必要:tf.function的行为就像按写的顺序运行,如tf.Variable和tf.assert,能够自动执行。
2、使用python对象追踪变量和损失
在TF2.0中,所有基于名称的变量追踪都是被强烈阻止的,使用Python对象来追踪变量。
(1)用 tf.Variable
替代 v1.get_variable
.
(2)每一个v1.variable_scope
应该被转换为Python对象,通常:
tf.keras.layers.Layer
tf.keras.Model
tf.Module
如果需要聚合变量列表(如 tf.Graph.get_collection(tf.GraphKeys.VARIABLES)
),用Layer和Model层和模型对象的.variables和.trainables_variables属性。
这些Layer和Model层和模型类实现了几个其他属性,这些属性消除了对全局集合的需要。他们的.losses属性可以用tf.GraphKeys.LOSSES集合替换。
3、升级训练循环
使用适合于你的用例的最高级别API,tf.keras.Model建立自己的训练循环。
如果你编写自己的训练循环,这些高级函数将管理许多低级的、容易被忽略的细节。例如,自动收集正则化损失,调用模型时设置training=True参数。
4、升级数据输入管道
使用tf.data数据集用于数据输入。他们可以直接传给tf.keras.Model.fit方法。
model.fit(dataset,epochs=5)
他们可以直接遍历标准python:
for example_batch,label_batch in dataset:
break
5、迁移compat.v1
符号
tf.compat.v1
模块包含完整的TF1.X API。
如果这种转换是安全的,TF2升级脚本将把符号转换为2.0等价物,将v1.arg_max重新命名为 tf.arg_max。
6、注意TF2.0相对于1.X的简化
(1)不需要进行变量初始化,变量在创建时初始化;
(2)不需要添加手动控制依赖项,即使在“立即”模式执行的tf.function操作。
7、新风格的度量和损失
在TF2.0中,度量metrics和损失loss是对象object,他们在tf.functions中,以立即模式起作用。
损失对象被调用,(y_true,y_pred)为参数:
cce = tf.losses.CategoricalCrossentropy(from_logits=True)
cce([[1, 0]], [[-1.0,3.0]]).numpy()
度量metric对象object有以下方法:
Metric.update_state()
——添加新的观察值
Metric.result()
——给定观察值,获得度量的当前结果
Metric.reset_states()
——清除所有的观察值
8、Keras优化器
在v1.train中的优化器,如v1.train.AdamOptimizer和
v1.train.GradientDescentOptimizer
,在TF2.0中为tf.keras.optimizers
.
优化器v1.train
转化为 keras.optimizers
应注意以下几点:
(1)升级优化器可能会使旧的检查点不兼容;
(2)epsilons默认为1e-7而不是1e-8(大多数情况下是可以忽略的)
(3)tf.keras.optimizers.SGD可以直接替换
v1.train.GradientDescentOptimizer;
(4)SGD优化器设置momentum参数tf.keras.optimizers.SGD(..., momentum=...)可以直接替换
v1.train.MomentumOptimizer;
(5)v1.train.AdamOptimizer
可以转为使用tf.keras.optimizers.Adam
. beta1和
beta2参数重命名为
beta_1和
beta_2
.
(6)v1.train.RMSPropOptimizer
可以转为使用tf.keras.optimizers.RMSprop
.decay
参数被重命名为rho
.
(7)v1.train.AdadeltaOptimizer
可以直接转为使用tf.keras.optimizers.Adadelta
.
(8)tf.train.AdagradOptimizer
可以直接转为使用tf.keras.optimizers.Adagrad
.
(9)tf.train.FtrlOptimizer
可以直接转为使用tf.keras.optimizers.Ftrl
.accum_name和
linear_name参数被去掉。
(10)tf.contrib.AdamaxOptimizer和tf.contrib.NadamOptimizer
可以直接转为使用 tf.keras.optimizers.Adamax和
tf.keras.optimizers.Nadam
. beta1
和beta2
参数重命名为beta_1和
beta_2
.
注意:如果模型出现不收敛,检查默认的学习率。
optimizers.SGD
, optimizers.Adam和
optimizers.RMSprop
.
以下的默认学习率都发生了改变:
optimizers.Adagrad
from 0.01 to 0.001
optimizers.Adadelta
from 1.0 to 0.001
optimizers.Adamax
from 0.002 to 0.001
optimizers.Nadam
from 0.002 to 0.001
9、TensorBoard
TF2.0,用来在TensorBoard写可视化总结数据的tf.summary接口有了较大变化,详见TensorBoard TF2.0 Migration Guide.
10、保存和加载
Checkpoint兼容性:TF2.0使用面向对象的Checkpoint.
如果小心的话,旧式的基于名称的checkpoint仍然可以加载使用,代码迁移过程可能会导致变量名的更改,但是可以解决:
(1)变量仍然包含可以设置的名称参数name argument;
(2)Keras模型也采用设置作为变量前缀的名称参数;
(3)和tf.variable_scope不同,v1.name_scope函数可以用来设置变量名前缀。他只影响名称,不跟踪变量和重用。
如果以上对你的用例不起作用,那么试着使用 v1.train.init_from_checkpoint函数
,该函数有一个assignment_map参数,该参数指定从旧名称到新名称的映射。
注意:与可以延迟加载的基于对象的检查点不同,基于名称的检查点需要在调用函数时构建所有的变量,有些模型将构建变量推迟到调用build或批数据运行模型之后。
Saved models兼容性:对于保存的模型没有明显的兼容性问题
(1)TF1.X的saved_models在TF2.0中继续有效;
(2)如果所有的操作支持的话,TF2.0的saved_models也可以在TF1.X中有效加载。
11、其他不同
(1)移除了tf.colocate_with:TF的设备放置device placement算法有了显著的改变,这应该不再是必须的。
(2)等价的函数tf.config
代替了v1.ConfigProto
。
12、整个流程为:
(1)运行升级脚本;
(2)删除contrib符号;
(3)将模型转换为面向对象形式(keras);
(4)使用 tf.keras
或 tf.estimator
训练和评估循环;
(5)另外,使用自定义循环,但一定要避免sessions & collections。
将代码转换为惯用的TF2.0需要做一些工作,会带来如下优点:
(1)更少的代码行;
(2)增加清晰度和简单性;
(3)代码更容易调试。