Обновлено: 24.04.2026
Как GNN превращают хаотичную структуру сайта в предсказуемую иерархию
Введение: почему глубина URL — это не просто количество слешей
В этой статье мы разберём, почему традиционный подход «главная → категория → подкатегория → товар» устарел, как GNN учитывает не только иерархию, но и потоки внимания пользователей, и как построить модель, которая сама предложит, где разместить новую страницу — на глубине 2 или на глубине 5.
Прежде чем погружаться в детали, стоит дать краткое определение для тех, кто не знаком с темой. Графовые нейронные сети (Graph Neural Networks, GNN) — это класс нейросетевых архитектур, работающих непосредственно с графовыми структурами данных. В отличие от свёрточных сетей (CNN), оперирующих регулярными сетками пикселей, или рекуррентных сетей (RNN), обрабатывающих последовательности, GNN принимают на вход произвольный граф — набор узлов и связей между ними — и обучаются на основе как свойств отдельных узлов, так и топологии их взаимосвязей. Именно эта способность делает GNN естественным инструментом для анализа веб-сайтов, которые по своей природе представляют собой графы страниц, связанных гиперссылками.

Часть 1. Почему классическая глубина URL — это прокси, а не решение
1.1 Традиционная логика: чем ближе к главной, тем важнее
В классическом SEO глубина URL (количество уровней пути после домена) используется как прокси-метрика важности:
domain.ru/→ глубина 0 (главная)domain.ru/category/→ глубина 1domain.ru/category/subcategory/→ глубина 2domain.ru/category/subcategory/product/→ глубина 3
Предполагается, что поисковый робот реже заходит на глубокие страницы, а PageRank затухает с каждым уровнем вложенности.
Важное уточнение: глубину URL часто путают с глубиной краулинга (crawl depth) — минимальным количеством кликов от главной страницы до целевой. Это разные метрики. URL domain.ru/a/b/c/d/page/ имеет 5 сегментов в пути, но если на главной есть прямая ссылка на эту страницу, её краулинговая глубина равна 1. Для поисковых роботов критична именно краулинговая глубина, а не количество слешей в URL-строке. Тем не менее, на практике эти две величины часто коррелируют, потому что архитектура URL обычно отражает навигационную иерархию сайта.
Проблема: это линейное приближение к нелинейной реальности. Страница на глубине 4 с десятком входящих внутренних ссылок может быть гораздо более «важной» для поисковика, чем страница на глубине 1, на которую никто не ссылается.
1.2 Реальность: граф ссылок важнее, чем путь в URL
Представьте два сценария:
Сценарий А: Товар «Насос КМ 80-50-200» лежит на глубине 3 (/catalog/nasosy/km-80-50-200/), но на него ссылаются 20 внутренних страниц: статьи блога, карточки совместимых уплотнений, обзоры из категории «хиты продаж».
Сценарий Б: Товар лежит на глубине 2 (/popular/product/), но на него ссылается только главная страница и больше никто.
Классическая модель глубины скажет, что сценарий Б лучше (глубина меньше). Но графовая модель покажет обратное: в сценарии А страница получает распределённый вес из разных семантических кластеров, что сигнализирует поисковику о её тематической значимости.
1.3 Историческая эволюция: от каталогов к графам
Чтобы понять, почему индустрия SEO десятилетиями опиралась на глубину URL, полезно вспомнить контекст. В эпоху каталогов (DMOZ, Yahoo Directory, конец 1990-х — начало 2000-х) иерархическая вложенность была единственным способом организации информации. Поисковые роботы первого поколения действительно обходили сайты преимущественно в ширину (BFS) от главной страницы, и глубина URL буквально определяла вероятность индексации. Рекомендация «не более 3 кликов от главной» сформировалась именно тогда.
С появлением XML-карт сайта (Sitemaps, 2005), приоритизации краулинга на основе PageRank и машинного обучения в ранжировании (RankBrain, 2015; BERT, 2019; MUM, 2021) роль физической глубины URL начала снижаться. Современные краулеры Googlebot’а способны обнаруживать и индексировать страницы на любой глубине, если они связаны достаточным количеством внутренних ссылок или указаны в sitemap.xml. Тем не менее, краулинговый бюджет — ограниченное число страниц, которые бот готов обойти за единицу времени, — остаётся реальным ограничением для крупных сайтов (свыше 100 000 страниц). GNN как раз позволяет моделировать распределение этого бюджета и находить оптимальное положение каждой страницы.
Именно здесь на сцену выходят графовые нейронные сети — модели, способные учитывать топологию ссылок, атрибуты узлов и семантику рёбер одновременно.
Часть 2. Теоретический фундамент: как GNN работают «под капотом»
Прежде чем переходить к построению графа сайта, необходимо разобраться в ключевых теоретических концепциях, на которых основаны графовые нейронные сети. Без этого фундамента практическая часть будет выглядеть как набор рецептов без понимания, почему они работают.
2.1 Основные архитектуры GNN
- GCN (Graph Convolutional Network, Kipf & Welling, 2017) — базовая архитектура, в которой каждый узел обновляет своё представление путём усреднения признаков соседей с нормализацией по степени. Формула одного слоя:
H^(l+1) = σ(D̃^(-1/2) à D̃^(-1/2) H^(l) W^(l)), гдеà = A + I— матрица смежности с добавленными петлями,D̃— её диагональная матрица степеней,W^(l)— обучаемая весовая матрица слоя,σ— функция активации. Простота GCN — одновременно её сила (быстрое обучение, мало параметров) и слабость (все соседи вносят одинаковый вклад, что не соответствует реальности веб-графов, где ссылки имеют разную значимость). - GAT (Graph Attention Network, Veličković et al., 2018) — архитектура с механизмом внимания, где модель обучается присваивать разные веса разным соседям. Для SEO-графов это критически важно: ссылка из тематически близкой авторитетной статьи должна вносить больший вклад в представление целевой страницы, чем ссылка из футера. GAT вычисляет коэффициенты внимания
α_ijдля каждой пары связанных узлов, что делает агрегацию адаптивной. - GraphSAGE (Hamilton et al., 2017) — архитектура, решающая проблему масштабируемости. Вместо того чтобы использовать всех соседей (как GCN), GraphSAGE сэмплирует фиксированное количество соседей на каждом уровне. Это позволяет обучать модели на графах с миллионами узлов — масштаб, характерный для крупных интернет-магазинов и контентных порталов.
- GIN (Graph Isomorphism Network, Xu et al., 2019) — теоретически наиболее мощная архитектура в терминах различительной способности. GIN может различать графовые структуры, которые GCN и GAT не могут, благодаря использованию инъективной функции агрегации. Для SEO это означает способность улавливать тонкие структурные паттерны — например, отличать «звёздную» топологию (хаб → много дочерних страниц) от «цепочечной» (страница А → Б → В → Г).
2.2 Передача сообщений (Message Passing) как основа GNN
Все перечисленные архитектуры объединяет парадигма передачи сообщений (Message Passing). Интуиция проста: каждый узел «общается» со своими соседями, собирая информацию об их состоянии и обновляя собственное представление. После нескольких раундов такого обмена каждый узел аккумулирует информацию не только о непосредственных соседях, но и о более далёких частях графа.
Количество слоёв GNN (K) определяет радиус восприятия узла: после K слоёв узел «видит» своё K-hop окружение. Для SEO-графов типичный выбор — 2–4 слоя. Меньше — модель не захватывает достаточно контекста; больше — начинается эффект over-smoothing, когда представления всех узлов становятся неразличимо похожими. Проблема over-smoothing особенно актуальна для веб-графов, где средний диаметр (максимальное кратчайшее расстояние между любыми двумя узлами) часто не превышает 6–8 — так называемый эффект «малого мира».
2.3 Гетерогенные графы: почему они важны для SEO
Веб-сайт — это гетерогенный граф, в котором существуют разные типы узлов (главная, категория, товар, статья, лендинг) и разные типы рёбер (навигационная ссылка, контекстная ссылка, хлебные крошки, ссылка из сайдбара, каноническая ссылка). Гомогенные модели (стандартные GCN/GAT) игнорируют эту типизацию, трактуя все узлы и рёбра одинаково.
Для корректного моделирования SEO-графа необходимы гетерогенные GNN (Heterogeneous GNN, HetGNN), которые поддерживают:
- Раздельные обучаемые матрицы для разных типов узлов.
- Раздельные функции агрегации для разных типов рёбер.
- Мета-путевое внимание (meta-path attention) — механизм, позволяющий модели обучаться значимости различных семантических путей. Например, мета-путь «товар ← категория ← главная» может иметь иной вес, чем «товар ← статья блога ← автор».
В библиотеке PyTorch Geometric гетерогенные графы реализованы через класс HeteroData, который мы используем в практической части.
Часть 3. Строим граф сайта: от сырых данных к обучающей выборке
Прежде чем предсказывать оптимальную глубину, нужно формализовать, что такое «сайт» для GNN.
3.1 Формальное определение графа сайта
В контексте GNN сайт — это ориентированный граф G = (V, E, X_v, X_e), где:
- V (Vertices/Nodes) — множество узлов, представляющих страницы сайта.
- E (Edges) — множество ориентированных рёбер, представляющих внутренние ссылки (от страницы-источника к странице-цели).
- X_v — матрица атрибутов узлов (размер |V| × d_v, где d_v — размерность признакового вектора страницы).
- X_e — матрица атрибутов рёбер (размер |E| × d_e, где d_e — размерность признакового вектора ссылки).
Опционально граф может быть расширен виртуальными рёбрами, которые не соответствуют реальным ссылкам, но отражают семантическую близость: если две страницы имеют косинусное сходство эмбеддингов выше порога (например, 0.85), между ними добавляется ребро типа semantically_similar. Это помогает модели обнаруживать «упущенные» ссылки — пары страниц, которые должны быть связаны, но не связаны.
3.2 Сбор данных: полный пайплайн
Прежде чем строить граф, нужно получить сырые данные. Вот полный пайплайн сбора, который часто подразумевается, но редко описывается:
Шаг 1: краулинг сайта. Используйте Screaming Frog, Sitebulb или open-source инструменты (Scrapy, advertools). Задача — получить полный список URL, их HTTP-статусы, канонические URL, мета-данные (title, description), и главное — все внутренние ссылки с указанием исходной и целевой страницы, текста анкора и позиции в DOM. Важно: краулер должен быть настроен на рендеринг JavaScript (режим Chrome/Puppeteer), иначе вы пропустите ссылки, генерируемые динамически (React, Vue, Angular-приложения).
Шаг 2: обогащение поведенческими данными. Экспорт из Google Analytics 4 (через BigQuery или API): сессии по страницам, средняя длительность, показатель отказов, глубина просмотра. Экспорт из Google Search Console (GSC): показы, клики, средняя позиция, CTR для каждого URL.
Шаг 3: обогащение лог-данными (для продвинутых). Серверные логи позволяют увидеть реальное поведение краулеров: как часто Googlebot посещает каждую страницу, сколько страниц обходит за сессию, какие пути предпочитает. Эти данные критически важны для валидации модели.
Шаг 4: генерация эмбеддингов. Для каждой страницы генерируется плотный векторный representation контента. Подробнее — в следующем разделе.
3.3 Атрибуты узлов (страниц)
| Атрибут | Тип | Источник | Зачем |
|---|---|---|---|
| Семантический вектор страницы | float[384/768/1024] | Sentence-BERT, E5, BGE | Кодирует тему страницы в плотном векторном пространстве |
| Тип страницы | one-hot (homepage, category, subcategory, product, article, landing, FAQ, contact) | Эвристики на основе URL-паттернов, шаблонов CMS или обученный классификатор | Разные типы страниц имеют разную «роль» в графе |
| PageRank | float | NetworkX (nx.pagerank()) или собственный расчёт |
Трастовый вес в графе ссылок |
| Вовлечённость пользователей | float (несколько компонент) | GA4: avg_session_duration, bounce_rate, pages_per_session, scroll_depth | Поведенческий сигнал качества контента |
| Возраст страницы (дни) | int | Дата первого появления в индексе (GSC), Wayback Machine API или CMS-метаданные | Свежие страницы могут требовать более плоской структуры для быстрого обнаружения |
| Количество входящих внутренних ссылок | int | Парсинг | Прямой сигнал важности |
| Количество исходящих внутренних ссылок | int | Парсинг | Сигнал «хабовости» — является ли страница навигационным центром |
| Частота краулинга Googlebot | float | Серверные логи | Как часто поисковый робот реально посещает страницу |
| Позиция в поиске (средняя) | float | GSC | Текущая видимость в поиске |
| Наличие структурированных данных | binary/categorical | Парсинг (Schema.org) | Страницы с разметкой могут получать расширенные сниппеты |
3.4 Атрибуты рёбер (ссылок)
| Атрибут | Тип | Источник | Зачем |
|---|---|---|---|
| Позиция ссылки в DOM | one-hot (header_nav, breadcrumb, main_content, sidebar, footer, pagination) | Парсинг HTML-структуры | Ссылки в основном контенте передают больше веса, чем навигационные |
| Семантика анкора | float[384] | Эмбеддинг анкорного текста (тот же энкодер, что для страниц) | Анкор, релевантный целевой странице, передаёт больше тематического веса |
| Косинусное сходство анкора и целевой страницы | float | Вычисляется из двух предыдущих эмбеддингов | Прямая мера релевантности ссылки |
| Свежесть ссылки (дни) | int | История изменений (Git, Wayback Machine, логи краулинга) | Новые ссылки могут иметь эффект «свежести» |
| Кликабельность (CTR внутренней ссылки) | float | GA4 (enhanced measurement) или логи | Насколько часто пользователи реально переходят по этой ссылке |
| Атрибут nofollow/sponsored/ugc | binary | Парсинг | Ссылки с rel=”nofollow” не передают PageRank |
| Визуальная заметность | float | Размер элемента, цвет, позиция в viewport (через headless browser) | Более заметные ссылки привлекают больше кликов |
3.5 Выбор модели эмбеддингов: практические рекомендации
Качество семантических эмбеддингов критически влияет на работу GNN. Для русскоязычных сайтов рекомендуются следующие модели:
- intfloat/multilingual-e5-large — хороший баланс качества и скорости, поддерживает русский язык, размерность 1024.
- BAAI/bge-m3 — мультиязычная модель с отличной производительностью на русском, поддерживает dense, sparse и multi-vector retrieval.
- cointegrated/rubert-tiny2 — лёгкая модель для русского языка (312-мерные эмбеддинги), если вычислительные ресурсы ограничены.
- sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 — компромисс между скоростью и качеством, 384-мерные эмбеддинги.
Важно: эмбеддинг страницы следует генерировать не только из title, но из конкатенации title + H1 + meta description + первые 512 токенов основного контента (после очистки от навигации и шаблонных элементов). Для карточек товаров имеет смысл включать и структурированные характеристики (бренд, категория, ключевые параметры).
3.6 Пример кода: построение графа в PyTorch Geometric
import torch
import pandas as pd
from torch_geometric.data import HeteroData
from sentence_transformers import SentenceTransformer
# 1. Загружаем данные о страницах и ссылках
pages_df = pd.read_csv('pages.csv')
# columns: page_id, url, title, content_preview, content_type, pagerank,
# avg_session_duration, bounce_rate, age_days, inlinks_count, outlinks_count
links_df = pd.read_csv('links.csv')
# columns: source_id, target_id, anchor_text, dom_position, is_nofollow, ctr
# 2. Генерируем эмбеддинги для каждой страницы
embedder = SentenceTransformer('intfloat/multilingual-e5-large')
page_texts = (pages_df['title'] + ' ' + pages_df['content_preview']).tolist()
page_embeddings = embedder.encode(page_texts, show_progress_bar=True, normalize_embeddings=True)
# 3. Генерируем эмбеддинги для анкоров
anchor_embeddings = embedder.encode(links_df['anchor_text'].fillna('').tolist(), normalize_embeddings=True)
# 4. Создаём гетерогенный граф (разные типы узлов)
data = HeteroData()
for content_type in pages_df['content_type'].unique():
mask = pages_df['content_type'] == content_type
idx = pages_df.loc[mask].index
data[content_type].x = torch.tensor(page_embeddings[idx], dtype=torch.float)
data[content_type].pagerank = torch.tensor(
pages_df.loc[mask, 'pagerank'].values, dtype=torch.float
)
# Дополнительные числовые признаки
numeric_features = pages_df.loc[mask, [
'avg_session_duration', 'bounce_rate', 'age_days',
'inlinks_count', 'outlinks_count'
]].values
data[content_type].numeric_features = torch.tensor(numeric_features, dtype=torch.float)
# 5. Рёбра: внутренние ссылки
edge_index = torch.tensor(
[links_df['source_id'].values, links_df['target_id'].values],
dtype=torch.long
)
data['page', 'links_to', 'page'].edge_index = edge_index
# 6. Атрибуты рёбер: эмбеддинг анкора + позиция в DOM + CTR + nofollow-флаг
dom_position_onehot = pd.get_dummies(links_df['dom_position']).values
edge_attr = torch.cat([
torch.tensor(anchor_embeddings, dtype=torch.float),
torch.tensor(dom_position_onehot, dtype=torch.float),
torch.tensor(links_df['ctr'].values, dtype=torch.float).unsqueeze(1),
torch.tensor(links_df['is_nofollow'].values, dtype=torch.float).unsqueeze(1),
], dim=1)
data['page', 'links_to', 'page'].edge_attr = edge_attr
print(data)
# HeteroData(
# category={ x=[150, 1024], pagerank=[150], numeric_features=[150, 5] },
# product={ x=[3000, 1024], pagerank=[3000], numeric_features=[3000, 5] },
# article={ x=[200, 1024], pagerank=[200], numeric_features=[200, 5] },
# ...
# (page, links_to, page)={ edge_index=[2, 25000], edge_attr=[25000, 1030] }
# )
Часть 4. Целевая переменная: что именно предсказываем и откуда берём разметку
Это ключевой раздел, который часто упускают при обсуждении ML в SEO. Модели машинного обучения с учителем требуют размеченных данных — то есть примеров, для которых известен правильный ответ. Откуда взять «оптимальную глубину» для обучения?
4.1 Проблема разметки: «правильной» глубины не существует в явном виде
В отличие от задач классификации изображений, где метка (кошка/собака) очевидна, «оптимальная глубина URL» — это латентная переменная, которую нельзя наблюдать напрямую. Её нужно конструировать.
Подход 1: Историческая ретроспектива. Если на сайте проводились эксперименты с реструктуризацией (перенос страниц на другую глубину), можно использовать результаты: глубина, при которой страница показала наилучшие метрики (трафик, позиции, конверсии), считается оптимальной. Проблема: таких экспериментов обычно мало.
Подход 2: Кросс-сайтовое обучение. Анализируем топ-10 конкурентов в нише. Для каждой тематической группы страниц определяем, на какой глубине располагаются наиболее успешные (по видимости в поиске) аналоги. Медиана глубины топ-конкурентов становится целевой меткой.
Подход 3: Суррогатная целевая переменная. Вместо абстрактной «оптимальной глубины» предсказываем метрику, зависящую от глубины — например, ожидаемый органический трафик, краулинговую частоту или PageRank-взвешенную видимость. Затем через оптимизацию ищем глубину, максимизирующую эту метрику.
Подход 4: Самоконтролируемое обучение (self-supervised). Модель обучается восстанавливать замаскированные признаки графа (например, предсказывать типы узлов или наличие рёбер). После предобучения, тонкая настройка (fine-tuning) на небольшом количестве размеченных примеров может быть достаточной.
4.2 Формулировка задачи: регрессия, классификация или ранжирование?
Есть три способа формализовать предсказание:
Регрессия: предсказываем непрерывное значение глубины (float). Функция потерь — MSE или Huber Loss. Преимущество: гранулярность. Недостаток: модель может предсказать нецелое число (2.7), которое нужно округлять.
Классификация: предсказываем класс глубины: {0: «корень», 1: «мелкая (1–2)», 2: «средняя (3)», 3: «глубокая (4+)»}. Функция потерь — Cross-Entropy. Преимущество: интерпретируемость. Недостаток: теряется информация о порядке (глубина 4 «ближе» к 3, чем к 1, но Cross-Entropy этого не учитывает).
Ранжирование: вместо абсолютной глубины модель учится предсказывать относительный порядок: «страница А должна быть ближе к корню, чем страница Б». Функция потерь — pairwise ranking loss (BPR, MarginRankingLoss). Преимущество: не требуется знать точную оптимальную глубину, достаточно относительных предпочтений.
На практике наиболее устойчивые результаты даёт комбинация: основная задача — ordinal regression (порядковая регрессия, учитывающая упорядоченность классов) с вспомогательной задачей — предсказание PageRank или трафика как регуляризатор.
Часть 5. Предсказание оптимальной глубины: архитектура и обучение
Теперь переходим к главному. Как GNN предсказывает, на какой глубине должна находиться страница?
5.1 Идея: глубина — это не вход, а выход
В традиционном подходе вы задаёте глубину страницы через структуру URL. В GNN-подходе вы предсказываете, какая глубина будет оптимальной для достижения максимального семантического авторитета.
5.2 Архитектура модели: от соседей к предсказанию
Современные подходы к GNN для SEO используют архитектуру Message Passing Neural Network (MPNN), обобщающую GCN, GAT, GraphSAGE и другие варианты. На каждом шаге (слое) узел «слушает» своих соседей и обновляет своё представление:
m_v^(k) = AGGREGATE( { MESSAGE(h_v^(k), h_u^(k), e_vu) for u in N(v) } )
h_v^(k+1) = UPDATE( h_v^(k), m_v^(k) )
Где:
h_v^(k)— представление узла v на шаге k,N(v)— соседи узла v,e_vu— атрибуты ребра от v к u,MESSAGE— функция, формирующая сообщение от соседа u к узлу v (может зависеть от атрибутов ребра),AGGREGATE— функция, объединяющая сообщения от всех соседей (суммирование, усреднение, attention, max-pooling),UPDATE— функция, обновляющая представление узла (обычно GRU или MLP + residual connection).
После K шагов модель получает финальное представление каждого узла, которое кодирует не только его собственный контент, но и контекст всей K-hop достижимой части графа.
Затем это представление пропускается через выходной слой (MLP-голову), который предсказывает глубину.
5.3 Полная архитектура модели: пример на PyTorch Geometric
import torch
import torch.nn.functional as F
from torch_geometric.nn import HeteroConv, GATv2Conv, Linear
class SEODepthPredictor(torch.nn.Module):
def __init__(self, in_channels, hidden_channels, num_layers=3, heads=4, dropout=0.3):
super().__init__()
self.convs = torch.nn.ModuleList()
self.norms = torch.nn.ModuleList()
self.dropout = dropout
for i in range(num_layers):
in_ch = in_channels if i == 0 else hidden_channels * heads
conv = HeteroConv({
('page', 'links_to', 'page'): GATv2Conv(
in_ch, hidden_channels, heads=heads,
edge_dim=edge_attr_dim, add_self_loops=False
),
('page', 'semantically_similar', 'page'): GATv2Conv(
in_ch, hidden_channels, heads=heads, add_self_loops=False
),
}, aggr='sum')
self.convs.append(conv)
self.norms.append(torch.nn.LayerNorm(hidden_channels * heads))
# Выходная MLP-голова для предсказания глубины
self.head = torch.nn.Sequential(
Linear(hidden_channels * heads, hidden_channels),
torch.nn.ReLU(),
torch.nn.Dropout(dropout),
Linear(hidden_channels, hidden_channels // 2),
torch.nn.ReLU(),
Linear(hidden_channels // 2, 1) # регрессия: одно значение
)
def forward(self, x_dict, edge_index_dict, edge_attr_dict=None):
for i, conv in enumerate(self.convs):
x_dict = conv(x_dict, edge_index_dict, edge_attr_dict)
x_dict = {key: self.norms[i](F.elu(x)) for key, x in x_dict.items()}
x_dict = {key: F.dropout(x, p=self.dropout, training=self.training)
for key, x in x_dict.items()}
# Предсказание для каждого узла
out = {key: self.head(x).squeeze(-1) for key, x in x_dict.items()}
return out
5.4 Функция потерь и обучение
Для задачи предсказания глубины используется комбинированная функция потерь:
def combined_loss(pred_depth, true_depth, pred_pagerank, true_pagerank,
alpha=0.7, beta=0.3):
# Основная задача: Huber Loss для робастной регрессии глубины
depth_loss = F.huber_loss(pred_depth, true_depth, delta=1.0)
# Вспомогательная задача: предсказание PageRank как регуляризатор
pr_loss = F.mse_loss(pred_pagerank, true_pagerank)
return alpha * depth_loss + beta * pr_loss
Huber Loss выбран вместо MSE, потому что он менее чувствителен к выбросам — страницам, чья «оптимальная» глубина определена неточно.
5.5 Почему это работает лучше, чем эвристики
Традиционные эвристики (например, «страницы с высоким PageRank должны быть на глубине 1») игнорируют семантическую связность. GNN, напротив, может обнаружить паттерны вроде:
- «Если страница типа “статья” семантически близка к трём страницам типа “категория” и получает от них ссылки, её оптимальная глубина — 2 (категория → статья), а не 3 (блог → категория → статья)».
- «Товарные страницы с уникальным семантическим профилем (не похожим ни на одну существующую подкатегорию) выигрывают от размещения на глубине 3 в новой подкатегории, а не от “размазывания” по существующим».
- «Страницы FAQ, на которые ссылаются и товары, и статьи из разных категорий, оптимальнее размещать на глубине 1 как общесайтовые ресурсы».
Именно способность GNN учитывать типы узлов, семантику, атрибуты рёбер и топологию одновременно делает её мощным инструментом для проектирования информационной архитектуры.
Часть 6. Прогнозирование потока веса: скрытая метрика глубины
Но предсказать оптимальную глубину недостаточно. Нужно понимать, как вес будет распределяться по графу при разной структуре URL.
6.1 Симуляция распространения PageRank с помощью GNN
Классический PageRank — это линейная итеративная формула:
PR(v) = (1 - d) / N + d × Σ(PR(u) / L(u)) для всех u, ссылающихся на v
где d — коэффициент демпфирования (обычно 0.85), N — общее число страниц, L(u) — количество исходящих ссылок из страницы u.
GNN может обучить нелинейную функцию распространения веса, которая превосходит классический PageRank за счёт учёта:
- Семантической релевантности ссылки. Анкор должен соответствовать целевой странице. Ссылка с анкором «насос центробежный» на страницу о насосах передаёт больше тематического веса, чем ссылка с анкором «подробнее».
- Позиции ссылки. Ссылка в основном контенте передаёт больше веса, чем в футере или сайдбаре. Это подтверждается патентами Google (Reasonable Surfer Model, 2004, патент US7716225B1), согласно которым вероятность клика по ссылке зависит от её позиции, визуальной заметности и контекста.
- Типа страницы-источника. Ссылка из авторитетной экспертной статьи ценнее ссылки из автоматически сгенерированной карточки товара.
- Поведенческих данных. Ссылка, по которой реально кликают пользователи, вероятно, более значима для поисковика.
6.2 Weighted Semantic PageRank: модифицированная формула
На основе GNN можно построить Weighted Semantic PageRank (WSPR) — модифицированную версию PageRank, где вес каждого ребра не равен 1/L(u), а определяется обученной функцией:
WSPR(v) = (1 - d) / N + d × Σ( f(h_u, h_v, e_uv) × WSPR(u) )
где f(h_u, h_v, e_uv) — нелинейная функция, обученная GNN, принимающая представления источника, цели и атрибуты ребра. Эта функция выполняет роль «умного» распределителя веса: ссылка получает тем больший вес, чем она семантически и поведенчески значимее.
6.3 Предсказание «бутылочных горлышек»
GNN можно обучить выявлять узлы, через которые проходит непропорционально большой поток траста — потенциальные узкие места. Формально это связано с метрикой betweenness centrality (промежуточная центральность) из теории графов, но GNN расширяет её семантическим контекстом.
Метрика: flow_concentration(v) = суммарный вес всех кратчайших путей, проходящих через v, взвешенных по семантической значимости
Высокая концентрация на мелкой глубине → «перегруженная» главная или категория верхнего уровня → нужна декомпозиция (разделение на подкатегории или создание промежуточных хаб-страниц).
Высокая концентрация на глубокой странице → обнаружен «скрытый хаб» → возможно, эту страницу стоит поднять ближе к корню.
Низкая концентрация на странице с высоким коммерческим потенциалом → страница «изолирована» → нужно нарастить внутреннюю перелинковку.
6.4 Визуализация потоков веса
Для практической работы критически важна визуализация. Рекомендуемые инструменты:
- Gephi — для интерактивного исследования графа, раскраски узлов по предсказанной глубине, толщине рёбер по весу.
- pyvis — Python-библиотека для создания интерактивных визуализаций в браузере.
- NetworkX + matplotlib — для статичных визуализаций в отчётах.
- D3.js — для создания кастомных интерактивных дашбордов.
Часть 7. Учёт поведенческих паттернов: внимание пользователей как сигнал
Одна из сильных сторон GNN-подхода — возможность интегрировать пользовательское поведение в модель графа.
7.1 Пользовательские пути как рёбра графа
Помимо гиперссылок, граф может быть обогащён поведенческими рёбрами — переходами, которые реальные пользователи совершают на сайте. Данные извлекаются из GA4 (event-based модель, события page_view с привязкой к ga_session_id).
Поведенческое ребро от страницы А к странице Б создаётся, если в данных наблюдается статистически значимое количество переходов А → Б. Атрибуты такого ребра: средняя частота перехода, процент сессий с таким переходом, средняя длительность просмотра Б после перехода с А.
Это позволяет модели обнаруживать фактические пути пользователей, которые могут сильно отличаться от проектируемой навигации. Например, пользователи могут систематически переходить из блога в товарный раздел, минуя категорийную иерархию — сигнал к тому, что эти разделы нужно связать напрямую.
7.2 Внимание пользователей как веса для модели
Данные о вовлечённости (время на странице, глубина скролла, частота возвратов) можно использовать для взвешивания узлов в процессе обучения. Страницы с высокой вовлечённостью получают больший вес в функции потерь — модель «старается» точнее предсказать их оптимальную глубину, потому что ошибки в размещении таких страниц стоят дороже.
Часть 8. Клинические применения: от теории к практике
8.1 Сценарий 1: Миграция на новую CMS
Проблема: При переезде на новую CMS старая структура URL ломается. Нужно спроектировать новую иерархию, которая минимизирует потерю веса.
Решение:
- Построить граф старого сайта со всеми атрибутами (семантика, ссылки, поведенческие данные).
- Обучить GNN предсказывать глубину для каждой страницы на основе семантических и ссылочных признаков.
- Применить модель к контенту новой CMS (новые URL, но тот же контент) и сгенерировать оптимальную структуру URL до того, как сайт будет опубликован.
- Сравнить предсказанную структуру с текущей — расхождения укажут на страницы, которые были неоптимально размещены в старой иерархии.
- Сгенерировать таблицу 301-редиректов на основе маппинга старых URL → новые URL с оптимальной глубиной.
Метрика успеха: сохранение ≥95% органического трафика через 3 месяца после миграции.
8.2 Сценарий 2: Добавление 500 новых товаров
Проблема: В интернет-магазине появляется новая линейка товаров. Куда их разместить? В существующую категорию (глубина 2) или создать новую подкатегорию (глубина 3)?
Решение: Для каждого нового товара генерируем эмбеддинг и добавляем его как узел без рёбер в граф. Модель через inductive inference (способность GNN обобщать на новые, невиданные во время обучения узлы) предсказывает оптимальную глубину, анализируя семантическую близость к существующим страницам.
Если товары семантически ближе к категории верхнего уровня, чем к любой подкатегории — глубина 2. Если формируют отдельный семантический кластер (среднее внутрикластерное сходство > 0.8) — глубина 3 с созданием новой подкатегории. Если товары распределяются между несколькими существующими подкатегориями — размещаем в соответствующих подкатегориях, а не создаём искусственную общую.
8.3 Сценарий 3: Аудит «умирающих» страниц
Проблема: Некоторые страницы теряют позиции, хотя их контент актуален.
Решение: Модель предсказывает для этих страниц «целевую глубину» (глубину, которая максимизирует вес при текущей ссылочной структуре). Сравниваем с фактической глубиной. Если предсказание значительно отличается (например, модель говорит «глубина 2», а страница лежит на глубине 4), проблема может быть в излишней вложенности. Поднимаем страницу ближе к корню и добавляем ссылки с промежуточных узлов.
Дополнительно модель может выявить «осиротевшие» страницы (orphan pages) — узлы, достижимые только через 1–2 ссылки с нерелевантных страниц. Для таких страниц рекомендация — не столько изменение URL-глубины, сколько наращивание внутренней перелинковки из семантически близких узлов.
8.4 Сценарий 4: Каннибализация ключевых слов
Проблема: Несколько страниц конкурируют за одни и те же запросы в поиске, размывая друг друга.
Решение: GNN выявляет кластеры узлов с высокой семантической близостью (cosine similarity > 0.9) и одновременно высоким пересечением целевых ключевых слов. Модель предлагает одно из решений: (а) объединить страницы в одну на оптимальной глубине, (б) дифференцировать контент и разнести страницы в разные семантические зоны графа, (в) установить каноническую ссылку от менее значимой к более значимой.
8.5 Сценарий 5: Мультиязычный сайт
Проблема: сайт доступен на нескольких языках. Каждая языковая версия — отдельный подграф. Как обеспечить согласованность архитектуры?
Решение: используем мультиязычные эмбеддинги (multilingual-e5, BGE-M3), которые проецируют страницы разных языков в общее семантическое пространство. GNN обучается на графе, объединяющем все языковые версии, с дополнительными рёбрами типа hreflang между языковыми аналогами. Это позволяет обнаруживать структурные расхождения: если страница в русской версии находится на глубине 2, а её английский аналог — на глубине 4, модель сигнализирует о несоответствии.
Часть 9. Ограничения и практические предостережения
9.1 Размер графа имеет значение
GNN требуют достаточно плотных графов для обучения. Если на вашем сайте менее 500 страниц, модель может не найти статистически значимых паттернов. В этом случае используйте трансферное обучение: предобучите модель на крупном датасете (например, краулинг Common Crawl с выделением подграфов отдельных сайтов, или открытые датасеты веб-графов вроде WebGraph от LAW group), а затем дообучите на своём сайте.
Для совсем маленьких сайтов (до 100 страниц) GNN, вероятно, избыточен — достаточно ручного анализа графа в Gephi в сочетании с простыми графовыми метриками (PageRank, betweenness centrality, clustering coefficient).
9.2 Вычислительная сложность
Наивная реализация GNN на полном графе из N узлов при K слоях имеет сложность O(K × |E| × d²), где |E| — число рёбер, d — размерность скрытых представлений. Для графов с десятками тысяч узлов и сотнями тысяч рёбер это вполне управляемо на современных GPU.
Для крупных сайтов (1M+ страниц) используются техники графового сэмплирования:
- GraphSAGE — сэмплирует фиксированное число соседей (обычно 10–25) на каждом уровне.
- Cluster-GCN — разбивает граф на кластеры и обучается на подграфах.
- ShaDow-GNN — извлекает локальные подграфы вокруг целевых узлов.
На практике сайт с 100 000 страниц обрабатывается за 10–30 минут обучения на GPU уровня NVIDIA RTX 3090 / A100.
9.3 Интерпретируемость
GNN часто критикуют за «чёрный ящик». В SEO это серьёзная проблема, потому что клиентам и разработчикам нужно объяснять решения. Несколько подходов к интерпретации:
GNNExplainer (Ying et al., 2019) — инструмент, который для каждого предсказания выделяет подграф и атрибуты, наиболее повлиявшие на результат. Реализован в PyTorch Geometric (torch_geometric.explain.GNNExplainer).
Пример вывода GNNExplainer: «Страница X предсказана на глубине 3. На это повлияли: (1) высокое семантическое сходство со страницей Y (глубина 2, вес влияния 0.34), (2) наличие двух входящих ссылок из статей блога с релевантными анкорами (вес 0.28), (3) тип страницы “справочная статья” (вес 0.22), (4) низкий текущий PageRank (вес 0.16)».
Attention-визуализация. Если модель использует GAT, коэффициенты внимания (attention weights) напрямую показывают, какие соседи повлияли на предсказание сильнее. Это можно визуализировать как тепловую карту на графе.
SHAP для графов. Адаптация SHAP (SHapley Additive exPlanations) для GNN — GraphSHAP — позволяет оценить вклад каждого признака узла и каждого ребра в предсказание.
9.4 Проблема причинно-следственной связи
Корреляция между структурой графа и метриками SEO не означает причинно-следственную связь. Если модель обнаружила, что страницы на глубине 2 получают больше трафика, это может объясняться не глубиной как таковой, а тем, что на эту глубину исторически помещали наиболее важный контент. Для установления каузальных связей необходимы A/B-тесты (о них — в разделе валидации).
9.5 Динамика графа: сайт меняется
Веб-сайт — это не статичный объект. Добавляются новые страницы, удаляются старые, изменяется ссылочная структура. Модель нужно регулярно переобучать (или дообучать инкрементально). Рекомендуемая частота: для активных интернет-магазинов — еженедельно, для контентных сайтов — ежемесячно.
Существуют архитектуры темпоральных GNN (Temporal GNN, T-GNN), которые моделируют эволюцию графа во времени. Для SEO это перспективное направление: модель может предсказывать, как изменения в ссылочной структуре сегодня повлияют на распределение веса через 1–3 месяца.
9.6 Граф Google: обратная сторона
Важно понимать, что Google активно развивает свои графовые модели — от Knowledge Graph до внутренних систем анализа веб-графа. Некоторые исследователи и практики указывают на использование Google графовых нейросетей для анализа семантической согласованности ссылочного профиля сайта. Конкретные детали внутренних систем Google не публичны, и любые утверждения о них следует воспринимать с долей скептицизма. Однако общий вектор очевиден: поисковые системы всё глубже анализируют не отдельные страницы, а связи между ними, и построение семантически связного внутреннего графа — это стратегия, устойчивая к любым алгоритмическим обновлениям.
Часть 10. Валидация модели: как убедиться, что GNN работает
Этот раздел принципиально важен и часто игнорируется в материалах о ML в SEO. Без строгой валидации модель рискует стать дорогой игрушкой, генерирующей бессмысленные рекомендации.
10.1 Оффлайн-валидация
Кросс-валидация на графе. Стандартная k-fold кросс-валидация некорректна для графовых данных, потому что узлы не независимы (они связаны рёбрами). Используйте транзитивный split: разбивайте граф на обучающую и тестовую части так, чтобы минимизировать число рёбер между ними, или используйте временной split (обучение на данных до момента T, тест — после T).
Метрики для регрессии глубины: MAE (Mean Absolute Error), RMSE, а также процент предсказаний, попадающих в ±1 от истинного значения (Accuracy@1). Для классификации: F1-score по классам глубины.
Базовые модели (baselines) для сравнения:
- Наивная модель: всем страницам присваивается медианная глубина.
- Эвристическая модель: глубина = f(тип страницы) — например, все товары на глубине 3, все категории на глубине 1.
- Линейная регрессия по числовым признакам узлов (без графовой информации).
- Только PageRank: глубина ~ 1/PageRank.
Если GNN не превосходит эти baselines статистически значимо, модель не стоит внедрять.
10.2 Онлайн-валидация (A/B-тесты)
Для выбранных страниц измените глубину (через 301-редиректы или реструктуризацию URL) в соответствии с предсказаниями модели. Контрольная группа — страницы, оставшиеся на текущей глубине.
Важные правила:
- Тест должен длиться не менее 4–8 недель (цикл переиндексации).
- Отслеживайте не только трафик, но и позиции, CTR, частоту краулинга.
- Используйте контролируемый эксперимент: изменяйте только глубину, не трогая контент, мета-теги, внешние ссылки.
- Учитывайте сезонность и трендовые факторы.
10.3 Мониторинг в продакшене
После внедрения модели необходим непрерывный мониторинг:
- Data drift: изменился ли граф настолько, что модель устарела? Метрика: расхождение распределения предсказаний текущей модели на новых данных vs. обучающих данных.
- Performance degradation: ухудшились ли метрики SEO после внедрения рекомендаций?
- Alert-система: автоматическое оповещение, когда количество страниц с аномальным расхождением фактической и предсказанной глубины превышает порог.
Часть 11. Инструменты и стек технологий
11.1 Рекомендуемый технологический стек
| Задача | Инструмент | Альтернатива |
|---|---|---|
| Краулинг | Screaming Frog, advertools | Scrapy + Playwright |
| Хранение графа | Neo4j, NetworkX (для малых графов) | ArangoDB, TigerGraph |
| Фреймворк GNN | PyTorch Geometric (PyG) | DGL (Deep Graph Library) |
| Эмбеддинги | sentence-transformers | FastText (для скорости) |
| Визуализация графа | Gephi, pyvis | Sigma.js, D3.js |
| Логирование экспериментов | MLflow, Weights & Biases | Neptune.ai |
| Деплой модели | FastAPI + PyTorch Serve | BentoML, Triton |
| Оркестрация пайплайна | Airflow, Prefect | Dagster |
11.2 Минимально жизнеспособный пайплайн (MVP)
Для быстрого старта достаточно:
- Screaming Frog → экспорт всех внутренних ссылок в CSV.
- Python-скрипт → построение графа в NetworkX, расчёт базовых метрик (PageRank, betweenness centrality, connected components).
- sentence-transformers → генерация эмбеддингов для всех страниц.
- PyTorch Geometric → обучение GCN/GAT-модели на задачу регрессии глубины.
- Gephi → визуализация результатов.
Такой пайплайн можно запустить за 1–2 дня на сайте до 10 000 страниц.
Часть 12. Этика и ответственное использование
12.1 Манипулятивное SEO vs. улучшение архитектуры
GNN для SEO — это инструмент проектирования информационной архитектуры, а не манипуляции поисковыми алгоритмами. Оптимальная глубина URL, предсказанная моделью, должна соответствовать реальной ценности контента для пользователя. Если модель рекомендует поднять страницу на глубину 1, но контент на этой странице не заслуживает такого уровня видимости — рекомендацию следует игнорировать.
12.2 Зависимость от данных: предвзятость модели
Модель обучается на исторических данных, которые могут содержать предвзятость. Если исторически все «важные» страницы были на мелкой глубине, модель может воспроизводить эту предвзятость, рекомендуя выносить всё на глубину 1–2. Для борьбы с этим используйте разнообразные обучающие данные (несколько сайтов, разные ниши) и регулярно анализируйте распределение предсказаний на предмет нереалистичной концентрации.
Заключение: от плоской иерархии к семантическому графу
Традиционная глубина URL — это прокси-метрика, которая в эпоху графовых алгоритмов теряет свою объяснительную силу. GNN предлагают альтернативу: предсказывать оптимальное положение страницы в семантическом пространстве сайта, а не механическое количество слешей в URL.
Ключевой сдвиг мышления: перестать думать о сайте как о дереве (иерархия каталогов) и начать думать о нём как о графе (сеть семантических связей). Дерево навязывает единственный путь от корня к листу. Граф позволяет множество путей, каждый из которых передаёт контекст и авторитет. Задача GNN — найти для каждой страницы такое положение в этом графе, которое максимизирует её доступность, семантическую связность и авторитет.
Практический чек-лист для внедрения:
- Постройте граф сайта — узлы = страницы, рёбра = внутренние ссылки, атрибуты — семантические эмбеддинги + тип страницы + PageRank + поведенческие метрики + атрибуты ссылок (позиция, анкор, CTR).
- Определите целевую переменную — решите, что вы предсказываете: абсолютную глубину (регрессия), класс глубины (классификация) или относительный порядок (ранжирование). Определите источник разметки.
- Выберите архитектуру — для начала GAT с 2–3 слоями. Для крупных сайтов — GraphSAGE. Для гетерогенных графов — HeteroConv.
- Обучите модель и сравните с baselines — если GNN не превосходит линейную регрессию, проблема в данных, а не в архитектуре.
- Для малых сайтов используйте трансферное обучение — предобученные модели на открытых веб-графах.
- Интерпретируйте результаты через GNNExplainer или attention-визуализацию. Каждая рекомендация должна иметь понятное обоснование.
- Валидируйте предсказания через A/B-тесты — для выбранных страниц измените глубину и отслеживайте изменения в трафике, позициях и краулинговой частоте через GSC и серверные логи на протяжении минимум 4–8 недель.
- Автоматизируйте мониторинг — модель ежемесячно сканирует граф сайта и сигнализирует о страницах с аномальным расхождением фактической и предсказанной глубины.
- Итерируйте — обновляйте модель по мере роста сайта и накопления данных об эффективности внедрённых рекомендаций.
Финальная мысль:
Глубина URL — это не характеристика страницы. Это характеристика пути пользователя и робота к ней. GNN позволяет измерить этот путь не в слешах, а в семантических шагах. И именно этот семантический путь — а не физическая вложенность каталогов — определяет, как поисковая система оценивает значимость контента.


