Используем большой структурированный источник мультиязычных текстов – Википедию для улучшения качества классификации текстов. Подход хорош высокой степенью автоматизма и независимостью от того, какая именно задача классификации решается. Наибольший эффект, однако, ожидается на задачах определения тематики.
Основная идея в том, что бы вытащить из Википедии только те тексты, которые помогают нам решать нашу задачу классификации, проигнорировав другие. Если мы классифицируем тексты про кошечек, вряд-ли нам понадобятся тексты по квантовой физике, хотя тексты по другим видам животных могут быть полезны. Автоматическое отделение таких текстов друг от друга и есть суть описываемого подхода.
Википедия, как известно, является набором статей по множеству областей знаний и интересов. При этом, значительная часть статей обладает связями со статьями аналогичной тематики, но на других языках. Это не переводы, а именно статьи общей тематики. Также большая часть статей отнесена к одной или нескольким категориям. Категории, в свою очередь, в массе своей организованы в виде иерархического дерева. То есть, задачу группировки статей Википедии по интересующей нас тематике решить можно.
Используем ресурс DBPedia – предварительно распаршенную и структурированную версию Википедии. DBPedia даёт нам всю необходимую информацию – названия статей, их аннотации, категории статей и вышестоящие категории для категорий. Начинаем с самого широко представленного в Википедии языка – английского. Если в вашей задаче нет, или мало, англоязычных текстов, используйте тот язык, документов по которому много.
Концентрируемся на категориях статей. Пока игнорируем их содержание. Категории образуют граф, преимущественно древовидный, но циклы тоже есть. Статьи – это конечные точки графа (листья), подключённые к одному или нескольким узлам графа. Используем инструмент Node2Vec для получения векторной репрезентации каждой категории и каждой статьи. Статьи сходной тематики кучкуются в векторном пространстве рядом.
Кластеризуем любым удобным методом статьи на довольно большое (сотни) количество кластеров.
Заменяем названия статей в полученных кластерах на их аннотации (Long Abstract и Short Abstract – примерно по одному абзацу текста на статью). Теперь у нас есть сотни кластеров, заданных в виде наборов текстов. Используем удобную модель и строим классификатор, решающий задачу мультиклассовой классификации: один кластер – один класс. Мы использовали FastText.
На выходе получается модель, принимающая на вход текст, и на выходе дающая вектор оценок степени принадлежности текста к нашим сотням кластеров-классов.
Если на первом шаге кластеризовать статьи Википедии не по их категориям, а по их содержанию, то, во-первых, мы потеряем информацию по категориям, а она важна, а во-вторых – получится вырожденная система – которая по текстам и кластеризуется, и строит модель классификатора. Итоговое качество, наверное, будет хуже, чем при раздельном подходе. Хотя я и не проверял.
Используем выборку своих боевых данных и подаём каждый документ на вход модели из шага 2. Модель возвращает вектор оценок. Используем этот вектор в качестве вектора признаков для рассматриваемого документа. В итоге, обработав всю свою обучающую выборку боевых документов, получим таблицу в стандартном для машинного обучения виде – метка класса, набор числовых признаков. Называем эту таблицу обучающей выборкой.
Строим на обучающей выборке классификатор, умеющий оценивать информативность отдельных признаков. Хорошо подходят деревья решений и любые их случайно-лесные вариации. Наиболее информативными признаками оказываются те кластеры статей Википедии, которые не только имеют сходную тематику с тематиками наших боевых документов, но, главное, — тематики этих статей позволяют хорошо разделять наши боевые классы. На первых итерациях гистограмма информативности признаков обычно достаточно пологая – несколько информативных кластеров и длинный хвост практически равных по информативности остальных сотен признаков.
Изучив гистограмму информативности признаков эмпирически каждый раз определялась точка перегиба, и примерно от 10 до 30% кластеров переходили на следующую итерацию. Суть итерации в том, что статьи из отобранных информативных кластеров объединялись, подавались на шаги 1-3, где снова кластеризовались, снова строились два классификатора и завершалось всё анализом гистограммы информативности. Понадобится от 3-4 итераций.
Оказалось, что на наших данных цифровые признаки, особенно номера годов, имеют очень сильный вес и перетягивают на себя информативность всего кластера. Как закономерный итог, самыми информативными стали кластеры, посвящённые ежегодным спортивным мероприятиям – масса цифр и дат, узкая лексика. Пришлось в текстах аннотаций статей убрать все цифры (на втором шаге). Стало заметно лучше, стали выделяться кластеры статей, действительно имеющих целевую тематику (как мы её себе представляли). При этом появились и неожиданные кластеры, которые логично ложились на нашу боевую задачу, имели нужную лексику, но при этом априори догадаться о полезности таких кластеров было ну очень трудно.
После нескольких итераций шагов 1-3, имеем разумное количество отобранных из Википедии статей, чья тематика помогает разделять наши боевые документы. Расширяем выборку статьями-аналогами на других интересующих нас языках и строим финальные кластеры, на этот раз – десятки. Данные кластеры можно использовать двояко – либо построить классификатор аналогичный шагу 2, и использовать для расширения цифрового вектора признаков в своей боевой задаче, либо использовать данные наборы текстов в качестве источника дополнительной лексики и внедрить их в свой боевой классификатор. Мы использовали второй путь.
Наш боевой классификатор является ансамблем двух моделей – урезанного наивного байеса и xgboost. Наивный байес работает на длинно-граммах, это граммы длиной от 1 до 16-ти элементов, и каждая найденная грамма склоняет итоговую сумму к одному из классов, но при этом сам байес финального решения не принимает – только выдаёт суммы весов грамм, относящихся к каждому из классов. Xgboost принимает выход байеса, других классификаторов и некоторых цифровых признаков, строимых по тексту независимо, и уже xgboost даёт финальную модель и финальную оценку. Такой подход позволяет легко подключить к модели граммного байеса любые наборы текстов, в том числе и полученные наборы статей из Википедии, а xgboost уже ищет закономерности в виде типичных реакций википедийных кластеров на боевые тексты.
Первый результат дал прирост с условных 60% точности до 62%. При замене аннотаций статей Википедии на шаге 4 на сами выкаченные статьи точность выросла до 66%. Результат закономерный, ведь размер аннотации – две-три фразы, а размер статьи на порядки больше. Больше лингвистического материала – выше эффект.
Стоит ожидать, что проделав всю процедуру на текстах статей, а не аннотациях, прирост качества будет ещё больше, но тут уже проблема число техническая – выкачать и обработать всю Википедию, или её заметную часть (если начинать не с первой итерации) – сложно. Также, если изначально использовать не только английский, а все интересующие языки – можно будет ещё что-то выиграть. В данном случае рост обрабатываемых объёмов кратный, а не на порядки, как в первом случае.
Для каждого документа строится вектор отношения документа к заданным тематикам на основе категорий Википедии. Вектор стоится либо методом, описанным в шаге 3, либо нашим граммным байесом. Соответственно, боевые документы можно кластеризовать по данным векторам и получить группировку боевых документов по тематике. Остаётся только проставить хештеги и каждый новый документ уже может попадать в базу с тегами. По которым потом пользователи могут искать. Это в случае, если проставлять теги явным и видимым пользователю образом. Выглядит модно, хотя я и не сторонник.
Более интересный метод использования семантических векторов документа – адаптивный поиск. Наблюдая за активностью пользователя, на каких именно документах он задерживается, а какие даже не читает, можно очертить сферу интересов пользователя и в долгосрочном смысле (ведь у пользователей тоже разделение сфер ответственности и каждый преимущественно ищет своё) и в рамках текущей поисковой сессии.
Документы, имеющие сходную тематику, имеют сходные семантические вектора, имеющие высокую косинусную меру, и это позволяет на лету оценивать документы в поисковой выдаче по степени их ожидаемого соответствия интересам пользователя, в результате чего повышать в поисковой выдаче нужные документы.
Как результат, даже при идентичных поисковых запросах у каждого пользователя поисковая выдача может быть настроена персонально на него и в зависимости от того, какие из документов на предыдущем шаге пользователя заинтересовали, следующий шаг поиска подстроится под потребности пользователя, даже если сам поисковый запрос не изменился.
Над проблемой адаптивного поиска мы сейчас и работаем.
Бизнес периодически приходит со светлыми идеями, которые очень трудно реализовать. Надо научиться находить документы по их описанию, не имея ни размеченной выборки для обучения, ни возможности подать асессорам какой-то набор документов для разметки. Такое обычно бывает, когда целевые документы встречаются редко относительно общего потока документов, и как результат – подав без предварительной фильтрации асессорам пул в 10 тыс. документов можно на выходе получить 1-2 нужных, а то и меньше.
Наш подход состоит в создании итеративного процесса обучения на основе семантических векторов. На первом шаге находим несколько текстов, задающих нашу целевую тематику – это могут быть статьи Википедии, либо тексты из других источников. Для каждого текста производится его семантический вектор. Если целевая тематика сложная, работает алгебра множеств – объединения, пересечения, исключения одних тематик из других. Например – есть статьи Википедии про “Научно-исследовательские разработки” и про “Косметика”, пересечение множеств даст “НИР про косметику”.
Все документы в базе можно отсортировать по степени их соответствия заданным тематикам, тогда алгебра множеств работает на самих документах следующим образом – документ считается имеющим отношение к тематике, если его семантический вектор ближе к вектору статей Википедии заданной тематики, чем в среднем по базе. Пересечение – если одновременно к обеим тематикам семантический вектор документа ближе, чем в среднем по базе. Другие операции – аналогично.
Находим набор из сотни-другой документов, имеющих наибольшую близость ко всем положительным тематикам и, одновременно, наименьшую близость ко всем отрицательным тематикам (если нас не интересуют в искомых исследованиях финансовые вопросы, то мы и зададим в качестве отрицательного примера статьи из категории “Финансы”). Отдадим эти документы асессорам, они в них найдут несколько положительных примеров, на основе этих примеров поищем другие документы с близкими семантическими векторами, разметим их, и на выходе получим достаточное количество документов для положительного класса для построения любого удобного классификатора. Возможно, потребуется несколько итераций.
Описанный подход позволяет автоматически, без ручного анализа, отобрать из Википедии или другого источника наборы текстов, помогающие решать задачу классификации. Просто подключив кластеры из Википедии к работающему классификатору можно ожидать значительного роста качества, не требуя при этом адаптации самого классификатора.
Ну и адаптивный поиск – это интересно.
Основная идея в том, что бы вытащить из Википедии только те тексты, которые помогают нам решать нашу задачу классификации, проигнорировав другие. Если мы классифицируем тексты про кошечек, вряд-ли нам понадобятся тексты по квантовой физике, хотя тексты по другим видам животных могут быть полезны. Автоматическое отделение таких текстов друг от друга и есть суть описываемого подхода.
Википедия, как известно, является набором статей по множеству областей знаний и интересов. При этом, значительная часть статей обладает связями со статьями аналогичной тематики, но на других языках. Это не переводы, а именно статьи общей тематики. Также большая часть статей отнесена к одной или нескольким категориям. Категории, в свою очередь, в массе своей организованы в виде иерархического дерева. То есть, задачу группировки статей Википедии по интересующей нас тематике решить можно.
Используем ресурс DBPedia – предварительно распаршенную и структурированную версию Википедии. DBPedia даёт нам всю необходимую информацию – названия статей, их аннотации, категории статей и вышестоящие категории для категорий. Начинаем с самого широко представленного в Википедии языка – английского. Если в вашей задаче нет, или мало, англоязычных текстов, используйте тот язык, документов по которому много.
Шаг 1. Кластеризация Википедии
Концентрируемся на категориях статей. Пока игнорируем их содержание. Категории образуют граф, преимущественно древовидный, но циклы тоже есть. Статьи – это конечные точки графа (листья), подключённые к одному или нескольким узлам графа. Используем инструмент Node2Vec для получения векторной репрезентации каждой категории и каждой статьи. Статьи сходной тематики кучкуются в векторном пространстве рядом.
Кластеризуем любым удобным методом статьи на довольно большое (сотни) количество кластеров.
Шаг 2. Обучение классификатора на Википедии
Заменяем названия статей в полученных кластерах на их аннотации (Long Abstract и Short Abstract – примерно по одному абзацу текста на статью). Теперь у нас есть сотни кластеров, заданных в виде наборов текстов. Используем удобную модель и строим классификатор, решающий задачу мультиклассовой классификации: один кластер – один класс. Мы использовали FastText.
На выходе получается модель, принимающая на вход текст, и на выходе дающая вектор оценок степени принадлежности текста к нашим сотням кластеров-классов.
Если на первом шаге кластеризовать статьи Википедии не по их категориям, а по их содержанию, то, во-первых, мы потеряем информацию по категориям, а она важна, а во-вторых – получится вырожденная система – которая по текстам и кластеризуется, и строит модель классификатора. Итоговое качество, наверное, будет хуже, чем при раздельном подходе. Хотя я и не проверял.
Шаг 3. Построение модели на своих, боевых, данных
Используем выборку своих боевых данных и подаём каждый документ на вход модели из шага 2. Модель возвращает вектор оценок. Используем этот вектор в качестве вектора признаков для рассматриваемого документа. В итоге, обработав всю свою обучающую выборку боевых документов, получим таблицу в стандартном для машинного обучения виде – метка класса, набор числовых признаков. Называем эту таблицу обучающей выборкой.
Строим на обучающей выборке классификатор, умеющий оценивать информативность отдельных признаков. Хорошо подходят деревья решений и любые их случайно-лесные вариации. Наиболее информативными признаками оказываются те кластеры статей Википедии, которые не только имеют сходную тематику с тематиками наших боевых документов, но, главное, — тематики этих статей позволяют хорошо разделять наши боевые классы. На первых итерациях гистограмма информативности признаков обычно достаточно пологая – несколько информативных кластеров и длинный хвост практически равных по информативности остальных сотен признаков.
Изучив гистограмму информативности признаков эмпирически каждый раз определялась точка перегиба, и примерно от 10 до 30% кластеров переходили на следующую итерацию. Суть итерации в том, что статьи из отобранных информативных кластеров объединялись, подавались на шаги 1-3, где снова кластеризовались, снова строились два классификатора и завершалось всё анализом гистограммы информативности. Понадобится от 3-4 итераций.
Оказалось, что на наших данных цифровые признаки, особенно номера годов, имеют очень сильный вес и перетягивают на себя информативность всего кластера. Как закономерный итог, самыми информативными стали кластеры, посвящённые ежегодным спортивным мероприятиям – масса цифр и дат, узкая лексика. Пришлось в текстах аннотаций статей убрать все цифры (на втором шаге). Стало заметно лучше, стали выделяться кластеры статей, действительно имеющих целевую тематику (как мы её себе представляли). При этом появились и неожиданные кластеры, которые логично ложились на нашу боевую задачу, имели нужную лексику, но при этом априори догадаться о полезности таких кластеров было ну очень трудно.
Шаг 4. Финализируем модель
После нескольких итераций шагов 1-3, имеем разумное количество отобранных из Википедии статей, чья тематика помогает разделять наши боевые документы. Расширяем выборку статьями-аналогами на других интересующих нас языках и строим финальные кластеры, на этот раз – десятки. Данные кластеры можно использовать двояко – либо построить классификатор аналогичный шагу 2, и использовать для расширения цифрового вектора признаков в своей боевой задаче, либо использовать данные наборы текстов в качестве источника дополнительной лексики и внедрить их в свой боевой классификатор. Мы использовали второй путь.
Наш боевой классификатор является ансамблем двух моделей – урезанного наивного байеса и xgboost. Наивный байес работает на длинно-граммах, это граммы длиной от 1 до 16-ти элементов, и каждая найденная грамма склоняет итоговую сумму к одному из классов, но при этом сам байес финального решения не принимает – только выдаёт суммы весов грамм, относящихся к каждому из классов. Xgboost принимает выход байеса, других классификаторов и некоторых цифровых признаков, строимых по тексту независимо, и уже xgboost даёт финальную модель и финальную оценку. Такой подход позволяет легко подключить к модели граммного байеса любые наборы текстов, в том числе и полученные наборы статей из Википедии, а xgboost уже ищет закономерности в виде типичных реакций википедийных кластеров на боевые тексты.
Результаты и выводы
Первый результат дал прирост с условных 60% точности до 62%. При замене аннотаций статей Википедии на шаге 4 на сами выкаченные статьи точность выросла до 66%. Результат закономерный, ведь размер аннотации – две-три фразы, а размер статьи на порядки больше. Больше лингвистического материала – выше эффект.
Стоит ожидать, что проделав всю процедуру на текстах статей, а не аннотациях, прирост качества будет ещё больше, но тут уже проблема число техническая – выкачать и обработать всю Википедию, или её заметную часть (если начинать не с первой итерации) – сложно. Также, если изначально использовать не только английский, а все интересующие языки – можно будет ещё что-то выиграть. В данном случае рост обрабатываемых объёмов кратный, а не на порядки, как в первом случае.
Семантический вектор документа
Для каждого документа строится вектор отношения документа к заданным тематикам на основе категорий Википедии. Вектор стоится либо методом, описанным в шаге 3, либо нашим граммным байесом. Соответственно, боевые документы можно кластеризовать по данным векторам и получить группировку боевых документов по тематике. Остаётся только проставить хештеги и каждый новый документ уже может попадать в базу с тегами. По которым потом пользователи могут искать. Это в случае, если проставлять теги явным и видимым пользователю образом. Выглядит модно, хотя я и не сторонник.
Адаптивный поиск
Более интересный метод использования семантических векторов документа – адаптивный поиск. Наблюдая за активностью пользователя, на каких именно документах он задерживается, а какие даже не читает, можно очертить сферу интересов пользователя и в долгосрочном смысле (ведь у пользователей тоже разделение сфер ответственности и каждый преимущественно ищет своё) и в рамках текущей поисковой сессии.
Документы, имеющие сходную тематику, имеют сходные семантические вектора, имеющие высокую косинусную меру, и это позволяет на лету оценивать документы в поисковой выдаче по степени их ожидаемого соответствия интересам пользователя, в результате чего повышать в поисковой выдаче нужные документы.
Как результат, даже при идентичных поисковых запросах у каждого пользователя поисковая выдача может быть настроена персонально на него и в зависимости от того, какие из документов на предыдущем шаге пользователя заинтересовали, следующий шаг поиска подстроится под потребности пользователя, даже если сам поисковый запрос не изменился.
Над проблемой адаптивного поиска мы сейчас и работаем.
Проверка бизнес-гипотез
Бизнес периодически приходит со светлыми идеями, которые очень трудно реализовать. Надо научиться находить документы по их описанию, не имея ни размеченной выборки для обучения, ни возможности подать асессорам какой-то набор документов для разметки. Такое обычно бывает, когда целевые документы встречаются редко относительно общего потока документов, и как результат – подав без предварительной фильтрации асессорам пул в 10 тыс. документов можно на выходе получить 1-2 нужных, а то и меньше.
Наш подход состоит в создании итеративного процесса обучения на основе семантических векторов. На первом шаге находим несколько текстов, задающих нашу целевую тематику – это могут быть статьи Википедии, либо тексты из других источников. Для каждого текста производится его семантический вектор. Если целевая тематика сложная, работает алгебра множеств – объединения, пересечения, исключения одних тематик из других. Например – есть статьи Википедии про “Научно-исследовательские разработки” и про “Косметика”, пересечение множеств даст “НИР про косметику”.
Все документы в базе можно отсортировать по степени их соответствия заданным тематикам, тогда алгебра множеств работает на самих документах следующим образом – документ считается имеющим отношение к тематике, если его семантический вектор ближе к вектору статей Википедии заданной тематики, чем в среднем по базе. Пересечение – если одновременно к обеим тематикам семантический вектор документа ближе, чем в среднем по базе. Другие операции – аналогично.
Находим набор из сотни-другой документов, имеющих наибольшую близость ко всем положительным тематикам и, одновременно, наименьшую близость ко всем отрицательным тематикам (если нас не интересуют в искомых исследованиях финансовые вопросы, то мы и зададим в качестве отрицательного примера статьи из категории “Финансы”). Отдадим эти документы асессорам, они в них найдут несколько положительных примеров, на основе этих примеров поищем другие документы с близкими семантическими векторами, разметим их, и на выходе получим достаточное количество документов для положительного класса для построения любого удобного классификатора. Возможно, потребуется несколько итераций.
Итог
Описанный подход позволяет автоматически, без ручного анализа, отобрать из Википедии или другого источника наборы текстов, помогающие решать задачу классификации. Просто подключив кластеры из Википедии к работающему классификатору можно ожидать значительного роста качества, не требуя при этом адаптации самого классификатора.
Ну и адаптивный поиск – это интересно.