Обзор модуляЧасть V · ~9 ч · Сложность: (средний) · Пререквизиты: Модуль 14
К этому моменту каскад ранжирования (Модуль 12) уже выдал список документов, отсортированный по предсказанной релевантности. Казалось бы, осталось только показать топ-k пользователю. На практике между «отсортированным списком» и «финальной выдачей (SERP, search engine results page)» лежит целый слой постранжирования (post-ranking, re-ranking layer) — правил и алгоритмов, которые переупорядочивают, прореживают, схлопывают и перемешивают результаты. Этот модуль — о той части постобработки, которая отвечает за состав и структуру выдачи, а не за оценку отдельного документа.
В сквозном конвейере «обход → индекс → факторы → ранжирование → выдача → постобработка → измерение» мы находимся строго после ранжирования и до показа. Вход слоя — упорядоченный список кандидатов с их признаками (хост, домен, сервис-источник, кластер-дубликат, предсказанный интент); выход — то, что увидит человек: ограниченное число результатов с одного сайта, без видимых дублей, с покрытием разных смыслов запроса и с корректно вставленными спецблоками (картинки, видео, карта, быстрые ответы).
Зачем это нужно? Чистая сортировка по релевантности близоруко оптимальна: она ставит наверх k документов, каждый из которых по отдельности лучший, но вместе они могут быть тремя страницами одного сайта об одном и том же. Пользователю это бесполезно — ему нужна полезность всей страницы целиком, а не сумма поточечных скоров. Группировка, дедупликация и разнообразие — это переход от оптимизации «лучший документ» к оптимизации «лучшая выдача».
Как читать по трекамВнимание. Это средний по сложности модуль ((средний)), но глава 15.3 (разнообразие) — продвинутая ((продвинутый)): там появляется субмодулярная оптимизация и жадные алгоритмы с гарантиями. Если MMR и интентное покрытие новы — задержитесь на интуиции, прежде чем читать формулы.
- Студент — обязательны 15.1 (группировка/схлопывание как ограничение) и 15.3 (формальная постановка разнообразия, MMR, субмодулярность, жадная аппроксимация 1 − 1/e). Глава 15.2 — на уровне идей (три уровня дедупликации). Глава 15.4 — обзорно.
- Инженер — всё обязательно. Особое внимание: инженерные заметки об overfetch (добор кандидатов под схлопывание), о порядке стадий пайплайна постранжирования, о ключах дедупликации и о слотовой модели вставки спецблоков.
- SEO — главы 15.1 (лимит ~2 результата на сайт — ключевая SEO-врезка модуля) и 15.4 (как спецблоки отъедают позиции). Дедупликация (15.2) важна как причина, по которой «зеркала» и параметрические URL не дают лишних позиций. SEO-врезки разбросаны по всему модулю.
- Смешанный — последовательно весь модуль; математику MMR и субмодулярности можно бегло просмотреть при первом проходе и вернуться позже.
- 15.1. Группировка по хосту/домену; host collapsing — ограничение числа результатов с одного сайта, схлопывание серий, добор кандидатов. (средний)
- 15.2. Дедупликация на выдаче — устранение повторов по URL, хосту и сервису-источнику; три уровня и их ключи. (средний)
- 15.3. Разнообразие выдачи — интентное покрытие, MMR-подобные подходы, субмодулярность, жадная аппроксимация. (продвинутый)
- 15.4. Управление позициями и вставка спецблоков — слотовая модель, blending/федерация, вытеснение органики. (средний)
Цели обучения
После главы студент сможет:
- Объяснить, почему сортировка по поточечной релевантности порождает «засилье одного сайта» и почему это вредит полезности выдачи.
- Различать уровни группировки: по хосту, по зарегистрированному домену (eTLD+1), по логическому сайту.
- Реализовать алгоритм схлопывания (host collapsing) с лимитом и «раскрытием» серии в один сгруппированный блок.
- Обосновать необходимость добора кандидатов (overfetch) при схлопывании и оценить нужный запас.
- Связать лимит на сайт с метриками качества выдачи и со стратегией SEO.
Проблема: жадная сортировка близорука
Каскад ранжирования оценивает каждый документ поточечно (pointwise) или попарно: «насколько этот URL релевантен запросу». Он не знает, что три верхних URL принадлежат одному сайту и рассказывают об одном и том же. Если просто взять топ-k, на коммерческом или информационном запросе легко получить выдачу, где первые 5 позиций — это разделы каталога одного крупного агрегатора.
Это проявление более общего принципа: полезность выдачи субаддитивна по похожим результатам. Второй почти-такой-же документ добавляет куда меньше, чем первый. Формально мы выйдем на это в главе 15.3 (субмодулярность); здесь — частный, но важнейший случай: похожесть «по принадлежности одному сайту».Интуиция. Представьте полку в магазине: даже если у одного бренда товары объективно лучшие, продавец не заставит всю полку одним брендом — покупателю нужен выбор. Поисковая выдача — та же полка. Польза для пользователя от четвёртой страницы одного сайта почти нулевая: если первые три его не убедили, четвёртая не поможет, а вот результат с другого источника может закрыть его потребность.
Что такое «один сайт»: уровни группировки
«Ограничить число результатов с одного сайта» требует определить, что считать «одним сайтом». Есть несколько уровней, и их легко перепутать:
Код: Выделить всё
Уровень | Ключ группировки | Пример: что схлопнётся вместе
-----------------------------------+---------------------+-----------------------------------------------------------
Полное имя хоста (FQDN) | shop.example.com | только страницы этого поддомена
Зарегистрированный домен (eTLD+1) | example.com | shop.example.com, blog.example.com, www.example.com
Логический сайт (site) | владелец/площадка | домен + его поддомены + связанные домены одного владельца
Инженерная заметка. Для корректного выделения eTLD+1 нужна актуальная таблица публичных суффиксов (public suffix list). Без неё user1.blogplatform.io и user2.blogplatform.io ошибочно склеятся в один «сайт», хотя это разные независимые авторы на общем хостинге. Это типичная ошибка: наивное «взять два последних поля домена» ломается на co.uk и на платформенных суффиксах.
Алгоритм схлопывания (host collapsing)Заблуждение. «Группировка по хосту и по домену — одно и то же.» Нет. На уровне хоста m.example.com и www.example.com — разные сайты, и оба могут попасть в топ. На уровне eTLD+1 они схлопываются. Большинство систем группируют по зарегистрированному домену (eTLD+1), а внутри него ещё и по хосту, чтобы не пропустить мобильное зеркало как «другой источник».
Базовый алгоритм с лимитом L результатов на сайт:
Код: Выделить всё
collapse(ranked_list, key_fn, L):
seen = {} # ключ сайта -> сколько уже показано
out = []
overflow = {} # ключ сайта -> хвост (скрытые результаты)
for doc in ranked_list: # порядок = по убыванию релевантности
site = key_fn(doc) # eTLD+1 (+ опц. хост)
c = seen.get(site, 0)
if c < L:
out.append(doc)
seen[site] = c + 1
if c == 0:
doc.is_group_head = True # первый — «голова» группы
else:
overflow.setdefault(site, []).append(doc) # в «ещё с этого сайта»
return out, overflow
- Жёсткое отсечение (hard cap). Просто выбросить всё сверх лимита. Просто, но теряем потенциально полезные страницы.
- Схлопывание в блок (collapsing / indented results). Показать первый результат как «голову» группы, а остальные L-1 (или ссылку «ещё N с этого сайта →») — как вложенный блок под ним. Пользователь видит один логический элемент выдачи, но может развернуть серию.
- Перенос вниз (demotion / spreading). Не выбрасывать, а сдвинуть лишние результаты ниже по списку, разрешив им появиться, только когда более разнообразные кандидаты закончились.
Зачем нужен добор кандидатов (overfetch)Пример. Запрос «рецепт борща», L = 2 по eTLD+1. Ранжировщик выдал: kuhnya.ru/borsch-1 (скор 9.8), kuhnya.ru/borsch-2 (9.7), kuhnya.ru/borsch-3 (9.6), eda-doma.ru/borsch (9.5), povar.ru/borsch (9.4). При лимите 2 в финал попадут два с kuhnya.ru, затем по одному с eda-doma.ru и povar.ru. Третий kuhnya.ru/borsch-3 уходит в overflow — либо под «голову» как «ещё рецепты с kuhnya.ru», либо вниз, либо отбрасывается.
Тонкий, но критичный инженерный момент. Схлопывание удаляет документы из топа. Если каскад вернул ровно k кандидатов, а половина из них — с одного сайта, после схлопывания финальная выдача окажется короче k — позиции просто опустеют.
Поэтому слой постранжирования должен запрашивать у ранжировщика больше документов, чем нужно показать: не топ-k, а топ-k·m, где m — коэффициент добора. Размер m зависит от ожидаемой «концентрации» по сайтам: чем чаще один сайт занимает много мест, тем больший запас нужен.
Инженерная заметка. Добор не бесплатен: расширение глубины с k до k·m увеличивает нагрузку на дорогие верхние стадии каскада (L2/L3 в Модуле 12). На практике m подбирают эмпирически (часто m ≈ 2…4 для лимита L=2…3) и иногда делают адаптивным: добирать ещё, только если после первого прохода схлопывания топ не заполнился. Это компромисс между латентностью и риском «дыр» в выдаче.
Связь с метриками качестваВнимание. Порядок стадий важен: схлопывание по сайту должно идти до дедупликации по сервису (15.2) и до вставки спецблоков (15.4), иначе спецблок может занять слот, который потом отнимут у схлопывания, и арифметика позиций «поедет». Конкретный порядок — инженерное решение, но он должен быть зафиксирован и единообразен.
Лимит на сайт нельзя выбрать «из головы» — его калибруют по метрикам полезности всей выдачи (Модуль 19): насколько часто пользователь находит ответ, не уходя на вторую страницу; растёт ли удовлетворённость при L=2 против L=3. Слишком жёсткий лимит вредит, когда сайт объективно — лучший источник по запросу (например, официальный сайт организации по навигационному запросу к ней). Поэтому лимит часто зависит от класса запроса: для навигационных запросов он мягче (логично показать несколько страниц искомого сайта), для широких информационных — жёстче.
Частые заблуждения
Заблуждение. «Схлопывание — это то же, что дедупликация.» Нет. Дедупликация (15.2) убирает результаты, которые по сути одинаковы (один контент, зеркала, дубль-URL). Схлопывание ограничивает количество разных, но однохостовых результатов. Три разные статьи одного сайта — не дубли, но схлопыванию подлежат.
Лаба / практикаЗаблуждение. «Если мой сайт лучший, я займу весь топ.» Лимит на сайт не даст. Даже идеальные по релевантности страницы сверх лимита уйдут в свёрнутый блок или вниз. Это и есть SEO-следствие ниже.
Дан ранжированный список из 12 кандидатов с полями (url, score, host). Реализуйте collapse(...) с лимитом L=2 по eTLD+1 (используйте мини-таблицу публичных суффиксов: .com, .ru, .co.uk, blogplatform.io). Затем добавьте overfetch: исходно ранжировщик «отдаёт» только топ-6; покажите, что после схлопывания финальный топ-5 не заполняется, и реализуйте адаптивный добор остальных кандидатов до заполнения. Сравните три политики overflow (отсечение / блок / перенос вниз) на одном входе.
Ожидаемый результат: финальный топ-5 без более чем 2 URL с одного домена; корректное выделение eTLD+1 для user.blogplatform.io; продемонстрированная «дыра» без добора и её закрытие с добором. Время ~50 мин. Критерий «сделано»: для эталонного входа выдача совпала, объяснено, почему наивное «два поля домена» ломается на co.uk.
Контрольные вопросы
- Чем группировка по хосту отличается от группировки по eTLD+1? Приведите пару URL, которые склеятся в одном случае и нет в другом.
- Почему для выделения «зарегистрированного домена» недостаточно взять две последние метки имени хоста?
- Что такое overfetch и почему без него после схлопывания в топе появляются пустые позиции?
- Опишите три политики обращения с «лишними» результатами сайта и их компромиссы.
- Почему лимит на сайт иногда делают зависящим от класса запроса? Приведите пример запроса, где мягкий лимит уместен.
- Где в пайплайне постранжирования должно стоять схлопывание относительно дедупликации и вставки спецблоков, и почему порядок важен?
- Как связан лимит на сайт с понятием субаддитивности полезности выдачи (предвосхищая 15.3)?
Цели обучения
После главы студент сможет:
- Разграничить дедупликацию на выдаче и дедупликацию на индексе/каноникализации (Модуль 3) — что и где происходит.
- Описать три уровня дедупликации выдачи: точный URL, контентный дубль, сервис-источник.
- Выбрать корректный ключ дедупликации для каждого уровня и объяснить риск ложного склеивания.
- Реализовать дедупликацию near-duplicate на выдаче поверх кластеров/сигнатур, пришедших из индекса.
Где проходит граница: индекс vs выдача
Большая часть устранения дублей происходит раньше — на стадии каноникализации (Модуль 3): зеркала склеиваются в каноническую форму URL, near-duplicate-документы кластеризуются по сигнатурам (shingling, SimHash/MinHash), в индекс попадает представитель кластера. Тогда зачем дедуплицировать ещё и на выдаче?
Потому что каноникализация не идеальна и работает на уровне всего корпуса, а не конкретного запроса:
- Остаточные дубли. Сигнатурная кластеризация имеет ошибки; два URL, не склеенные в индексе, могут оказаться рядом в топе по конкретному запросу — и только здесь их сходство становится видимым и вредным.
- Запросо-зависимая близость. Два документа могут быть «не дублями» в целом, но по данному запросу их сниппеты и релевантная часть совпадают (например, одна и та же новость в перепечатке).
- Федерация источников. В выдачу подмешиваются результаты из разных вертикалей/сервисов (15.4), и одна и та же сущность (организация, товар) может прийти из нескольких источников.
Три уровня дедупликации выдачиИнтуиция. Каноникализация — это «уборка склада» (один раз, для всех). Дедупликация на выдаче — «последняя проверка перед подачей»: даже на чистом складе на одну тарелку могло попасть две одинаковые ложки именно для этого заказа.
Код: Выделить всё
Уровень | Что устраняем | Ключ | Риск
--------------------------------------+----------------------------------------------------------------+-------------------------------------------+-----------------------------------------
1. Точный URL | один и тот же адрес дважды (после федерации/слияния списков) | нормализованный URL | почти нулевой
2. Контентный дубль (near-duplicate) | разные URL, одинаковый по сути контент | сигнатура контента / id кластера дублей | ложное склеивание разных страниц
3. Сервис / сущность | одна сущность от разных источников | id сущности / ключ сервиса | склеивание похожих, но разных сущностей
Уровень 2 — контентный дубль. Опирается на сигнатуры/кластеры из индекса. Каждый кандидат несёт cluster_id (идентификатор кластера near-duplicate) или сигнатуру (SimHash). На выдаче оставляем одного представителя на кластер — того, что выше по релевантности.
Код: Выделить всё
dedup_near(list):
seen_clusters = set()
out = []
for doc in list: # по убыванию релевантности
cid = doc.cluster_id or simhash_bucket(doc.signature)
if cid in seen_clusters:
continue # дубль уже представлен выше
seen_clusters.add(cid)
out.append(doc)
return out
Уровень 3 — сервис/сущность. Самый тонкий. В федеративной выдаче (15.4) одна сущность — например, организация — может прийти как органический результат (её сайт), как карточка из справочника, как объект на карте. Это не дубли по URL и не дубли по контенту, но показывать три раза одну организацию избыточно. Дедупликация по entity_id (если сущности разрешены/слинкованы) либо по ключу сервиса (не более одного результата от данного сервиса на сущность).Инженерная заметка. Если cluster_id из индекса доступен — используйте его (он точнее, считался на полном корпусе). Сравнение SimHash «на лету» (по расстоянию Хэмминга в пределах порога) — запасной вариант для остаточных случаев и для свежедобавленных документов, которые ещё не прошли полную кластеризацию.
Заблуждение. «Дедупликация на выдаче не нужна, ведь есть каноникализация.» Каноникализация устраняет дубли в индексе на уровне всего корпуса. Запросо-зависимые совпадения, ошибки кластеризации и федеративные повторы видны только на выдаче — поэтому финальная проверка обязательна.
Взаимодействие со схлопываниемВнимание. Главный риск дедупликации — ложное склеивание (false merge): агрессивный ключ убьёт разные полезные результаты. Две карточки товара с почти одинаковым названием, но разными характеристиками — не дубли. Порог сходства и выбор ключа калибруют так, чтобы цена ложного склеивания (потеря полезного) не превысила выигрыш от удаления повтора.
Дедупликация и схлопывание (15.1) решают разные задачи, но порядок их применения влияет на результат. Обычно: сначала дедуплицируют точные и контентные дубли (чтобы они не «съедали» лимит сайта впустую), затем применяют схлопывание по сайту, затем — дедуп по сущности/сервису уже на почти финальном списке.
Частые заблужденияSEO-врезка. Параметрические URL (?utm=…, ?sort=…, сессионные id), HTTP/HTTPS- и www/non-www-зеркала, AMP/мобильные версии и «копии» страниц не дают дополнительных позиций: они схлопываются каноникализацией и финальной дедупликацией в один результат. Размножение почти-одинакового контента ради «занять больше места» не работает и тратит краулинговый бюджет (Модуль 2). Полезнее консолидировать сигналы на одной канонической странице.
Заблуждение. «Раз страницы на разных доменах — это точно не дубли.» Контентный дубль не зависит от домена: один и тот же текст на двух разных сайтах (перепечатка, синдикация) — near-duplicate, и на выдаче останется один представитель.
Лаба / практикаЗаблуждение. «Дедуп по URL ловит зеркала.» Только если URL нормализован одинаково. http://x.com/a и https://www.x.com/a/ — это один контент, но без нормализации (схема, www, слеш) ключи разные. Нормализация — обязательная часть ключа.
Дан список из 10 кандидатов: часть отличается только трекинг-параметрами, часть — это разные URL с одинаковым cluster_id, часть — одна организация из трёх источников (entity_id совпадает). Реализуйте трёхуровневую дедупликацию: (1) нормализация + дедуп по URL, (2) дедуп по cluster_id, (3) дедуп по entity_id с лимитом 1 результат на сущность. Затем введите «ловушку»: два разных товара с почти одинаковым названием — покажите, что дедуп по названию (плохой ключ) их ошибочно склеивает, а дедуп по entity_id/sku — нет.
Ожидаемый результат: из 10 кандидатов остаётся корректное число уникальных; продемонстрирован вред слишком агрессивного ключа (ложное склеивание). Время ~40 мин. Критерий «сделано»: ни один настоящий дубль не остался, ни один не-дубль не удалён; объяснён выбор ключа на каждом уровне.
Контрольные вопросы
- Чем дедупликация на выдаче отличается от каноникализации в индексе? Назовите три причины, по которым первая нужна несмотря на вторую.
- Перечислите три уровня дедупликации выдачи и подходящий ключ для каждого.
- Почему нормализация URL — обязательная часть ключа дедупликации первого уровня?
- Что такое ложное склеивание и какой ценой оборачивается слишком агрессивный ключ?
- Когда два документа на разных доменах являются дублями для целей выдачи?
- В каком порядке разумно применять дедуп-уровни и схлопывание по сайту? Обоснуйте.
- Почему размножение параметрических URL не даёт сайту дополнительных позиций?
Цели обучения
После главы студент сможет:
- Объяснить проблему неоднозначных и многоинтентных запросов и почему «лучшие по релевантности» документы не дают лучшую выдачу.
- Сформулировать диверсификацию как оптимизацию полезности всей выдачи и связать её с субмодулярностью.
- Вывести и реализовать MMR (Maximal Marginal Relevance) и объяснить роль параметра λ.
- Описать интентное покрытие (intent coverage) и алгоритмы покрытия аспектов (например, IA-подобные подходы).
- Обосновать гарантию 1 − 1/e жадного алгоритма на монотонной субмодулярной функции и оценить стоимость диверсификации.
Проблема: неоднозначность и многоинтентность
Запрос редко имеет ровно один смысл. «Ягуар» — это и автомобиль, и животное, и ОС, и спортклуб. «Питон» — змея и язык программирования. Даже однозначный по теме запрос имеет разные интенты (intents): «купить», «отзывы», «инструкция», «официальный сайт». Ранжировщик, оптимизирующий поточечную релевантность, поставит наверх документы доминирующего смысла — и пользователь редкого смысла уйдёт ни с чем.
Формально: система не знает истинный интент конкретного пользователя, она знает лишь распределение P(intent | query). Хорошая выдача максимизирует ожидаемую полезность по этому распределению, а не полезность для самого вероятного интента.Интуиция. Если 70% спрашивающих «ягуар» имеют в виду машину, а 30% — животное, то выдача из 10 ссылок только про машины обслуживает 70% и полностью проваливает 30%. А выдача 7 про машину + 3 про животное почти не теряет в первой группе и резко выигрывает во второй. Разнообразие — это страховка от неопределённости интента.
Полезность выдачи субмодулярна
Ключевая идея, объединяющая весь модуль. Пусть f(S) — полезность множества показанных результатов S. Эта функция обладает двумя свойствами:
- Монотонность: добавление результата не уменьшает полезность — f(S ∪ {d}) ≥ f(S).
- Субмодулярность (убывающая отдача, diminishing returns): ценность нового результата тем меньше, чем больше похожего уже показано. Формально для A ⊆ B:
Код: Выделить всё
f(A ∪ {d}) − f(A) ≥ f(B ∪ {d}) − f(B)
Задача диверсификации: выбрать S размера k, максимизирующее f(S). В общем виде максимизация субмодулярной функции при ограничении на размер — NP-трудна. Но есть спасение.Интуиция. Первая ссылка про «ягуар-животное» закрывает целый непокрытый интент — огромный прирост. Третья ссылка про то же — почти ничего. Это и есть убывающая отдача: предельная (marginal) польза результата падает по мере роста множества похожих на него. Схлопывание по сайту (15.1) и дедупликация (15.2) — частные случаи: однохостовость и одинаковость контента — это формы похожести, гасящие предельную пользу до нуля.
Жадный алгоритм и гарантия 1 − 1/e
Для монотонной субмодулярной функции простой жадный алгоритм даёт строгую гарантию:
Код: Выделить всё
greedy_diversify(candidates, k, f):
S = []
while len(S) < k:
d* = argmax_{d ∉ S} ( f(S ∪ {d}) − f(S) ) # макс. предельный прирост
S.append(d*)
return S
MMR: Maximal Marginal RelevanceИнженерная заметка. 1 − 1/e ≈ 63% — это худший случай; на реальных выдачах жадный алгоритм почти всегда заметно ближе к оптимуму. Важна не сама цифра, а вывод: не нужно искать оптимальное подмножество перебором — жадная вставка по убыванию предельной пользы достаточно хороша и работает за O(k · n) оценок f.
MMR — самая известная конкретизация жадной диверсификации. На каждом шаге выбираем документ, балансируя релевантность и новизну относительно уже выбранных:
Код: Выделить всё
MMR-выбор:
d* = argmax_{d ∉ S} [ λ · Rel(d, q) − (1 − λ) · max_{s ∈ S} Sim(d, s) ]
- λ = 1 — чистая релевантность, диверсификации нет (исходная сортировка).
- λ = 0 — чистая новизна, релевантность игнорируется (можно набрать разнообразный мусор).
- λ ≈ 0.7…0.8 — типичный рабочий диапазон: релевантность главенствует, новизна корректирует.
Пример. Запрос «ягуар», кандидаты по релевантности: авто-1 (0.95), авто-2 (0.93), авто-3 (0.92), животное-1 (0.85), ОС-1 (0.70). При λ=0.75 и высоком Sim между всеми «авто-*»: после выбора авто-1 предельная польза авто-2 падает (штраф за сходство), и на каком-то шаге животное-1, несмотря на меньшую Rel, обгоняет авто-3 — потому что не похоже ни на что выбранное. Итог: авто-1, авто-2, животное-1, авто-3, ОС-1 вместо авто-1..3 подряд.
Интентное покрытие (intent coverage) и IA-подходыВнимание. MMR требует меры сходства Sim(d, s). Её качество критично: плохая Sim (например, только по совпадению слов) не уловит, что два по-разному написанных текста об одном и том же — похожи. На практике Sim берут из эмбеддингов (нейропредставлений, Модуль 10) или из тематических меток.
MMR оперирует попарным сходством, но не «знает» про интенты явно. Альтернативное (и часто комбинируемое) семейство — покрытие аспектов/интентов. Идея: у запроса есть набор интентов {c} с весами P(c | q); у каждого документа — вероятность покрыть интент c, то есть P(d релевантен | c). Полезность выдачи S — это ожидаемая доля «удовлетворённых» пользователей:
Код: Выделить всё
U(S) = Σ_c P(c | q) · [ 1 − Π_{d ∈ S} (1 − P(d удовлетворяет | c)) ]
Сколько диверсифицировать: цена и рискИнтуиция. MMR штрафует «похожесть на уже показанное». Intent-coverage поощряет «закрытие ещё не закрытого спроса». Часто это две стороны одной монеты, но intent-модель явнее и позволяет управлять покрытием по весам P(c|q) — показать редкий интент пропорционально его доле, а не выкинуть совсем.
Диверсификация — это сознательное смещение от чистой релевантности. Если переборщить, мы понизим объективно лучший результат ради «разнообразия» и навредим большинству. Поэтому:
- Сила диверсификации (λ или вес покрытия) зависит от неоднозначности запроса: чем выше энтропия P(intent|q), тем агрессивнее диверсифицируем; для однозначных навигационных запросов диверсификацию почти отключают.
- Эффект измеряют диверсити-чувствительными метриками (Модуль 19): не плоский nDCG, а его интентно-взвешенные варианты (например, α-nDCG, ERR-IA), которые вознаграждают покрытие аспектов и штрафуют избыточность.
Частые заблужденияSEO-врезка. Диверсификация — ещё одна причина, по которой нельзя «занять весь топ» одной интерпретацией запроса. Если ваш контент покрывает доминирующий интент, на менее частые интенты система всё равно поднимет других. Практический вывод: чтобы ранжироваться по неоднозначному запросу, бейте в конкретный интент и закрывайте его исчерпывающе, а не пытайтесь покрыть всё разом размытой страницей — диверсификатор предпочтёт чёткого специалиста по нужному аспекту.
Заблуждение. «Разнообразие — это просто не показывать похожее.» Это половина правды (так делает MMR через штраф Sim). Вторая половина — покрытие интентов: цель не «непохожесть ради непохожести», а максимизация ожидаемой полезности по распределению намерений. Можно набрать разнообразный, но бесполезный набор.
Заблуждение. «Жадный алгоритм даёт лишь грубое приближение, надо искать оптимум.» Для монотонной субмодулярной функции жадность гарантированно даёт ≥63% оптимума в худшем случае и обычно гораздо ближе, а оптимум NP-труден. Перебор не оправдан.
Лаба / практикаЗаблуждение. «Чем больше λ к нулю — тем лучше выдача разнообразнее.» При λ→0 релевантность игнорируется, и в топ полезут новые, но нерелевантные документы. Разнообразие без релевантности бесполезно; рабочая зона λ — ближе к релевантности.
Дан запрос с 6 кандидатами: каждый помечен интентом (auto/animal/os) и имеет Rel(d,q). Заданы попарные Sim (высокие внутри интента, низкие между). (1) Реализуйте MMR и постройте топ-4 для λ ∈ {1.0, 0.7, 0.3}; покажите, как меняется состав. (2) Реализуйте intent-coverage U(S) с весами P(c|q) = {auto:0.6, animal:0.3, os:0.1} и жадно постройте топ-4; сравните с MMR. (3) Посчитайте простой α-nDCG-подобный показатель для обеих выдач и для исходной сортировки по Rel.
Ожидаемый результат: при λ=1 — три auto подряд; при λ=0.7 — animal поднимается в топ; intent-coverage явно резервирует слот под animal пропорционально весу. Время ~70 мин. Критерий «сделано»: показано влияние λ, продемонстрирована убывающая отдача (предельный прирост второго auto меньше первого animal), интентно-взвешенная метрика выше у диверсифицированной выдачи.
Контрольные вопросы
- Почему сортировка по поточечной релевантности плоха на неоднозначном запросе? Сформулируйте через ожидаемую полезность по P(intent|q).
- Что значит «полезность выдачи субмодулярна»? Запишите неравенство убывающей отдачи.
- Какую гарантию даёт жадный алгоритм на монотонной субмодулярной функции и почему это практически важно?
- Выпишите формулу выбора MMR и объясните роль каждого слагаемого и параметра λ.
- Что произойдёт с выдачей при λ=1 и при λ=0? Почему ни та, ни другая крайность не годится?
- Чем intent-coverage отличается от MMR по постановке? Что даёт явная модель интентов?
- Почему силу диверсификации привязывают к неоднозначности запроса и какими метриками её измеряют?
- Покажите, что схлопывание по сайту (15.1) — частный случай субмодулярной диверсификации.
Цели обучения
После главы студент сможет:
- Описать слотовую модель выдачи и роль движка федерации (federation/blending) в сборке финальной страницы.
- Объяснить, как и по каким условиям вертикальные результаты (картинки, видео, карта, быстрый ответ) вставляются между органическими.
- Реализовать простой blending: решение о включении спецблока и выборе его позиции.
- Оценить влияние спецблоков на видимость органики и связать это с измерением (CTR по позициям).
Выдача — это не один список, а собранная страница
До сих пор мы говорили об одном ранжированном списке (органика). Но реальная SERP — это федерация нескольких источников: основной веб-индекс плюс вертикали (verticals) — специализированные индексы (картинки, видео, новости, товары, карта/местные результаты, быстрые ответы/прямые ответы). За их совмещение отвечает движок федерации (federation / blending engine).
Архитектурно это слотовая модель: финальная страница — последовательность слотов (позиций), и каждый слот занимает либо органический результат, либо спецблок. Спецблок может занимать один слот или быть «толстым» (карусель картинок на ширину нескольких органических позиций).
Код: Выделить всё
SERP = [ slot_1, slot_2, ..., slot_n ]
каждый slot ← {органический результат} ∪ {спецблок вертикали}
Два решения федерации: включать и куда ставитьИнтуиция. Думайте о выдаче как о вёрстке газетной полосы: есть основная колонка (органика) и врезки (фото, врезка-карта, инфоблок). Редактор решает, стоит ли врезка этого запроса и куда её поставить, чтобы помочь читателю, а не мешать.
Для каждой вертикали движок решает две вещи:
- Триггер (включать ли). Нужна ли эта вертикаль данному запросу? «Погода в Москве» → блок погоды (да). «Купить дрель» → товарная галерея (да). «Теорема Пифагора» → быстрый ответ (да), а картинки/карта — вряд ли. Решение принимает классификатор по запросу (предсказанный интент, Модуль 5) и по «уверенности» вертикали в своих результатах.
- Позиция (куда ставить). Спецблок вставляется на позицию, пропорциональную его предсказанной полезности относительно органики на той же позиции. Сильный спецблок (явный интент картинок) идёт наверх; слабый — ниже или вовсе подавляется.
Код: Выделить всё
blend(organic, specials):
page = []
pos = 0
while собираем страницу:
best_organic = organic.peek() # лучший оставшийся орг. результат
best_special = argmax_v specials[v].value_at(pos)
if best_special and best_special.value > best_organic.value * threshold(pos):
page.append(best_special); pos += best_special.height
specials.consume(best_special)
else:
page.append(best_organic); pos += 1
organic.consume()
Инженерная заметка. Калибровка ценности между источниками — центральная сложность федерации. Скор картиночной вертикали и текстовый скор несравнимы напрямую; их сводят к общей метрике (например, предсказанной вероятности клика/удовлетворения на данной позиции) на обучающих данных. Без калибровки спецблоки либо лезут всюду, либо не появляются.
Спецблоки и быстрые ответыВнимание. Спецблоки и органика делят слотовый бюджет. Если вертикаль заняла верхние слоты, органических позиций «над сгибом» становится меньше. Поэтому решения федерации, схлопывания (15.1) и диверсификации (15.3) нельзя принимать независимо — итоговая полезность страницы зависит от их совокупности. Хорошие реализации оценивают полезность всей собранной страницы, а не каждого слота изолированно.
Особый случай — прямой/быстрый ответ (direct answer / answer box): блок, отвечающий на запрос прямо на странице (факт, определение, расчёт, расписание). Он экономит пользователю клик, но меняет поведение: часть запросов становится «без клика» (zero-click). Это влияет и на измерение (клик перестаёт быть сигналом удовлетворённости — Модуль 11 о сложностях клик-метрик), и на органику (её видимость снижается).
Влияние на измерение и эксперименты
Любое изменение состава/позиций меняет CTR по позициям и наблюдаемое поведение. Поэтому решения федерации калибруют и валидируют через A/B (Модуль 19), отслеживая не локальный CTR спецблока, а полезность сессии: не выросло ли число переформулировок и отказов из-за того, что спецблок вытеснил нужную органику.
Частые заблужденияSEO-врезка. Спецблоки и быстрые ответы сдвигают органику вниз и часть кликов забирают себе (zero-click). Практические следствия: (1) «позиция 1 в органике» уже не равна «первому, что видит пользователь» — над ней могут быть галерея и ответ-блок; (2) попадание в спецблок (товарная галерея, видео, локальная карточка, источник быстрого ответа) часто ценнее высокой органической позиции — оптимизировать стоит под формат, которого требует интент запроса; (3) для запросов с быстрым ответом органический трафик структурно ниже — это надо учитывать в прогнозах, а не списывать на «падение позиций».
Заблуждение. «Спецблоки вставляются всегда на фиксированные позиции.» Нет: и факт включения, и позиция — результат решения федерации по конкретному запросу. На одном запросе галерея картинок наверху, на другом её нет вовсе.
Лаба / практикаЗаблуждение. «Главное — максимизировать клики по спецблоку.» Локальный CTR блока обманчив: блок может перетягивать клики, ухудшая исход сессии (пользователь не нашёл нужное и переформулировал). Оптимизируют полезность всей страницы/сессии, а не отдельный блок.
Дано: органический список (5 результатов со скором, приведённым к общей шкале) и три вертикали (images, video, answer), каждая со своей value_at(pos) и высотой (images занимает 1 «толстый» слот высотой 2). Реализуйте blend(...) с порогом threshold(pos), убывающим с позицией. Прогоните три запроса: навигационный (вертикали слабые), «как выглядит X» (сильные картинки), «сколько будет 2+2» (сильный answer наверху). Покажите, как меняется сборка и сколько органических позиций осталось «над сгибом» (первые 4 слота).
Ожидаемый результат: для навигационного запроса спецблоки подавлены; для «как выглядит» галерея наверху и вытеснила органику; для арифметики answer-box занял слот 1. Время ~50 мин. Критерий «сделано»: корректная арифметика позиций (с учётом высоты толстого блока), продемонстрировано вытеснение органики и зависимость от запроса.
Контрольные вопросы
- Что такое слотовая модель выдачи и какова роль движка федерации?
- Какие два решения принимает федерация для каждой вертикали? От чего зависит каждое?
- Почему калибровка ценности между разнотипными источниками — главная сложность blending?
- Как «толстый» спецблок влияет на арифметику позиций и слотовый бюджет?
- Что такое быстрый ответ (zero-click) и как он влияет на измерение и на органику?
- Почему нельзя оптимизировать спецблок по его локальному CTR в отрыве от исхода сессии?
- Сформулируйте для SEO, почему «первая позиция в органике» больше не гарантирует первое внимание пользователя.
- Постранжирование оптимизирует выдачу целиком, а не отдельный документ. Между отсортированным списком и показом лежит слой, который схлопывает, дедуплицирует, диверсифицирует и собирает страницу из источников. Цель — полезность всей SERP, а не сумма поточечных скоров.
- Схлопывание по сайту (host collapsing) ограничивает число результатов с одного хоста/домена (eTLD+1). Требует корректного выделения зарегистрированного домена через таблицу публичных суффиксов и добора кандидатов (overfetch), иначе в топе появляются пустые позиции.
- Дедупликация на выдаче работает в три уровня — точный URL, контентный near-duplicate (по кластеру/сигнатуре из индекса), сущность/сервис — и дополняет каноникализацию там, где сходство видно только запросо-зависимо. Главный риск — ложное склеивание разных полезных результатов.
- Полезность выдачи монотонна и субмодулярна (убывающая отдача от похожих результатов). Схлопывание и дедупликация — частные случаи: однохостовость и одинаковость гасят предельную пользу.
- Диверсификация страхует от неопределённости интента: максимизирует ожидаемую полезность по P(intent|q). Реализуется жадным алгоритмом с гарантией 1 − 1/e от оптимума.
- MMR балансирует релевантность и новизну через λ (рабочая зона ближе к релевантности, λ≈0.7…0.8); intent-coverage явно закрывает непокрытые интенты пропорционально их весам. Силу диверсификации привязывают к неоднозначности запроса и измеряют интентно-взвешенными метриками.
- Финальная SERP — федерация источников по слотовой модели. Движок blending решает, включать ли вертикаль и куда её поставить, приводя разнотипные источники к общей шкале полезности. Спецблоки и быстрые ответы делят слотовый бюджет с органикой и сдвигают её вниз.
- Главное: схлопывание, дедупликация, диверсификация и федерация — взаимозависимы и должны оцениваться по полезности всей собранной страницы и сессии, а не по локальным метрикам отдельных слотов.
- Постранжирование (post-ranking, re-ranking layer) — слой между сортировкой по релевантности и показом, формирующий состав и структуру выдачи.
- Выдача (SERP, search engine results page) — финальная страница результатов, собранная из органики и спецблоков.
- Группировка / схлопывание по сайту (host collapsing) — ограничение числа результатов с одного хоста/домена с переносом «лишних» в свёрнутый блок, вниз или в отброс.
- eTLD / публичный суффикс (public suffix) — эффективный домен верхнего уровня, включая составные (.co.uk) и платформенные (blogplatform.io).
- eTLD+1 (зарегистрированный домен) — публичный суффикс плюс одна метка слева; «реально купленный» домен.
- Добор кандидатов (overfetch) — запрос у ранжировщика большего числа документов, чем нужно показать, чтобы компенсировать удаления при схлопывании/дедупликации.
- Дедупликация на выдаче — финальное устранение повторов по URL, контенту (near-duplicate) и сущности/сервису.
- Контентный дубль (near-duplicate) — разные URL с по сути одинаковым контентом; кластеризуются по сигнатурам (SimHash/MinHash, shingling).
- Ложное склеивание (false merge) — ошибочное удаление разных полезных результатов слишком агрессивным ключом дедупликации.
- Разнообразие / диверсификация (diversity) — формирование выдачи, покрывающей разные интенты/аспекты запроса.
- Интент (intent) — намерение за запросом; P(intent|q) — распределение намерений по запросу.
- Субмодулярность (submodularity) — свойство убывающей предельной отдачи: новый похожий результат добавляет тем меньше, чем больше похожего уже показано.
- Жадная аппроксимация 1 − 1/e — гарантия жадного алгоритма на монотонной субмодулярной функции (≈63% оптимума в худшем случае).
- MMR (Maximal Marginal Relevance) — жадный отбор, балансирующий релевантность Rel(d,q) и новизну (штраф Sim) через параметр λ.
- Интентное покрытие (intent coverage, IA-подходы) — диверсификация через явную максимизацию ожидаемой доли удовлетворённых интентов.
- α-nDCG / ERR-IA — интентно-взвешенные метрики качества, вознаграждающие покрытие аспектов и штрафующие избыточность.
- Федерация / blending — совмещение органики и вертикалей в единую выдачу.
- Вертикаль (vertical) — специализированный источник/индекс (картинки, видео, новости, товары, карта, быстрый ответ).
- Слотовая модель — представление SERP как последовательности позиций-слотов, занимаемых органикой или спецблоками.
- Триггер вертикали — решение, включать ли спецблок данной вертикали для запроса.
- Быстрый/прямой ответ (direct answer, zero-click) — блок с ответом прямо на странице, нередко без перехода на сайт.
- Опирается на Модуль 19 (оценка и эксперименты: метрики и A/B) — лимиты, λ, пороги федерации калибруют по метрикам полезности выдачи и сессии; диверсити-чувствительные метрики (α-nDCG, ERR-IA) родом оттуда (базовые метрики nDCG/MAP — Модуль 1).
- Принимает вход от Модуля 12 (каскад L0-L3 и serving) — упорядоченный список кандидатов с признаками и предсказанным интентом (сам интент — из Модуля 5); overfetch нагружает верхние стадии каскада.
- Опирается на Модуль 3 (каноникализация) — дедупликация выдачи дополняет индексную каноникализацию остаточными и запросо-зависимыми случаями; ключи нормализации общие.
- Использует кластеры/сигнатуры дублей — cluster_id/SimHash приходят из стадии индексирования и каноникализации.
- Связан с Модулем 10 (нейропоиск, эмбеддинги) — мера сходства Sim(d,s) для MMR/диверсификации часто строится на эмбеддингах.
- Перетекает в Модуль 16 (антиспам) — манипуляции, нацеленные на захват выдачи (doorway-страницы, размножение зеркал ради позиций), нейтрализуются совместно схлопыванием/дедупликацией и антиспам-сигналами.
- Классические работы по диверсификации результатов поиска (MMR; intent-aware подходы и покрытие аспектов).
- Литература по максимизации монотонных субмодулярных функций и жадным алгоритмам с гарантией 1 − 1/e (Nemhauser–Wolsey–Fisher).
- Обзоры по диверсити-чувствительным метрикам оценки (α-nDCG, ERR-IA, intent-взвешенный nDCG).
- Работы по обнаружению near-duplicate документов (shingling, SimHash, MinHash) и оценке порогов сходства.
- Материалы по таблицам публичных суффиксов и корректному выделению зарегистрированного домена.
- Литература по федеративному/агрегированному поиску (federated/aggregated search, vertical selection, result presentation) и калибровке разнотипных источников к общей шкале полезности.