N-граммы: возвращаем порядок слов
N-граммы — простой способ вернуть в bag-of-words хотя бы локальный порядок слов: считать не отдельные слова, а их короткие цепочки.
N-грамма — последовательность из N подряд идущих единиц (слов или символов). Биграмма — пара, триграмма — тройка.
Зачем нужны n-граммы
Мы знаем главную беду «мешка слов»: он теряет порядок, и «не понравилось» распадается на «не» и «понравилось». N-граммы лечат это частично: вместо отдельных слов берём их пары и тройки. Тогда «не понравилось» становится одним токеном-биграммой, и отрицание сохраняется.
Строим n-граммы
def ngrams(tokens, n):
return [tuple(tokens[i:i + n]) for i in range(len(tokens) - n + 1)]
tokens = "мне не понравился этот фильм".split()
print("Униграммы:", ngrams(tokens, 1))
print("Биграммы :", ngrams(tokens, 2))
print("Триграммы:", ngrams(tokens, 3))
Вывод:
Униграммы: [('мне',), ('не',), ('понравился',), ('этот',), ('фильм',)]
Биграммы : [('мне', 'не'), ('не', 'понравился'), ('понравился', 'этот'), ('этот', 'фильм')]
Триграммы: [('мне', 'не', 'понравился'), ('не', 'понравился', 'этот'), ('понравился', 'этот', 'фильм')]
Биграмма ('не', 'понравился') — это уже осмысленная единица, которая прямо кодирует негатив. Униграммный «мешок» такого не умел.
Символьные n-граммы
N-граммы бывают не только из слов, но и из символов. Символьные n-граммы устойчивы к опечаткам и хорошо ловят морфологию: формы «бегать», «бегает» делят общие символьные триграммы «бег», «ега».
def char_ngrams(word, n):
return [word[i:i + n] for i in range(len(word) - n + 1)]
print(char_ngrams("бегать", 3))
print(char_ngrams("бегает", 3))
# общие триграммы — мера похожести слов
common = set(char_ngrams("бегать", 3)) & set(char_ngrams("бегает", 3))
print("Общие триграммы:", common)
Вывод:
['бег', 'ега', 'гат', 'ать']
['бег', 'ега', 'гае', 'ает']
Общие триграммы: {'бег', 'ега'}
Цена за порядок: взрыв размерности
За всё надо платить. Униграмм в языке — десятки тысяч. Биграмм — миллионы (почти любое сочетание двух слов). Триграмм — ещё на порядки больше. Векторы становятся гигантскими и ещё более разрежёнными, а большинство n-грамм встречается один раз и бесполезно. Поэтому на практике:
- Обычно ограничиваются униграммами и биграммами (иногда триграммами).
- Отсекают слишком редкие n-граммы (встретившиеся 1-2 раза).
- Комбинируют с TF-IDF-взвешиванием.
N-граммы — это ещё и языковые модели
Помимо признаков для классификации, n-граммы лежат в основе простейших языковых моделей: зная две предыдущие n-граммы, можно оценить вероятность следующего слова. Этим мы займёмся отдельно в разделе про классические модели — там n-граммы заиграют как генераторы текста.
Итог
- N-грамма — цепочка из N подряд идущих слов или символов.
- Биграммы и триграммы возвращают локальный порядок и ловят «не понравилось».
- Символьные n-граммы устойчивы к опечаткам и морфологии.
- Плата — резкий рост размерности, поэтому n обычно держат маленьким (1-2).