tf.distribute.Strategy.scope()中必须包含什么?

时间:2019-06-11 11:33:49

标签: python tensorflow tensorflow2.0

我目前正在使用tensorflow 2.0中的分发策略,如此处https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/distribute/Strategy

所述

我想知道with ...scope()块中必须包含什么,什么是“可选”。

特别是以下操作。我是否必须将...放在with ...scope()内才能正常工作?

  • 创建优化程序
  • 数据集创建
  • 数据集experimental_distribute_dataset
  • apply_gradients呼叫
  • 用于循环的数据集迭代
  • experimental_run_v2

我开玩笑了一点,即使我完全不使用with ...scope,我的代码也似乎可以正常工作。如果这有一些副作用,我现在不知道,我感到困惑。

不带scope的代码:

strat = tf.distribute.MirroredStrategy()

BATCH_SIZE_PER_REPLICA = 5

print('Replicas: ', strat.num_replicas_in_sync)

global_batch_size = (BATCH_SIZE_PER_REPLICA * strat.num_replicas_in_sync)

dataset = tf.data.Dataset.from_tensors(tf.random.normal([100])).repeat(1000).batch(
    global_batch_size)

g = Model('m', 10, 10, 1, 3)

dist_dataset = strat.experimental_distribute_dataset(dataset)

@tf.function
def train_step(dist_inputs):
  def step_fn(inputs):
    print([(v.name, v.device) for v in g.trainable_variables])
    return g(inputs)

  out = strat.experimental_run_v2(step_fn, args=(dist_inputs,))

for inputs in dist_dataset:
    train_step(inputs)
    break

具有范围的代码:

strat = tf.distribute.MirroredStrategy()

BATCH_SIZE_PER_REPLICA = 5

print('Replicas: ', strat.num_replicas_in_sync)

global_batch_size = (BATCH_SIZE_PER_REPLICA * strat.num_replicas_in_sync)

with strat.scope():
    dataset = tf.data.Dataset.from_tensors(tf.random.normal([100])).repeat(1000).batch(
        global_batch_size)

    g = Model('m', 10, 10, 1, 3)

    dist_dataset = strat.experimental_distribute_dataset(dataset)

    @tf.function
    def train_step(dist_inputs):
        def step_fn(inputs):
            print([(v.name, v.device) for v in g.trainable_variables])
            return g(inputs)

        out = strat.experimental_run_v2(step_fn, args=(dist_inputs,))

    for inputs in dist_dataset:
        train_step(inputs)
        break

编辑:似乎strat.experimental_run_v2自动进入strat的范围。那么with strat.scope()为什么存在?

3 个答案:

答案 0 :(得分:0)

您无需将数据集,数据集迭代循环等放入scope()中。您只需要定义顺序模型及其内部的编译即可。所以像这样-

mirrored_strategy = tf.distribute.MirroredStrategy()
with mirrored_strategy.scope():
  model = tf.keras.Sequential()
  model.add(tf.keras.layers.Embedding(vocab_size, 64))
  model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, activation= 'tanh', recurrent_activation= 'sigmoid', recurrent_dropout = 0, unroll = False, use_bias= True)))
  # One or more dense layers.
  # Edit the list in the `for` line to experiment with layer sizes.
  for units in [64, 64]:
    model.add(tf.keras.layers.Dense(units, activation='relu'))
  # Output layer. The first argument is the number of labels.
  model.add(tf.keras.layers.Dense(3, activation='softmax'))
  model.compile(optimizer='adam',
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy'])

它将要做的是,它将在每个GPU上创建模型及其参数的副本,并在训练过程中对其进行训练。您将定义的批次大小将除以可用GPU的数量,然后将这些批次发送到这些GPU,例如,如果您拥有batch_size = 64并且有两个GPU,则每个GPU将获得32个批次。您可以阅读更多here

答案 1 :(得分:0)

根据我的实验,唯一需要在内部声明的是模型创建。如果您使用Keras .fit()而不是自定义培训,那么model.compile()也必须放在里面。

您可以执行以下操作:

def create_model():
    """ This can be outside of the scope
    """"
    ...
    return model

with strategy.scope():
    model = create_model()

如果您使用tf.train.Checkpoint,请确保其实例化和checkpoint.resume()的调用都在范围之内。

答案 2 :(得分:0)

您不需要致电strat.scope()

experimental_run_v2是一种将计算放入strat.scope()中的简单方法。

请参见下面的experimental_run_v2源代码,它实际上将fn包装在您的范围内。

https://github.com/tensorflow/tensorflow/blob/919dfc3d066e72ee02baa11fbf7b035d9944daa9/tensorflow/python/distribute/distribute_lib.py#L729