Skip to content

Defining a programming language from source code using machine learning

Notifications You must be signed in to change notification settings

batogov/programming-language-detection

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Задача

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

Используемые инструменты и библиотеки

  • Python 3;
  • Pandas для работы с данными;
  • BeautifulSoup4 для парсинга данных;
  • Scikit-Learn для применения алгоритмов машинного обучения и т.д.

Обучающая выборка

Одна из самых сложных частей данной работы – создание обучающей выборки. Необходимо было найти большое количество размеченных исходных кодов (исходный код + метка языка програмирования, на котором этот код написан). В качестве сайтов для парсинга рассматривались сервисы, предоставляющие в свободном доступе короткие программные коды на разных языках программирования. Например, gist.github.com или ideone.com. Сайтом для парсинга был выбрал ideone.com по причине удобства парсинга, большего разнообразия и качества исходных кодов.

Главная страница сайта ideone.com представляет из себя текстовый редактор с возможностью написания кода и дальшейшего его выполнения. В данной задаче нас интересует не она, а страница с адресом ideone.com/recent. На ней отображаются последние исполненные на сайте сниппеты кода. На странице внизу присутствует блог пагинации, с помощью которого можно просматривать более старые сниппеты (так же навигацию можно осуществлять с помощью дописывания к адресу ideone.com/recent/ номер интересующей страницы). Каждый блок с исходным кодом помимо прочего содержит ссылку на страницу сниппета и полезные для нас строки: строку с языком кода и строку с результатом выполнения (компилируется, ошибка компиляции, успешно и т.д.). Перейдя по ссылке из блока мы попадаем на страницу исходного кода, на которой полностью отображается исходный код и ссылка на файл.

Парсер работает следующим образом:

  1. Проходит по страницам от n до k (от ideone.com/recent/n до ideone.com/recent/k);
  2. На каждой странице просматривает все блоки кода и отбирает те, у которых строка с результатом выполнения сигнализирует об успешности;
  3. Для отобранных блоков кода запоминает язык и скачивает исходный файл (парсить исходных код со страницы каждого кода сложно из-за структуры html-кода);
  4. Финальный отбор – скрипт оставляет только те исходные коды, количество строк в которых не превышает 50. Это необходимо для того, чтобы отсеять громоздкие сниппеты, которые будут вредить алгоритму машинного обучения из-за того, что скорее всего помимо «полезной выжимки» кода будут содержать много мусора;
  5. Если это первый запуск скрипта, то он создаёт файл raw_data.csv и записывает в него результат. Иначе открывает этот файл и дозаписывает результат.

Парсер в процессе своей работы посылает много запросов на сайт ideone.com, из-за чего часто возникают http-ошибки. Чтобы ошибки не прерывали процесс парсинга, написана функция-обёртка с обработчиком исключений, который при возникновении ошибки продолжает процесс парсинга.

Код отвечающий за парсинг и сохранение его результатов в .csv находится в файле data_parsing.py.

Результат парсинга

С помощью вышеописанного алгоритма была собрана выборка размером 12923 объектов. Из-за нехватки времени и того факта, что скрипт-парсер работает медленно, создать выборку большего объёма не представилось возможным. Так же из недостатков собранной выборки стоит отметить дисбаланс классов. Например, исходных кодов на языке «C» в десятки раз больше, чем на языке «Python».

Обработка выборки

Следующий этап работы – обработка выборки. Идеальным алгоритмом обработки сырых данных в данной работе будет алгоритм, который сможет удалить из исходных кодов все «малозначащие» элементы. Забегая вперёд стоит отметить, что алгоритм машинного обучения, который мы будем использовать далее, будет оперировать численными представлениями слов наших исходных кодов. Соответственно, классификация будет основана на различии комбинаций этих численных представлений. Чтобы качественно выполнить эту задачу, алгоритму необходимо подготовить данные таким образом, чтобы тексты кодов на разных языках программирования имели разные особенности, т.е. нужно удалить всё общее, что имеют коды на разных языках программирования. Эти общие части я и называю в данном контексте «малозначащами» элементами (например, имена переменных и их значения или комментарии в тексте кода).

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

Однако, небольшую обработку кодов сделать можно. А именно:

  • Удалить все символы переноса строк и табуляции;
  • Удалить все цифры;
  • Удалить лишние пробелы – оставить только пробелы между словами.

Построение модели и результаты

После обработки текстов можно приступить к построению модели. В этой работе я использую линейный классификатор (минимизация с помощью стохастического градиентного спуска), векторизацию данных с помощью TF-IDF и схему n-грамм (1, 4).

По результатам валидации, лучшая модель имеет следующие параметры: alpha – 0.0001, penalty – none, loss – hinge.

Качество модели ≈ 0.83.

About

Defining a programming language from source code using machine learning

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages