어제의 엄청난 방문자수는 블랙스완? – 블로그 방문자수 예측 모형 –

이 블로그는 호스팅을 받기 때문에 트래픽에 대한 어느정도의 예상치는 알고 있어야 나중에 곤욕을 당하지 않는다. 바로 어제(2014.12.12) 이문열 삼국지 텍스트 분석 포스팅의 엄청난 인기 때문에 약 세번의 트래픽 리셋이 있었고, 거기다 추가적으로 매일 4G의 웹 트래픽을 더 구입해서 임시적으로나마 내년 2월 중순까지 버텨 보기로 했다(트래픽 최소 구입 단위가 4G였으며, 기간은 무조건 호스팅 계약 종료시까지였다).

아래와 같은 메시지를 어제 하루동안 세번을 받았다. ㅜㅜ

exceed


그동안 미뤄 오던 블로그 방문자 수 예측(forecasting) 모형을 만들어 보고자 한다. 그리고 어제의 방문자 수가 과거 패턴으로 볼때 발생확률이 어느정도인지도 계산해보자!

필자의 경우 GA(http://www.google.com/analytics/)을 2011년부터 적용해오고 있어서 방문자 time series 분석을 하기엔 크게 어렵지 않았다. 그리고 GA의 API를 이용하기 위해서 rga 패키지를 사용했다.

suppressPackageStartupMessages({
library(rga)
library(xts)
library(forecast)
})
rga.open(instance="ga", where="./ga.rga")


daily_visits_src <- ga$getData(
  key,
  start.date = "2011-01-01",
  end.date = "2014-12-13",
  metrics = "ga:users",
  dimensions = "ga:date",
  sort = "ga:date",
  batch = TRUE
)

daily_visits <- daily_visits_src 

데이터를 읽어왔으니 본격적으로 시계열 모형을 만들자.
문제를 좀더 간단히 하기 위해서 주단위 방문자 수를 예측하는 모형을 만들어본다.

library(forecast)

daily_xts <- xts(daily_visits$users, order.by = daily_visits$date,frequency = 7)

weekly_sum <- apply.weekly(daily_xts, sum)

weekly_ts <- ts(as.numeric(weekly_sum), start = c(2011, 1),frequency = 52)

plot(stl(weekly_ts, s.window="periodic"))

plot of chunk times

decompose를 보면 몇가지 흥미로운 사실을 알 수 있다.

  • 년단위 seasonality가 있으나 그 정도가 크지 않다는 것.
    • 회사 생활과 학교를 병행하고 있어서 방학때 포스팅이 많은 이유인지 방문자가 여름과 겨울에 많은 패턴이 보인다.
    • 주별 평균 포스팅 갯수와 방문자들의 상관관계가 높을 것으로 예상되나 주별 포스팅 숫자는 WordPress DB를 확인해야 되서 이 데이터 분석은 내년 2월 호스팅 서비스 선택시점까지 미뤄본다.
  • 한창 KoNLP를 개발하고 개선하던 시점에 블로그 방문자가 많았다는 것
  • 이번주 (2014-12-07 ~ 2014-12-13) 기록 사상 역대 최고의 방문자수를 기록 했다는 것
weekly_ar <- auto.arima(weekly_ts)

tsdiag(weekly_ar)

plot of chunk times2

Seasonal ARIMA 모형으로 모형 피팅을 한다. 이때 auto.arima 함수는 최적의 p,d,q 파라메터를 AIC 혹은 다른 모델 적합 관련 함수로 자동으로 선택해 주기 때문에 아주 편함. 물론 ACF, PACF같은 함수로 적절한 파라메터로 서치를 하는 작업도 필요하나 auto.arima는 이런 작업 결과와 큰 차이를 보여주지 않기 때문에 그냥 사용한다.

무엇보다 모델 검정이 중요하다. Ljung-Box 검정으로 확인해보니 잔차의 시차간 상관관계가 없다는 귀무가설을 지지하는 결과를 보여주고 실제 ACF로 볼때 잔차의 상관 패턴이 보이지 않아 S-ARIMA에서 뽑을 수 있는 패턴은 제대로 뽑혔다는 것을 확인해 볼 수 있다.

accuracy(weekly_ar)
##                    ME     RMSE      MAE         MPE     MAPE      MASE
## Training set 14.54806 168.7241 127.5051 -0.09397117 11.94629 0.9204207
##                    ACF1
## Training set 0.03437268

모형의 평균 에러는 12% 정도(training set only)

hist(weekly_ar$residuals,breaks = 30)

plot of chunk unnamed-chunk-3

dist <- sample(weekly_ar$residuals,10000,replace = TRUE)

idx <- which.max(dist[order(dist,decreasing = T)] >= weekly_ar$residuals[length(weekly_ar$residuals)])

pval <- idx/10000

잔차의 분포를 보니 정규분포는 아닌것으로 보여 prediction interval에 큰 의미를 부여할 필요는 없다는 것을 알 수 있다.
그리고 잔차의 분포를 생성하기 위해 bootstrap 방식으로 리샘플링 해서 최근 1주의 트래픽이 발생할 확률값을 계산했다(p-value : 0.0001).
확률값으로 알 수 있는 것처럼 만번에 한번 발생할까 말까한 '블랙스완'에 가까운 방문자수라 할 수 있으며, 약 2주 정도는 금주 트래픽 효과가 지속될 것으로 보인다.

plot(forecast(weekly_ar,h = 7,level=0, fan=FALSE))

plot of chunk unnamed-chunk-4

그리고 마지막으로 호스팅 재계약인 2월 중순까지 방문자수 예측을 해봤다.

모델 예측 결과로는 금주 많은 트래픽이 몰렸다고 해서 성급하게 고사양의 호스팅 서비스를 계약하는건 시기상조라는 이야기를 해주고 있으며 내년에도 금년과 유사한 트래픽 상품을 계약하거나 안전하게 한단계 정도 높은 서비스를 계약하는게 나을거라 예상해본다. 그러나 최종 결정은 호스팅 회사에서 제공하는 일별 트래픽 데이터를 기반으로 2월 초 정도에 분석해 상품을 결정할 예정이다(방문자와 트래픽 사용량의 관련성 파악과 방문자 1인당 사용 트래픽량 시뮬레이션 등등).


분석 결과를 요약하면 아래와 같다.

  • 어제 성급하게 상위 상품으로 계약 갱신을 했다면 낭비가 발생 했을 것이며, 2만원 정도로 현재의 서비스 만기까지 4G 트래픽을 더 구입한건 현재 내가 할 수 있는 범위에서 최적의 선택이였다.
  • 주 혹은 개월 단위로 트래픽을 자신이 원하는 기간동안 더 구매할 수 있는 호스팅 서비스를 찾아볼 생각이다. 이는 고 방문자수 영향의 지속 기간이 최대 2주로 모델링 결과에서 볼 수 있기 때문이다.
  • 호스팅 재계약 시점인 내년 2월 초에 실제 트래픽 데이터를 받아서 통합 분석해보자!

CC BY-NC 4.0 어제의 엄청난 방문자수는 블랙스완? – 블로그 방문자수 예측 모형 – by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.