Обучайте сложные модели nn с помощью tf.eager (лучше с символической поддержкой TF2)

Есть ли (более или менее) простой способ написать сложную модель NN, чтобы ее можно было обучать в активном режиме? Есть примеры такого кода?

Например, я хочу использовать InceptionResnetV2. У меня есть код, созданный с помощью tf.contrib.slim. По этой ссылке https://github.com/tensorflow/tensorflow/issues/16182 , slim устарел, и мне нужно использовать Keras. И я действительно не могу использовать тонкий код для обучения с нетерпеливым, потому что я не могу взять список переменных и применить градиенты (хорошо, я могу попытаться обернуть модель в GradientTape, но не уверен, что делать с потерями регуляризации).

Хорошо, попробуем Keras.

In [30]: tf.__version__                                                                                                                                                                          
Out[30]: '1.13.1'

In [31]: tf.enable_eager_execution()

In [32]: from keras.applications.inception_resnet_v2 import InceptionResNetV2

In [33]: model = InceptionResNetV2(weights=None)
...
/usr/local/lib/python3.6/dist-packages/keras_applications/inception_resnet_v2.py in InceptionResNetV2(include_top, weights, input_tensor, input_shape, pooling, classes, **kwargs)
    246 
    247     if input_tensor is None:
--> 248         img_input = layers.Input(shape=input_shape)
    249     else:
    250         if not backend.is_keras_tensor(input_tensor):
...
RuntimeError: tf.placeholder() is not compatible with eager execution.

Не работает по умолчанию.

В этом уроке говорится, что мне нужно сделать свой собственный класс модели и самостоятельно поддерживать переменные https://www.tensorflow.org/tutorials/eager/custom_training#define_the_model. Я не уверен, что хочу делать это для «Начала». Слишком много переменных для создания и обслуживания. Это как вернуться к старым версиям TF, в те времена, когда даже slim не существовало.

В этом руководстве сети создаются с использованием Keras https://www.tensorflow.org/tutorials/eager/custom_training_walkthrough#create_a_model_using_keras, но я сомневаюсь, что смогу легко поддерживать сложную структуру таким образом, определяя только модель, не используя ее с Input. Например, в этой статье, если я правильно понимаю, автор инициализирует keras Input и распространяет его по модели (что вызывает RuntimeError при использовании с Eager, как вы видели ранее). Я могу создать свою собственную модель, создав подкласс класса модели, как здесь: https://www.tensorflow.org/api_docs/python/tf/keras/Model. Упс, таким образом мне нужно поддерживать слои, а не переменные. Мне кажется почти такая же проблема.

Здесь есть интересное упоминание о AutoGrad https://www.tensorflow.org/beta/guide/autograph#keras_and_autograph . Они перезаписывают только __call__, поэтому мне кажется, что в этом случае мне не нужно поддерживать переменные, но я еще не проверял.


Итак, есть ли какое-нибудь простое решение?

Завернуть стройную модель в GradientTape? Как я могу затем применить reg loss к весам?

Отслеживать каждую переменную самостоятельно? Звучит немного болезненно.

Использовать Keras? Как использовать его с нетерпением, когда у меня есть ветки и сложная структура в модели?


person ckorzhik    schedule 19.08.2019    source источник


Ответы (1)


Ваш первый подход, вероятно, является наиболее распространенным. Эта ошибка:

RuntimeError: tf.placeholder() несовместим с нетерпеливым выполнением.

это потому, что нельзя использовать tf.placeholder в нетерпеливом режиме. Нет такого понятия при выполнении жадно.

Вы можете использовать tf.data API, чтобы создать набор данных для ваших обучающих данных и передать их в модель. . Что-то вроде этого с наборами данных, замененными вашими реальными данными:

import tensorflow as tf
tf.enable_eager_execution()

model = tf.keras.applications.inception_resnet_v2.InceptionResNetV2(weights=None)

model.compile(tf.keras.optimizers.Adam(), loss=tf.keras.losses.categorical_crossentropy)

### Replace with tf.data.Datasets for your actual training data!
train_x = tf.data.Dataset.from_tensor_slices(tf.random.normal((10,299,299,3)))
train_y = tf.data.Dataset.from_tensor_slices(tf.random.uniform((10,), maxval=10, dtype=tf.int32))
training_data = tf.data.Dataset.zip((train_x, train_y)).batch(BATCH_SIZE)

model.fit(training_data)

Этот подход работает и в TensorFlow 2.0, как указано в вашем заголовке.

person Stewart_R    schedule 20.08.2019