Статья: https://arxiv.org/abs/2010.01544

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

По этой причине в настоящее время почти в каждой профессиональной команде разработчиков программного обеспечения есть что-то, называемое проверкой кода. Это означает, что когда вы являетесь другим программистом в такой команде и отправляете фиксацию, перед объединением вашей фиксации с базой кода второй (обычно старший) член команды просматривает код и комментирует, есть ли в коде дефекты и как их исправить. Затем эти комментарии возвращаются к вам - кодеру, и ваша задача - исправить код, отправить его и снова запустить тот же процесс. А теперь, уважаемый программист, хотите, чтобы ИИ прочитал за вас эти комментарии и автоматически выполнил эти исправления? Конечно ты будешь. Ленивый - неофициальное название должности каждого программиста. Это то, что мы пытались сделать в нашей работе Review4Repair. Итак, пристегнитесь и продолжайте читать, чтобы узнать, как мы это сделали, и я также расскажу кое-что о нейронном машинном переводе (NMT).

Вы когда-нибудь задумывались, как Google Translate превращает ваше Bonjour étranger в Hello, незнакомец? Это так называемая последовательность нейронной сети. Он состоит из двух частей: кодировщика и декодера. Задача кодировщика - закодировать (да!) Исходный язык (в данном примере французский), а задача декодера - декодировать закодированную версию языка в целевой язык (здесь английский ). Если мы обучим такую ​​модель кодировщика-декодера кучей и связкой французско-английских параллельных предложений, кодировщик научится представлять французский язык так, чтобы декодер мог лучше всего понять, а декодер научится правильно декодировать из закодированная версия. По окончании обучения модель может переводить французское предложение, которого она никогда раньше не видела! Я не буду вдаваться в подробности, это одна из дальновидных статей, в которых была предложена эта идея, очень рекомендуется для всех желающих.

Самое интересное в том, что модель не знает, переводится ли она с французского на английский или с телегу на маратхи. Он просто переводит одну последовательность в другую. Какими бы параллельными последовательностями она ни обучалась, модель способна научиться выполнять один и тот же перевод. Отсюда и название - последовательность к последовательности (также ласково называемая seq2seq). Эта модель seq2seq уже давно потрясает мир переводов. Недавно некоторые исследователи (Chen et al.2019, Tufano et al.2019) начали думать, что исходный код также является последовательностью, можно ли обучить модель seq2seq принимать ошибочный код в качестве входных данных и создавать фиксированный код. как выход? Оказывается, да. В этих двух документах собраны большие наборы данных кода с ошибками, фиксированного кода, параллельных данных и показано, что модель seq2seq, на самом деле, может научиться исправлять ошибочный код. Chen et al. В 2019 году была предложена модель под названием SequenceR, сеть генератора указателей (более интересная модель seq2seq) и обученная с помощью ошибочных и фиксированных кодов. Их результаты были многообещающими.

Звучит слишком просто, правда? Не так быстро. Исходный код и естественные языки могут быть последовательностями, но это не одно и то же. В человеческих языках количество слов обычно ограничено. Например, 10 000 наиболее часто встречающихся слов обычно достаточно для представления всего английского языка, а любое слово вне этого списка можно игнорировать как менее важное. Это хорошо для нейронных сетей, потому что нейронные сети требуют, чтобы вы дали им фиксированный набор словаря. Почему? Ну, нейронная сеть - это, по сути, несколько матриц, а обучение нейронной сети настраивает каждую матрицу. Прежде чем определять нейронную сеть, мы должны определить размер матрицы. На следующем рисунке показана очень грубая визуализация того, как слова представлены в виде вектора в любой нейронной модели, а не только в seq2seq. Поскольку средняя матрица должна быть определена, количество слов в нашем словаре (левый вектор) должно быть зафиксировано с самого начала.

Но это подводит нас к следующей задаче в разработке нейронной модели для исходного кода: количество возможных словарных статей в исходном коде бесконечно, потому что имена переменных, функций, классов или любых идентификаторов могут быть произвольными, а наша модель должна понимать все из них. их одинаково. Это означает, что наша модель должна понимать «int x = 0;» так же хорошо, как «int numberOfPacketSentPerSecond = 0;». Итак, как нам создать нейронную сеть, которая должна иметь словарь фиксированного размера, чтобы обрабатывать бесконечное количество слов? Оба Tufano et al. и SequenceR предложили два разных способа решения этой проблемы.

Туфано и др. 2019 год решил проблему бесконечной переменной, ну, как бы это сказать, не решив ее. Они проделали хитрый трюк, заменив все имена переменных токеном общего идентификатора. Например, первая переменная кода становится VAR0, вторая переменная становится VAR1 и так далее. Таким образом, независимо от того, является ли имя переменной x или numberOfPacketSentPerSecond, модель будет видеть ее только как VAR0, VAR1 и т. Д. И обычно в коде есть конечное количество переменных, поэтому модели никогда не придется иметь дело с беспорядочным миром именования идентификаторов. .

SequenceR нашел еще одну умную идею. Эта проблема с неизвестной переменной была проблемой и в естественном языке. Такие, как названия мест и людей в данных на естественном языке, также являются произвольными (модель, обученная с помощью Нью-Йорк - красивый город, также должна хорошо работать для Раджшахи - красивый город). Таким образом, эта проблема уже частично решена в Обработке естественного языка с помощью техники, называемой Механизм копирования. Что он делает, так это то, что если он видит неизвестный токен на входе, он учится копировать это слово прямо на выход, даже если его нет в словаре. Подробнее об этой статье.

Хорошо, хватит о чужих работах! В Review4Repair мы взяли идею SequenceR об использовании механизма копирования для решения неизвестной словарной проблемы, использовали сеть генератора указателей (то есть более причудливую модель seq2seq) и обучили ее на данных с ошибочным кодом и комментарием обзора кода в качестве входных данных, а также на коде. исправить как результат (‹комментарий + дефектный код, исправленный код›). Если вы являетесь экспертом в моделях seq2seq, вы можете сказать в своей голове: «Но, Masum, комментарий и код - это совершенно разные модальности, один - естественный язык, другой - язык программирования. Если сложить их вместе, как ваша модель узнает, что есть что? » Не волнуйтесь, эксперт, мы позаботились об этом, добавив 4 специальных токена, отмечающих начало и конец как комментария, так и кода. Итак, вот как ввод выглядит на практике:

Наблюдая за большим количеством данных, модель внутренне определяет содержимое двух специальных токенов ‹| startcomment |› и ‹| endcomment |› - это комментарий, а содержимое внутри ‹| startcode |› и ‹| endcode |› является кодом. Если вам интересно, что означают токены ‹| startfocus |› и ‹| endfocus |› - они указывают на ту часть кода, которую необходимо изменить. Платформы проверки кода позволяют обозревателям выбрать часть кода, которую необходимо изменить. В нашем вводе мы помечаем его как focus. И выходные данные модели генерируют альтернативное исправление только для этой части. Наблюдая за этими специальными жетонами, модели также знают, что исправить.

А теперь самое интересное. Внутри модели машинного обучения мы никогда не рассказывали, что означают эти специальные токены. Мы просто помещаем в данные специальные токены и надеемся, что наша модель сама их вычислит. И прекрасно, да. В процессе обучения модель узнает, что ей нужно только предсказать альтернативу для части внутри токенов ‹| focus |›. Если этого не происходит, результаты плохие. Модель никогда явно не учат видеть эти токены иначе, чем другие, но во время обучения снова и снова она видит, что изменение содержимого внутри токенов ‹| focus |› дает лучшие результаты. А модель заботится только о том, чтобы набрать больше очков. Точно так же модель также видит, что использование инструкций внутри тегов ‹| comment |› также помогает при оценке. Таким образом, он учится понимать содержание комментариев и использовать их инструкции. Я думаю, что это самый важный вывод из этой статьи для исследования Deep Learning.

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

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

model_cc - наша модель с комментарием обзора, а model_c - наша модель без помощи комментариев обзора. Мы видим, что наша модель исправляет код намного лучше, чем SequenceR, а также модель с комментарием обзора явно остается впереди.

То же самое мы видим по сравнению с Tufano et al. 2019 тоже.

Вот как наши две модели с комментарием обзора кода и без него сравниваются друг с другом.

Мы видим, что модель с комментарием (model_cc) работает примерно на 9% лучше при создании правильного исправления, чем модель без комментария обзора (model_c) в топ-10 точности. Это доказывает, что комментарий к обзору на самом деле помогает исправить код. Поскольку единственное различие между этими двумя моделями - это комментарий обзора, мы можем сказать, что модель выполняет инструкции в комментариях обзора для исправления для достижения более высоких результатов.

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

Эта работа является совместной работой меня (Масум Хасан), Фариа Хук Оайши, Махима Анзума Панто, Сазана Махбуба и под руководством профессора Аниндьи Икбал и Туфика Ахмеда. Вычислительная мощность, необходимая для этой работы, была предоставлена ​​компанией Intelligent Machines, Дакка.

Использованная литература:

SequenceR (2019) - З. Чен, С. Коммруш, М. Туфано, Л.-Н. Пуше, Д. Пошиваник, М. Монперрус, Секвенсор: последовательное обучение для непрерывного восстановления программ, IEEE Transaction on Software Engineering (2019).

Туфано и др. - М. Туфано, Дж. Пантючина, К. Уотсон, Г. Бавота, Д. Пошиваник, Об изучении значимых изменений кода с помощью нейронного машинного перевода, в: Материалы 41-й Международной конференции по разработке программного обеспечения, IEEE Press, 2019, стр. 25–36.