«Спорим, ты не знаешь, что такое дропаут?» Смотрим глубже на базовые техники в ML

Привет! Меня зовут Алексей Чаплыгин, я Chief Information Officer в Reface, руковожу техническим департаментом, в том числе ML-отделом. До этого запускал с нуля отдел Data Science и ML в компании PVH в Амстердаме. С 2012 года живу в Нидерландах. По образованию я физик, поэтому люблю решать разные задачи, будь то AI, бизнес или стратегия.

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

Скажу ужасную для ресерчера вещь: я никогда не читаю пейперы!* Сначала стараюсь дойти до решения сам и понять каждую деталь до последнего бита: как работает та или иная модель, из каких операций она состоит, какой в них математический и функциональный смысл, как они будут имплементированы, что происходит физически на уровне «железа». И эта глубина позволяет понять суть, а значит, оперировать не набором кубиков лего, а понимать модели на молекулярном уровне. Ведь даже из базовых понятий при их глубоком понимании можно получить огромное количество инсайтов. Только в этом случае становится возможным делать то, чего никто еще прежде не делал.

* На самом деле, конечно, я читаю пейперы. Но только после того, как разобрался в проблеме и сам придумал решение. Тогда статьи позволяют провалидировать подход и подсказывают новые пути, а не загоняют в рамки чужих идей. Именно в такой исследовательской парадигме мы стараемся растить инженеров в Reface.

Почему я перешел из разработки в ML

Лет 8 я занимался девелопментом разного уровня, начиная с низкоуровнего Си (без всяких плюсОв) и заканчивая ERP-системами. В какой-то момент кодить несколько наскучило, так как прикладное программирование — решение по сути решаемых задач. Это как решать школьные примеры, когда знаешь, что правильный ответ точно есть и задача сводится только к тому, чтобы его найти и записать. С опытом «найти» становится все проще, а «записать» все скучнее.

Работа с ERP-системами требует постоянной работы с данными, поэтому постепенно к своему инженерному опыту я начал добавлять Data Science, параллельно освежил математику (благо образование в области теоретической физики позволяло), а в свободное время уходил с головой в ML. Момент, когда я оказался полностью в ML, прошел незаметно даже для меня, так как 7 лет назад уже был хайп вокруг AI, специалистов не хватало, поэтому работодатели были только рады моему перевоплощению.

Волей случая я попал в компанию PVH (Tommy Hilfiger, Calvin Klein и другие бренды) с HQ в Амстердаме, где с нуля поднял отдел DS и ML. В целом динамики хватало, но все равно казалось, что в прикладном ML я работаю на 5% от расчетной мощности. Корпоративная медлительность, узкий спектр задач — не то, что драйвит ресерчера, поэтому я решил создать что-то свое и параллельно с основной работой два года самостоятельно занимался АI-проектом виртуальных примерочных Beyond Belief. Если бы не поддержка семьи и жены, наверное, я бы в какой-то момент все бросил, но в итоге сделал MVP продукта, который был по сути Full Body Swap, записал проморолик, выложил на YouTube, и через пару дней на меня отовсюду посыпались предложения о сотрудничестве. Первым же, кто постучался в Facebook, был Олесь Петрив, с которым мы созвонились буквально через пару дней, и я сразу понял, что именно с Reface нам по пути.

Как создавать новое с помощью ML

Сегодня я остановлюсь детальнее на подходе, который позволил мне в одиночку создать Beyond Belief, при том что до сих пор некоторые из задач остаются нерешенными и нет ни одного пейпера, гита или продукта, который бы описывал пайплайн технологии Full Body Swap.

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

Например, дропаут. Что это на самом деле?

Я часто задаю этот вопрос кандидатам на интервью сразу же после «Что такое производная?» (кстати, на вопросе про производную в Европе отлетают 90% кандидатов, в то время как у ребят из СНГ подобное спрашивать иногда даже стыдно, университетская восточноевропейская матподготовка и правда на порядок сильнее узкопрактической европейской). И почти всегда ответ формально правильный, ровно как написано в книжках, но при этом показывающий, что собеседник не задумывался о том, как именно работает подобная техника.

Что не так с книжными определениями

Я взял определения дропаута из «Википедии», гугла и «Медиума».

  • «Исключение» (дропаут) нейрона означает, что при любых входных данных или параметрах он возвращает 0... (дальше можно не продолжать...)
  • Термин «dropout» («выбивание», «выбрасывание») характеризует исключение определённого процента (например, 30%) случайных нейронов (находящихся как в скрытых, так и видимых слоях) на разных итерациях (эпохах) во время обучения нейронной сети.
  • ... dropout refers to ignoring units (i.e. neurons) during the training phase of certain set of neurons which is chosen at random. By «ignoring», I mean these units are not considered during a particular forward or backward pass.

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

Определение сути дропаута

Я не фанат овертеории и нагромождения формул, но подсолить текст легким формализмом иногда помогает:

Если сильно упростить, то нейросеть — функция, которая получает какой-то тензор на вход, совершает с ним какие-то математические операции и в результате выдает опять-таки тензор — выход сети.

output = f(x), f — функция, определяющая нейросеть.

x — входной тензор.

Сети у нас, как качественный французский круассан, весьма слоистые, поэтому f(x) можно представить как набор функций g, применяемых в целом последовательно. И тогда какой-то слой можно представить как:

layerN = g(layerN-1), где g — функция, определяющая один слой;

layerN — тензор из некого латентного пространства, возникающий по ходу преобразований.

Да, очень желательно, чтобы и f, и g обладали рядом известных приятных свойств, но то, что это просто какие-то математические преобразования, сути не меняет.

Тогда Dropout — это:

  1. Определим тензор А, в котором есть значения строго 0 или 1, где выбор между 0 или 1 происходит согласно равномерному распределению с вероятностью p (скажем, вероятность p определяет выбор значения 1).
  2. Договоримся по-джентльменски, что размерность А совпадает с размерностью layerN-1.
  3. layerN = g(A · layerN-1 / p), где · — dot product.

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

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

К тому же становится понятно, почему работа дропаута как регулизатора — побочный эффект, в то время как, по сути, это техника создания ансамбля моделей. Матрица А состоит строго из случайного набора нулей и единиц, после умножения на нее зануляются некоторые члены функции g, а значит и f. Но зануление равнозначно отсутствию, что меняет вид самой g и f. То есть, применяя дропаут, мы обучаем очень много, пусть структурно похожих, но все же разных моделей f.

Как поможет глубокое понимания дропаута на примере

«Пример курильщика» — это картинка из интернета, которая, как мне кажется, не дает полного понимания, как работает дропаут и что с ним делать. Как он определен? Какие операции стоят за кружочками и стрелочками?

«Пример здорового человека». Справа — матрица А, слева layerN-1, на выходе — layerN после применения dropout. Да вот и всё... И тут можно начать задавать вопросы: почему А состоит только из нулей и единиц? Почему заполняется ими согласно юниформному распределению? Можем ли мы вместо нулей и единиц использовать другие значения? Да, можем. Или выбрать другое распределение — это тоже можем. Такое понимание делает инструмент гибким.

Есть ли в этом практический смысл? Конечно. Например, в сверточных сетях dropout из коробки может не всегда быть эффективен, слишком высока избыточность информации. Можно начать выбирать 0/1 синхронно по глубине, если хочется равномерности распределения информации по всем каналам. Или синхронизировать выбор по пространственным размерностям, чтобы ослеплять сеть локально, если хотим, чтобы сеть ориентировалась на информацию из всего изображения в целом, а не только из какой-то его локальной области.

Для примера: классификатор эмоций, который будет с удовольствием фититься на зубы, ассоциируя их с улыбкой. Вряд ли в датасете у вас будет много злобно скалящихся лиц, чтобы сеть перестала падать в тривиальное решение «что-то белое где-то по центру изображения внутри чего-то розово-красного = улыбка» и начала обращать внимание на мимику в целом. Spatial dropout может помочь заставить сеть смотреть на общую картину, даже при ограниченном датасете.

Вывод

Чтобы стать ML-художником исследователем, бессмысленно зубрить пейперы, молиться на мнения экспертов и коллекционировать «бест практисес». Не надо ударяться в оверформализм с теоремами и формулами, которые только закапывают понимание сути. Серьезно, когда я открываю пейперы, нашпигованные греческими символами, начиная с заголовка и до списка литературы, я чувствую себя дурачком, хотя зачастую за всеми математическими баррикадами скрывается банальщина. Если вы сможете объяснить самые сложные ходы на пальцах — значит вы достигли глубокого понимания.

В молодости мой отец программировал под БЭСМ-6, когда в машинный зал размером со школьную столовую необходимо было записываться за неделю, печатать программу на перфокартах, когда вместо экрана был принтер и рулоны бумаги, когда малейшая ошибка откладывала получение результата на дни до следующей попытки. Эта ситуация мне напоминает современный ML: да, теперь тренировка сетей стала возможна, но тяжелые модели все еще необходимо тренировать днями. Возможно, через 15 лет время перфокарточного ML пройдет и ML станет не сложнее прикладного программирования на высокоуровневых языках, но сегодня цена ошибки все еще высока. А значит, проектировать действительно сложные модели надо обдуманно, в голове: на пробежке, во время похода в магазин, перед сном. Для этого необходимо развивать «интуицию», что на самом деле не более, чем опыт и глубокое понимание деталей.

Похожие статьи:
Стаття написана у співавторстві з Ярославом Клочником та Андрієм Забавським. Привіт, я Юлія Матушкевич, Talent Success Lead (TSL) у львівському...
Проблема — сложный вопрос, задача, требующие разрешения, исследования. © Толковый словарь Ожегова Итак, само определение проблемы...
В сфере IT я уже более десяти лет, пять из которых работаю инженером по обеспечению качества в компании DataArt. Училась на факультете...
Літо — гарна пора, щоб збиратись разом і відпочивати. Торік через каратин багато хто ще побоювався проводити час разом в офлайні....
Важным событием прошедших дней стала конференция для разработчиков Microsoft Build 2020. Несмотря на эпидемию COVID-19, Microsoft провела свое...
Яндекс.Метрика