Статья

Алгоритмы ранжирования в W3A: Как работают умные ленты новостей и комментариев

Погружение в математические основы сортировки контента на примере формул Вильсона и Reddit-style hotness

В современных социальных новостных агрегаторах и платформах пользовательского контента (UGC) критически важно правильно сортировать материалы. Простая сортировка по дате или количеству голосов не работает: новые материалы с высоким качеством тонут в потоке, а старые спорные публикации продолжают висеть в топе.

В проекте W3A используются два продвинутых алгоритма ранжирования:

  1. Интервал Вильсона (Wilson Score Interval) — для умного ранжирования комментариев
  2. Алгоритм «горячести» (Hotness) — для динамической сортировки историй

Разберем каждый из них подробно.


Часть 1: Интервал Вильсона для комментариев

         p + z²/(2n) - z√[(p(1-p)/n + z²/(4n²)]
confidence = ─────────────────────────────────────
                    1 + z²/n

Проблема среднего арифметического

Представьте два комментария:

  • Комментарий A: 10 голосов «за», 0 «против» (100% положительных)
  • Комментарий B: 950 голосов «за», 50 «против» (95% положительных)

Если сортировать по среднему рейтингу, Комментарий A окажется выше, хотя у Комментария B в 95 раз больше голосов и статистически более надежный рейтинг.

Решение — интервал Вильсона.

Как это работает

Формула Вильсона вычисляет нижнюю границу доверительного интервала для биномиального распределения. Проще говоря: она отвечает на вопрос «какой минимальный рейтинг мы можем гарантировать с определенной уверенностью?»

function wilson_score(int $score, int $flags): float
{
    $ups = $score + $flags;
    $downs = $flags;
    $n = $ups + $downs;
    
    if ($n === 0) {
        return 0.0;
    }
    
    // Z-оценка для 80% доверительного интервала
    $z = 1.281551565545;
    $p = $ups / $n; // Доля положительных голосов
    
    // Формула Вильсона
    $zSquared = $z * $z;
    $left = $p + (1 / (2 * $n) * $zSquared);
    $right = $z * sqrt(($p * ((1 - $p) / $n)) + ($zSquared / (4 * $n * $n)));
    $under = 1.0 + ((1.0 / $n) * $zSquared);
    
    $confidence = ($left - $right) / $under;
    
    return max(0.0, min(1.0, $confidence));
}

Ключевые параметры

  • $z = 1.281551565545 — Z-оценка для 80% доверительного интервала (в Reddit используют 1.28)
  • $p — доля положительных голосов (upvotes / total)
  • $n — общее количество голосов

Почему это лучше?

Пример расчета:

Комментарий Upvotes Flags % Positive Wilson Score
A 10 0 100% 0.722
B 950 50 95% 0.938
C 3 0 100% 0.463

Несмотря на 100% рейтинг, Комментарии A и C получают более низкий Wilson Score из-за малого количества голосов. Комментарий B с 95% и большим числом голосов оказывается выше — это справедливо!

Преимущества подхода

Защита от накрутки: Новые комментарии с 1-2 голосами не попадают в топ
Статистическая надежность: Учитывается размер выборки
Автоматическая фильтрация спама: Флаги сильно снижают рейтинг
Баланс нового и качественного: Хорошие комментарии поднимаются по мере получения голосов


Часть 2: Алгоритм Hotness для историй

hotness = -((sign × log₁₀(max(|score|, 1)) + seconds / 45000) + Σ hotness_mod_tags)

Проблема хронологической сортировки

Простая сортировка по дате (новые сверху) игнорирует качество контента. Сортировка по общему рейтингу favoreт старые публикации, которые просто успели набрать больше голосов.

Решение — комбинированная метрика «горячести».

Как это работает

Алгоритм объединяет логарифм рейтинга с временным затуханием:

function calculate_hotness(int $score, string $createdAt): float
{
    // Логарифмическая шкала рейтинга
    $order = log10(max(abs($score), 1));
    
    // Знак (положительный/отрицательный рейтинг)
    $sign = $score > 0 ? 1 : ($score < 0 ? -1 : 0);
    
    // Epoch для расчета времени (база: 8 декабря 2005 — запуск Reddit)
    $epoch = strtotime('2005-12-08');
    $seconds = strtotime($createdAt) - $epoch;
    
    // Финальная формула: (логарифм рейтинга) + (время / константа затухания)
    return round(($sign * $order) + ($seconds / 45000), 7);
}

Разбор формулы

1. Логарифмическая шкала (log10)

score = 10    → order = 1
score = 100   → order = 2
score = 1000  → order = 3
score = 10000 → order = 4

Логарифм предотвращает доминирование сверхпопулярных материалов. Разница между 10 и 100 голосами важнее, чем между 1000 и 1010.

2. Временной компонент (seconds / 45000)

  • 45000 секунд ≈ 12.5 часов — период полураспада «горячести»
  • Каждая публикация получает временной бонус, который уменьшается со временем
  • Новые материалы автоматически получают преимущество

3. Константа эпохи (8 декабря 2005)

Это дата запуска Reddit. Используется как базовая точка отсчета для совместимости с оригинальной формулой Reddit.

Пример работы

Допустим, сейчас 22 июня 2026 года:

История Score Дата публикации Hotness Score
A 100 2 часа назад 4.8921234
B 500 1 день назад 4.6987654
C 1000 3 дня назад 4.3010299

Несмотря на то, что История C имеет в 10 раз больше голосов чем A, она оказывается ниже из-за возраста. История A «горячее» — она новая и уже набрала хороший рейтинг.

Почему 45000 секунд?

Это эмпирическая константа, подобранная Reddit. Она означает:

  • Через 12.5 часов история теряет примерно 1 порядок логарифмической шкалы
  • Через 24 часа даже очень популярная история (score=1000) уступит новой с score=10
  • Это создает быстро обновляемую ленту, где всегда есть место новому контенту

Преимущества подхода

Баланс старого и нового: Популярные материалы не доминируют вечно
Защита от «вечного топа»: Старые истории плавно опускаются
Стимулирование активности: Новые публикации получают шанс
Логарифмическая справедливость: 10→100 важнее чем 1000→1010


Часть 3: Сравнение с другими платформами

Reddit

  • Hotness: Использует аналогичную формулу с константой 45000
  • Comments: Wilson Score с Z=1.28 (80% доверие)
  • W3A: Полная совместимость с подходом Reddit

Hacker News

  • Использует формулу: (p - 1) / (t + 2)^gravity
  • Где p — очки, t — время в часах, gravity ≈ 1.8
  • Более агрессивное временное затухание

Lobsters

  • Комбинация votes, comments и времени
  • Формула: votes + comments * 0.5 с временным множителем
  • Более мягкое ранжирование

Часть 4: Практические рекомендации

Когда использовать Wilson Score?

✅ Рейтинги с голосами «за/против»
✅ Комментарии и отзывы
✅ Пользовательский контент с модерацией
✅ Любые ситуации с малым количеством голосов

Когда использовать Hotness?

✅ Ленты новостей
✅ Социальные агрегаторы
✅ Платформы с частыми публикациями
✅ Когда важно показывать свежий качественный контент

Настройка под свой проект

Для Wilson Score:

  • Измените $z для другого доверительного интервала:
    • 1.28 — 80% (Reddit, W3A)
    • 1.64 — 90%
    • 1.96 — 95% (более консервативно)

Для Hotness:

  • Измените делитель 45000:
    • 25000 — быстрее обновление (6 часов полураспада)
    • 75000 — медленнее (24 часа полураспада)
    • 100000 — очень медленно (36 часов)

Заключение

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

Интервал Вильсона защищает от статистического шума и накруток, давая преимущество материалам с проверенным качеством.

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

Вместе они создают сбалансированную систему ранжирования, которая:

  • Показывает релевантный контент
  • Борется со спамом и накрутками
  • Стимулирует постоянную активность
  • Справедлива к новым пользователям

Эти формулы проверены годами работы Reddit, Hacker News и других крупных платформ. Их реализация в W3A — пример использования математически обоснованных подходов вместо интуитивных решений.


Дополнительные ресурсы


Автор: Евгений К
Дата: 23 июня 2026
Сайт: https://w3a.ru/

Опубликовано в Блог Evg

3 Ответа

  1. В общем, протестирую решение на w3a, после чего его можно будет перенести на LibArea. Там я использую довольно интересные подходы — возможно, на первый взгляд они покажутся сложными, но нужно оценить их эффективность. На Reddit эти методы уже проверены временем, а здесь их ещё предстоит протестировать.

    Если внедрять их в libarea, то запросы для центральной страницы придётся полностью переписать. Это большой объём работы. Возможно, стоит привлечь ИИ для оптимизации кода и оценки потенциального выигрыша в производительности. Буду изучать этот вопрос.

  1. Читал про алгоритмы книгу, еще на учебе, если честно не понял практичесно нечего, но сам принцип ясен.
    Кстати, Женя привет, давно к тебе не заходил)

    1. Привет. Первый раз лет 10 назад смотрел на эти алгоритмы, ни фига не понял. А сейчас повторно, вроде проще стало. 😄