Вы должны определить случайное начальное число в конфигурации, передаваемой в оценщик:
seed = 2018
config = tf.estimator.RunConfig(model_dir=model_dir, tf_random_seed=seed)
estimator = tf.estimator.Estimator(model_fn, config=config, params=params)
Вот документация для RunConfig
.
Одна вещь, о которой следует быть осторожным, заключается в том, что каждый раз, когда вы запускаете estimator.train(train_input_fn)
, создается новый график для обучения модели (вызывая train_input_fn
для создания входного конвейера и вызывая model_fn
на выходе train_input_fn
).
Одна из проблем заключается в том, что этот новый график также будет каждый раз иметь одно и то же случайное начальное число.
Пример
Позвольте мне объяснить на примере. Предположим, что вы выполняете увеличение данных в своем входном конвейере, и вы оцениваете свою модель каждую эпоху. Это даст вам что-то вроде этого:
def train_input_fn():
features = tf.random_uniform([])
labels = tf.random_uniform([])
dataset = tf.data.Dataset.from_tensors((features, labels))
return dataset
def model_fn(features, labels, mode, params):
loss = features
global_step = tf.train.get_global_step()
train_op = global_step.assign_add(1)
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
seed = 2018
config = tf.estimator.RunConfig(model_dir="test", tf_random_seed=seed)
estimator = tf.estimator.Estimator(model_fn, config=config)
num_epochs = 10
for epoch in range(num_epochs):
estimator.train(train_input_fn, steps=1)
estimator.evaluate(train_input_fn, steps=1)
Функция ввода создает случайные объекты (и метки). Что происходит, так это то, что созданные функции будут одинаковыми в каждой эпохе. Вывод будет выглядеть так:
INFO:tensorflow:loss = 0.17983198, step = 1
INFO:tensorflow:Saving dict for global step 1: global_step = 1, loss = 0.006007552
INFO:tensorflow:loss = 0.17983198, step = 2
INFO:tensorflow:Saving dict for global step 2: global_step = 2, loss = 0.006007552
INFO:tensorflow:loss = 0.17983198, step = 3
INFO:tensorflow:Saving dict for global step 3: global_step = 3, loss = 0.006007552
...
Вы можете видеть, что потери (равные входным характеристикам) одинаковы в каждой эпохе, что означает, что в каждой эпохе используется одно и то же случайное начальное число.
Это проблема, если вы хотите оценивать каждую эпоху и выполнять увеличение данных, потому что в итоге вы получите одинаковое увеличение данных в каждую эпоху.
Решение
Одним из быстрых решений является удаление случайного семени. Однако это мешает вам проводить воспроизводимые эксперименты.
Еще одним лучшим решением является создание новой оценки в каждой эпохе с тем же model_fn
, но другим случайным начальным числом:
seed = 2018
num_epochs = 10
for epoch in range(num_epochs):
config = tf.estimator.RunConfig(model_dir="test", tf_random_seed=seed + epoch)
estimator = tf.estimator.Estimator(model_fn, config=config)
estimator.train(train_input_fn, steps=1)
estimator.evaluate(train_input_fn, steps=1)
Функции будут корректно меняться в каждую эпоху:
INFO:tensorflow:loss = 0.17983198, step = 1
INFO:tensorflow:Saving dict for global step 1: global_step = 1, loss = 0.006007552
INFO:tensorflow:loss = 0.22154999, step = 2
INFO:tensorflow:Saving dict for global step 2: global_step = 2, loss = 0.70446754
INFO:tensorflow:loss = 0.48594844, step = 3