Алгоритми · Лінійна алгебра
📅 Липень 2026 ⏱ ≈ 12 хв читання 🎯 Середній рівень · Останнє оновлення: 9 липня 2026 р.

PageRank як ланцюг Маркова: випадковий серфер і стаціонарний розподіл

Оригінальна стаття Google про PageRank переформулювала питання «наскільки важлива ця сторінка» у суто математичну задачу: якщо знуджений серфер вічно клацає по випадкових посиланнях, де він проведе найбільше часу? Відповідь — стаціонарний розподіл (стійка, довгострокова ймовірність опинитися на кожній сторінці) ланцюга Маркова, а знайти його можна простим повторенням множення матриць.

Коротко: PageRank розглядає веб як випадкове блукання: серфер, що клацає посилання (і час від часу телепортується на випадкову сторінку), із часом виходить на стійкий довгостроковий розподіл — стаціонарний розподіл. Цей розподіл обчислюють дешево через степеневий метод — повторне множення матриць — замість прямого розв'язання величезної системи рівнянь.

Ланцюги Маркова: стани та переходи

Ланцюг Маркова — послідовність станів, де ймовірність переходу до наступного стану залежить лише від поточного стану, а не від історії, що до нього призвела, — марковська властивість. Формально ланцюг над станами {1, …, n} задається матрицею переходів P, де Pij — ймовірність переходу зі стану i в стан j:

P(Xₜ₊₁ = j | Xₜ = i, Xₜ₋₁, …, X₀) = P(Xₜ₊₁ = j | Xₜ = i) = Pᵢⱼ
Кожен рядок P сумується до 1 — P є рядково-стохастичною

Для веба «станами» є сторінки, а Pᵢⱼ — ймовірність того, що серфер на сторінці i натисне посилання на сторінку j. Якщо сторінка i має k вихідних посилань, найпростіша модель призначає Pᵢⱼ = 1/k для кожної сторінки j, на яку є посилання, і 0 — інакше.

Стаціонарний розподіл

Нехай π — рядок-вектор, де πᵢ — ймовірність перебування у стані i. Після одного кроку новий розподіл дорівнює π·P. Стаціонарний розподіл π* — це нерухома точка цього перетворення:

π* · P = π*
π* — лівий власний вектор P з власним значенням 1

π*ᵢ — це довгострокова частка часу, яку ланцюг проводить у стані i, незалежно від початкового стану — за умови, що ланцюг незвідний (кожен стан досяжний з будь-якого іншого) та аперіодичний (без жорсткої довжини циклу). PageRank — це саме π* для ланцюга «веб-серфер»: сторінки з найвищою стаціонарною ймовірністю посідають найвищі місця.

Модель випадкового серфера

Уявіть серфера, який на кожному кроці або (a) клацає рівномірно випадкове вихідне посилання з ймовірністю d (коефіцієнт загасання, зазвичай 0.85), або (b) йому набридає і він переходить на рівномірно випадкову сторінку будь-де у вебі з ймовірністю (1 − d). Це дає повний перехід PageRank:

PR(p) = (1 − d)/N + d · Σ_{q → p} PR(q) / L(q)
N = загальна кількість сторінок, L(q) = кількість вихідних посилань на сторінці q,
сума береться по всіх сторінках q, що посилаються на p

Термін випадкового переходу запобігає тому, щоб серфер назавжди застряг у підграфі без виходу, і гарантує, що ланцюг незвідний та аперіодичний — тому унікальний стаціонарний розподіл існує незалежно від форми веб-графа.

Тупикові вузли та коефіцієнт загасання

Тупиковий вузол — сторінка без вихідних посилань (PDF, зображення, глухий кут). Без спеціальної обробки вся її ймовірнісна маса просто зникає із системи, а рядки P більше не сумуються до 1. Стандартне рішення — перерозподілити масу тупикової сторінки рівномірно на всі N сторінок, ніби вона посилається на всіх:

Значення dІнтерпретаціяШвидкість збіжностіЕфект
0.0Чистий випадковий перехідМиттєво (1 крок)Однорідний рейтинг — ігнорує посилання
0.85Оригінальний вибір Google~50-100 ітераційБаланс структури посилань і стійкості
0.99Майже чисте слідування посиланнямДуже повільноЧутливе до тупикових вузлів / циклів
Чому саме 0.85? Оригінальна стаття Бріна і Пейджа обрала це значення емпірично: воно сходиться приблизно за 50-100 кроків степеневого методу для графа розміру веба, водночас зберігаючи достатньо «телепортації», щоб зробити ланцюг стійким до пасток-павуків і від'єднаних компонент.

Степеневий метод у JavaScript

Замість того, щоб розв'язувати π·P = π напряму (нездійсненно для мільярдів сторінок), PageRank використовує степеневий метод (power iteration): почати з рівномірного розподілу і повторно множити на матрицю переходів, доки він не перестане змінюватися.

function pageRank(adjacency, d = 0.85, iterations = 100, tol = 1e-9) {
  const N = adjacency.length;
  const outDegree = adjacency.map(links => links.length);
  let pr = new Float64Array(N).fill(1 / N);

  for (let iter = 0; iter < iterations; iter++) {
    const next = new Float64Array(N).fill((1 - d) / N);

    // Перерозподілити масу тупикових вузлів рівномірно на всі N сторінок
    let danglingMass = 0;
    for (let i = 0; i < N; i++)
      if (outDegree[i] === 0) danglingMass += pr[i];
    const danglingShare = d * danglingMass / N;

    // Розподілити ранг кожної сторінки по її вихідних посиланнях
    for (let i = 0; i < N; i++) {
      if (outDegree[i] === 0) continue;
      const share = d * pr[i] / outDegree[i];
      for (const j of adjacency[i]) next[j] += share;
    }
    for (let j = 0; j < N; j++) next[j] += danglingShare;

    // Перевірка збіжності по L1-нормі
    let delta = 0;
    for (let j = 0; j < N; j++) delta += Math.abs(next[j] - pr[j]);
    pr = next;
    if (delta < tol) break;
  }
  return pr; // pr[i] ≈ π*ᵢ, сума дорівнює 1
}
Складність: кожна ітерація — O(E), де E — кількість ребер (посилань), оскільки ми торкаємось кожного ребра лише раз. Для сучасного веба (E ≈ 10¹¹) саме це робить PageRank взагалі здійсненним — щільне множення матриць було б O(N²) і цілком нездійсненним.

Чому це сходиться: теорема Перрона-Фробеніуса

Степеневий метод сходиться завдяки теоремі Перрона-Фробеніуса: матриця з усіма додатними елементами (якою є демпфована, телепортуюча матриця переходів, оскільки кожен елемент не менший за (1−d)/N > 0) має унікальне найбільше власне значення λ₁ = 1, а її власний вектор строго додатний. Повторне застосування матриці геометрично пригнічує всі інші компоненти власного вектора зі швидкістю, яка визначається |λ₂/λ₁|:

π_t = π₀ · P^t = c₁λ₁ᵗv₁ + c₂λ₂ᵗv₂ + … ≈ v₁ при t → ∞
Швидкість збіжності ∝ |λ₂|ᵗ, а коефіцієнт загасання d обмежує |λ₂| ≤ d

Саме тому коефіцієнт загасання впливає на швидкість збіжності: він безпосередньо обмежує друге за величиною власне значення, тому менше d сходиться швидше (але дає більш однорідні ранги), а більше d зберігає структуру посилань, проте сходиться повільніше.

Поза вебом: інші застосування

Та сама ідея «випадковий обхідник + стаціонарний розподіл» з'являється в інформатиці й поза нею всюди, де потрібно ранжувати вузли графа за структурною важливістю, а не за локальними властивостями:

🎲 Дослідити ланцюги Маркова наживо

Будуйте матриці переходів, спостерігайте, як виникає стаціонарний розподіл, і побачте PageRank у дії

Відкрити симуляцію →