Пользовательский оценщик TensorFlow - восстановление модели после небольших изменений в model_fn

Я использую tf.estimator.Estimator для разработки своей модели,

Я написал model_fn и обучил 50 000 итераций, теперь я хочу внести небольшие изменения в свой model_fn, например добавить новый слой.

Я не хочу начинать обучение с нуля, я хочу восстановить все старые переменные из контрольной точки 50 000 и продолжить обучение с этого момента. Когда я пытаюсь это сделать, я получаю NotFoundError

Как это можно сделать с tf.estimator.Estimator?


person mtngld    schedule 02.01.2018    source источник
comment
Не могли бы вы предоставить полную трассировку ошибок? Это может помочь получить более подробный контекст ошибки.   -  person Olivier Moindrot    schedule 04.01.2018
comment
Вот пример игрушки: gist.github.com/mtngld/147335874af6fe5d79a5673406679640   -  person mtngld    schedule 05.01.2018
comment
Мой первоначальный вопрос касался model_fn, но в этом смысле я фактически вижу ту же ошибку при использовании универсального DNNClassifier при добавлении новых слоев. Спасибо!   -  person mtngld    schedule 05.01.2018
comment
Связанная проблема с tf: github.com/tensorflow/tensorflow/issues/10155   -  person mtngld    schedule 05.01.2018


Ответы (1)


TL; DR Самый простой способ загрузить переменные из предыдущей контрольной точки - использовать функцию _ 1_. Всего один вызов этой функции внутри model_fn вашего оценщика переопределит инициализаторы соответствующих переменных.


Первая модель с двумя скрытыми слоями

Более подробно, предположим, что вы обучили первую модель с двумя скрытыми слоями в MNIST с именем model_fn_1. Вес сохранен в каталоге mnist_1.

def model_fn_1(features, labels, mode):
    images = features['image']

    h1 = tf.layers.dense(images, 100, activation=tf.nn.relu, name="h1")
    h2 = tf.layers.dense(h1, 100, activation=tf.nn.relu, name="h2")

    logits = tf.layers.dense(h2, 10, name="logits")

    loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

    optimizer = tf.train.GradientDescentOptimizer(0.01)
    train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())

    return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

# Estimator 1: two hidden layers
estimator_1 = tf.estimator.Estimator(model_fn_1, model_dir='mnist_1')

estimator_1.train(input_fn=train_input_fn, steps=1000)

Вторая модель с тремя скрытыми слоями

Теперь мы хотим обучить новую модель model_fn_2 с тремя скрытыми слоями. Мы хотим загрузить веса для первых двух скрытых слоев h1 и h2. Для этого мы используем tf.train.init_from_checkpoint():

def model_fn_2(features, labels, mode, params):
    images = features['image']

    h1 = tf.layers.dense(images, 100, activation=tf.nn.relu, name="h1")
    h2 = tf.layers.dense(h1, 100, activation=tf.nn.relu, name="h2")
    h3 = tf.layers.dense(h2, 100, activation=tf.nn.relu, name="h3")

    assignment_map = {
        'h1/': 'h1/',
        'h2/': 'h2/'
    }
    tf.train.init_from_checkpoint('mnist_1', assignment_map)

    logits = tf.layers.dense(h3, 10, name="logits")

    loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

    optimizer = tf.train.GradientDescentOptimizer(0.01)
    train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())

    return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

# Estimator 2: three hidden layers
estimator_2 = tf.estimator.Estimator(model_fn_2, model_dir='mnist_2')

estimator_2.train(input_fn=train_input_fn, steps=1000)

assignment_map загрузит каждую переменную из области h1/ в контрольной точке в новую область h1/, то же самое с h2/. Не забывайте / в конце, чтобы TensorFlow узнал, что это переменная область видимости.


Я не мог найти способ сделать эту работу, используя готовые оценщики, так как вы не можете изменить их model_fn.

person Olivier Moindrot    schedule 06.01.2018