У мене є напівробоча система, яка вирішує цю проблему, відкрита за допомогою 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, проведіть неправильно класифіковані твіти назад через Vectorizer, щоб побачити, як виглядає основне представлення Bag of Words - там буде менше токенів, ніж ви почали з сирого твіту - чи достатньо для класифікації?)
- Подивіться на мій приклад коду на https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py, щоб отримати працюючу версію цього підходу
Що слід врахувати:
- Вам потрібен більший набір даних. Я використовую 2000 твітів із міткою (це зайняло у мене п’ять годин), і як мінімум ви хочете збалансований набір із> 100 на клас (див. Примітку про переобладнання нижче)
- Удосконаліть маркер (дуже легко за допомогою scikit-learn), щоб зберегти # @ у маркерах, і, можливо, додати детектор з великими літерами (як зазначає користувач @ user2425429)
- Розгляньте нелінійний класифікатор (як, наприклад, пропозиція @ oiez вище), коли справа стає складнішою. Особисто я виявив, що LinearSVC робить гірше, ніж логістична регресія (але це може бути пов'язано з просторим простором функцій, який я ще не скоротив).
- Тег-специфікатор частини мовлення (на мою скромну думку, не Стенфорда, як пропонує @Neil - він погано працює з поганою граматикою Twitter, на мій досвід)
- Після того, як у вас буде багато токенів, ви, мабуть, захочете трохи зменшити розмірність (я ще не пробував цього - див. Мій пост у блозі про покарання LogisticRegression l1 l2)
Re. переобладнання. У моєму наборі даних із 2000 елементів я маю 10-хвилинний знімок твітів про "яблуко". Приблизно 2/3 твітів стосуються Apple Inc, 1/3 - для інших видів використання. Я виймаю збалансовану підмножину (приблизно 584 рядки) кожного класу і виконую п'ятикратну перехресну перевірку для навчання.
Оскільки я маю лише 10-хвилинний інтервал часу, у мене є багато твітів на одну і ту ж тему, і, мабуть, саме тому мій класифікатор працює так добре щодо існуючих інструментів - він буде переобладнаний для навчальних функцій, не добре узагальнюючи (тоді як існуючий комерційний інструменти працюють гірше на цьому знімку, але надійніше в ширшому наборі даних). Я буду розширювати своє часове вікно, щоб перевірити це як наступну роботу.