Microsoft предлагает метод карты программы: учиться на исходном коде и находить досадные ошибки

искусственный интеллект Microsoft Нейронные сети NLP

Автор|Майкрософт
Компиляция | Дебра
Редактор | Эмили
Руководство по передовой ИИЗа последние пять лет методы, основанные на глубоком обучении, произвели революцию во многих приложениях, таких как те, которые могут понимать изображения, речь и естественный язык. У компьютерщиков возникает естественный вопрос: научились ли компьютеры понимать исходный код? На первый взгляд это может показаться тривиальным вопросом, поскольку языки программирования действительно предназначены для понимания компьютерами. Однако появление многих программных ошибок на самом деле отражает реальную психологию разработчиков: они хотят, чтобы код работал так, как они хотят, а не так, как они его написали. Другими словами, небольшие опечатки могут иметь серьезные последствия.

Для получения дополнительных галантерейных товаров, пожалуйста, обратите внимание на публичный аккаунт WeChat «AI Frontline» (ID: ai-front)

Вот простой пример:

float getHeight { вернуть эту ширину; }.

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

Анализ программ в прошлом в основном фокусировался на программах с формальной, машинно интерпретируемой семантикой или рассматривал программы как (несколько странно) примеры естественного языка. Первый метод основан на математической логике (https://www.microsoft.com/en-us/research/research-area/programming-languages-software-engineering/) и требует обширной работы для каждого нового случая, который необходимо решить. выполнял инженерно-конструкторские работы. С другой стороны, методы естественного языка включают применение инструментов обработки естественного языка (https://www.microsoft.com/en-us/research/research-area/human-language-technologies/), которые хорошо работают с задачами. , но пока не удалось изучить семантику программы.

В новой статье, опубликованной в ICLR 2018, исследователи из Microsoft Research и Университета Саймона Фрейзера в Ванкувере предлагают новый метод, который сочетает в себе оба метода и показывает, как появляются ошибки в выпущенном программном обеспечении.

Схема программы

Чтобы иметь возможность учиться на богатой структуре исходного кода, ее сначала необходимо преобразовать в граф программы. Узлы графа включают токены программы (т. е. переменные, операторы, имена методов и т. д.) и узлы ее абстрактного синтаксического дерева (элементы, определяющие грамматику языка, такие как условные операторы). Графы программ содержат ребра двух разных типов: синтаксические ребра, которые просто указывают, как следует анализировать код, например, циклы while и блоки if, и семантические ребра, являющиеся результатом простого анализа программы.


Синтаксические ребра включают простое ребро «NextToken», ребро «Child», используемое для представления абстрактного синтаксического дерева, и ребро «LastLexicalUse», используемое для соединения исходного кода с последним вхождением в текст исходного кода. На рис. 1 показано такое ребро на примере оператора Assert.NotNull(clazz), где узлы, соответствующие токенам, представляют собой серые прямоугольники, а узлы, соответствующие нетерминалам грамматики программы, — синие эллипсы. Дочерние ребра отображаются как сплошные синие ребра, а ребра NextToken — черные двойные ребра.

Семантические ребра включают ребра «LastUse», которые соединяют переменные с последним возможным использованием в выполнении программы, ребра «LastWrite» с последними записанными переменными и ребра «ComputedFrom» для подключения переменных к вычисляемым значениям. Дополнительные семантические границы можно получить с помощью других инструментов в наборе инструментов анализа программ, таких как псевдонимы и одноранговый анализ, а также условия пути. На рис. 2 показаны некоторые семантические ребра (черные) в небольшом фрагменте кода.


Связь LastUse показана с зеленой рамкой. Так, например, y связан с последним использованием y перед циклом и самим собой. Опять же, связь LastWrite показана с красной кромкой, поэтому использование x в условии while связано с присвоением x перед циклом и назначением x внутри цикла. Наконец, отношение ComputedFrom представлено синим краем, соединяющим переменную с переменной, из которой она была вычислена.

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

учиться на графиках

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

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

искать ошибки

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

При запуске этой модели в новом коде и предсказании var1 с высокой вероятностью, но программист выбрал var2, это может указывать на ошибку. Отмечая эти вопросы для проверки экспертами-людьми, мы можем обнаружить настоящие ошибки. В качестве примера возьмем код, полученный компилятором Microsoft C# Roslyn:


Обратите внимание на выделенный путь к файлу параметров и использование поля _filePath, их легко спутать. _filePath был опечаткой, и разработчики исправили ее после того, как исследователи сообщили об этой и подобных проблемах. Подобные ошибки были обнаружены в некоторых других проектах C# и исправлены после того, как о них сообщили.

Этот новый подход превосходит традиционные методы машинного обучения в более крупных количественных оценках. В качестве метода сравнительного анализа он учитывает двунаправленные рекуррентные нейронные сети (BiRNN), работающие непосредственно с исходным кодом, и простые расширения BiRNN, которые получают доступ к информации о потоках данных. Чтобы оценить различные модели, они проанализировали проекты C# с открытым исходным кодом, содержащие в общей сложности 2,9 миллиона строк исходного кода. Протестировано в различных моделях машинного обучения с использованием исходного кода, в котором удаляется одна переменная и предлагается предсказать исходную переменную (при условии, что код хорошо протестирован и всегда верен). В первом эксперименте они обучали эти модели с помощью сохраненных файлов. Во втором эксперименте эти модели были протестированы с использованием данных совершенно нового проекта. Результаты показаны в таблице ниже, а результаты тестов лучше с новой диаграммой программы. изображение

будущие приложения

Графы программ — универсальный инструмент для применения методов глубокого обучения к программам. Microsoft продолжит исследования своих будущих приложений в программе AI Residency Program в следующем году (https://www.microsoft.com/en-us/research/academic-program/microsoft-ai-residency-program/).


Ссылки по теме


  • Реализация с открытым исходным кодом: https://github.com/Microsoft/gated-graph-neural-network-samples

  • Deep Program Understanding projecthttps://www.microsoft.com/en-us/research/project/program/

  • Документ о нейронной сети с закрытым графом https://arxiv.org/abs/1511.05493

  • Кодовая база нейронной сети с закрытым графом https://github.com/Microsoft/gated-graph-neural-network-samples

  • Обучение графическим программам - Документ ICLR'18 https://arxiv.org/abs/1711.00740

Оригинальная ссылка:

https://www.microsoft.com/en-us/research/blog/learning-source-code/