В Tensorflow 2 API обнаружения объектов разделил обучение и проверку на два разных процесса. Более того, они должны работать одновременно, отслеживая тот же каталог, где сохранены контрольные точки. В этой статье объясняется прием, позволяющий пользователям запускать проверку как истинный постпроцесс, который, насколько мне известно, недоступен в текущей реализации API обнаружения объектов.

Оглавление

1). By default, how is Training and Validation supposed to intertwine?
2). The Pros & Cons of the aforementioned approach
3). Make Validation a true Post-process
4). Verify
5). Conclusion

Как по умолчанию обучение и валидация должны переплетаться?

Предполагая, что все настроено правильно, от подготовки данных в виде TFRecord до загрузки моделей репозитория Git, компиляции прототипов, установки setup.py API Tensorflow Object Detection и настройки pipeline.config, затем выполняется процесс обучения, с помощью команды:

python model_main_tf2.py \
  --pipeline_config_path="some_path/pipeline.config" \
  --model_dir="some_path" \
  --checkpoint_every_n=100 \
  --num_train_steps=1000 \
  --alsologtostderr

В то же время запускается проверка следующим образом:

python model_main_tf2.py \
  --pipeline_config_path="some_path/pipeline.config" \
  --model_dir="some_path" \
  --checkpoint_dir="some_path" \
  --eval_timeout=60

Всякий раз, когда обучение сохраняет файл контрольной точки, например, ckpt-1(ckpt-1.data-00000-of-00001 и ckpt-1.index), проверка обнаруживает, принимает файл, начинает проверку и сохраняет результат, например, как events.out.tfevents.1645005144.6403b50c5b59.912.0.v2. Эти процессы продолжаются до тех пор, пока обучение не будет завершено, а затем истечет время проверки (нет новой контрольной точки).

Плюсы и минусы вышеупомянутого подхода

Читатель может иметь другую схему настройки ресурсов для обучения и проверки. Например, у них может быть один или два мощных ПК с большим количеством CPU/GPU. Но в моем случае используется Google Colab. К сожалению, блокнот CoLab выполняет ячейки одну за другой; в одной ячейке, одна команда за другой, например. !python model_main_tf2.py…. При выполнении проверки после обучения проверка будет учитывать только последнюю контрольную точку, как показано ниже:

# 1). module "model_main_tf2.py", line 81.
if FLAGS.checkpoint_dir: # if checkpoint_dir argument is used.
  model_lib_v2.eval_continuously(...
# 2). module "model_lib_v2.py", function eval_continuously(), line 1136:
for latest_checkpoint in tf.train.checkpoints_iterator(
  checkpoint_dir, timeout=timeout, min_interval_secs=wait_interval):
# 3). module "checkpoint_utils.py", function checkpoints_iterator(), line 194:
while True:
  new_checkpoint_path = wait_for_new_checkpoint(
    checkpoint_dir, checkpoint_path, timeout=timeout)
# 4). same module, function wait_for_new_checkpoint(), line 139:
while True:
  checkpoint_path = checkpoint_management.latest_checkpoint(checkpoint_dir)

Может быть несколько трюков для одновременной работы нескольких ячеек, таких как ipyparallel (но я не разбираюсь в этом методе и не уверен, что он вообще может работать с CoLab).

Насколько мне известно, плюсы и минусы обучения и проверки параллельного выполнения):

  • Плюсы:
    - Нет необходимости хранить все контрольные точки (в моем случае одна контрольная точка стоит 42,5 МБ). Действительно, Training поддерживает только последние 7 контрольных точек. Эта конфигурация не может быть изменена извне.
    - В сочетании с Tensorboard в режиме реального времени можно остановить обучение раньше, если, например. loss уже существенно не уменьшается.
  • Минусы:
    — ресурсы должны быть разделены между обучением и проверкой, что может замедлить обучение. Проверка может также использовать GPU (Рисунок [1]).
    - В процессе проверки учитывается только последняя контрольная точка. В некоторых случаях, например. большой набор проверок и более детальный checkpoint_every_n, проверка может пропустить некоторые контрольные точки, что приведет к менее детализированной визуализации для данных проверки.
    - Сложность: в CoLab непросто запустить несколько ячеек параллельно (т. Обучение, одна ячейка для проверки).

Следовательно, может возникнуть необходимость в проведении процесса валидации после процесса обучения. Это было бы особенно удобно в случае использования CoLab.

Сделайте валидацию настоящим постпроцессом

Код для проверки, а именно: прием контрольной точки, восстановление модели, проверка ее на соответствие набору проверки, должен быть разбросан по нескольким местам в моделях репозитория Git. Сборка всех частей может занять много времени, а также может привести к возникновению новых тонких проблем.

Безопасный и быстрый подход должен состоять в том, чтобы сохранить текущий способ выполнения, т. е. вызвать model_main_tf2.py с аргументом checkpoint_dir, но изменить несколько мест в коде, где вместо постоянного наблюдения за каталогом в поисках нового Checkpoint, он будет просто перечислять все контрольные точки в каталоге и обрабатывать каждую из них как если бы каждая из них была единственной последней контрольной точкой. Благодаря этому сохраняется правильность всего процесса проверки. Каждый созданный артефакт должен быть затем хорошо отформатирован и доступен, например. Тензорборд.

Во-первых, в тренировке сохраняются только последние 7 контрольных точек:

# 1). module "model_main_tf2.py", line 105:
with strategy.scope():
  model_lib_v2.train_loop(
    pipeline_config_path=FLAGS.pipeline_config_path,
    model_dir=FLAGS.model_dir,
    train_steps=FLAGS.num_train_steps,
    use_tpu=FLAGS.use_tpu,
    checkpoint_every_n=FLAGS.checkpoint_every_n,
    record_summaries=FLAGS.record_summaries)
# 2). module "model_lib_v2.py", function train_loop(), line 443:
def train_loop(
  pipeline_config_path,
  model_dir,
  config_override=None,
  train_steps=None,
  use_tpu=False,
  save_final_config=False,
  checkpoint_every_n=1000,
  checkpoint_max_to_keep=7,
  record_summaries=True,
  performance_summary_exporter=None,
  num_steps_per_iteration=NUM_STEPS_PER_ITERATION,
  **kwargs):

К сожалению, этот аргумент нельзя изменить извне. Лучше всего добавить checkpoint_max_to_keep=some_big_number к вызову train_loop() в модуле model_main_tf2.py (модуль, используемый для обучения и проверки).

Далее в модуле model_lib_v2.py, функция eval_continuously(), строка 1136:

for latest_checkpoint in tf.train.checkpoints_iterator(
    checkpoint_dir, timeout=timeout, min_interval_secs=wait_interval):
  ...
ckpt.restore(latest_checkpoint).expect_partial()

Учитывая переменную latest_checkpoint, это строка, описывающая полный путь к последнему файлу контрольной точки, например absolute_path/ckpt-33. После определения пути он переходит к проверке, т. е. восстанавливает модель с контрольной точкой, сохраненной на пути, а затем начинает проверку.

Если мы заменим использование tf.train.checkpoints_iterator() каким-нибудь кодом, который перечисляет все контрольные точки, и передаст каждую в тело цикла for, все должно происходить как обычно! Правильность будет сохранена. Вот что я сделал: заменил итератор кодом, выделенным жирным шрифтом. (кроме того, нужны дополнительные библиотеки (regex, glob) и служебная функция (natural_sort))

import regex as re
import glob
def natural_sort(l): 
  convert = lambda text: int(text) if text.isdigit() else text.lower() 
  alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
  return sorted(l, key = alphanum_key)
for latest_checkpoint in natural_sort(list(set(map(lambda n: n[:n.index(".")], glob.glob(f"{checkpoint_dir}/ckpt-*.*"))))):

И последнее, но не менее важное: все вышеперечисленные изменения должны иметь место после клонирования моделей Github Repo и до выполнения !cp object_detection/packages/tf2/setup.py . и !pip install ..

Проверять

Я думаю, что аргумент checkpoint_every_n должен делиться на 100, то есть NUM_STEPS_PER_ITERATION. Причину можно увидеть здесь: после одной итерации Обучение пытается сохранить контрольную точку только в том случае, если только накопленных шагов больше checkpoint_every_n. Делая его делящимся на 100, мы можем легко оценить, сколько контрольных точек будет сгенерировано, учитывая num_train_steps.

Обучение теперь начинается первым. После завершения следует проверка. Все последовательно. В конце, внутри checkpoint_dir, будут папки eval и train, содержащие данные для визуализации с помощью Tensorboard:

tensorboard --logdir=checkpoint_dir

Заключение

Мы узнали, как сделать валидацию настоящим постпроцессом для Tensorflow Object-Detection API. Этот трюк, по крайней мере, полезен в моем случае: простая настройка в CoLab для обучения и проверки выполняется последовательно.

P.s. Если эта статья окажется полезной, рассмотрите возможность подписки на мой Medium. 😋