«Как предсказать "смерть" open-source проекта с помощью статистики выживания»
Введение
Жизненный цикл open-source проекта не линеен. После всплеска начального интереса многие репозитории переходят в режим поддержки, затем редких правок, и только потом фактически останавливаются. Традиционные подходы (классификация «активен/заброшен» по порогу дней без коммитов) игнорируют два ключевых аспекта:
-
- Временную динамику: риск «заморозки» меняется со временем.
- Правостороннее цензурирование: на момент анализа часть проектов еще активна, и мы не знаем, когда они остановятся.
Статистика выживаемости (survival analysis) изначально разрабатывалась для медицины и инженерии надежности, но идеально ложится на задачу моделирования
«времени до события» (time-to-event). В нашем случае событие – это переход репозитория в состояние «заморозки», а время – месяцы с момента создания или первой значимой активности.
Данные и определение события
Для построения модели потребуются:
- repo_id – уникальный идентификатор репозитория;
- start_date – дата создания репозитория или первого коммита;
- last_activity_date – дата последнего коммита, PR или issue, связанного с кодом;
- snapshot_date – дата сбора данных.
Определение «заморозки». Проект считается замерзшим, если в течение Tfreeze = 6 месяцев не зафиксировано ни одного коммита и ни одного issue/PR, требующего изменений в коде. Порог можно адаптировать под домен (например, 3 месяца для веб-фреймворков, 12 месяцев для системных утилит).
Цензурирование. Если на snapshot_date проект еще активен, его наблюдение считается цензурированным: мы знаем, что он «выжил» до текущего момента, но не знаем точное время «смерти». Это ключевое отличие от обычной регрессии и причина, почему Kaplan-Meier предпочтительнее простых средних.
Статистика выживания: интуитивное объяснение
Функция выживаемости S(t) определяет вероятность того, что проект останется активным дольше времени t:
S(t) = P (T > t),
где T – случайная величина «время до заморозки».
Оценщик Каплана–Мейера строит ступенчатую кривую S(t), обновляя ее в моменты наблюдаемых «смертей» проектов. Формула:
Sˆ(t) = Y 1 − di ,niti≤t
где:
- t – момент времени, когда зафиксирована заморозка хотя бы одного проекта;
- d – число проектов, замерзших в момент ti;
- n – число проектов, «находящихся под риском» незадолго до ti (активных и еще не цензурированных).
Аналогия. Представьте, что вы наблюдаете за 100 новыми репозиториями. Через 3 месяца 10 из них замораживаются. Из оставшихся 90 еще 5 перестают получать коммиты к 6-му месяцу, а 20 мы просто теряем из виду (цензурирование, т.к. они все еще активны на момент среза). Каплан–Мейер аккуратно учитывает каждый шаг, не «выбрасывая» живые проекты и не искажая статистику средними значениями.
Реализация на Python с использованием lifelines
Для расчетов удобно использовать библиотеку lifelines. Ниже приведен минимальный рабочий пайплайн.
import pandas as pd
import numpy as np
from lifelines import KaplanMeierFitter
import matplotlib.pyplot as plt
# 1. Загружаем данные (пример формата: данные из GHTorrent или GitHub API)
# Колонки: repo_id, created_at, last_activity_at, snapshot_date
df = pd.read_csv("github_repos_activity.csv", parse_dates=["created_at", "last_activity_at", "snapshot_date"])
# 2. Определяем длительность жизни репозитория и цензурирование
FROZE_MONTHS = 6
df["duration_months"] = (
(df["last_activity_at"] - df["created_at"]).dt.days / 30.44
)
# Событие: репозиторий "замёрз" (нет активности дольше FROZE_MONTHS на момент snapshot_date)
df["event"] = (
(df["snapshot_date"] - df["last_activity_at"]).dt.days / 30.44
) >= FROZE_MONTHS
# Цензурируем активные репозитории (ещё не замёрзли)
mask_active = ~df["event"]
df.loc[mask_active, "duration_months"] = (
(df.loc[mask_active, "snapshot_date"] - df.loc[mask_active, "created_at"]).dt.days / 30.44
)
# 3. Строим кривую выживания Каплана-Мейера
kmf = KaplanMeierFitter()
kmf.fit(durations=df["duration_months"], event_observed=df["event"], label="Выживаемость репозиториев")
# 4. Визуализация
plt.figure(figsize=(8, 5))
kmf.plot_survival_function(ci_show=True)
plt.axhline(0.5, color="gray", linestyle="--", linewidth=1)
plt.axvline(kmf.median_survival_time_, color="red", linestyle="--", linewidth=1)
plt.xlabel("Время (месяцы)")
plt.ylabel("Вероятность выживания, S(t)")
plt.title("Кривая выживания репозиториев (с цензурированием)")
plt.grid(True, alpha=0.3)
plt.show()
Интерпретация результатов и «период полужизни»
После построения кривой можно извлечь несколько практических метрик:
- Медианное время жизни (kmf.median_survival_time_) – момент, когда S(t) =
0.5. Это и есть «период полужизни»: к этому сроку половина проектов из выборки уже замерзла.
- Вероятность выживания через N месяцев: kmf.survival_function_at_times(N). Например, S(24) = 0.62 означает, что через 2 года 62% репозиториев все еще активны.
- Сегментный анализ: разбивая выборку по языку, количеству звезд или раз- меру комьюнити, можно строить несколько кривых на одном графике и сравнивать устойчивость экосистем.
На реальных данных GitHub (по выборкам за 2015–2023 гг.) кривая обычно имеет характерную форму: резкий спад в первые 3–6 месяцев (отсев экспериментальных форков), затем плавный пологий хвост. Медианное время жизни часто составляет 18–30 месяцев для типичных user-репозиториев и 40+ месяцев для проектов с > 500 звезд.
Заключение и ограничения
Применение статистики выживаемости к данным GitHub позволяет перейти от бинарных метрик к вероятностным прогнозам, учитывающим время и цензурирование. Каплан–Мейер дает прозрачную, не требующую сложных предположений оценку риска «заморозки», которую легко интерпретировать и визуализировать.
Ограничения:
-
- Определение «смерти» через порог месяцев без активности субъективно и может не учитывать проекты в режиме долгосрочной поддержки (LTS).
- Модель не учитывает коварианты (размер команды, финансирование, наличие CI/CD). Для их включения требуется регрессия Кокса (Cox PH) или случайные леса выживания.
- Данные GitHub API подвержены выборочному смещению: приватные репозитории, архивированные проекты и репозитории без issue-трекинга могут искажать выборку.
Перспективы: расширение модели за счет динамического обновления кривых, использования scikit-survival для предсказания индивидуальных рисков и интеграции с метриками CHAOSS (bus factor, time to response, contribution diversity). В сочетании с мониторингом активности такой подход станет полезным инструментом для оценки надежности зависимостей в enterprise-стеке и принятия решений о форках или спонсорстве.
Список литературы
- Трофимова Е.А., Кисляк Н.В., Гилев Д.В., – Теория вероятностей и математи- ческая статистика: учебное пособие. – Екатеринбург: Издательство Уральского университета, 2018.
- Воробьев Э.И., Статическое моделирование и анализ данных с применением язы- ка программирования Python. – Воронеж, 2017.
- Emily C. Zabor, Survival analysis in R. – 2025.


