Модель Хольта-Уинтерса. Сравнение модели Хольта и Хольта-Уинтерса.

Модель Хольта-Уинтерса отличается от простой модели Хольта в первую очередь тем, что учитывает сезонные колебания, однако она также как и модель Хольта содержит только линейный тренд, поэтому достоверным можно считать прогноз, лишь на один наг вперед. Кроме того, модели Хольта-Уинтерса могут учитывать сезонность в мультипликативном и аддитивном вариантах.

Модель Хольта-Уинтерса строится по следующим формулам:

f1

где S'(t) – прогноз, очищенный от тренда (по сути, представляет экспоненциальное сглаживание);

F(t) – линейный тренд;

R(t) – сезонная составляющая;

S(t,T) – функция прогноза;

A, B, C – коэффициенты чувствительности модели;

T – порядковый номер периода прогноза;

t – момент времени;

L – число периодов.

 

Для определения начальных значений S0 и F0 применяют линейную модель метода наименьших квадратов (МНК) к первым членам ряда. Начальные точки и коэффициенты чувствительности в данной работе подбираются аналогично методам, описанным в статье про модель Хольта.

Пример прогнозирования построенный на модели Хольта-Уинтерса, приведен в приложении на рис.

gr1

Точность краткосрочного (часового) прогноза программы составляет в среднем 92.5%, что на 6% лучше, чем у простой модели Хольта.

gr2

Модель Хольта-Уинтерса на PHP:

<?php
  /* Константы модели */
 
  // Сколько дней брать для прогноза
  define('DAY_BACK', 5);
  // С какого часа учитывать данные для прогноза
  define('HOUR_START', 1);
  // Константы экспоненты
  define('ALPHA_1', 0.201117186);
  define('ALPHA_2', 0.010413451);
  define('ALPHA_3', 0.742343487);
 
  $conn = mysql_connect('mysql47.1gb.ru', ',);
  mysql_select_db('gb_w7news', $conn);
 
    $time = time();
 
  $date_now = date('Y-m-d', $time);
  $hour_now = date('G', $time);
  //$hour_now = 11;
 
  // Выбрать данные за последние N дней, сутки начинать с K часов
  $sql = "
  SELECT
    DATE_FORMAT(`time`, '%d|%k') AS `t`, ROUND(AVG(`impressions_sum`),2) AS `s`
  FROM
    `vk_stat`
  WHERE
    DATE_FORMAT(`time`, '%Y-%m-%d') BETWEEN ('$date_now' - INTERVAL ".DAY_BACK." DAY) AND '$date_now'
  AND
    hour(`time`) >= ".HOUR_START."
  GROUP BY
    day(`time`), hour(`time`)";
 
    /*
  $sql = "
  SELECT
    DATE_FORMAT(`time`, '%d|%k') AS `t`, ROUND(AVG(`impressions_sum`),2) AS `s`
  FROM
    `vk_stat`
  WHERE
    DATE_FORMAT(`time`, '%Y-%m-%d') >= '2014-03-16' AND
    DATE_FORMAT(`time`, '%Y-%m-%d') <= '2014-03-20'
    AND hour(`time`) >= 4
  GROUP BY
    day(`time`), hour(`time`)";
    */
 
  $i = $j = $day_w = 0;
  $a_array = $b_array = $c_array = $p_array_h = $e_array = $e_ab_array = $p_array = array();
 
  echo '
  <table border="1">
    <tr><td><b>Время</b></td><td><b>Скорость показов</b></td></td><td><b>Сглаж. exp</b></td>
    <td><b>Тренд</b></td><td><b>Сезонная сост.</b></td><td><b>Прогноз</b></td><td><b>Ошибка</b></td><td><b>Абс. ошибка</b></td></tr>';
 
  $result = mysql_query($sql);
  while ($row = mysql_fetch_array($result)){
    list($day, $hour) = explode('|', $row['t']);
    //if ($day == 20 && $hour >= 11) break;
    $s = (float)$row['s'];
 
    if ($day_w != 0 && $day_w != $day){
      $day_w = $day;
      $j++;
    } elseif ($day_w == 0){
      $day_w = $day;
    }
 
    if ($i == 0){
        	$a_array[$i] = $s;
            $b_array[$i] = 0;
   			if ($j == 0)
   				$c_array[$i] = 1;
   			else {
   				$s_t = 24 - HOUR_START;
   				$c_array[$i] = ALPHA_3*$s/$a_array[$i] + (1-ALPHA_3)*($c_array[$i-$s_t]);
   			}
    } else {
   			if ($j == 0){
        $a_array[$i] = ALPHA_1*($s/1)+(1-ALPHA_1)*($a_array[$i-1]+$b_array[$i-1]);
   				$c_array[$i] = 1;
   			} else {
        $s_t = 24 - HOUR_START;
        $a_array[$i] = ALPHA_1*($s/$c_array[$i-$s_t])+(1-ALPHA_1)*($a_array[$i-1]+$b_array[$i-1]);
   				$c_array[$i] = ALPHA_3*$s/$a_array[$i] + (1-ALPHA_3)*($c_array[$i-$s_t]);
 
        $p_array[$i] = ($a_array[$i] + $c_array[$i])*$c_array[$i-$s_t];
        $e_array[$i] = $s-$p_array[$i-1];
        $e_ab_array[$i] = $e_array[$i]/$s;
   			}
      $b_array[$i] = ALPHA_2*($a_array[$i]-$a_array[$i-1])+(1-ALPHA_2)*$b_array[$i-1];
    }
 
      echo '<tr><td>'.$row['t'].'</td><td>'.str_replace('.',',',$row['s']).'</td>
      <td>'.str_replace('.',',',round($a_array[$i],2)).'</td><td>'.str_replace('.',',',round($b_array[$i],2)).'</td><td>'.str_replace('.',',',round($c_array[$i],2)).
      '</td><td>'.str_replace('.',',',round($p_array[$i],2)).'</td>
      <td>'.str_replace('.',',',round($e_array[$i],2)).'</td><td>'.str_replace('.',',',abs(round($e_ab_array[$i],2)*100)).'%</td></tr>';
    $i++;
  }
  echo '</table>';
 
  $last_a = array_pop($a_array);
  $last_b = array_pop($b_array);
  $j = 1;
 
  for ($i=$hour_now+1; $i<24; $i++){
    $s_t = 24-HOUR_START;
    $s_i = sizeof($c_array)-1-$s_t+$j;
    $p_array_h[$i] = ($last_a + $j*$last_b)*$c_array[$s_i];
    $j++;
  }
 
  echo '<p><b>Прогноз на текущие сутки:</b></p>';
  echo '<pre>';
  print_r($p_array_h);
  echo '</pre>';
?>

Сравнение модели Хольта и Хольта-Уинтерса

По результатам моделирования модели Хольта и Хольта-Уинтерса определены основные отличия моделей:

  • обе модели учитывают лишь линейные тренды и адекватно прогнозируют либо на один шаг вперед, либо на несколько коротких шагов;
  • по сравнению с моделью Хольта – модель Хольта-Уинтерса требует значительно большего объема данных для прогнозирования;
  • подбор коэффициентов чувствительности модели Хольта-Уинтерса более трудоемок, чем у модели Хольта;
  • модель Хольта-Уинтерса показала результаты прогнозирования на 6% точнее, чем простая модель Хольта.
Facebook Comments

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

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