Хабрахабр

Опыт моделеварения от команды Computer Vision Mail.ru

За несколько лет существования наша команда решила десятки задач компьютерного зрения, и сегодня расскажу вам о том, какие методики мы используем для успешного создания моделей машинного обучения, которые работают на широком спектре задач. Меня зовут Эдуард Тянтов, я руковожу командой Computer Vision в Mail.ru Group. Поделюсь трюками, которые могут ускорить получение модели на всех этапах: постановка задачи, подготовка данных, обучение и развертывание в продакшен.

Computer Vision в Mail.ru

Начну с того, что такое Computer Vision в Mail.ru, и какими проектами мы занимаемся. Мы предоставляем решения в наши продукты, такие как Почта, Облако Mail.ru (приложение для хранения фото и видео), Vision (B2B-решения на основе компьютерного зрения) и другие. Приведу несколько примеров.

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

О нем я сегодня чуть подробнее расскажу. Для Почты мы делали OCR — распознавание текста с картинки.

Например, есть очередь на горнолыжный подъемник, и требуется посчитать, сколько в ней человек. Для В2В-продуктов мы делаем распознавание и подсчет людей в очередях. Там есть несколько касс и соответственно несколько очередей, и мы, используя несколько камер (по одной на каждую из очередей), с помощью модели считаем, сколько людей в очередях и сколько примерно минут в каждой из них стоять. Для начала, чтобы протестировать технологию и поиграться, мы развернули прототип в столовой в офисе. Таким образом, мы можем лучше балансировать очереди в столовой.

Постановка задачи

Начнем с критически важной части любой задачи — ее постановки. Практически любая ML-разработка занимает минимум месяц (это в лучшем случае, когда вы знаете, что надо делать), а в большинстве случаев несколько месяцев. Если неверно или неточно поставить задачу, то велик шанс в конце работы услышать от продакт-менеджера что-то в духе: «Все неправильно. Это не годится. Я хотел другое». Чтобы этого не произошло, нужно предпринимать некие шаги. В чем особенность продуктов на основе ML? В отличие от задачи на разработку сайта, задачу в машинном обучении нельзя формализовать одним только текстом. Более того, как правило, неподготовленному человеку кажется, что и все и так очевидно, и просто требуется сделать все «красиво». А уж какие там мелкие детали, постановщик задачи, может быть, даже не знает, никогда о них не думал и не подумает, пока не увидит финальный продукт и скажет: «Что же вы наделали?»

Проблемы

Давайте на примере поймем, какие могут быть проблемы. Допустим, перед вами стоит задача распознавания лиц. Вы ее получаете, радуетесь и звоните маме: «Ура, интересная задача!» Но можно ли прямо срываться и начинать делать? Если так поступить, то в конце вас могут ожидать сюрпризы:

  • Бывают разные национальности. Например, в датасете не было азиатов или еще кого-то. Ваша модель, соответственно, совсем не умеет их распознавать, а продукту это оказалось надо. Или наоборот, вы потратили лишние три месяца на доработку, а в продукте будут только европеоиды, и делать это было необязательно.
  • Бывают дети. Для таких бездетных отцов, как я, все дети на одно лицо. Я абсолютно солидарен с моделью, когда она всех детей отправляет в один кластер — реально ж непонятно, чем отличаются большинство детей! 😉 Но у людей, у которых есть дети, совершенно другое мнение. Обычно они еще и твои руководители. Или бывают еще забавные ошибки распознавания, когда голова ребенка успешно сравнивается с локтем или головой лысого мужика (true story).
  • Что делать с рисованными персонажами, вообще непонятно. Надо их распознавать или нет?

Такие аспекты задачи очень важно определить в начале. Поэтому с менеджером надо работать и общаться с самого начала «на данных». Нельзя принимать устные объяснения. Надо смотреть именно на данные. Желательно из того же распределения, на котором модель будет работать.

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

Даже если вначале вы хорошо поставите задачу, то дальше по мере разработки модели будут появляться все новые проблемы, новые особенности, которые вы будете узнавать про свои данные. Постановка задачи в ML — это постоянная работа между продакт-менеджером и специалистом по ML. Хорошие руководители всегда транслируют своим ML-командам, что надо брать ответственность на себя и помогать менеджеру ставить задачи. Все это нужно постоянно обсуждать с менеджером.

Машинное обучение — это достаточно новая сфера. Почему так? Как чаще всего люди учатся решать новые задачи? У менеджеров нет (или мало) опыта ведения таких задач. Если вы не хотите, чтобы ваш любимый проект стал ошибкой, то надо вовлекаться и брать ответственность на себя, учить продакт-менеджера грамотно ставить задачу, вырабатывать чек-листы и политики; все это здорово помогает. На ошибках. Все, что я вам сейчас рассказал, я и сам забываю. Я каждый раз себя одергиваю (или меня одергивает кто-то из коллег), когда приходит новая интересная задача, и мы бежим ее делать. Поэтому важно иметь какой-то чек-лист, чтобы себя проверять.

Данные

Данные — это суперважно в ML. Для deep learning, чем больше данных скормишь модели, тем лучше. Синий график показывает, что обычно модели deep learning сильно улучшаются при добавления данных.

А «старые» (классические) алгоритмы с какого-то момента уже не могут улучшиться.

Их размечали люди, которые всегда врут (с). Обычно в ML датасеты грязные. Мы пользуемся такой техникой: берем данные, которые у нас есть, обучаем на них модель, а потом с помощью этой модели прочищаем данные и повторяем цикл заново. Асессоры часто бывают невнимательны и допускают очень много ошибок.

Допустим, мы скачали «ВКонтакте» аватарки пользователей. Давайте подробнее на примере того же самого распознавания лиц. Мы детектируем лица, которые есть на всех 4 изображениях, и прогоняем через модель распознавания лиц. К примеру, у нас есть профиль пользователя с 4 аватарками. Дальше мы выбираем самый большой кластер, предполагая, что аватарки пользователя в основном содержат именно его лицо. Так мы получаем эмбеддинги лиц, с помощью которых можно их «склеивать» похожие лица в группы (кластеризовать). После этого мы можем снова повторить цикл: на прочищенных данных обучить модель и с ее помощью прочистить данные. Соответственно, все остальные лица (являющиеся шумом) мы таким образом можем вычистить. Повторять можно несколько раз.

Это иерархический алгоритм кластеризации, в котором очень удобно задавать пороговое значение для «склейки» похожих объектов (это как раз то, что требуется для прочистки). Практически всегда для подобной кластеризации мы используем алгоритмы CLink. Это важно, так как мы часто учим метрическое пространство этих эмбеддингов. CLink генерирует сферические кластеры. Алгоритм имеет сложность О(n2), что, в принципе, ок.

Генеративный подход позволяет производить огромное количество данных. Иногда данные настолько тяжело достать или разметить, что не остается ничего, как только начать их генерировать. Самый простой пример — это OCR, распознавание текста на изображениях. Но для этого надо что-то программировать. Даже сотню страниц текста асессоры (люди, занимающиеся разметкой) будут размечать крайне долго, а для обучения нужно гораздо больше. Разметка текста для этой задачи дико дорогая и шумная: нужно каждую строчку и каждое слово выделить, подписать текст и так далее. Очевидно, что можно каким-то образом сгенерировать текст и как-то его «пошевелить», чтобы модель на нем училась.

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

Например, товары на полках магазинов. Иногда нам нужны какие-то объекты реального мира. Как вы думаете, левая или правая? Одна их этих картинок автоматически сгенерирована.

Если не присматриваться к мелким деталям, то отличия от реальности не заметить. На самом деле, обе сгенерированы. Делаем мы это с помощью Blender (аналог 3dmax).

У него есть отличный Python API, который позволяет прямо в коде размещать объекты, конфигурировать и рандомизировать процесс и в итоге получить разнообразный датасет. Основное важное преимущество — это то, что он open source.

Это достаточно затратная процедура, но она выдает результат с отличным качеством. Для рендеринга используется ray tracing. Как правило, их надо покупать. Самый главный вопрос: где брать модели для объектов? Понятно, что для продакшена нужно закупать или заказывать у кого-то отрисованные модели. Но если вы бедный студент и хотите с чем-то поэкспериментировать, всегда есть торренты.

Перейдем к обучению. На этом про данные всё.

Metric learning

Цель Metric learning — обучить сеть таким образом, чтобы она похожие объекты переводила в похожие регионы в метрическом пространстве embedding. Приведу снова пример с достопримечательностями, который необычен тем, что в сущности это задача классификации, но на десятки тысяч классов. Казалось бы, зачем здесь metric learning, который, как правило, уместен в задачах типа face recognition? Давайте попробуем разобраться.

Если использовать стандартные лоссы при обучении задачи классификации, например Softmax, то классы в метрическом пространстве хорошо разделятся, но в embedding пространстве точки разных классов могут находится близко друг к другу…

небольшое отличие в исходных данных может изменить результат классификации. Это создает потенциальные ошибки при генерализации, т.к. Для этого применяют различные техники metric learning. Нам бы очень хотелось, чтобы точки были более компактные. Например, Center loss, идея которого крайне простая: мы просто стягиваем точки к обучаемому центру каждого класса, которые по итогу становятся более компактными.

компактность приводит к лучшей обобщающей способности. Center loss программируется буквально в 10 строчек на Python, работает очень быстро, а что самое главное — улучшает качество классификации, т.к.

Angular Softmax

Мы пробовали множество разных методов metric learning, и пришли к выводу, что Angular Softmax приводит к самым лучшим результатам. Среди research-сообщества он также считается state of the art.

Давайте разберем его на примере face recognition. Вот у нас есть два человека. Если воспользоваться стандартным Softmax, то будет проведена разделяющая плоскость между ними — на основе двух векторов весов. Если сделать норму эмбеддингов 1, то точки лягут на окружность, т.е. на сферу в n-мерном случае (картинка справа).

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

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

Все они играются с тем, умножать на m этот угол или прибавлять, или умножать и прибавлять. Есть несколько вариантов Angular Softmax. State-of-the-art — ArcFace.

На самом деле, этот достаточно просто встраивается в пайплайн классификации.

Прогоняем его фотографию через сетку в процессе обучения. Разберем на примере Джека Николсона. В данном случае у фотографии Николсона скор 20, самый большой. Получаем эмбеддинг, прогоняем через линейный слой для классификации и получаем на выходе скоры, которые отражают степень принадлежности к классу. Дальше мы делаем все, как обычно: Softmax + Cross Entropy. Далее по формуле из ArcFace мы снижаем скор с 20 до 13 (делается только для groundtruth класса), усложнив таск для нейросети.

По итогу ArcFace на большей части задач лучше всех прочих методов. Итого, обычный линейный слой заменяется на слой ArcFace, который пишется уже не в 10, а в 20 строчек, но дает отличные результаты и минимум оверхеда на внедрение. Он отлично встраивается в задачи классификации и улучшает качество.

Transfer learning

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

Суть задачи — выдавать по изображению (query) семантически похожие из базы. Мы сделали свой поиск по изображениям.

Логично брать сеть, которая уже училась на большом количестве изображений — на датасетах ImageNet или OpenImages, в которых миллионы картинок, и дотренировывать на наших данных.

После обучения с ArсFace мы получили следующий результат. Мы набрали данных для этой задачи на основе по похожести картинок и кликов пользователей и получили 200к классов.

Т.е. На картинке выше мы видим, что для запрашиваемого пеликана, в выдачу попали еще и воробьи. Самое обидное, что изначальная модель, с которой мы дообучались, знала эти классы и прекрасно их различала. embedding получился семантически верный — это птица, но расово неверный. То есть сеть при дообучении забывает предыдущий таск, иногда даже полностью. Здесь мы видим эффект, который свойственен всем нейросетям, под названием catastrophic forgetting. Это как раз то, что мешает в данной задаче достичь лучшего качества.

Knowledge distillation

Лечится это с помощью техники под названием knowledge distillation, когда одна сеть учит другую и “передает ей свои знания”. Как это выглядит (полный пайплайн обучения на картинке ниже).

Вспомним, что у нас есть сеть, с которой мы претрейнились. У нас уже знакомый пайплайн классификации с Arcface. С помощью BCE мы заставляем сеть выдавать похожее распределение этих скоров. Мы ее заморозили и просто вычисляем ее эмбеддинги на всех фотографиях, на которых мы учим нашу сеть, и получаем скоры классов OpenImages: пеликаны, воробьи, машины, люди и т.д… От исходной обучаемой нейросети отпочковываемся, и учим еще один эмбеддинг под классы OpenImages, который выдает аналогичные скоры. Если правильно сбалансировать градиенты в условной пропорции 50/50, то это позволит оставить всех пеликанов в топе и выкинуть оттуда всех воробьев. Таким образом, с одной стороны мы учим новый таск (в верхней части картинки), но и заставляем сеть не забывать ее корни (в нижней части) — помнить о тех классах, которые она раньше знала.

Это достаточно много. Когда мы это применили, мы получили целый процент в mAP.

Так что если ваша сеть забывает предыдущий таск, то лечите с помощью knowledge distillation — это отлично работает.

Дополнительные головы

Базовая идея очень простая. Снова на примере Face Recognition. У нас в датасете есть набор персон. Но также часто в датасетах есть прочие характеристики лица. Например, сколько лет, какой цвет глаз и т.д. Все это можно добавлять как еще один доп. сигнал: учить отдельные головы на предсказание этих данных. Таким образом, у нас сеть получает больше разнообразного сигнала, и может, как следствие, лучше выучить основной таск.

Еще один пример: детект очередей.

Поэтому мы добавили в сеть к предсказанию bounding box’а человека еще и предсказание bounding box’а головы, и получили прирост в 0,5% к точности (mAP), что прилично. Часто в датасетах с людьми помимо туловища есть отдельная разметка положения головы, что, очевидно, можно использовать. на продакшне дополнительная голова «отключается». А главное — бесплатно с точки зрения производительности, т.к.

OCR

Более сложный и интересный кейс — это OCR, уже упомянутый выше. Стандартный пайплайн такой.

С помощью модели детектирования мы выделяем этот текст. Пусть имеется постер с пингвином, на нем написан текст. Допустим, наша сеть ошибается и вместо «i» в слове penguins предсказывает «l». Дальше мы этот текст подаем на вход модели распознавания, которая выдает распознанный текст. Вопрос в том, как этого избежать — pengulns перевести в penguins? Это на самом деле очень распространенная проблема в OCR, когда сеть путает похожие символы. у него есть знания о структуре языка. Когда человек смотрит на этот пример, ему очевидно, что это ошибка, т.к. Поэтому следует встроить в модель знания о распределении символов и слов в языке.

Это алгоритм сжатия, который вообще был изобретен еще в 90-х не для машинного обучения, но сейчас он очень популярен и используется в deep learning. Мы для этого использовали штуку под названием BPE (byte-pair encoding). Допустим, у нас есть строка «aaabdaaabac», и мы хотим получить для нее BPE. Смысл алгоритма в том, что часто встречающиеся подпоследовательности в тексте заменяются на новые символы. Мы заменяем ее на новый символ «Z», получаем строку «ZabdZabac». Мы находим, что пара символов «аа» — самая частая в нашем слове. Теперь «ZY» — самая частая подпоследовательность, ее мы заменяем на «X», получаем «XdXac». Повторяем итерацию: видим, что ab — самая частая подпоследовательность, заменяем ее на «Y», получаем строку «ZYdZYac». Если мы встречаем слово, в котором очень «странные» (редкие для обучающего корпуса) подпоследовательности, значит, это слово подозрительное. Таким образом, мы кодируем некие статистические зависимости в распределении текста.

aaabdaaabac
ZabdZabac Z=aa
ZYdZYac Y=ab
XdXac X=ZY

Как это всё встраивается в распознавание.

В этом векторе закодирована пространственная информация о символах. Мы выделили слово «penguin», отправили его в сверточную нейросеть, которая выдала пространственный эмбеддинг (вектор фиксированной длины, например 512). Дальше с помощью CTC-Loss мы раскручиваем эти состояния и получаем наше предсказание для всего слова, но с ошибкой: L на месте i. Далее мы используем рекуррентную сеть (UPD: на самом деле, мы уже используем модель Transformer), она выдает некие скрытые состояния (зеленые столбики), в каждом из которых зашито распределение вероятностей — какой по мнению модели символ изображен на конкретной позиции.

Мы хотим уйти от предсказания отдельных символов к словам, поэтому мы делаем ответвление от состояний, в которых зашита информация о символах, и натравливаем на них еще одну рекуррентную сеть; она и предсказывает BPE. Теперь интеграция BPE в пайплайн. Это значительно отличается от правильной последовательности для слова penguins, то есть «pen», «gu», «ins». В случае с описанной выше ошибкой получается 3 BPE: «peng», «ul», «ns». Это гораздо бóльший сигнал для сети, что что-то пошло не так, и надо исправить свое поведение. Если посмотреть на это с точки зрения обучения модели, то при посимвольном предсказании сеть ошиблась только в одной букве из восьми (ошибка 12,5 %); а в терминах BPE она ошиблась в 100%, неверно предсказав все 3 BPE. Эта дополнительная голова при инференсе убирается, выполнив свою роль при обучении. Когда мы это внедрили, то смогли исправить ошибки подобного рода и уменьшили Word Error Rate на 0,25% — это много.

FP16

Последнее, что я хотел сказать про обучение, — это FP16. Так исторически сложилось, что сети обучались на GPU в единичной точности, то есть FP32. Но это избыточно, в особенности для инференса, где хватает и половинной точности (FP16) без потери качества. Однако при обучении это не так.

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

А правая часть, в рабочем рейнже FP16, вообще никак не используется. То есть мы будем обнулять очень большое количество градиентов. В итоге, если обучать в лоб на FP16, то процесс скорее всего разойдется (серый график на картинке ниже).

Mixed precision реализует два трюка. Если обучать, используя технику mixed precision, то результат получается практически идентичный FP32.

Таким образом, мы скейлим все градиенты, и перемещаем их значения от нуля в сторону рабочего рейнджа FP16. Первый: мы просто умножаем loss на константу, например, 128. Второй: мы храним мастер-версию весов FP32, которая используется только для обновления, а в операциях вычисления forward и backward pass сетей используется только FP16.

NVIDIA сделала для него специальную сборку с так называемым APEX, который реализует описанную выше логику. Мы используем Pytorch для обучения сетей. Первый — Automatic mixed precision. У него есть два режима. По коду ниже можно убедиться на сколько просто его использовать.

Что делает AMP? В код обучения добавляется буквально две строчки, которые оборачивают loss и процедуру инициализации модели и оптимизаторов. Что конкретно происходит? Он monkey patch’ит все функции. Тогда он ее заменяет на свою, которая сначала делает cast к FP16, а потом уже выполняет операцию свертки. Например, он видит, что есть функция свертки, а она получает профит от FP16. Для каких-то не делает, т.к. Так AMP делает для всех функций, которые могут использоваться в сети. Для большинства задач этот метод подойдет. не будет ускорения.

Подходит в случае, если вы хотите сами задавать какие слои будут в FP16, а какие в FP32. Второй вариант: FP16 optimizer для любителей полного контроля. Он не заводится с полпинка (по крайней мере нам пришлось попотеть, чтобы его завести). Но в нем есть ряд ограничений и сложностей. Также FP_optimizer работает только с Adam, да и то только с тем Adam, который есть в APEX (да, у них свой Adam в репозитории, который имеет совершенно другой интерфейс, чем пайторчевый).

Мы провели сравнение при обучении на картах Tesla T4.

При обучении мы видим, что фреймворк Apex дает 20 % ускорения относительно просто FP16. На Inference у нас ожидаемое ускорение в два раза. Халява. В итоге мы получаем тренировку, которая в два раза быстрее и потребляет в 2 раза меньше памяти, а качество обучения никак не страдает.

Inference

Т.к. мы используем PyTorch, то стоит остро вопрос, как же его деплоить в продакшен.

Есть 3 варианта, как его это делать (и все из них мы использовали(-ем).

  • ONNX -> Caffe2
  • ONNX -> TensorRT
  • И с недавнего времени Pytorch C++

Давайте разберем каждый из них.

ONNX и Caffe2

1,5 года назад появился ONNX. Это специальный фреймворк для конвертации моделей между различными фреймворками. А Caffe2 — фреймворк, смежный с Pytorch, оба разрабатывают в Facebook. Исторически Pytorch развивается гораздо быстрее, чем Caffe2. Caffe2 отстает по фичам от Pytorch, поэтому не каждую модель, которую вы обучили в Pytorch, можно конвертнуть в Caffe2. Часто приходится переучивать с другими слоями. К примеру, в Caffe2 нет такой стандартной операции как upsampling с nearest neighbor interpolation. В итоге мы пришли к тому, что под каждую модель завели специальный docker image, в котором мы прибиваем версии фреймворков гвоздями во избежания расхождений при их будущих обновлений, чтобы когда в очередной раз обновится какая-нибудь из версий, мы не тратили время на их совместимость. Все это не очень удобно и удлиняет процесс деплоя.

Tensor RT

Есть еще Tensor RT, фреймворк от NVIDIA, который оптимизирует архитектуру сети для ускорения инференса. Мы произвели свои замеры (на карте Tesla T4).

Если посмотреть на графики, то можно увидеть, что переход от FP32 к FP16 дает 2x ускорение на Pytorch, а TensorRT при этом дает аж 4x. Очень существенная разница. Мы это тестировали на Tesla T4, у которой есть тензорные ядра, которые как раз очень хорошо утилизируют вычисления FP16, что очевидно отличное используется в TensorRT. Поэтому, если есть высоконагруженная модель, работающая на десятках видеокартах, то есть все мотиваторы попробовать Tensor RT.

К сожалению, каждый раз, когда мы используем этот фреймворк, то приходится немного пострадать, чтобы конвертнуть модель. Однако при работе с TensorRT еще больше боли, чем в Caffe2: в нем еще меньше поддерживается слоев. Но для высоконагруженных моделей приходиться это делать 😉 Замечу, что на картах без тензорных ядер такого массивного прироста не наблюдается.

Pytorch C++

И последнее — Pytorch C++. Полгода назад разработчики Pytorch осознали всю боль людей, которые используют их фреймворк, и выпустили TorchScript tutorial, который позволяет трейсить и сериализовать Python модель в статический граф без лишних телодвижений (JIT). Она вышла в декабре 2018, мы сразу же начали ей пользоваться, сразу же словили несколько багов производительности и ждали несколько месяцев фикса от Чинталы. Но сейчас это достаточно стабильная технология, и мы ее активно используем для всех моделей. Единственное, не хватает документации, которая активно дополняется. Конечно, всегда можно посмотреть по *.h-файлам, но людям, не знающим плюсы, это тяжело. Но зато там действительно идентичная работа с Python. В C++ запускается от-jit’енный код на минимальном интерпретаторе Python’а, что практически гарантирует идентичность С++ с Python.

Выводы

  • Постановка задачи — это суперважно. С продакт-менеджерами общаться нужно обязательно на данных. Перед тем, как начать делать задачу, желательно иметь готовый тестсет, на котором замеряем финальные метрики перед стадией внедрения.
  • Сами данные мы чистим с помощью кластеризации. Получаем модель на исходных данных, чистим данные с помощью кластеризации CLink и повторяем процесс до сходимости.
  • Metric learning: помогает даже классификации. State-of-the-art — ArcFace, который легко интегрировать в процесс обучения.
  • Если вы делаете transfer learning с предобученной сети, то, чтобы сеть не забывала старый таск, используйте knowledge distillation.
  • Также полезно использовать несколько голов сети, которые будут утилизировать разные сигналы из данных, для улучшения основного таска.
  • Для FP16 надо использовать сборки Apex от NVIDIA, Pytorch.
  • И на инференсе удобно использовать Pytorch C++.
Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть