TF 1.0到2.0迁移
在TensorFlow 2.0中,仍然可以运行未经修改的1.x代码(contrib除外):
import tensorflow.compat.v1 as tf tf.disable_v2_behavior()
但是,这并不能让您利用TensorFlow
2.0中的许多改进。本指南将帮助您升级代码,使其更简单、更高效、更易于维护。
自动转换脚本
第一步是尝试运行升级脚本。
这将在将代码升级到TensorFlow
2.0时执行初始步骤,但是它不能使您的代码适合TensorFlow
2.0。您的代码仍可以使用tf.compat.v1端点来访问占位符、会话、集合和其他1.x样式的功能。
使代码2.0原生化
本指南将介绍将TensorFlow 1.x代码转换为TensorFlow
2.0的几个示例。这些更改将使您的代码利用性能优化和简化的API调用。
在每一种情况下,模式是:
1. 替换tf.Session.run调用
每个tf.Sessionrun调用都应该被Python函数替换:
feed_dict和tf.placeholder变成函数参数
fetches变成函数的返回值
您可以使用标准Python工具(如pdb)逐步调试该函数。如果您对它的工作满意,可以添加一个tf.function装饰器,使其在图形模型下高效运行。有关其工作原理的更多信息,请参阅AutoGraph指南。
2. 使用Python对象来跟踪变量和损失
使用tf.Variable代替tf.get_variable。每个variable_scope可转换成Python对象,通常这是下面几个之一:
tf.keras.layers.layer
tf.keras.Model
tf.Module
如果需要聚合变量列表(如tf.Graph.get_collection(tf.GraphKeys.VARIABLES)),请使用Layer和Model对象的.variables和.trainable_variables属性。
这些Layer和Model类实现了几个其他属性,无需全局几何。他们的.losses属性可以替代使用tf.GraphKeys.LOSSES集合。
有关详细信息,请参阅Keras指南。
3. 升级您的训练循环
使用适用于您的用例的最高级API,最好是tf.keras.Model.fit建立自己的训练循环。
如果您编写自己的训练循环,这些高级函数可以管理很多困难容易遗漏的低级细节。例如,它们会自动收集正则化损失,并在调用模型时设置training=True参数。
4. 升级数据输入管道
使用tf.data数据集进行数据输入,这些对象是高效的、富有表现力的,并且与张量流很好地集成。它们可以直接传递给tf.keras.Model.fit方法。
model.fit(dataset, epochs=5)
它们可以直接在标准Python上进行迭代:
for example_batch, label_batch in dataset: break
转换模型
1. 安装
from __fucture__ import absolute_import, division, print_function
import tensorflow as tf \# pip install –q tensorflow==2.0.0-alpha0
import tensorflow_datasets as tfds
2. 低阶变量和操作执行
低级API使用的示例包括:
使用变量范围来控制重用
使用tf.get_variable创建变量
明确地访问集合
使用以下方式隐式访问集合:
tf.global_variables
tf.losses.get_regularization_loss
使用tf.placeholder设置图形输入
使用session.run执行图
手动初始化变量
转换前
以下是使用TensorFlow 1.x在代码中看起来像这些模式的内容:
in_a = tf.placeholder(dtype=tf.float32, shape=(2))
in_b = tf.placeholder(dtype=tf.float32, shape=(2))
def forward(x):
with tf.variable_scope(‘matmul’, resuse=tf.AUTO_RESUE):
W = tf.get_variable(‘W’, initializer=tf.ones(shape=(2,2)), regularizer=tf.contrib.layers.l2_regularizer(0.04))
b = tf.get_variable(‘b’, initializer=tf.zeros(shape=(2)))
return x \* train_data + b
out_a = model(in_a)
out_b = model(in_b)
reg_loss = tf.losses.get_regularization_loss(scope=’matmul’)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
outs = sess.run([out_a, out_b, reg_loss], feed_dict={in_a: [1, 0], in_b: [0, 1]})
转换后
在转换后的代码中:
变量是本地Python对象
前向函数依然定义了计算
sess.run调用被替换为forward的调用
可以添加可选的tf.function装饰器以提高性能
正则化是手动计算的,不设计任何全局集合
没有sessions和placeholders
W = tf.Variable(tf.ones(shape=(2, 2)), name=”W”)
b = tf.Variable(tf.zeros(shape=(2)), name=”b”)
@tf.function
def forward(x):
return W \* x + b out_a = forward([1, 0]) print(out_a)
out_b = forward([0, 1])
regularizer = tf.keras.regularizers.l2(0.02)
reg_loss = regularizer(W)
3. 基于tf.layers的模型
tf.layers模块用于包含依赖于tf.variable_scope来定义和重用变量的层函数。
转换前
def model(x, training, scope=’model’):
with tf.variable_scope(scope, reuse=tf.AUTO_REUSE):
x = tf.layers.conv2d(x, 32, 3, activation=tf.nn.relu, kernel_regularizer = tf.contrib.layers.l2_regularizer(0.04))
x = tf.layers.max_pooling2d(x, (2, 2), 1)
x = tf.layers.flatten(x)
x = tf.layers.dropout(x, 0.1, training=training)
x = tf.layers.dense(x, 64, activation=tf.nn.relu)
x = tf.layers.batch_normalization(x,training=training)
x = tf.layers.dense(x, 10, activation=tf.nn.softmax)
return x
train_out = model(train_data, training=True)
test_out = model(test_data, training=False)
转换后
简单的层堆栈可以整齐地放入tf.keras.Sequence中。(对于更复杂的模型,请参见自定义层和模型,以及函数API)
模型跟踪变量和正则化损失
转换是一对一的,因为它是从tf.layers到tf.keras.layers直接映射的。
大多数参数保持不变,但注意区别:
训练参数在运行时由模型传递给每个层
原来模型函数的第一个参数(intput x)消失,这是因为层将构建模型与调用模型分开了。
同时也要注意:
如果你使用tf.contrib的初始化器的正则化器,那么它们的参数变化会比其他变量更多。
代码不在写入集合,因此像tf.losses.get_regularization_loss这样的函数将不再返回这些值,这可能会破坏您的训练循环。
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, 3, activation=’relu’, kernel_regularizer=tf.keras.regularizers.l2(0.02), input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.1),
tf.keras.layers.Dense(64, activation=’relu’),
tf.keras.lyaers.BatchNormalization(),
tf.keras.layers.Dense(10, activation=’softmax’)
])