У меня есть частично работающая система, которая решает эту проблему, с открытым исходным кодом с использованием scikit-learn, с серией сообщений в блогах, описывающих то, что я делаю. Проблема, которую я пытаюсь решить, - это устранение неоднозначности смысла слова (выбор одного из нескольких вариантов смысла слова ), что отличается от распознавания именованных сущностей. Мой основной подход в некоторой степени конкурирует с существующими решениями и (что очень важно) настраивается.
Существуют некоторые существующие коммерческие инструменты NER (OpenCalais, DBPedia Spotlight и AlchemyAPI), которые могут дать вам достаточно хороший коммерческий результат - попробуйте сначала!
Я использовал некоторые из них для клиентского проекта (я консультируюсь с использованием NLP / ML в Лондоне), но меня не удовлетворил их отзыв ( точность и отзыв ). В основном они могут быть точными (когда они говорят «Это Apple Inc», они обычно правы), но с низким уровнем запоминания (они редко говорят «Это Apple Inc», хотя для человека твит явно касается Apple Inc). Я подумал, что было бы интеллектуально интересным упражнением создать версию с открытым исходным кодом, адаптированную для твитов. Вот текущий код:
https://github.com/ianozsvald/social_media_brand_disambiguator
Замечу - я не пытаюсь решить общую проблему устранения неоднозначности в словах с помощью этого подхода, а просто пытаюсь устранить неоднозначность бренда (компании, люди и т.д.), когда у вас уже есть их имя. Вот почему я считаю, что такой простой подход сработает.
Я начал это шесть недель назад, и он написан на Python 2.7 с использованием scikit-learn. Он использует очень простой подход. Я векторизирую с помощью векторизатора двоичного счета (я считаю только то, появляется ли слово, а не сколько раз) с 1-3 н-граммами . Я не масштабируюсь с TF-IDF (TF-IDF хорош, когда у вас есть переменная длина документа; для меня твиты состоят только из одного или двух предложений, и мои результаты тестирования не показали улучшения с TF-IDF).
Я использую базовый токенизатор, который очень прост, но на удивление полезен. Он игнорирует @ # (поэтому вы теряете некоторый контекст) и, конечно, не расширяет URL-адрес. Затем я тренируюсь с использованием логистической регрессии , и мне кажется, что эта проблема в некоторой степени линейно разделима (много терминов для одного класса не существует для другого). В настоящее время я избегаю любых стеммингов / чисток (я пробую «Простейшую возможную вещь, которая может сработать»).
В коде есть полный README, и вы сможете относительно легко воспринимать свои твиты, а затем следовать моим предложениям для тестирования.
Это работает для Apple, поскольку люди не едят и не пьют компьютеры Apple, мы не печатаем и не играем с фруктами, поэтому слова легко разделить на ту или иную категорию. Это условие может не выполняться при рассмотрении чего-то вроде #definance для телешоу (где люди также используют #definance в отношении арабской весны, матчей по крикету, пересмотра экзаменов и музыкальной группы). Здесь вполне могут потребоваться более умные подходы.
У меня есть серия сообщений в блоге, описывающих этот проект, включая часовую презентацию, которую я провел в группе пользователей BrightonPython (которая превратилась в более короткую презентацию для 140 человек в DataScienceLondon).
Если вы используете что-то вроде LogisticRegression (где вы получаете вероятность для каждой классификации), вы можете выбрать только достоверные классификации, и таким образом вы можете добиться высокой точности, торгуя против отзыва (так что вы получите правильные результаты, но их будет меньше). Вам нужно будет настроить это на свою систему.
Вот возможный алгоритмический подход с использованием scikit-learn:
- Используйте двоичный CountVectorizer (я не думаю, что счетчик терминов в коротких сообщениях добавляет много информации, поскольку большинство слов встречается только один раз)
- Начните с классификатора дерева решений. У него будет объяснимая производительность (см. Пример в разделе « Переоснащение деревом решений» ).
- Перейти к логистической регрессии
- Исследуйте ошибки, сгенерированные классификаторами (прочтите экспортированный вывод DecisionTree или просмотрите коэффициенты в LogisticRegression, обработайте неправильно классифицированные твиты обратно через векторизатор, чтобы увидеть, как выглядит базовое представление Bag of Words - там будет меньше токенов, чем вы начали с сырого твита - достаточно ли этого для классификации?)
- Посмотрите мой пример кода в https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py, чтобы увидеть рабочую версию этого подхода.
Что нужно учитывать:
- Вам нужен больший набор данных. Я использую 2000 помеченных твитов (у меня это заняло пять часов), и как минимум вам нужен сбалансированный набор с> 100 на класс (см. Примечание по переобучению ниже)
- Улучшите токенизатор (очень просто с помощью scikit-learn), чтобы сохранить # @ в токенах, и, возможно, добавить детектор бренда с заглавной буквы (как отмечает user @ user2425429)
- Рассмотрим нелинейный классификатор (например, предложение @ oiez выше), когда становится сложнее. Лично я обнаружил, что LinearSVC хуже, чем логистическая регрессия (но это может быть из-за многомерного пространства функций, которое мне еще предстоит уменьшить).
- Часть речевого теггера, связанная с твитами (по моему скромному мнению, не у Стэндфорда, как предполагает @Neil - по моему опыту, он плохо работает при плохой грамматике Twitter)
- Как только у вас будет много токенов, вы, вероятно, захотите немного уменьшить размерность (я еще не пробовал этого - см. Мое сообщение в блоге о наказании LogisticRegression l1 l2)
Re. переоснащение. В моем наборе данных с 2000 элементами у меня есть 10-минутный снимок «яблочных» твитов из Twitter. Около 2/3 твитов адресовано Apple Inc, 1/3 - другим пользователям Apple. Я выбираю сбалансированное подмножество (я думаю, около 584 строк) каждого класса и делаю пятикратную перекрестную проверку для обучения.
Поскольку у меня есть только 10-минутное временное окно, у меня много твитов на ту же тему, и, вероятно, именно поэтому мой классификатор работает так хорошо по сравнению с существующими инструментами - он будет переоснащен функциями обучения без хороших обобщений (тогда как существующий коммерческий инструменты работают хуже в этом снапшопе, но более надежно для более широкого набора данных). Я буду расширять свое временное окно, чтобы проверить это в качестве последующей работы.