Tensorflow 2.0 Keras тренируется в 4 раза медленнее, чем 2.0 Estimator

Недавно мы перешли на Keras для TF 2.0, но когда мы сравнили его с оценщиком DNNClassifier в 2.0, мы увидели примерно в 4 раза меньшую скорость с Keras. Но я хоть убей не могу понять, почему это происходит. Остальной код для обоих идентичен, с использованием input_fn (), который возвращает один и тот же tf.data.Dataset, и с использованием идентичных feature_columns. Уже несколько дней борюсь с этой проблемой. Любая помощь будет принята с благодарностью. Спасибо

Код оценщика:

estimator = tf.estimator.DNNClassifier(
        feature_columns = feature_columns,
        hidden_units = [64,64],
        activation_fn = tf.nn.relu,
        optimizer = 'Adagrad',
        dropout = 0.4,
        n_classes = len(vocab),
        model_dir = model_dir,
        batch_norm = false)

estimator.train(input_fn=train_input_fn, steps=400)

Код Кераса:

feature_layer = tf.keras.layers.DenseFeatures(feature_columns);

model = tf.keras.Sequential([
        feature_layer,
        layers.Dense(64, input_shape = (len(vocab),), activation = tf.nn.relu),
        layers.Dropout(0.4),
        layers.Dense(64, activation = tf.nn.relu),
        layers.Dropout(0.4),
        layers.Dense(len(vocab), activation = 'softmax')]);

model.compile(
        loss = 'sparse_categorical_crossentropy',
        optimizer = 'Adagrad'
        distribute = None)

model.fit(x = train_input_fn(),
          epochs = 1,
          steps_per_epoch = 400,
          shuffle = True)

ОБНОВЛЕНИЕ: для дальнейшего тестирования я написал настраиваемую модель подкласса (см. Начало работы для экспертов), который работает быстрее, чем Keras, но медленнее, чем Estimators. Если Оценщик тренируется за 100 секунд, пользовательская модель занимает примерно ~ 180 секунд, а Keras - примерно ~ 350 секунд. Интересно отметить, что оценщик работает медленнее с Adam (), чем с Adagrad (), в то время как Keras, кажется, работает быстрее. С Adam () Keras занимает в два раза больше времени, чем DNNClassifier. Предполагая, что я не испортил пользовательский код, я начинаю думать, что DNNClassifier просто имеет много внутренней оптимизации / эффективности, которые заставляют его работать быстрее, чем Keras.

Пользовательский код:

class MyModel(Model):
  def __init__(self):
    super(MyModel, self).__init__()
    self.features = layers.DenseFeatures(feature_columns, trainable=False)
    self.dense = layers.Dense(64, activation = 'relu')
    self.dropout = layers.Dropout(0.4)
    self.dense2 = layers.Dense(64, activation = 'relu')
    self.dropout2 = layers.Dropout(0.4)
    self.softmax = layers.Dense(len(vocab_of_codes), activation = 'softmax')

  def call(self, x):
    x = self.features(x)
    x = self.dense(x)
    x = self.dropout(x)
    x = self.dense2(x)
    x = self.dropout2(x)
    return self.softmax(x)

model = MyModel()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adagrad()

@tf.function
def train_step(features, label):
  with tf.GradientTape() as tape:
    predictions = model(features)
    loss = loss_object(label, predictions)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

itera = iter(train_input_fn())
for i in range(400):
  features, labels = next(itera)
  train_step(features, labels)

ОБНОВЛЕНИЕ: возможно, это набор данных. Когда я печатаю строку набора данных в train_input_fn (), в оценщиках она распечатывает неактивное определение Tensor. В Keras он распечатывает ожидаемые значения. Проходя через бэкэнд-код Keras, когда он получает tf.data.dataset в качестве ввода, он обрабатывает его с нетерпением (и ТОЛЬКО с нетерпением), поэтому он вылетал всякий раз, когда я использовал tf.function в train_input_fn (). В принципе, я предполагаю, что DNNClassifier обучается быстрее, чем Keras, потому что он выполняет больше кода набора данных в графическом режиме. Буду размещать любые обновления / находки.


person Byest    schedule 14.03.2019    source источник


Ответы (2)


Я считаю, что он медленнее, потому что он не выполняется на графике. Для выполнения на графике в TF2 вам понадобится функция, украшенная декоратором tf.function. Ознакомьтесь с этим разделом, чтобы узнать, как реструктурировать код.

person DecentGradient    schedule 14.03.2019
comment
Спасибо за ответ. ^^ Я согласен, что это наиболее вероятная причина замедления. Я был неуверен только потому, что предполагал, что команда Google / TF написала Keras fit () и Estimator train () для автоматического использования tf.function или кода графика в бэкэнд-реализации. Я пытался запустить код в графическом режиме большую часть дня, используя либо tf.function, либо tf.compat.v1.disable_eager_execution (). В графическом режиме оценщики обучаются правильно, но Керас испытывает массу странных ошибок в слое DenseFeatures (). Буду копать и выкладывать обновления. Спасибо. ^^ - person Byest; 16.03.2019
comment
Я немного покопался и обнаружил следующее: слои / модели Keras наследуются от tf.train.Checkpointable и интегрированы с функцией @ tf.function, что позволяет напрямую выполнять контрольную точку или экспортировать SavedModels из объектов Keras. (Эффективный TF2) Итак, я предполагаю, что код уже использует режим графа. Единственное, что у меня есть, - это наши feature_columns, которые в основном представляют собой 1 миллион словаря indicator_column (category_column (...)). Я думаю, может быть, Керас намного медленнее в этом размере и типе. Буду копать и выкладывать все находки. - person Byest; 18.03.2019

Для тех, кто (как и я) находит этот вопрос и использует слои встраивания Keras:

Даже если графический процессор присутствует, но включено активное выполнение, слои внедрения всегда размещаются на центральном процессоре, что приводит к значительному замедлению.

См. https://github.com/tensorflow/tensorflow/issues/44194, который также содержит обходной путь.

person Till Brychcy    schedule 08.03.2021