Автокорреляция и функция ACF
Учимся измерять, насколько значение ряда связано со своим прошлым, и читать сезонность по пикам ACF.
Автокорреляция — корреляция ряда с самим собой, сдвинутым на k шагов (лаг k); функция ACF показывает эту связь для всех лагов сразу.
Зачем измерять связь с прошлым
Если сегодняшнее значение сильно зависит от вчерашнего, прогноз по прошлому возможен. ACF количественно отвечает, на сколько шагов назад тянется «память» ряда. Пик ACF на лаге 7 у дневного ряда — это недельная сезонность. Медленно затухающая ACF — признак тренда. Так один график подсказывает структуру ряда.
Представьте, что вы отвечаете за склад интернет-магазина. Спрос на товар в понедельник почти всегда повторяет прошлый понедельник, а вот связь со вторником слабее. ACF превращает это интуитивное «почти всегда повторяет» в число: 0.8 на недельном лаге означает, что для прогноза заказов достаточно посмотреть на ту же дату неделей раньше. Без такого измерения вы либо закупаете вслепую, либо строите громоздкую модель там, где хватило бы простого правила «как в прошлый понедельник».
То же самое с веб-трафиком и продажами. Трафик на сайт по будням и выходным живёт по разным законам, выручка в декабре подскакивает каждый год, а посещаемость новостного портала реагирует на вчерашний всплеск ещё пару дней. Все эти эффекты — «память» ряда, и ACF показывает их сразу для всех расстояний во времени, не заставляя вас вручную перебирать гипотезы «а вдруг тут недельный цикл, а вдруг месячный».
Как считается ACF
Для лага k берут пары (x_t, x_{t-k}) и считают их корреляцию, нормируя на общую дисперсию. Значение от -1 до 1: ближе к 1 — сильная прямая связь, около 0 — связи нет, ниже 0 — обратная.
По сути мы сдвигаем копию ряда на k позиций и смотрим, насколько хорошо она ложится на оригинал. Если высокие значения совпадают с высокими, а низкие с низкими — корреляция положительна и близка к 1. Если же пики оригинала приходятся на провалы сдвинутой копии, корреляция уходит в минус. Нормировка на дисперсию делает результат безразмерным: ACF не зависит от того, измеряем мы рубли, штуки или клики, поэтому формы графиков для разных рядов можно сравнивать напрямую.
Важная деталь — при сдвиге на k шагов первые k точек ряда остаются без пары, и сумма в числителе идёт только по тем индексам, где обе точки существуют. Знаменатель же берёт дисперсию всего ряда целиком. Из-за этого с ростом лага в числителе остаётся всё меньше слагаемых, и оценка ACF на дальних лагах становится менее надёжной. На практике это значит, что разглядывать ACF имеет смысл лишь до лагов порядка четверти длины ряда — дальше шум начинает преобладать над сигналом, и красивые пики могут оказаться артефактом малой выборки.
def mean(xs): return sum(xs)/len(xs)
def acf(xs, k):
m = mean(xs); n = len(xs)
num = sum((xs[i]-m)*(xs[i-k]-m) for i in range(k, n))
den = sum((x-m)**2 for x in xs)
return round(num/den, 3)
# ряд с периодом 4 (пилообразный)
s = [1,2,3,4,5,4,3,2,1,2,3,4,5,4,3,2]
for k in range(0, 6):
print(f"lag {k}: ACF = {acf(s, k)}")
Вывод:
lag 0: ACF = 1.0 lag 1: ACF = 0.583 lag 2: ACF = -0.042 lag 3: ACF = -0.583 lag 4: ACF = -0.75 lag 5: ACF = -0.417
На лаге 0 автокорреляция всегда 1 (ряд идеально совпадает сам с собой). Лаг 1 высок (0.583) — соседние точки похожи. А отрицательный пик на лаге 4 (-0.75) показывает: через половину периода (8/2) ряд «зеркалит» сам себя. По форме ACF читается период колебаний.
Обратите внимание на знак: на лаге 2 значение почти нулевое (-0.042), потому что подъёмы пилы здесь встречаются со спусками примерно поровну и взаимно гасятся. А чередование плюсов и минусов вдоль лагов — характерная подпись регулярного цикла. Если бы вместо чистой пилы у нас был трафик с недельной волной, ровно так же по знаку и величине ACF мы бы вычислили длину волны, не зная её заранее.
Что показывают типичные формы ACF
| Форма ACF | О чём говорит |
| медленно затухает | есть тренд (ряд нестационарен) |
| пики на лагах m, 2m, 3m | сезонность с периодом m |
| быстро падает к нулю | короткая память, близко к шуму |
На практике эти формы редко встречаются в чистом виде: реальный ряд продаж обычно сочетает медленное затухание (растущий бизнес даёт тренд) и пики на лагах 7, 14, 21 (недельная сезонность). Поэтому ACF читают как наложение нескольких эффектов и сначала снимают самый грубый — тренд, чтобы под ним проступила сезонная структура.
Эта последовательность — сначала убрать тренд, потом разглядывать сезонность — и есть рабочий алгоритм аналитика. Допустим, вы смотрите на дневную выручку магазина за два года. Сырая ACF почти наверняка будет медленно сползать к нулю: бизнес рос, и каждая точка коррелирует с соседней просто потому, что обе лежат на общем восходящем склоне. Этот склон забивает всё остальное. Стоит взять разности (вычесть из каждого дня предыдущий), как тренд исчезает, и в ACF проступают честные пики на лагах 7 и 14 — те самые недельные циклы, ради которых вы и затевали анализ. Без этого шага вы рискуете сделать вывод «у ряда длинная память» там, где на деле просто был тренд.
Как работает под капотом
ACF — это оценка теоретической автокорреляционной функции стационарного процесса. Её значения значимы, если выходят за «доверительный коридор» примерно ±2/√n: внутри коридора колебания неотличимы от случайных. Поэтому на графике ACF рисуют горизонтальные пунктиры — пики выше них считаются настоящими, остальное игнорируют как шум.
Ширина коридора зависит от длины ряда: чем больше у вас наблюдений n, тем уже коридор и тем меньшие значения ACF уже считаются значимыми. На коротком ряде из 30 точек коридор широкий, и даже заметный на глаз пик может оказаться случайным; на ряде из тысячи дневных продаж коридор узкий, и значимым станет даже скромный недельный отклик. Это объясняет, почему один и тот же бизнес-цикл «виден» на длинной истории и «теряется» на короткой — дело не в данных, а в нехватке статистики.
Частые ошибки
- Считать ACF по нестационарному ряду и удивляться медленному затуханию (это тренд, а не память).
- Принимать колебания внутри доверительного коридора за значимую структуру.
- Забывать, что ACF на лаге 0 всегда равна 1 и не несёт информации.
- Смотреть только первые несколько лагов и пропустить сезонный пик, который сидит дальше — например, на лаге 12 у месячных данных.
- Сравнивать абсолютную высоту пиков на рядах разной длины, забыв, что порог значимости у них разный.
Итоги
- ACF измеряет связь ряда с собственным прошлым на каждом лаге.
- Медленное затухание — тренд; пики на кратных лагах — сезонность с этим периодом.
- Значимы лишь пики за пределами коридора ±2/√n.
- Знак и чередование пиков подсказывают длину цикла, а ширина коридора зависит от объёма данных.