Определение ключевых слов (языка программирования) - PullRequest
4 голосов
/ 07 сентября 2010

это продолжение моего недавнего вопроса ( Код для определения языка программирования в текстовом файле ).Я очень благодарен за все ответы, которые я получил, это мне очень помогло. Мой код для этой задачи завершен, и он работает довольно хорошо - быстро и достаточно точно.

Я использовал следующий метод: у меня есть "обучающий" скрипт на Perl, которыйопределяет наиболее часто используемые слова в языке, выполняя гистограмму слова над набором файлов примеров.Эти данные затем загружаются программой c ++, которая затем проверяет заданный текст и накапливает баллы для каждого языка на основе найденных слов, а затем просто проверяет, какой язык набрал наибольшее количество баллов.

Теперь я хотел бысделать это еще лучше и немного поработать над качеством идентификации. Проблема в том, что я часто получаю «неизвестность» в результате (многие языки набирают небольшое количество баллов, но ни один из них не превышает моего порога).После некоторой отладки, исследований и т. Д. Я обнаружил, что это, вероятно, связано с тем, что все слова считаются равными.Это означает, что просмотр «#include», например, имеет тот же эффект, что и «while» - оба указывают на то, что это может быть c / c ++ (сейчас я игнорирую тот факт, что «while» используется во многих другихязыки), но, конечно, в больших файлах .cpp может быть тонна "while", но в большинстве случаев только несколько "#include".

Так что факт "#include"«важнее игнорируется, потому что я не смог придумать, как определить, является ли слово более важным, чем другое». Теперь имейте в виду, что скрипт, который создает данные, довольно глуп, его толькогистограмму слова, и каждому выбранному слову присваивается оценка 1. Он даже не смотрит на слова (поэтому, если в файле часто встречается «# & |? /», он может быть выбран как хорошее слово).

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

Есть ли у кого-нибудь предложения, как определить ключевые слова или, в более общем смысле, важные слова? Некоторые вещи, которые могут помочь: у меня есть число вхождений каждого слова и количествоВсего слов (так что соотношение может быть рассчитано).Я также думал о том, чтобы стереть такие символы, как; и т. Д., Так как скрипт гистограммы часто добавляет, например, «продолжить»;в результате, но важное слово «продолжить».Последнее замечание: все проверки на равенство выполняются для точного соответствия - без подстрок, с учетом регистра.Это в основном из-за скорости, но подстроки могут помочь (или повредить, я не знаю) ...

ПРИМЕЧАНИЕ: спасибо всем, кто потрудился ответить, вы мне очень помогли.

Моя работа с этим почти закончена, поэтому я опишу, что я сделал, чтобы получить хорошие результаты.

1) Получите приличный обучающий набор, около 30-50 файлов на язык из различных источников, чтобы избежатьсмещение стиля кодирования2) Напишите Perl-скрипт, который выполняет гистограмму слова.Реализация черного и белого списков (подробнее об этом ниже)3) добавить фиктивные слова в черный список, такие как «лицензия», «the» и т. Д. Они часто встречаются в начале файла в информации о лицензии.4) добавить около пяти самых важных слов для каждого языка в белый список.Это слова, которые встречаются в большинстве исходных кодов данного языка, но не достаточно часто встречаются в гистограмме.Например, для C / C ++ у меня были: #include, #define, #ifdef, #ifndef и #endif в белом списке.5) Подчеркните начало файла, поэтому дайте больше очков словам, найденным в первых 50-100 строках.6) при выполнении гистограммы слова токенизируйте файл, используя @words = split(/[\s\(\){}\[\];.,=]+/, $_); Это должно быть приемлемо для большинства языков, которые я считаю (дает мне лучшие результаты).Для каждого языка, около 10-20 наиболее часто употребляемых слов в окончательных результатах.7) Когда гистограмма будет завершена, удалите все слова, найденные в черном списке, и добавьте все те, которые находятся в белом списке.
8) Напишите программу, которая обрабатывает текстовый файл так же, как скрипт - токенизируйте по тем же правилам. Если в данных гистограммы найдено слово, добавьте точки на нужный язык. Слова в гистограмме, которые соответствуют только одному языку, должны добавлять больше точек, а те, которые принадлежат нескольким языкам, должны добавлять меньше.

Комментарии приветствуются. В настоящее время около 1000 текстовых файлов я получаю 80 неизвестных (в основном на очень короткие файлы - в основном JavaScript с одной или двумя строками). Около 20 файлов распознаются неправильно. Размер файлов составляет около 11 КБ в диапазоне от 100 до 100 КБ (почти 11 МБ). Обработка их всех занимает одну секунду, что для меня достаточно.

Ответы [ 4 ]

3 голосов
/ 07 сентября 2010

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

Практически: ваш классификатор не должен точно оценивать, насколько близок к C ++ определенный ввод; ему просто нужно определить, больше ли ввод похож на C, чем на C ++. Это делает вашу работу намного проще - большинство ваших текущих «неизвестных» дел будут близки к одному или двум языкам, даже если они не превышают ваш базовый порог.

Теперь, когда вы поймете это, вы также увидите, что нужно вашему классификатору для обучения: не какой-то случайный аспект файлов примеров, но что отличает два языка. Следовательно, когда вы проанализировали свои сэмплы C и сэмплы C ++, вы увидите, что #include не выделяет их отдельно. Тем не менее, class и template будут гораздо чаще встречаться в C ++. С другой стороны, #include различает между C ++ и Java.

Конечно, есть и другие аспекты, помимо ключевых слов, которые вы можете использовать. Например, наиболее очевидной будет частота {, а ; аналогично различается. Еще одна очень полезная функция для вашего классификатора - это маркеры комментариев для разных языков. Конечно, основной проблемой будет их автоматическая идентификация. Опять же, жесткое кодирование //, /*, ', --, # и ! в качестве псевдоключевых слов поможет.

Это также определяет другое правило классификации: SQL часто будет иметь -- в начале строки, тогда как в C он часто будет появляться где-то еще. Таким образом, вашему классификатору может быть полезно принять во внимание и контекст.

2 голосов
/ 07 сентября 2010

Используйте Google Code Search, чтобы узнать весовые коэффициенты для набора ключевых слов: #include в C ++ получает 672.000 обращений, в Python только ~ 5000.

Вы можете нормализовать результаты, посмотрев на общее количество результатов по языку: C ++ дает около 770 000 файлов, тогда как Python возвращает 120 000.

Таким образом, "#include" крайне редко встречается в файлах Python, но существует почти в каждом файле C ++. (Теперь вам все еще нужно научиться различать C ++ и C. Конечно, все, что осталось, - это правильно рассуждать о вероятностях.

1 голос
/ 07 сентября 2010

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

0 голосов
/ 07 сентября 2010

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

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

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