Если вы работали над проектом по реферированию текстов, то вы могли заметить сложность получения тех результатов, которые ожидалось получить. Если у вас имелись представления относительно того, как должен работать некий алгоритм, какие предложения он должен выделять при формировании рефератов, то этот алгоритм, чаще всего, выдавал результаты, весьма далёкие от ваших представлений. А ещё интереснее — ситуация с извлечением из текстов ключевых слов. Дело в том, что существует множество самых разных алгоритмов — от тех, что используют тематическое моделирование, до тех, где применяется векторизация данных и эмбеддинги. Все они работают очень хорошо. Но если дать одному из них абзац текста, то выданный им результат, опять же, будет далеко не самым правильным. А дело тут в том, что слова, которые встречаются в тексте чаще всего — это не всегда самые важные слова. Требования к препроцессингу и очистке данных могут сильно варьироваться в зависимости от задачи, которую пытаются решить с помощью NLP-моделей. Я попытаюсь создать универсальный пайплайн, который должен хорошо подойти для всех NLP-моделей. Но то, что делается в ходе выполнения этого пайплайна, нужно будет подстраивать под каждую конкретную ситуацию. В этом материале я буду говорить об NLP-моделях, нацеленных на решение следующих задач: тематическое моделирование, извлечение из текстов ключевых слов, реферирование текстов. На вышеприведённом изображении показаны шаги, которым мы будем следовать, создавая препроцессинговый пайплайн для NLP-моделей. Эти четыре шага мы рассмотрим ниже, проиллюстрировав их с помощью кода. Специально для этого материала создан Jupyter-блокнот, в котором приведена полная реализация пайплайна. Суть этого пайплайна в том, чтобы подвергнуть текстовые данные такому преобразованию, которое позволит повысить эффективность алгоритмов машинного обучения, предназначенных для обработки этих данных. Мы будем говорить о том, как выжать максимум из обучения NLP-моделей, передавая им входные данные, выглядящие наилучшим образом. Первый шаг нашего пайплайна — это очистка входных текстовых данных. Сам этот шаг может быть разбит на несколько более мелких шагов. Тут всё зависит от той модели, которую пытаются создать с использованием обрабатываемых данных, и от тех результатов, которые ожидают от этой модели получить. Алгоритмы машинного обучения (или, в широком смысле, все компьютерные алгоритмы, скорее даже — все компьютерные инструкции) работают с числами. Именно поэтому разработка моделей для обработки текстовых данных — это трудная и интересная задача. Мы, создавая такую модель, фактически просим компьютер изучить и обработать то, чего он никогда раньше не видел. А это требует времени. Ниже я приведу код первой из функций нашего пайплайна, которая производит очистку текстовых данных. В этой функции выполняется множество действий, смысл которых я пояснил в комментариях к коду. Ниже показан результат использования этой функции для очистки текста: По выходным данным этой функции можно судить о том, что переданный ей текст очищен от HTML-тегов, что эмоджи в нём заменены на их текстовые описания, что из текста удалены знаки препинания и специальные символы. С таким текстом легче будет работать на следующих шагах нашего пайплайна, где мы займёмся его дальнейшим улучшением. Этот шаг нашего пайплайна, возможно, представляет собой самую важную и самую недооценённую процедуру в деле обработки естественного языка. На следующей схеме показано приблизительное представление того, чем будет заниматься соответствующий алгоритм. Почему же устранение «шума» — это так важно? Дело в том, что текст «шума», хотя и присутствует во входных данных, не содержит никакой полезной информации, которая способна улучшить результаты обучения модели. Документы — наподобие юридических соглашений, новостных статей, государственных контрактов и прочих подобных содержат большие объёмы шаблонных формулировок, специфичных для различных сфер деятельности. Представьте себе создание проекта по тематическому моделированию, который ориентирован на работу с юридическими договорами. В рамках проекта нужно разобраться с наиболее важными условиями, имеющимися в наборе договоров. При этом в договорах имеются большие объёмы текстов — очень важных, но не отражающих специфику каждого конкретного документа. Это могут быть, например, какие-то формулировки, взятые из текстов законов. Если алгоритм будет ориентироваться на эти формулировки — результаты его работы, в целом, окажутся бесполезными, так как создателям проекта нужно, чтобы он извлекал бы из текстов договоров информацию, уникальную для каждого из них. Удаление шаблонных формулировок из текстовых данных — это непростая, но чрезвычайно важная задача. Так как эти формулировки представлены в виде обычного текста, внешне ничем не выделяющегося, их тяжело находить и удалять. Но если оставить их в тексте, передаваемом модели, это может сильно ухудшить результаты её обучения. Рассмотрим реализацию функции, которая убирает из входного текста «шум» и шаблонные формулировки. Применяемый здесь алгоритм использует кластеризацию для поиска часто встречающихся предложений и слов. Алгоритм исходит из предположения о том, что если частота появления в тексте неких структур превышает заданное пороговое значение, эти структуры, вероятно, являются «шумом». «Шум», найденный в тексте, удаляют. Ниже приведены результаты обработки этой новостной статьи с помощью нашей функции. Тут можно заметить, что алгоритму передали текст длиной 7574 символа, а после удаления из текста «шума» и шаблонных фрагментов его размер сократился до 892 символов. Получается, что нам удалось уменьшить размеры входного текста примерно на 88%. Фактически, мы удалили из текста мусор, который иначе добрался бы до алгоритма машинного обучения. Итоговый текст — это более аккуратная, осмысленная, тезисная форма входных данных. Убрав из текста всё лишнее, мы как бы указываем нашему алгоритму на то, что ему нужно сосредоточиться лишь на самом важном. Частеречная разметка текста (parts-of-speech tagging, POS-tagging) — это процесс назначения словам входного текста определённых меток. Программа читает слова и разбирается в их взаимоотношениях с другими словами предложения, понимает, в каком контексте они применяются. В частности, речь идёт об отнесении слов к таким грамматическим категориям, как имена существительные, глаголы, имена прилагательные, местоимения, предлоги, наречия, союзы и междометия. Это — крайне важный этап предварительной подготовки текста. Дело в том, что многим алгоритмам обработки текста необходимо понимать контекст, в котором используются слова. Это справедливо для алгоритмов, анализирующих тональность текстов и занимающихся классификацией текстов, для алгоритмов, извлекающих из текстов какую-то информацию, занимающихся машинным переводом, или каким-то образом анализирующих текст. Контекст, в котором используются слова, способен сильно повлиять на работу тех частей алгоритмов, которые отвечают за понимание естественного языка. Теперь нам осталось рассмотреть лишь последний шаг нашего пайплайна. Это — преобразование текста в векторные эмбеддинги, которые будут использоваться алгоритмом машинного обучения. Но, прежде чем перейти к этой теме, обсудим ещё два важных момента — лемматизацию и стемминг. Лемматизация и стемминг — это распространённые в сфере обработки естественного языка подходы приведения слов, изменённых грамматически, к их базовой или начальной форме. Лемматизация и стемминг — это, вероятно, ещё и одни из наиболее спорных механизмов NLP, поэтому стоит разобраться с тем, когда их нужно использовать, а когда не нужно. В основе обоих этих механизмов лежит идея уменьшения размерности входного пространства признаков. Это помогает увеличить производительность моделей машинного обучения, к которым в итоге попадут обработанные данные. Стемминг — это удаление «лишних» фрагментов слов для приведения их к базовой форме. А в процессе лемматизации текста для приведения слов к их базовой форме используется словарь и разновидность морфологического анализа. При лемматизации текст подвергается более точной обработке, чем в ходе стемминга, но лемматизация при этом отличается более высокой вычислительной сложностью. На вопрос о том, что именно выбрать для конкретного проекта, можно ответить, учтя необходимый баланс между скоростью и точностью применяемых инструментов. Вот несколько важных соображений, которые стоит учитывать, размышляя о применении лемматизации или стемминга в проекте: При лемматизации сохраняется семантика входного текста. Алгоритмы, рассчитанные на анализ тональности текста, могут показывать лучшие результаты в том случае, если в обрабатываемых ими текстах сохраняется информация о временах глаголов. Иногда то, что произошло в прошлом, может иметь эмоциональную окраску, отличную от той, которую имеет то же самое, произошедшее в настоящем. Стемминг быстрее лемматизации, но точность этого процесса ниже. В случаях, когда речь идёт о задачах классификации текстов, в ходе решения которых нужно разделить по категориям тысячи слов, стемминг, исключительно из-за более высокой скорости, может оказаться лучше, чем лемматизация. Как и в других подобных ситуациях, выбирая между лемматизацией и стеммингом, можно исследовать оба этих подхода в применении к конкретному проекту. Ответ о том, что именно выбрать, даст сравнение результатов работы модели. Кроме того, некоторые модели глубокого обучения отличаются способностью автоматически изучать представления слов, что делает неактуальным использование в них стемминга или лемматизации. Последний шаг нашего пайплайна включает в себя лемматизацию текста и преобразование слов в векторные эмбеддинги (не будем забывать о том, что машины лучше работают с числами, а не со словами). Как уже говорилось, лемматизация нужна не во всех проектах. Тут всё зависит от того, каких результатов ожидают от модели, и о от того, какими алгоритмами обучения пользуются. Я, чтобы сделать мой пайплайн универсальнее, включил в него лемматизацию. Функция, код которой приведён ниже, извлекает слова, подвергнутые частеречной разметке, из полученных ей входных данных. Затем она подвергает слова лемматизации и преобразует их в векторные эмбеддинги. Дополнительные пояснения к этой функции содержатся в комментариях к ней. Эта функция возвращает массив numpy размера (num_words, X), где num_words — количество слов во входном тексте, а X — размер векторных эмбеддингов. Слова, представленные в виде векторных эмбеддингов (числовые представления слов), должны быть теми входными данными, которые передаются алгоритму машинного обучения. Иногда, при использовании некоторых моделей глубокого обучения или некоторых больших языковых моделей, нет нужды ни в векторных эмбеддингах, ни в лемматизации, так как используемый в таких моделях алгоритм достаточно развит для того, чтобы создавать собственные представления слов. Это значит, что данный шаг можно исключить из пайплайна в том случае, если он применяется вместе с такими «самообучающимися» алгоритмами. В предыдущих четырёх разделах этого материала мы рассмотрели отдельные элементы нашего препроцессингового пайплайна. Здесь лежит Jupyter-блокнот, в котором можно поэкспериментировать с кодом. Мне хотелось бы обратить ваше внимание на то, что этот пайплайн нельзя назвать универсальным, подходящим абсолютно для всех задач обработки естественного языка. В его основе лежит идея создания надёжного механизма, предназначенного для подготовки данных перед передачей их алгоритмам машинного обучения. Ожидается, что именно такие данные позволят добиться от этих алгоритмов наилучших результатов. Приведённая выше последовательность шагов пайплайна должна решить примерно 70% задач по подготовке данных конкретного проекта. А оставшиеся 30% — это то, что разработчику проекта придётся сделать самостоятельно, занимаясь тонкой настройкой и доработкой пайплайна. Надеюсь, у вас, после прочтения этой статьи, появилось представление о подготовке данных для проектов по обработке естественного языка. Работа со словами — это одна из самых сложных задач из мира искусственного интеллекта. Но если, перед передачей моделям, правильно очищать тексты, подвергать их предварительной обработке, можно добиться хороших результатов в обучении моделей. При этом последовательность применения шагов, описанных в этом материале, так же важна, как и правильная реализация действий, входящих в эти шаги. Каждый шаг зависит от успешности выполнения предыдущего шага. Так, логика, ответственная за удаление шаблонных фраз, не сможет правильно идентифицировать «шум» в том случае, если полученные ей данные содержат много стоп-слов или HTML-тегов. А частеречная разметка текста, лемматизация, векторизация текста — всё это ресурсозатратные операции, они редко применяются без должного контроля за тем, что поступает на их вход, и что оказывается у них на выходе. Предлагаю вам поэкспериментировать с этим пайплайном и насладиться теми улучшениями, которые он принесёт в ваши NLP-проекты. Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки. Мы предлагаем интересные и сложные задачи по анализу данных и low latency разработке для увлеченных исследователей и программистов. Гибкий график и никакой бюрократии, решения быстро принимаются и воплощаются в жизнь. Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров. Присоединяйтесь к нашей команде.