Числа Муаммара. Как я проходил летнюю стажировку в Яндексе

fffa12ef9a874b6694426a4939407aed.jpgЛето 2015 года. Сессия успешно сдана. Нормальный человек, наверное, скажет: «Ура! Свобода! Целый день буду играть в футбол и слетаю на море в Турцию». Но только не настоящий исследователь с пытливым умом. Я решил, что в любом случае буду работать над каким-нибудь собственным проектом… Но время непродуктивно со свистом неслось вперед. И тут мне в голову пришла светлая мысль:, а почему бы не пойти на стажировку в Яндекс? Наверняка у них есть куча интересных исследовательских задач, к тому же это бесценный опыт работы в огромной компании с множеством профессионалов в своих областях, у которых есть чему поучиться. О том, как попасть на стажировку в Яндекс, чем там можно заниматься и что вас ждет потом, я и хочу сегодня поделиться.

Для начала пару слов о себе. Зовут меня Муаммар, 21 год от роду, на данный момент являюсь студентом пятого курса мехмата МГУ. А еще я выпускник ШАДа, ведущий семинаров по Natural Language Processing в ШАДе и младший разработчик в команде речевых технологий Яндекса. Какой-то супергениальностью не отличаюсь, но люблю и умею работать. Пожалуй, хватит себя расхваливать, поговорим о стажировке. Кому интересно — добро пожаловать под кат! Может, моя история кого-то вдохновит.

Процесс подбора команды


Так вот, решил я летом поработать в Яндексе. Недолго думая, написал Юле Кривовой, которая является куратором студенческих программ, сказал, хочу заниматься какими-нибудь сложными задачами, при том не забыл упомянуть, что увлекаюсь NLP. Как там в «Поле чудес»? Пользуясь случаем, хотел бы сказать маме, что я ее очень люблю передать Юле большую благодарность: она приложила немало усилий для подбора команды, которая в конце концов пришлась мне по вкусу. Вообще, процесс поиска команды в моей истории заслуживает отдельного внимания. К тому же всем всегда интересно, что же спрашивают не этих «жутко страшных» собеседованиях в Яндексе и как к ним готовиться, —, а лучше всего сразу получить готовый рецепт, как их успешно пройти!

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

Через некоторое время обо мне проведал один из моих ШАДовских преподавателей по информационному поиску — Саша Болховитянов, а им как раз нужен был человек на позицию младшего разработчика в команду поиска дубликатов. Неделю спустя меня пригласили на три подряд идущих технических очных собеседования: алгоритмы, проектирование и C++. Алгоритмы и структуры данных я знал прекрасно, да и в целом ничего сверхъестесвтенного не спрашивали. В проектировании на вопросы типа «а как построить распределенную отказоустойчивую систему» и «а что если в этой системе…» помогла смекалка. А вот с C++ возникли серьезные проблемы. Хотя я и понимал, как написать программу, что делает любая конкретная строчка кода, тем не менее о том, как все это устроено на уровень глубже, в памяти, на тот момент я не имел особого представления. Человек я коммуникабельный, поэтому, чтобы хоть как-то разбавить фиаско, поговорил с собеседующим по душам. Суммарное впечатление я произвел положительное, но вот задачи, которыми они предлагали заниматься, лично меня не сильно вдохновляли. И я четко решил: уж лучше за небольшую зарплату, зато на интересные лично мне задачи пойти пускай стажером в машинный перевод, чем в поиск дубликатов младшим разработчиком.

Время шло, а вот все остальное почему-то так и стояло на месте…, но недолго! Точно уж и не припомню когда, но для красоты давайте вообразим, что в три часа утра, ко мне на почту приходит письмо от Юли: команда разработки голосовых интерфейсов ищет себе сотрудника! «Да это же чистое NLP», — пронеслось в голове. Извлечение информации из текста, определение именованных сущностей, чат-боты — в общем, я прямо-таки загорелся к ним попасть. Сначала ребята устроили скайп-собеседование по Python, заодно уточняя мои знания Bash. Если в первом я соображал неплохо, то вот что такое Bash — я и знать не знал! После собеседования они дали мне большое домашнее задание — написать диалогового агента, который по человеческим запросам, к примеру «Что такое Эйфелева башня?», находил бы наиболее подходящие статьи из Википедии. Мне до сих пор кажется, что я сделал добротно, но, как бы там ни было, их руководитель сказал, что в команду требуется все же готовый разработчик, а не стажер, с которым нужно нянчиться и всему учить.

Осталась единственная команда — распознавания речи. Если честно, об этой области я не знал ничего, к тому же смутно представлял, где именно там NLP. Мой нынешний руководитель Илья iliia Едренкин заверил, что мне у них понравится, к тому же задачи, которыми они занимались, мне показались крайне сложными. В сухом остатке меня поджидали еще два собеседования: первое — по продвинутым алгоритмам, где вдобавок к обычным знаниям требовалась немалая смекалка, а второе — по машинному обучению. Прошел я их не с блеском, но приличненько. Буквально через день-два пришло письмо от Юли, что меня готовы взять в команду. Ура, товарищи, счастье наступило!

Отдельно хотелось бы отметить несколько моментов, которые, как мне кажется, положительно влияли на прохождение собеседований. Во-первых, отсутствие волнения: в Яндекс я шел с таким настроем, будто не меня будут собеседовать, а я собирался там всех собеседовать, да и результат мне был совершенно не важен: возьмут — прекрасно, не возьмут — тоже слава Богу. Во-вторых, даже если где-то я и тупил, тем не менее старался в целом завязать беседу, поговорить на отвлеченные темы, выставить себя в положительном свете. В-третьих, я никогда не тратил на подготовку к собеседованию более трех часов, а единственное, что делал во время подготовки, так это освежал знания в той или иной области.

Технический аспект стажировки


Каждому стажеру в Яндексе ставят небольшую, но достаточно творческую задачку в предположении, что он решит ее за 3–6 месяцев. Причем слово «решит» не стоит понимать буквально. Иногда речь и правда идет о решении некоторой небольшой задачи, в каких-то случаях это может быть улучшение метрик, бывает так, что нужно придумать какой-нибудь новый метод или подход к задаче. В моем случае нужно было научиться определять степень уверенности распознавания фраз и отдельных слов нашей ASR-системой (ASR — Automatic Speech Recognition). Напомню, как происходит распознавание речи. Процесс преобразования звука в текст состоит из нескольких этапов.

  1. Предобработка. Мы дробим звуковую запись на фреймы по 25 мс с шагом 10 мс. (Возможно, также стараемся некоторыми методами избавиться от шума.)
  2. Извлечение фичей. Из каждого фрейма извлекаются некоторые численные фичи.
  3. Преобразование фичей в распределение по фонемам (на самом деле в реальной модели не фонемы, а сеноны — классы контекстно-зависимых фонем). Фичи от нескольких соседних фреймов соединяются вместе, и на это добро натравливается некоторая нейронная сеть (DNN, LSTM, GRU — что душе угодно). На выходе мы получаем вероятностное распределение по фонемам.
  4. Декодирование. Далее с учетом языковой модели, лексикона и нашего представления о мире происходит декодирование найденных распределений вероятностей, и мы получаем цепочку слов.


Вся проблема заключается в шаге 3. Нейронная сеть — дискриминативная модель. Она говорит, насколько хорошо одна фонема отличается от другой в данном фрагменте звука, но не говорит, насколько много/хорошо та или иная фонема в этом куске звука представлена. Тут возможна такая аналогия. Некоторых людей мы знаем настолько хорошо, что можем описать их полностью, — это генеративная модель. А бывает так, что мы увидели человека и что-то отложилось в нашей памяти, описать человека мы не можем, но зато если нам покажут фотографию произвольного человека, то мы можем сказать, он на фото или нет, — это дискриминативная модель. Проблема такой модели состоит в том, что был у нас, например, некоторый фрейм и на нем звучал звук «п» в обычных условиях и в условиях зашумленности. Если этот звук в принципе — что в одном случае, что в другом — отличим от других звуков, то нейронная сеть вполне может в обоих случаях присвоить им одинаковую вероятность, а мы все же хотим как-то различать эти два случая.

Так вот, в силу сказанного выше, ASR-система плохо умеет понимать, насколько чистой/зашумленной была запись. А нам важно это понимать, потому что если запись очень зашумленная, то лучше переспросить человека, чтобы он еще раз повторил свой запрос, чем распознать и выдать ему полную чушь. Степень уверенности в записи называется конфиденсом (confidence). Определение уверенности фразы также полезно для того, чтобы давать асессорам размечать лишь записи со средним конфиденсом. С большим конфиденсом записи и так хорошо распознаются, с низким — просто шум, а вот со средним — самые полезные, ибо это сложные примеры для нашей системы. А чем более сложные примеры мы даем системе распознавания речи, тем быстрее она учится (тут как с человеком: если ему постоянно давать решать »2 + 2», интеграл он не посчитает).

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

  • определение уверенности каждого слова в отдельности,
  • определение уверенности фразы в целом.


В первом случае стоит задача классификации: либо мы угадали слово (класс 1), либо мы ошиблись (класс 0). Во втором случае стоит задача регрессии. Да, забыл сказать, что качество распознавания измеряется метрикой WER (Word Error Rate). Так вот, во втором случае мы будем стараться предсказать 1 — WER, после чего это и назовем пофразовым конфиденсом. Также стоит отметить, что если мы хорошо умеем решать первую задачу, то уже неплохой оценкой для 1 — WER будет средний пословный конфиденс, так что именно на эту задачу я сконцентрировал основные силы.

Все уже, наверное, подумали, что технические детали на этом закончились? Ан нет. Пожалуй, это не столь секретная информация, поэтому расскажу в общих чертах, какое конечное решение было у задачи. Для пословного конфиденса были использованы два типа фичей: акустические и языковые. Подбор акустических фичей был попыткой бороться с дискриминативностью нейронной сети. Мы собрали некоторые статистики по всему обучающему корпусу (средняя длительность по фонемам и т. п.), а далее для каждого слова при распознавании конкретной фразы сравнивали его параметры со статистически средними по корпусу. Это смягчало дискриминативность и вносило некоторую информацию о внешнем мире. В качестве языковых фичей были взяты вероятности n-грамм с целью отслеживания различных несогласованностей типа «зеленый трава». В конечном счете на это был натравлен градиентный бустинг, и вуаля — мы имеем пословный конфиденс! Результаты получились вполне достойными: порядка 25–50% (вариация в зависимости от модели) прироста качества по отношению к бейзлайну (sMBR). Для оценки пофразового конфиденса были использованы всего две фичи: средний пословный конфиденс и степень того, насколько сильно различаются между собой N лучших гипотез, которые выдала ASR-система при распознавании (смысл в том, что если гипотезы различаются сильно, то скорее всего фраза была произнесена нечетко и ее WER будет большим).

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

Напоследок отмечу, что Илья Едренкин предложил называть конфиденсы «числами Муаммара». Еще было довольно забавно, что я периодически слышал эти слова, когда коллеги о чем-то говорили, но каждый раз думал, что мне это слышится. А на одном из собраний команды мне сказали: «А ты не знаешь, что конфиденсы уже месяц как называются числами Муаммара?» Ну, а дальше как-то прижилось :).

Минусы и плюсы стажировки в Яндексе


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

О плюсах. Как вы могли догадаться, человек я достаточно верующий, поэтому первым плюсом поставлю именно возможность соблюдения религиозных практик. В Яндексе людей ценят не за веру и политические или другие убеждения, а за то, как хорошо они делают свою работу, и устраивают все так, чтобы работать было удобнее. Поэтому даже в таком чувствительном вопросе Яндекс готов идти навстречу. С пятикратной молитвой вообще нет никаких проблем: нашел свободную переговорку — и хоть на голове там стой. Но это еще не все. Как многим, наверное, известно, каждый половозрелый мужчина из числа мусульман обязан посещать пятничную проповедь. Поэтому для себя я четко решил: если не будет возможности ходить на проповедь, то мне такая работа не подойдет. Хотя график и гибкий, волею случая оказалось, что именно в пятницу, именно во время пятничной проповеди у нас было еженедельное собрание команды. Я сразу сказал: Илья, извини, но конкретно в это время я не смогу присутствовать. К моему великому удивлению, ради стажера, не проработавшего и одной недели в команде, порядка десяти человек (некоторые годятся мне в отцы и имеют многолетний стаж) согласились перенести встречу на удобное для меня время. Сказать, что такое отношение со стороны членов команды радует и располагает, — ничего не сказать.

Второй плюс: Яндекс предоставляет море возможностей для развития в профессиональном плане: можно посещать разнообразные научные семинары, доклады ученых и многое другое. Я вот даже умудрился слетать на ШАДовскую конференцию —, но это скорее исключение, чем правило! Причем приобретение новых знаний в области Computer Science является частью твоей работы. Яндекс хочет, чтобы его сотрудники становились умнее! Более того, у меня есть хобби — преподавание: ну вот нравится чему-то учить людей. Вообще не вопрос, говорит Яндекс, преподавание в ШАДе — пожалуйста, выступления на научных семинарах — с радостью! В продолжение научной темы хочется отметить, что в нашей команде каждому человеку выделяется достаточно много, по моим меркам, вычислительной мощности, поэтому если ты хочешь позаниматься своими собственными исследованиями вне рабочего времени, то флаг тебе в руки, никто не будет тебя укорять.

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

Есть ли жизнь после стажировки?


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

© Habrahabr.ru