Цель этого поста - поделиться некоторыми мыслями, которые мы собрали о том, как проводить хакатон компьютерного зрения, основываясь на нашем опыте соревнования Пьера Фабра, проведенного в Довиле 24 и 25 ноября 2017 года.

Этот пост не является руководством по ConvNets или Keras. Мы не утверждаем, что то, что мы пробовали или то, что мы здесь рассказываем, является единственным путем, которым нужно следовать, мы просто хотим поделиться. Просто поделиться. Это все ! И мы будем рады вашим отзывам.

Вот различные (довольно независимые) темы, о которых мы говорим в этом посте:

  • Подготовьте свою среду
  • Код, развертывание, мониторинг
  • О Keras 2.0 и графических процессорах
  • «План битвы ConvNets»
  • Рентабельность инвестиций и увеличение изображений
  • Кризисное управление
  • Последний совет: получайте удовольствие!

Подготовьте свою среду

Microsoft была одним из партнеров хакатона, в котором мы участвовали, поэтому мы решили разместить нашу среду в Microsoft Azure. Было бы неплохо иметь в вашей команде кого-то, у кого есть хотя бы небольшой опыт работы в облачных средах с виртуальными машинами, графическими процессорами и дисками. Просто выберите один из Amazon Web Service, Google Cloud Platform, Microsoft Azure или других, и вы обязательно сможете запускать виртуальные машины с чипами GPU, оптимизированными для вычислений (Nvidia Tesla K80, P100…) *.

Со своей стороны, вот что мы использовали в Azure:

  • 1 NC-6 (1 GPU K80, 6 виртуальных ЦП, 55 Гб оперативной памяти)
  • 2 NC-12 (2 GPU K80, 12 vCPU, 110 Гб RAM)
  • 1 диск для хранения файлов объемом 500 ГБ

Первое, что нужно сделать, - это поместить в репозиторий весь сценарий, который вы используете для подготовки виртуальных машин. Это позволило нам создать наши новые виртуальные машины и легко сделать их готовыми к использованию. Например, если вы хотите подключить и смонтировать диск для хранения файлов на виртуальной машине Linux в Microsoft Azure, вам нужно будет запустить этот сценарий:

Я не думаю, что для такой короткой задачи, как эта, было бы неплохо попытаться установить все пакеты с нуля, драйверы для вашего графического процессора, вашей среды и т. Д. Облачные платформы, такие как Azure, имеют образы с установленным вашим любимым фреймворком. для уверенности. В AWS ищите AMI на торговой площадке (т.е. этот http://vict0rsch.github.io/2017/02/22/p2-aws-tensorflow-1/). В Azure ищите образы виртуальных машин, такие как Виртуальная машина глубокого обучения, где вы найдете TensorFlow, Keras2, Caffe2… Это тот, который мы использовали.

Еще два момента, которыми мы хотели бы поделиться с вами по этой теме:

  • Дайте вашим различным виртуальным машинам (забавные) имена. Это, во-первых, позволит вам избежать несоответствия того, что работает на какой виртуальной машине, потому что простое использование IP-адресов или VM1, VM2 в качестве имен действительно сбивает с толку. Во-вторых, вы увидите, что во время испытания будет легче справиться с напряженным периодом, если вы скажете своему коллеге «CholletCacao мертв», а не «vm-gpu-1 не работает»!
  • Помните о стоимости ваших виртуальных машин. Все мы знаем, что графические процессоры недешевы. При запуске двух, трех и даже более экземпляров ваш счет может быстро взорваться. Чтобы решить эту проблему, попробуйте запускать виртуальные машины только во время вычислений. Если задача достаточно короткая - как задача Пьера Фабра - у вас не будет времени подумать, все ваши виртуальные машины должны будут работать без остановки с различными задачами.

Разверните правильно и быстро

Вы должны проводить обучение разных моделей (параллельно или нет), не теряя времени. Потому что для схождения ResNet50 или Inceptionv3 требуется время. Вот почему мы постарались подготовить несколько сценариев развертывания для разумного обновления кода на серверах. И мы попытались построить наш репозиторий для запуска той или иной модели, просто указав аргументы, которые относятся к файлам конфигурации, в которых определены детали модели.

Собственно, это была теория. Первая точка пошла не так, как ожидалось. К сожалению, нехватка времени заставила нас очень плохо справиться с этой стратегией развертывания. Во-первых, мы никогда не согласовывали какой-либо процесс DevOps для автоматического развертывания определенной ветки на виртуальных машинах. Мы просто подключались к машинам через ssh, извлекали код из удаленного репозитория и запускали оттуда наше приложение. А во-вторых, мы немного испортили все, изменив ветку непосредственно на экземплярах или сделав быстрые исправления с помощью старого доброго vim.

По нашему мнению, если бы нам пришлось начать с этого соревнования, мы бы запретили выпуск кода на виртуальных машинах (мы знаем, что сейчас это звучит очевидным образом, но мы можем заверить вас, что очевидность кажется совершенно иной, когда соревнование заканчивается через 4 часа, а у вас нет » t спал последние 20 часов). И мы могли бы подготовить несколько простых сценариев для загрузки и извлечения машин, а затем начать обучение на экране (полезно для последующего мониторинга).

Что касается второго пункта, мы подготовили наш код как можно более модульный, чтобы легко запустить один VGG с этими предварительно обученными весами на BigHinton, а через секунду запустить прогноз Inception на CholletCacao.

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

А затем, например, чтобы запустить обучение с архитектурой VGG, инициализированной с некоторыми весами, сброшенными в файл, нам просто нужно выполнить команду:

python main.py train vgg /sharedfiles/vgg_pretrained.h5

Следите за своими моделями

Чтобы управлять своим временем и иметь возможность принимать решения, такие как остановка фазы обучения одной модели, вам необходимо контролировать свои модели. И если вы используете Tensorflow (либо изначально, либо в бэкэнде Keras), вам действительно следует использовать Tensorboard, чтобы видеть, что происходит во время фазы обучения.

Как использовать это с Керасом? Просто добавьте функцию обратного вызова, которая будет записывать журналы в определенный каталог, как вы можете видеть здесь:

А затем, например, на экране вы выполняете команду tensorboard, указав каталог журнала, который вы установили чуть выше.

tensorboard --logdir /tmp/tensorflow

Если ваша виртуальная машина имеет правильные права на входящие / исходящие порты и имеет работающий сервер, такой как nginx или apache, вы обычно сможете увидеть:

Весь код доступен в нашем репозитории GitHub и может стать интересной отправной точкой, если вы регистрируетесь в онлайн-соревновании или хотите поиграть с набором данных ISIC.

Знай свой фреймворк

Как мы объясняли ранее, мы развернули виртуальную машину глубокого обучения (DLVM) на наших различных NC-6 и NC-12. В нашей команде у нас был некоторый опыт работы с Tensorflow 1.0, Keras 1.6, Caffe 1, поэтому выбор фреймворка был больше связан с требованиями, представленными в нашем плане битвы. Как вы увидите в деталях нашего боевого плана, мы хотели использовать хорошо известные сверточные нейронные сети, такие как ResNet или Inception, и инициализировать их весами, вычисленными при обучении ImageNet. Использование причудливых настраиваемых нейронных сетей не входило в наши планы, поэтому мы решили использовать Keras поверх серверной части Tensorflow.

Вы можете видеть, что на DLVM Keras установлен в версии 2. Это нас не беспокоило вначале, мы были убеждены, что наш опыт работы с Keras 1.6 будет достаточно надежным, чтобы освоить версию 2. Это ошибка, которую мы заплатили наличными позже. во время вызова.

Генератор поставщиков данных Keras 2.0

То, что мы реализовали в первую очередь для поставщика данных наших нейронных сетей, было основано на ImageDataGenerator из Keras, роль которого заключалась в переходе в каталог, структурированный с одним подкаталогом по классам (здесь злокачественный и доброкачественный ), считывать изображения пакетами, увеличивать количество изображений, преобразовывая их с помощью классического преобразования изображений (поворот, переворот, масштабирование и т. д.), и, наконец, передавать эти пакеты в сеть.

Когда мы начали наши первые тренинги, мы были удивлены тем, сколько времени ушло на прохождение разных эпох наших моделей. Проблема заключалась в том, что графические процессоры просто загружали данные в память, но не выполняли параллельные вычисления. Взгляд на вывод nvidia-smi дал нам ключ к разгадке:

Мы знали, что проблема возникла не из-за установки библиотек или драйверов, поскольку Keras 2.0 правильно использовал графические процессоры, когда мы пытались запустить код репозитория CapsNet для Keras.

Сначала мы попытались реализовать собственный генератор данных, но проблема все еще существовала. Поэтому мы решили загрузить в память как можно больше изображений, прежде чем загружать их в сеть по пакету. Вы можете видеть в коде, который мы использовали lib multiprocessing, чтобы не терять слишком много времени на этапе загрузки нашего процесса.

Изображения, которые мы загружали в память, уже были дополнены нашим методом обработки изображений (см. Ниже), поэтому мы не могли загрузить все 50 КБ изображений за один раз. Вот почему нам пришлось обучить сеть только с некоторыми видами преобразованных изображений, сбросить веса, очистить память, а затем перезагрузить некоторые другие виды преобразованных изображений и обучить сеть, инициализировав ее с помощью сброшенных весов, чтобы продолжить обучение с того места, где мы остановились. .

Работа с несколькими графическими процессорами с помощью Keras 2.0 и Tensorflow

Еще одна проблема, с которой мы должны были столкнуться раньше: обработка нескольких графических процессоров. Во время соревнований мы выяснили, что Keras 2.0 не обрабатывает два графических процессора самостоятельно на наших виртуальных машинах. Для этого вам нужно подготовить трюк, чтобы заставить оба GPU 1 и 2 выполнять вычислительные задачи.

Как видите, вам нужно скопировать сеть в каждый графический процессор, нарезать пакеты, чтобы транслировать их в разные графические процессоры, и в конце объединить выходы на процессоре. Не так уж и очевидно, не правда ли? Но нам удалось использовать эту расширенную версию нашего кода для последних тренировок, и это сэкономило нам несколько драгоценных минут.

Подготовьте свой план битвы

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

Со своей стороны, мы достигли этой архитектуры в конце:

Это недалеко от того, что мы планировали: использовать еще 2 или 3 разных свертки, прежде чем применять подход к объединению с классификатором xgboost или просто методом взвешенного среднего.

На создание этой цели нас вдохновили два источника: видео и статья Бретта Купреля и разработчиков Google о классификации изображений рака кожи и различных методах, объясненных победителями конкурсов изображений Kaggle в блоге Kaggle:

Соревнование« Собаки против кошек на игровой площадке Redux, интервью победителя: Боян Тунгуз
Собаки против кошек . Соревнование на игровой площадке Redux: Kernels Edition возродило одно из наших любимых изображений для развлечения… blog.kaggle.com»

Мы также решили добавить два полностью связанных слоя поверх наших сетей, чтобы повысить уровень абстракции, не теряя знаний, присутствующих на предыдущих уровнях обучения в ImageNet, путем их размораживания. Это позволило нам сделать переобучаемым только последний полностью связанный слой каждой сети и при этом иметь модели, которые подходят для этой действительно конкретной задачи классификации меланомы.

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

Поскольку нам приходилось справляться с различными кризисами GPU, нам не удалось обучить столько моделей, сколько ожидалось. Мы предпочли сосредоточиться на ResNet50 и InceptionV3, пытаясь оптимизировать различные параметры, которые у нас были (количество настраиваемых слоев, количество слоев для переобучения, форма наших слоев ...).

Наконец, что лучше всего сработало для метода ансамбля, так это применение средневзвешенного значения к выходным данным различных слоев softmax (с весом 0,7 в ResNet). Мы также пытались передать выходные данные полностью подключенных слоев в качестве входных данных в лес xgboost, но в результате в нашем проверочном тесте точность была ниже. Это может быть связано с тем, что мы, наконец, не успели оптимизировать гиперпараметры xgboost и поэтому использовали только те, которые были по умолчанию. Если бы я сделал несколько шагов назад, я думаю, это не сильно повлияло бы на уровень точности нашей модели.

У нас могла быть более точная модель, добавив больше сетей к нашему «ансамблевому» подходу или потратив больше времени на визуальную предварительную обработку изображений.

Умная обработка изображений

Всякая архитектура глубокого обучения и алгоритмы машинного обучения бессмысленны, если ваши данные - дерьмо. Как мы обсуждали ранее, архитектуры свертков являются наиболее эффективными и используются при обработке и классификации изображений. После быстрого просмотра нашего набора данных изображений мы быстро увидели, что изображения не были равны с точки зрения положения (например, ROI неравных размеров), формы (например, объект в круге с черными углами из-за используемого устройства), окклюзии (например, маркеры) , лобковые волосы,…) или даже цвета (например, синий свет из-за вспышки). Еще одним серьезным ограничением было разнообразие представленных размеров изображений и возможные проблемы, связанные с единообразным изменением размера.

Мы решили предварительно обработать наши изображения с учетом этих условий:

  • Высокая контрастность (наименьшее значение 0, наибольшее 1)
  • Цветовые каналы (красный, зеленый, синий) нормализованные (среднее значение = 0 и стандартное значение = 1 для каждого канала)
  • Выделите только интересующий регион, удалив другие факторы (кожа, маркеры и т. Д.)

Увеличение контрастности и нормализацию цветовых каналов можно легко выполнить с помощью манипуляций с матрицами и значениями. Из-за нехватки времени мы решили использовать простой, но эффективный метод для извлечения рентабельности инвестиций.

  1. Изменение размера изображений, обрезка для сохранения соотношения сторон и фиксированный размер изображения 500x500
  2. Создайте макет изображения, отделяющий самую большую интересную область от остальных, просто размыв изображения, чтобы удалить мелкие детали, и примените порог 0,5.
  3. Выделение рамки вокруг маски и использование ее в качестве информации для обрезки

В итоге мы получили довольно крутую рентабельность инвестиций, изображения были квадратными и, возможно, разных размеров. Мы допустили небольшую деформацию входного конвейера Keras, поскольку форма не была полностью различима при классификации злокачественных новообразований.

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

Мы твердо уверены, что тщательная обработка и отбор изображений из набора данных сыграли важную роль в исходе конкурса.

С другой стороны, предварительная обработка изображений была первым шагом к повышению качества изображения, но грубый выбор уменьшил бы наш набор данных и, следовательно, уменьшил бы обобщение нашей модели для классификации. В CNN используются классические методы увеличения данных, и мы решили провести более глубокое исследование того, как это было применено к конкретной классификации рака кожи. Мы решили выполнить аналогичную процедуру, описанную в https://arxiv.org/pdf/1702.07025.pdf, но только для геометрического увеличения, вместо того, чтобы воспроизводить ее на Keras.

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

Кризисное управление

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

Такие вещи, как паника, разочарование и потеря времени, начинают появляться вместе с непредвиденными событиями, и необходимо задать некоторые ключевые вопросы, прежде чем тратить на это слишком много времени:

  • Обязательны ли эти функции к нашей проблеме?
  • Видим ли мы какое-либо решение, которое может быстро решить наши проблемы?
  • Каковы другие наши цели?
  • Есть ли другая возможность, даже если она будет проще и хуже по результатам?
  • Можно ли его пока отложить?

Чтобы не закончиться без правильного решения и справиться с растущей усталостью, мы решили следовать следующему контрольному списку:

  • Отложите все, что не было обязательным
  • Определите ограничение по времени, чтобы исправить проблему
  • В то же время ищите возможный план резервного копирования

Мы столкнулись с серьезной проблемой, которой нельзя было избежать, и другой незначительной проблемой, которая, если бы она была решена, могла бы принести нам спасение:

  • Графические процессоры не использовались во время обучения и тестирования.
  • Невозможность правильно использовать несколько графических процессоров и в конце сохранить нашу обученную модель.

Наш резервный план для первой проблемы заключался в полном повторном внедрении Caffe, что было хорошо известно одному из наших товарищей по команде. Это было бы кошмаром, и это принесло нам прилив мотивации.

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

Чтобы решить эти проблемы, потребовалось время, большие усилия и несколько тестов. Эта потеря повлияла на наш общий план попробовать больше архитектур и добавить некоторые функции, которые могли бы улучшить нашу оценку. Однако, в отличие от многих команд, мы пришли к одному из лучших решений.

Возможность сделать шаг назад, когда это необходимо, быть организованной и принять решение - главное преимущество такого ограниченного по времени мероприятия, как хакатон. Мы поняли, что наличие окончательной рабочей модели более важно, чем наличие каких-то наполовину убойных функций, но без каких-либо функций в конечном итоге.

Получайте удовольствие и делитесь

Хакатоны утомляют и вызывают стресс. Так что, если вы приедете на хакатоны с единственной целью написать код, код, код, вы не получите в полной мере удовольствия от подобных мероприятий.

Хакатоны собирают множество умных и вдохновляющих участников, готовых не спать всю ночь, чтобы решить проблему. Хакатоны собирают менеджеров из компаний, которые приходят поделиться с вами данными и опытом, чтобы их компании пошли дальше. Вы не можете прийти и проигнорировать это. Не стесняйтесь делиться с окружающими (даже если они будут вашими конкурентами в течение нескольких часов, впоследствии они могут стать коллегами или друзьями!).

Не относитесь ко всему серьезно, большая часть того, что вы будете реализовывать на хакатонах, не будет использоваться как есть, даже если вы выиграете. Таким образом, вы определенно можете позволить себе называть свои серверы забавными именами (BigHinton, FatMostafa & CholletCacaco для нас…), ваш командный проект с именем, которое запомнят члены жюри и т. Д. Но оставайтесь профессионалом в своем коде, это ядро ​​вашего продукт.

Мы не выиграли это последнее соревнование (на несколько сотых чертовых average_precision_score), но мы многому научились, познакомились с множеством интересных людей и отлично повеселились! Мы с нетерпением ждем следующего хакатона Data Science Hackathon и будем рады видеть вас там!

LES AUTEURS

Особая благодарность Джули, Томасу, Эдвину и Джей Би за их рецензии на пост.

(*) Вначале мы планировали использовать AWS, но обнаружили, что нам нужно запросить расширение квоты, чтобы запустить несколько больших экземпляров g2. *. Квота, которую мы получили через 2 дня после окончания испытания. Если вы используете учетную запись с оплатой по мере использования в Azure, вам также потребуется запросить увеличение квоты для запуска более одной виртуальной машины NC6 (экземпляр с 1 K80 и 6 виртуальными ЦП). Мы получили положительный ответ на этот запрос в течение 24 часов.