Не будем вспоминать в очередной раз «что такое кластеризация» и «для чего она нужна». На эти вопросы давным-давно дали ответы различные сервисы, предлагающие услуги по кластеризации поисковых запросов на основании SERP. Ниже мы разберем, как провести эту нехитрую процедуру самостоятельно и бесплатно, или с символическими затратами.

Для начала надо установить и настроить python, но, поскольку желающих с этим возиться немного, то рекомендую сразу обратиться к сборке Anaconda, которая позволяет быстро установить сам python и все необходимые библиотеки.

Ниже по тексту будут приведены сниппеты для python 3.

Векторное представление ключевых слов

Чтобы сделать наши ключевые слова удобными для обработки, необходимо провести их векторизацию. Звучит пугающе, но на самом деле все очень просто – все ключевые фразы разбиваются на уникальные слова и кодируются. По сути они преобразуются в большой список и дальше вместо каждого ключевого слова мы размещаем длинную строчку цифр, соответствющую нашему списку всех уникальных слов. Если слово есть в фразе – то ставим 1, если нет , то 0. Получается что-то вроде такой таблицы.

z_1Чтобы не придумывать велосипед, удобно воспользоваться готовыми библиотеками. Такую матрицу можно получить при помощи класса CountVectorizer из библиотеки scikit-learn.

z_2

Здесь мы создаем два разных векторизатора, которые отличаются лишь одним параметром – минимальной частотой слова. Для векторизатора cv минимальная частота слова, которое он учитывает равна единице, а для cv2 двойке, то есть все слова с частотой меньше двух – не учитываются при построении вектора. Если слово встречается только один раз во всех ключевых фразах – то нет смысла занимать оперативную память подобной информацией. Мы не сможем найти какие либо подходящие пересечения по слову, у которого нигде нет пары.

Результатом обработки списка phrases, на котором мы будем разбирать примеры векторизации видно, как поменялись итоговые таблицы для сравнений.

z_3

Слова, которые использовались лишь единожды, были отброшены, и наши многословные ключевые фразы превратились в двухсловники.

Внимательный читатель, конечно, заметил, что многие значимые слова были порезаны настройками векторизатора, и имели смысловую пару, но бездушная машина сама по себе не способна увидеть что «моделей» и «модели» это просто разные склонения одного и того же слова. Для того, чтобы устранить подобные ошибки мы предварительно проведем процедуру, которая называется лемматизация – приведение словоформы в её нормальную форму.

z_4

Таким несложным способом мы можем трансформировать все наши ключевые фразы в нормализованный вид и переучить векторизаторы.

z_5

В итоге мы получаем следующие матрицы:

z_6

Теперь, после применения второго векторизатора, нам удалось сохранить намного больше полезной информации. Он хорошо видит слово «модель» и различные формы «радиоуправляемого».

Поскольку все SEO-специалисты не понаслышке знают, что количество слов редко переходит в качество вместо CountVectroizer лучше использовать TfidfVectorizer. Он очень похож на предыдущий векторизатор, но вместо числа 1 или 0 проставляет значимость каждого слова рассчитывая её по Tf-Idf .

Используется он точно так же как и обычный CountVectorizer, но возвращает другие результаты.

z_7

Ну и вишенкой на торте совместим лемматизатор и TfidfVectorizer в один класс, который позволит проводить преобразование на лету. Вообще, для задач кластеризации в этом нет необходимости, но такой код, на мой взгляд, выглядит более удобным и читаемым. Использовать его или нет – личное дело каждого.

z_8

Настройка векторизаторов

У всех разобранных векторизаторов есть несколько общих настроек, которые могут пригодиться:
• stop-words – список слов, которые не будут учитываться при векторизации;
• token_pattern – регулярное выражение, по которому строка разбивается на токены. Обычно это просто разделение на слова, но могут быть выделены и другие сущности;
• max_df – токены имеющие частотность выше этого значения не будут учитываться. Можно указать процент через коэффициент — 0.9 будет обозначать что 10% наиболее частых слов будут отброшены;
• min_df – токены имеющие частотность ниже этого значения не будут учитываться. Можно указать процент через коэффициент — 0.1 будет обозначать что 10% наиболее редких слов будут отброшены.

Полный список всех параметров можно посмотреть тут.

Кластеризация по составу фраз алгоритмом K-Means

Вот мы, наконец, и добрались до кластеризации, ради которой все это и затевалось. В данном примере мы рассмотрим кластеризацию по составу фраз, которая позволит выделить те словосочетания, которые между собой сильно связаны и имеют большое количество пересечений значимых слов.

Для дальнейшей работы нам пригодится класс KMeans из библиотеки scikit-learn. Ниже скриншот подготовительной части, где мы подгружаем ключевые слова из внешнего текстового файла, создаем класс для векторизации и заполняем список стоп-слов, если он у вас есть.

z_9

Для настройки алгоритма KMeans удобно использовать следующие параметры:

• n_clusters – количество кластеров, на которые будут делиться данные. Минусом данного алгоритма является необходимость изначально указать, на какое количество групп будут поделены слова.
• max_iter – максимальное количество итераций. Работа будет принудительно остановлена при достижении этого числа. Иногда алгоритм «залипает» на некоторых видах данных, и указывается конкретное статичное число, которое позволяет избежать бесконечной работы.
• n_init – сколько раз будет инициализироваться алгоритм с различными начальными центроидами. Чем больше инициализаций – тем лучше кластера описывают реальную структуру данных и тем дольше работает алгоритм.
• tol — доверительный предел, при достижении которого кластеризация будет остановлена.
• n_jobs – количество параллельных потоков работы алгоритма
• random_state – параметр позволяющий добиться воспроизводимости одних и тех же результатов при разных запусках алгоритма

Сама кластеризация много места не занимает.

z_10

Так можно посмотреть, что у нас там получилось, и при помощи последнего сниппета сохранить результаты в csv

z_11

Иерархическая кластеризация по SERP Яндекса

z_12

Иерархические алгоритмы строят не одно разбиение выборки на непересекающиеся кластеры, а систему вложенных разбиений. На выходе мы получаем дерево кластеров, корнем которого является вся выборка, а листьями – наиболее мелкие кластера.

Для начала нам нужно собрать ТОП из какой либо поисковой системы. Для примера был выбран топ Яндекса, т.к. с ним удобно работать через XML. По глубине — топ 10, хотя вменяемые результаты получаются и на топ 20-30, но вот дальше начинается ерунда в группировке. После того, как мы собрали серпы у нас получаются следующие конструкции:
• keywords – список в котором лежат наши ключевые слова
• serps — список в котором лежат на соответствующих ключам строках серпы, в которых все урлы серпа просто разделены между собой пробелом.

Вот тут нам как раз и пригодится возможность указывать собственное регулярное выражение для разбиения фразы на специфические токены. Для нас каждым уникальным токеном будет какой либо уникальный url.

z_13

Ну и аналогично предыдущему примеру производим кластеризацию:

z_14

У функций linkage и fcluster достаточно много различных настроек, но, думаю, они больше будут интересны исследователям и специалистам, так что ограничусь лишь ссылкой, где можно найти все необходимые описания.

Использование данного алгоритма так же позволяет получить адекватные результаты группировки:

z_15

Ну и при желании можно визуализировать дерево, которое получилось в процессе кластеризации:

z_16

Михаил Жуковец
SEO-специалист агрегатора Price.ru. Сфера интересов – анализ данных, машинное обучение, разработка инструментов и методик для поискового продвижения.

Прокомментировать

10 Комментарий на "Кластеризация поисковых запросов в Ipython"

Notify of
Sort by:   newest | oldest | most voted
Alexey Makarov
Гость

Благодарю за статью! А можно ссылку на ipynb-файл?

Михаил Жуковец
Гость
Alexey Makarov
Гость

Спасибо!

Юрий
Гость

Очень понравилась статья, есть конечно некоторые огрехи, но они, по большей части, связаны с огрехами морфи (он иногда предлагает в леммы очень странные слова) те все равно требуется ручная доработка плюс очистка от «мусорных» слов не всегда решается ограничениями на TF, мне тут недавно попалось «ёлки-палки» чей TF в ядре был довольно высок.
Вцелом, приведенный метод не является «серебряной пулей», но сам материал подготовлен и представлен в очень достойном виде: есть проблема — вот решение, пользоваться так, нужно для вот этого с примерами и прочим.

Михаил Жуковец
Гость

Ну серебряной пули, имхо, вообще не найти) Но думаю потребности 80% сеошников в кластеризации можно покрыть и таким методом)

По вопросу — не не думал, вопрос автоматического расширения семантики в данной задаче перед собой не ставил) У меня вообще есть сомнения в необходимости сбора гигантских ядер для их проработки) По сути кластеризация чаще всего применяется как раз для снижения размерности семантических ядер до каких то разумных обрабатываемых размеров. Куда интереснее было бы дальше построить что то вроде тематических деревьев для семантики, но и тут поджидают сложности)

Юрий
Гость
Ну да, в принципе лемматизация-> кластеризация -> приведение к униграммам призвана уменьшить неструктурированное полотно из миллионов фраз, тем не менее лично меня всегда занимал вопрос полноты исходной семантики и тут лично я вижу хоть и топорное, но не совсем уж плохое решение в виде: Тк ядро уже кластеризовано, то, теоретически, проблем со связями у нас быть не должно. Дальше на примере одной группы фраз: парсим топ-10 по каждой фразе, лемматизируем каждый документ, приводим к униграммам, минусуем из них уже существующие в группе слова и минус-слова, затем по какой-то отбивке, например 3(волшебная цифра с потолка) выбираем наиболее часто встречаемые в коллекции… Read more »
iLeg0
Гость

А если попробовать реализовать иерархическую кластеризацию методом k-means (или любым другим) в несколько проходов с уменьшением порога схожести кластеров.
Т.е. бьем сначала запросы на первичные кластеры.
Потом берем из каждого кластера по эталону и эти эталоны между собой кластеризуем.
И так в несколько проходов.

Плюс можно попробовать добавить к пространству признаков, например, домены.

atimutsa
Гость

В статье взят уже готовый кластер из 3-х фраз. Очень не хватает примера с кластеризацией 1000 фраз. Хочется увидеть исходный список и хотя бы примерно что получилось после кластеризации.

Михаил Жуковец
Гость

ближе к концу статьи идут примеры на семантике в 2 к ключей. по одной тематике правда, но на нескольких тематиках сработает так же

Zinochka Horeckaya
Гость

Очень интересная статься, спасибо! Хотела бы у Вас узнать в какую директорию, как назвать и где вызывать файлы? Подскажите, пожалуйста. Сейчас пишу диплом о seo хочу внедрить кластеризацию поисковых запросов как изюминку.

wpDiscuz