Обработка естественного языка

Регулярные выражения и текст

Цели урока

  • Строить regex для извлечения email, телефонов и URL из неструктурированного текста
  • Понимать разницу NFC/NFD нормализации и когда она ломает производственные системы
  • Различать overstemming и understemming, выбирать между stemmer-ами
  • Применять lemmatization с правильным POS-тегом для получения словарной формы

Предварительные знания

  • Введение в NLP

Alan Turing и машина, которая понимает язык

1950 год. Alan Turing публикует "Computing Machinery and Intelligence". Центральный вопрос: "Can machines think?" - Тьюринг считает его бессмысленным и предлагает другой: может ли машина вести диалог так, что человек не отличит её от человека? Тест Тьюринга. Этот вопрос запустил всё: от regex-паттернов 1950-х до BERT и GPT-4. Preprocessing текста - regex, нормализация, stemming - это нижний уровень той же пирамиды, которую Тьюринг обозначил 70 лет назад.

2003 год. Спам составлял 45% всей email-трафика. Первые фильтры - чистый regex: `V[1!i]AGRA`, `fr33 m0n3y`. Спамеры обходили через замену букв цифрами. Фильтры адаптировались. Это гонка вооружений продолжается. В 2024 году Gmail блокирует 99.9% спама - первый рубеж обороны всё ещё regex, но за ним стоят BERT и собственные LLM Google.

  • **Elasticsearch** использует Snowball stemming для 23 языков: запрос "running" находит "runs", "runner", "ran" - без дополнительных настроек
  • **Gmail spam filter** - regex паттерны как первый быстрый уровень фильтрации перед ML-моделями
  • **spaCy production pipeline** - Unicode NFKC нормализация + lemmatization для 60+ языков, основа NER в медицинских и юридических системах
  • **Hugging Face tokenizers** - Unicode normalization перед BPE: без NFKC один и тот же символ может кодироваться по-разному

Регулярные выражения

2003 год. Gmail запускает спам-фильтр. Первый уровень защиты - не нейросеть. **Regex**: паттерны `V[1!i]AGRA`, `fr33 m0n3y`, `click h3re` блокируют миллионы писем до любого ML. Сегодня в spaCy pipeline, Hugging Face tokenizers, OpenAI text prep - везде regex на первом шаге. Одна строка паттерна заменяет десятки строк кода.

СимволЗначениеПримерСовпадения
.Любой символc.tcat, cot, c9t
*0 или болееab*cac, abc, abbc
+1 или болееab+cabc, abbc (не ac)
?0 или 1colou?rcolor, colour
[]Класс символов[aeiou]a, e, i, o, u
\dЦифра\d{3}123, 999, 007
\wБуква/цифра/_\w+hello, var_1
|ИЛИcat|dogcat, dog
()Группа(ab)+ab, abab, ababab

**Regex - выразительный, но хрупкий инструмент.** Regex для валидации email по RFC 5322 занимает ~6000 символов. Для NLP-задач regex отлично подходит для preprocessing (удаление URL, hashtag-ов, HTML-тегов), но не для понимания смысла. Знак `$` в regex-паттернах - анкор конца строки, не доллар. Для денежных сумм в тексте писать словами.

**regex101.com** - тестирование паттернов в реальном времени с подсветкой совпадений и объяснением каждого символа. Незаменим при отладке сложных выражений.

Что найдёт выражение `re.findall(r'\b\w{3}\b', 'The cat sat on a mat')`?

Unicode-нормализация

2010 год. Поисковик авиакомпании не находит рейсы в "Sao Paulo" - в базе город записан как "São Paulo". Один диакритический знак, тысячи несостоявшихся бронирований. Корень проблемы: Unicode позволяет записать один символ разными способами. `"café" == "cafe\u0301"` возвращает `False`, хотя строки выглядят одинаково. **Нормализация** - приведение к каноническому виду, чтобы одинаковые по смыслу строки стали одинаковыми по байтам.

ФормаНазваниеЧто делаетКогда использовать
NFCCanonical CompositionСкладывает символы (e + combining -> é)По умолчанию для NLP
NFDCanonical DecompositionРаскладывает символы (é -> e + combining)Для удаления акцентов
NFKCCompatibility CompositionNFC + совместимость (fi -> fi)Поиск, индексация
NFKDCompatibility DecompositionNFD + совместимостьМаксимальная нормализация

**Case folding** - это расширенный lowercasing. В немецком `"ss".lower()` = `"ss"`, но `"ss".casefold()` = `"ss"`. В турецком `"I".lower()` = `"i"` (без точки!), а не `"i"`. Метод `str.casefold()` в Python учитывает языковые особенности - критично для multilingual NLP.

**Не удалять акценты для всех языков!** В испанском "ano" (год) и "ano" (анатомия) - разные слова. В чешском "s" и "s" - разные буквы. Удаление акцентов безопасно только для задач, где recall важнее precision.

Почему `"cafe\u0301" == "café"` возвращает False, хотя строки выглядят одинаково?

Stemming

Elasticsearch индексирует миллиарды документов. Запрос "running shoes" должен находить и "runs shoes" и "runner gear". **Stemming** - алгоритмическое отрезание суффиксов для приведения слова к основе (стему). Быстро, интерпретируемо, не требует GPU. Martin Porter опубликовал первый алгоритм в 1980 году - он до сих пор в ядре Elasticsearch и Lucene.

**Stemming - это грубый алгоритм.** Результат - не обязательно реальное слово. Porter превращает "university" и "universe" в одинаковый стем "univers" (overstemming), а "organization" -> "organ" (тоже не слово). Для задач, где важна точность смысла, stemming не подходит.

StemmerЯзыкиСкоростьКачество
PorterТолько английскийОчень быстрыйМного ошибок
Snowball23 языка (вкл. русский)БыстрыйЛучше Porter
LancasterТолько английскийБыстрыйСамый агрессивный

**Когда stemming оправдан:** поисковые системы, information retrieval, где важен recall (найти ВСЁ релевантное), а не precision. Elasticsearch использует Snowball stemming как анализатор для расширения поисковых запросов.

Porter Stemmer превращает "university" и "universe" в одинаковый стем "univers". Как называется эта ошибка?

Lemmatization

Stemming отрезает суффиксы механически. **Lemmatization** идёт другим путём - словарь и морфологический анализ, чтобы найти **лемму** (словарную форму). "better" -> "good", "mice" -> "mouse", "went" -> "go". Результат всегда реальное слово. spaCy, Stanza, NLTK WordNet - production инструменты, которые это делают. Google Assistant и Siri используют lemmatization на этапе intent parsing.

**Лемма** - каноническая (словарная) форма слова. Для существительных - именительный падеж единственного числа ("mice" -> "mouse"). Для глаголов - инфинитив ("went" -> "go"). Для прилагательных - положительная степень ("better" -> "good").

КритерийStemmingLemmatization
МетодАлгоритм отрезания суффиксовСловарь + морфологический анализ
СкоростьОчень быстрый (~1M слов/сек)Медленнее (нужен словарь/модель)
РезультатНе обязательно слово ("univers")Всегда реальное слово ("university")
POS нужен?НетДа ("running" -> "run" только если глагол)
Неправильные формыНе справляется ("went" -> "went")Справляется ("went" -> "go")
ПрименениеПоиск, IRChatbots, QA, генерация

**Правило большого пальца:** для поиска и индексации - stemming (скорость важнее точности). Для понимания смысла (intent detection, QA, sentiment analysis) - lemmatization. ChatGPT не использует stemming - его токенизатор BPE работает принципиально иначе, без словаря.

Stemming достаточно для любой NLP-задачи - lemmatization только медленнее, а результат тот же

Stemming и lemmatization дают РАЗНЫЕ результаты. Stemming ломает слова ('university' -> 'univers'), путает несвязанные слова (overstemming) и не справляется с неправильными формами ('went' не станет 'go'). Lemmatization сохраняет смысл, но требует знания части речи.

Stemming - это эвристика на основе правил отрезания суффиксов. Lemmatization - это поиск в лингвистическом словаре. Для задач, где важен смысл (sentiment analysis, intent detection, QA), stemming генерирует слишком много ошибок.

Почему `WordNetLemmatizer().lemmatize('running')` возвращает 'running', а не 'run'?

Ключевые идеи

  • **Regex** - первый рубеж NLP pipeline: очистка HTML, URL, mentions. Одна строка паттерна = десятки строк кода. Gmail, Elasticsearch, spaCy начинают с этого
  • **Unicode-нормализация** (NFC/NFD) - «Sao Paulo» vs «São Paulo» - это реальный баг реальной авиакомпании. `str.casefold()` вместо `str.lower()` для multilingual
  • **Stemming** - быстрый и грубый: отрезает суффиксы, не гарантирует реальное слово. Overstemming ("university" = "universe") - цена скорости
  • **Lemmatization** - точный, но медленный: словарь + POS = "went" -> "go". Google Assistant, Siri используют этот подход для intent parsing
  • **Выбор инструмента**: поиск и recall -> stemming; понимание смысла и precision -> lemmatization. Нейросетевые токенизаторы (BPE) обходят оба подхода для LLM

Связанные темы

Текстовый preprocessing - фундамент для следующих шагов NLP:

  • Введение в NLP — Preprocessing - часть NLP pipeline из предыдущего урока
  • Bag of Words и TF-IDF — Нормализованные токены - вход для векторных представлений

Вопросы для размышления

  • В каких случаях stemming может навредить результату поиска (hint: overstemming)?
  • Почему spaCy-лемматизация работает лучше, чем WordNet без указания POS?
  • Если строится поисковая система для турецкого языка - какие особенности Unicode/case folding нужно учесть?

Связанные уроки

  • nlp-01 — NLP pipeline и понятие токенизации из вводного урока
  • nlp-03 — Нормализованные токены - вход для TF-IDF и Bag of Words
  • ir-01 — Stemming и regex используются в поисковых индексах Elasticsearch
  • aie-03-llm-fundamentals — LLM токенизация строится поверх тех же принципов нормализации
  • dl-01 — Препроцессинг текста предшествует эмбеддингам и нейросетевым моделям
  • fl-05-regex
Регулярные выражения и текст

0

1

Войти