Наивные алгоритмы прогнозирования

При создании «наивных» моделей предполагается, что некоторый последний период прогнозируемого временного ряда лучше всего описывает будущее этого прогнозируемого ряда, поэтому в этих моделях прогноз, как правило, является очень простой функцией от значений прогнозируемой переменной в недалеком прошлом.

Алгоритм прогнозирования по обычному среднему

Один из наивных алгоритмов прогнозирования основан на обычном усреднении, то есть, предполагается, что завтра будет в среднем, как было в течение недели. Применить данный алгоритм возможно только к системам, пребывающим в состоянии устойчивого равновесия. К реальным динамическим системам этот метод не применим.

gr_sr

Алгоритм прогнозирования коэффициентами прироста

Пусть скорость показов между часами повторяется изо дня в день. Тогда, введя коэффициент корреляции между часами, можно получить прогноз, умножив коэффициент на текущие показатели часа. Причем на ближайшие часы такой прогноз может оказаться высокоточным.

Кроме того, добавив к этому методу метод средней взвешенной, можно отследить текущий тренд, усилив значение последних данных. Однако, например, для праздничных дней такой прогноз может оказаться совершенно некорректным, т.к. в эти дни существенно смещается распределение трафика по часам, а, как следствие, и коэффициенты связи между часами.

Для пошагового рассмотрения работы алгоритма прогноза, в таблице задаются исходные данные.

Данные для прогнозирования коэффициентами прироста (без учета праздничных дней)

04.03.2014 05.03.2014 11.03.2014 12.03.2014 13.03.2014 14.03.2014 17.03.2014 18.03.2014 19.03.2014 20.03.2014
0 1166 884 1188 431 236 148 891 655 46 221
1 372 263 362 176 134 73 237 214 17 89
2 268 317 170 136 130 70 165 140 20 81
3 160 98 107 55 64 29 47 107 12 47
4 64 39 41 33 48 17 17 59 7 28
5 42 27 31 30 44 14 11 50 6 31
6 54 33 39 35 50 20 11 71 11 55
7 86 61 88 85 81 48 25 134 20 138
8 132 91 163 107 97 70 110 203 91 203
9 230 157 212 171 130 106 143 299 145 308
10 312 247 276 252 168 333 194 431 191 398
11 422 346 363 314 210 621 242 584 293 569
12 515 428 458 341 262 768 506 527 441 968
13 660 596 528 442 300 993 794 1133 913 2244
14 1057 905 858 652 400 1539 1345 1979 1816 3363
15 2038 1263 1200 1048 596 2030 2847 3935 3046 6265
16 3385 2076 1677 1505 832 2448 5867 4020 4324 10029
17 5163 2987 1972 1625 952 2673 9378 4134 6298 10565
18 8064 3559 2309 1821 1140 3076 12031 8261 8206 13293
19 10915 4585 2797 2142 1212 3502 15958 14516 11253 15227
20 9872 5781 3258 3465 1248 4367 21823 19250 14544 19770
21 13270 7057 3484 3947 1300 5016 27784 23606 17154 26747
22 13376 5914 3380 3008 1139 4706 16767 20838 15645 15251
23 9844 3855 3126 1743 836 4041 9136 5515 5379 5690

 

Строится, а затем и вычисляется MAPE для 20.03.2014, для этого находятся коэффициенты корреляции между часами, по формуле:

f_1

где N – данные исхода;

t – рассматриваемый момент времени.

Найденные коэффициенты заносятся в таблицу:

04.03.2014 05.03.2014 11.03.2014 12.03.2014 13.03.2014 14.03.2014 17.03.2014 18.03.2014 19.03.2014
1 0,319 0,298 0,305 0,408 0,568 0,493 0,266 0,327 0,37
2 0,72 1,205 0,47 0,773 0,97 0,959 0,696 0,654 1,176
3 0,597 0,309 0,629 0,404 0,492 0,414 0,285 0,764 0,6
4 0,4 0,398 0,383 0,6 0,75 0,586 0,362 0,551 0,583
5 0,656 0,692 0,756 0,909 0,917 0,824 0,647 0,847 0,857
6 1,286 1,222 1,258 1,167 1,136 1,429 1 1,42 1,833
7 1,593 1,848 2,256 2,429 1,62 2,4 2,273 1,887 1,818
8 1,535 1,492 1,852 1,259 1,198 1,458 4,4 1,515 4,55
9 1,742 1,725 1,301 1,598 1,34 1,514 1,3 1,473 1,593
10 1,357 1,573 1,302 1,474 1,292 3,142 1,357 1,441 1,317
11 1,353 1,401 1,315 1,246 1,25 1,865 1,247 1,355 1,534
12 1,22 1,237 1,262 1,086 1,248 1,237 2,091 0,902 1,505
13 1,282 1,393 1,153 1,296 1,145 1,293 1,569 2,15 2,07
14 1,602 1,518 1,625 1,475 1,333 1,55 1,694 1,747 1,989
15 1,928 1,396 1,399 1,607 1,49 1,319 2,117 1,988 1,677
16 1,661 1,644 1,398 1,436 1,396 1,206 2,061 1,022 1,42
17 1,525 1,439 1,176 1,08 1,144 1,092 1,598 1,028 1,457
18 1,562 1,191 1,171 1,121 1,197 1,151 1,283 1,998 1,303
19 1,354 1,288 1,211 1,176 1,063 1,138 1,326 1,757 1,371
20 0,904 1,261 1,165 1,618 1,03 1,247 1,368 1,326 1,292
21 1,344 1,221 1,069 1,139 1,042 1,149 1,273 1,226 1,179
22 1,008 0,838 0,97 0,762 0,876 0,938 0,603 0,883 0,912
23 0,736 0,652 0,925 0,579 0,734 0,859 0,545 0,265 0,344

С помощью метода взвешенной средней получены коэффициенты корреляции, занесенные в таблицу.
По полученным коэффициентам стоится прогноз (для скорости показа замеренной в 0 часов – 221 показ/минуту).

 

Нормированные коэффициенты корреляции, прогноз на 20.03.2014

Часы Ср. 20.03.2014 (прогноз) 20.03.2014 (реальные) Ошибка
1 0,379 84 89 0,06
2 0,865 77 81 0,05
3 0,515 42 47 0,11
4 0,538 25 28 0,11
5 0,811 23 31 0,26
6 1,362 42 55 0,24
7 2,037 112 138 0,19
8 2,527 349 203 0,72
9 1,478 300 308 0,03
10 1,611 496 398 0,25
11 1,42 565 569 0,01
12 1,353 770 968 0,20
13 1,622 1571 2244 0,30
14 1,669 3746 3363 0,11
15 1,701 5719 6265 0,09
16 1,433 8976 10029 0,10
17 1,268 12714 10565 0,20
18 1,367 14445 13293 0,09
19 1,336 17754 15227 0,17
20 1,285 19570 19770 0,01
21 1,178 23279 26747 0,13
22 0,848 22674 15251 0,49
23 0,555 8466 5690 0,49
Точность прогноза 80,95107

 

gr_2

По полученным данным строится график, представленный на графике, реальной и прогнозируемой функции.

Ошибка прогноза составляет: 18,26%. Однако экспериментальные данные были получены при достаточно стабильном состоянии системы (CTR и цена клика не изменялись в течение недели). Для всплесков, праздничных дней, выходных и других резких изменений системы прогноз будет недостоверным.

gr_3

Пример прогноза коэффициентами:

<?
  mysql_select_db('', $conn);
 
  $date_now = date('Y-m-d', time());

  $sql = "SELECT DATE_FORMAT(`time`, '%k') AS `t`, 0 AS `m`, replace(ROUND(AVG(`impressions_sum`),2),'.',',') AS `s` FROM `vk_stat` WHERE
  DATE_FORMAT(`time`, '%Y-%m-%d') = '$date_now'
  AND DATE_FORMAT(`time`, '%k') BETWEEN 6 AND 23
  GROUP BY hour(`time`)";
 
  $alpha = 0.89914;
  $beta = 0.72565;
 
  $sezon = array (
    0 => 0.17,
    2 => 2.33,
    3 => 0.38,
    4 => 0.73,
    5 => 1.18,
    6 => 1.42,
    7 => 2.05,
    8 => 1.34,
    9 => 1.60,
    10 => 1.36,
    11 => 1.33,
    12 => 1.20,
    13 => 1.29,
    14 => 1.68,
    15 => 1.59,
    16 => 1.45,
    17 => 1.23,
    18 => 1.25,
    19 => 1.26,
    20 => 1.22,
    21 => 1.17,
    22 => 0.88,
    23 => 0.69
  );
 
  $j = $pre_s = 0;
  $s_arr = $t_arr = $p_arr = $e_arr = $e_ab_arr = array();
  $result = mysql_query($sql);
  while ($row = mysql_fetch_array($result)){
    	$y_array[] = $row;
  }
  echo '
  <p><b>Рассчет краткосрочного прогноза:</b></p>
  <table border="1">
    <tr><td><b>Время</b></td><td><b>Скорость показов</b></td><td><b>Динамика</b></td><td><b>Сглаж. exp</b></td>
    <td><b>Тренд</b></td><td><b>Прогноз</b></td><td><b>Ошибка</b></td><td><b>Абс. ошибка</b></td></tr>';
    foreach ($y_array as $row){
      $speed = (float)$row['s'];
 
      if ($j == 0){
        $s_arr[$j] = $speed;
        $t_arr[$j] = $y_array[$j+1]['s']-$y_array[$j]['s'];
        $p_arr[$j] = $s_arr[$j]+$t_arr[$j];
        $e_arr[$j] = 0;
        $e_ab_arr[$j] = 0;
      } else {
        $s_arr[$j] = $alpha*$speed + (1-$alpha)*($s_arr[$j-1]+$t_arr[$j-1]);
        $t_arr[$j] = $beta*($s_arr[$j]-$s_arr[$j-1]) + (1-$beta)*$t_arr[$j-1];
        $p_arr[$j] = $s_arr[$j]+$t_arr[$j];
        $e_arr[$j] = $speed-$p_arr[$j-1];
        $e_ab_arr[$j] = $e_arr[$j]/$speed;
      }
 
      if ($pre_s <= $speed) {
        $d = '+';
        $c = '#CCFFE6';
      } else {
        $d = '-';
        $c = '#FFCACA';
      }
      echo '<tr><td>'.$row['t'].':'.($row['m']*10).'</td><td>'.$row['s'].'</td><td bgcolor="'.$c.'">'.$d.'</td>
      <td>'.round($s_arr[$j],2).'</td><td>'.round($t_arr[$j],2).'</td><td>'.round($p_arr[$j],2).'</td>
      <td>'.round($e_arr[$j],2).'</td><td>'.abs(round($e_ab_arr[$j],2)*100).'%</td></tr>';
      $i++; $j++;
      $pre_s = $speed;
    }
  echo '
  </table>';
  $e_ab_abs = 0; $i = 0;
  foreach ($e_ab_arr as $e_val){
    if ($i > 1)	$e_ab_abs += abs($e_val);
    $i++;
  }
  $error = 100-abs(($e_ab_abs/($i-2))*100);
 
  echo '<b>Точность краткосрочного прогноза:</b> '.round($error,2).'%<hr />';
  echo '<p><b>Рассчет суточного прогноза:</b></p>';
  echo '<table border="1">
    <tr><td><b>Время</b></td><td><b>Прогноз</b></td></tr>';
 
  $j = 0;
  $prognoz = array_pop($p_arr);
  for ($i=date('G', time())+1; $i<24; $i++){
    $m = (int)date('i', time());
        if ($j == 0){
        	$k = $sezon[$i-1] + (($sezon[$i]-$sezon[$i-1])/60)*$m;
      	$prognoz = $prognoz*$k;
        } else $prognoz = $prognoz*$sezon[$i];
    echo '<tr><td>'.$i.'</td><td>'.round($prognoz,2).'</td></tr>';
    $j++;
  }
  echo '<table>';
?>
Facebook Comments

Леонид Чернядьев

Увлекаюсь программированием, интернет маркетингом, прогнозированием, дизайном и версткой. Принимаю заказы на лидогенерацию. Связь через - https://www.facebook.com/lenid.chernyadyev