Известная утилита дистрибутивной семантики Word2Vec демонстрирует удивительные результаты и стабильно обеспечивает использующих её специалистов призовыми местами на конкурсах машинной лингвистики. Преимущество утилиты, как впрочем, и её аналогов – Glove и AdaGram, состоит в дешевизне процесса обучения и подготовки обучающих текстов. Но есть и недостатки – представление слов в виде векторов хорошо работает на словах, удовлетворительно на словосочетаниях, так-себе на фразах и вообще никак – на длинных текстах.
В данной статье предлагается к обсуждению подход, позволяющий представить текст любой длины в виде вектора, позволяющий проводить с текстами операции сравнения (вычисления дистанции), сложения и вычитания.
От векторных репрезентаций к семантическому вектору
Векторные репрезентации слов, полученных в результате работы Word2Vec, обладают следующим интересным свойством – смысл имеют только расстояния между векторами, а не сами вектора. Другими словами – разложить саму векторную репрезентацию конкретного слова на составляющие и изучить её представляется трудноразрешимой задачей. В первую очередь потому, что процесс обучения стартует с неких случайных начальных векторов и более того, сам процесс обучения случаен. Его случайность связана с принципом стохастического обучения, когда параллельно выполняющиеся потоки обучения не синхронизируют вносимые изменения друг с другом, реализуя в чистом виде гонку данных. Но качества обучения эта гонка существенно не снижает, тогда как скорость обучения увеличивается весьма заметно. Именно благодаря случайной структуре алгоритма и данных – векторная репрезентация слова не раскладываема на осмысленные составляющие и может использоваться только в целом.
Негативным эффектом указанного свойства векторной репрезентации является быстрая деградация векторов при операциях над ними. Сложение векторов двух слов обычно демонстрирует то общее, что есть между этими словами (если слова действительно связаны в реальном мире), но попытка увеличить количество слагаемых очень быстро приводит к потере какого-либо практически ценного результата. Сложить слова одной фразы – ещё можно, нескольких фраз – уже нет. Необходим иной подход.
С точки зрения обывательской логики, как можно описать какой-либо текст? Попытаться указать его тематику, может быть – сказать пару слов о стиле. Тексты, посвящённые автомобилям, очевидно, будут содержать достаточно большое количество слов “автомобиль” и близких к нему, могут содержать слово “спорт”, названия автомобильных марок и так далее. С другой стороны, тексты на другую тематику будут содержать подобных слов намного меньше или не содержать вовсе. Таким образом, перечислив достаточное количество возможных тематик текста, мы можем посчитать статистику наличия в тексте соответствующих каждой тематике слов и получить семантический вектор текста – вектор, каждый элемент которого обозначает отношение данного текста к тематике, кодированной этим элементом.
Стиль текста, в свою очередь тоже определяется статистическими методами – это характерные для автора слова паразиты и речевые обороты, специфика начала фраз и расстановки знаков пунктуации. Поскольку мы при обучении разделяем заглавные и прописные буквы и не убираем из текста знаки пунктуации, то словарь Word2Vec полон словами типа “текста,” – именно так, с запятой. И именно такие слова и могут использоваться для выделения авторского стиля. Разумеется, для устойчивого выделения стиля необходимы действительно громадные текстовые корпуса, или, как минимум, очень оригинальный авторский стиль, но, тем не менее, отличить газетную заметку от записи на форуме или твита несложно.
Таким образом, для построения семантического вектора текста необходимо описать достаточное количество устойчивых кластеров, отражающих тематику и стиль текста. В самой утилите Word2Vec есть встроенный кластеризатор на основе kMeans, им и воспользуемся. Кластеризатор поделит все слова из словаря на заданное число кластеров, и, если количество кластеров будет достаточно большим, можно ожидать, что каждый кластер будет указывать на достаточно узкую тематику текста, а точнее – на узкий признак тематики или стиля. В своей задаче я использовал две тысячи кластеров. То есть – длина семантического вектора текста составляет две тысячи элементов, и каждый элемент этого вектора может быть объяснён через соответствующие данному кластеру слова.
Относительная плотность слов из каждого кластера в исследуемом тексте хорошо описывает текст. Разумеется, каждое конкретное слово имеет отношение ко многим кластерам, к каким-то больше, к каким-то меньше. Поэтому, в первую очередь необходимо вычислить семантический вектор слова – как вектор, описывающий расстояние от слова до центра соответствующего кластера в векторном пространстве Word2Vec. После чего, складывая семантические вектора отдельных слов, составляющих текст, мы получаем семантический вектор всего текста.
Описанный алгоритм, основанный на вычислении относительной частоты слов, задающих соответствующие тематики, хорош тем, что подходит для текстов любой длины. От одного слова и до бесконечности. При этом, как мы знаем, трудно найти достаточно длинный текст одной тематики, часто тематика текста изменяется от его начала к концу. Короткий текст, или сообщение, наоборот, не может охватить множество тем именно за счёт своей кратости. Как итог, получается, что семантический вектор длинного текста отличается признаками нескольких тем от короткого текста, в которых признаков тем намного меньше, но они представлены намного сильнее. Длина текста явно не учитывается, тем не менее алгоритм надёжно разводит короткие и длинные тексты в векторном пространстве.
Как использовать семантический вектор текста?
Поскольку каждому тексту поставлен соответствие вектор в семантическом пространстве, мы можем вычислить расстояние между любыми двумя текстами как косинусную меру между ними. Имея расстояние между текстами, можно использовать алгоритм kMeans для проведения кластеризации или классификации. Только в этот раз – уже в векторном пространстве текстов, а не отдельных слов. Например, если у нас стоит задача отфильтровать из потока текстов (новости, форумы, твиты и т.д.) только имеющие интересующую нас тематику, можно подготовить базу заранее размеченных текстов, а для каждого исследуемого текста вычислять класс, к которому он тяготеет более всего (максимум усреднённой косинусной меры по нескольким лучшим вхождениям каждого класса – kMeans в чистом виде).
Указанным способом была успешно решена довольно сложная задача классификации текстов на большое (несколько сотен) число классов, при значительном различии текстов по стилю (разные источники, длина, даже языки сообщений) и при наличии тематической связанности классов (один текст часто может иметь отношение к нескольким классам). К сожалению, конкретные цифры полученных результатов находятся под NDA, но общая результативность подхода следующая – 90% точности на 9% классов, 99% точности на 44% классов, 76% точности на 3% классов. Эти результаты следует интерпретировать следующим образом – классификатор сортирует все несколько сотен целевых классов по оценке степени соответствия текста данному классу, после чего, если мы возьмём топ 3% классов, то целевой класс окажется в этом списке с 76% вероятностью, а на 9% классов вероятность уже превысит 90%. Без преувеличения, это удивительный по силе результат, имеющий большую практическую пользу для заказчика.
Более подробный доклад с детальным описанием алгоритма, формулами, графиком и результатами я приглашаю вас послушать на ближайшем Диалоге.
Как ещё использовать семантический вектор?
Семантический вектор текста, как уже упоминалось, состоит из осмысляемых (никто не будет осмыслять все две тысячи элементов вектора, но это возможно) элементов. Да, они не являются независимыми, но, тем не менее, являются готовым к использованию вектором признаков, который можно загрузить в ваш любимый универсальный классификатор – SVM, деревья или глубокие сетки.
Выводы
Метод превращения текста произвольной длины в вектор с опорой на векторные репрезентации слов Word2Vec действительно работает и даёт хорошие результаты в задачах кластеризации и классификации текстов. Признаки текста, кодируемые семантическим вектором, не деградируют с увеличением длины текста, а наоборот – позволяют более тонко дифференцировать длинные тексты друг от друга и сильно разводят тексты с существенно разной длиной. Общий объём вычислений скромный – один месяц на нормальном сервере.