Модель Хольта-Уинтерса отличается от простой модели Хольта в первую очередь тем, что учитывает сезонные колебания, однако она также как и модель Хольта содержит только линейный тренд, поэтому достоверным можно считать прогноз, лишь на один наг вперед. Кроме того, модели Хольта-Уинтерса могут учитывать сезонность в мультипликативном и аддитивном вариантах.
Модель Хольта-Уинтерса строится по следующим формулам:
где S'(t) – прогноз, очищенный от тренда (по сути, представляет экспоненциальное сглаживание);
F(t) – линейный тренд;
R(t) – сезонная составляющая;
S(t,T) – функция прогноза;
A, B, C – коэффициенты чувствительности модели;
T – порядковый номер периода прогноза;
t – момент времени;
L – число периодов.
Для определения начальных значений S0 и F0 применяют линейную модель метода наименьших квадратов (МНК) к первым членам ряда. Начальные точки и коэффициенты чувствительности в данной работе подбираются аналогично методам, описанным в статье про модель Хольта.
Пример прогнозирования построенный на модели Хольта-Уинтерса, приведен в приложении на рис.
Точность краткосрочного (часового) прогноза программы составляет в среднем 92.5%, что на 6% лучше, чем у простой модели Хольта.
Модель Хольта-Уинтерса на 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% точнее, чем простая модель Хольта.