
МО_Иванова_4117_ЛР_4
.docxГУАП
КАФЕДРА № 41
ОТЧЕТ
ЗАЩИЩЕН С ОЦЕНКОЙ
ПРЕПОДАВАТЕЛЬ
Старший преподаватель |
|
|
|
В.В.Боженко |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ №4 |
ПРОГНОЗИРОВАНИЕ ВРЕМЕННОГО РЯДА |
по курсу: МАШИННОЕ ОБУЧЕНИЕ |
|
|
РАБОТУ ВЫПОЛНИЛА
СТУДЕНТКА ГР. |
4117 |
|
|
|
А.В.Иванова |
|
|
|
подпись, дата |
|
инициалы, фамилия |
Санкт-Петербург 2024
Цель работы:
Выполнить прогнозирование временного ряда
Ссылка на colab:
https://colab.research.google.com/drive/163ygJbi_Df06YRBX1BlzE3cMc12QJxu4?usp=sharing
Задание:
Вариант 10: выполнить прогнозирование временного ряда объема выработки электроэнергии крупной электростанции (в млн. кВт. Ч) по месяцам с 1999 по 2003 гг.
Ход работы:
Набор данных был представлен в виде таблицы. Поэтому решено было скопировать данные в excel файл, откуда загрузить в Colab в виде датасета при помощи библиотеки pandas. В качестве целевого признака будет рассматриваться столбец 'данные' - с показателями выработанной электроэнергии.
Для начала построен график изменения объемов выработки электроэнергии по месяцам. Как видно (Рисунок 1) с годами вырабатываемый объем снижался, имея небольшие скачки в росте в конце каждого года. Однако после 5 лет скачкообразного спада объем выработки снова начал немного возрастать.
Рисунок 1 – График изменения объема выработки энергии по месяцам
В данном задании требуется реализовать Сеть радиально-базисных функций. Это искусственная нейронная сеть, которая использует радиальные базисные функции в качестве функций активации.
В данном случае сеть представляет из себя полно связную модель, состоящую из 4 полно связных слоёв: входного, двух скрытых и выходного, а также слоя Dropout, добавленного для случайного сброса некоторых значений нейронов во избежание переобучения. На последнем скрытом слое в качестве функции активации использовалась радиально базисная функция, которая разрабатывалась вручную и представлена как функция custom_activation.
На других слоях в качестве функции активации была выбрана relu. На выходном слое используется линейная, так как использование других функций активации вида sigmoid, relu или softmax привело к высокой неточности модели.
После создания функции активации была разработана модель нейронной сети. На вход подавались два параметры: год и месяц. На выходном слое один нейрон - предсказанное значение объёма выработки электроэнергии.
Перед использование модели было необходимо обработать входные параметры. Для предсказания используется номер месяца с учетом года, поэтому в качестве данных для обучения был взят столбец значений 'время'. Предсказывалось значение объёма вырабатываемой электроэнергии, поэтому в качестве y взят столбец 'данные', где записан вырабатываемый объем энергии.
Далее наборы разбиты на тренировочную и валидационную выборки в соотношении 4 к 1. После чего модель собрана и проведено обучение в 80 эпох, с размером рассматриваемого пакета 12. В результате на последней эпохе (Рисунок 2) были получены следующие результаты метрик: ошибка на тренировочных данных достаточно мала, но на реальных гораздо выше, что может свидетельствовать о переобучении, вызванном таким небольшим набором данных, состоящим всего из 60 значений.
Рисунок 2 – Результаты обучения построенной модели
Далее на основе полученных предсказаний выстроена диаграмма остатков (Рисунок 3). Одно из основных предположений линейной регрессии состоит в том, что остатки нормально распределены.
В данном случае можно утверждать, что предсказания модели выше, чем реальные значения, тем не менее остатки распределены относительно равномерно. Достаточно много нулевых- около нулевых остатков.
Рисунок 3 – Гистограмма остатков
Модель была успешно обучена, после чего можно было использовать ее для предсказания объемов выработки энергии на следующий месяц.
Следующее значение входных параметров [2004, 1] или январь 2004 года. Выполнено следующее предсказание (Рисунок 4).
Рисунок 4 – Предсказание на 1 месяц
Предсказанное значение - 48.46 кВт /ч больше, чем было за предыдущий месяц, что похоже на правду при наблюдаемом в начале нового года росте выработки.
Далее было выполнено прогнозирование временного ряда на 6 месяцев вперед (Рисунок 5).
Рисунок 5 – Предсказание на полгода вперед
Аналогичным образом выполнено предсказание на 1 год вперед (Рисунок 6).
Рисунок 6 – Предсказание на год вперед
Полученные результаты отображены на графике (Рисунок 7) изменения объема вырабатываемой энергии по месяцам. Модель предсказала новый скачок роста вырабатываемого объема в новом году.
Рисунок 7 – График предсказанного поведения объемов выработки энергии на следующие 12 месяцев
Вывод:
В результаты выполнения работы произошло ознакомление с временными рядами. Была изучена сеть радиально-базисных функций. На полученном графике аппроксимации видно, что модель утверждает рост объема вырабатываемой энергии. Гистограмма остатков показала допустимый результат с половиной нулевых остатков и относительно равномерным распределением.
Рассмотренные сети RBF полезны, когда требуется быстрое и эффективное обучение и когда структура данных не линейна. Они особенно хороши в задачах, где важна способность к обобщению с небольшим количеством обучающих данных, как в данной задаче, где набор был ограничен 60 показателями за 60 месяцев.
Полный код реализации задачи приведен в Приложении А.
ПРИЛОЖЕНИЕ А. ПОЛНЫЙ ПРОГРАММНЫЙ КОД.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
df = pd.read_excel('/content/lab4_data.xlsx', index_col=0)
energy = np.array(df['данные'])
plt.figure(figsize=(12, 6))
plt.plot(range(1,61), energy, label='Данные')
plt.xlabel('Месяц')
plt.ylabel('Выработка электроэнергии')
plt.title('Предсказание объема выработки электроэнергии')
plt.legend()
plt.show()
from keras import backend as K
def custom_activation(r):
K.set_epsilon(0.1)
return K.sqrt(1 + (r*K.epsilon())*(r*K.epsilon()))
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Input
from keras.layers import Dropout, BatchNormalization
model = Sequential()
model.add(Input(shape=(1,)))
model.add(Dense(64, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(128, activation="relu"))
model.add(BatchNormalization())
model.add(Dense(200, activation=custom_activation))
model.add(Dense(1)) # Линейная функция активации
from sklearn.preprocessing import MinMaxScaler
X = np.array(df['время']).reshape(-1, 1)
y = np.array(df['данные']).reshape(-1, 1)
X_train = X[:48]
y_train = y[:48]
X_test = X[48:60]
y_test = y[48:60]
model.compile(loss="mean_squared_error", optimizer="adam", metrics=["mean_absolute_error"])
model.fit(X_train, y_train, epochs=80, batch_size=12, validation_split=0.2)
predictions_valid = model.predict(X_test)
residuals = y_test - predictions_valid[0]
plt.figure(figsize=(12, 6))
plt.hist(residuals, bins=20, color='skyblue', edgecolor='black', alpha=0.7)
plt.xlabel('Остатки')
plt.ylabel('Частота')
plt.title('Гистограмма остатков')
plt.grid(axis='y', alpha=0.75)
plt.show()
next_data = np.array([61]).reshape(-1, 1)
next_prediction = model.predict(next_data)
print(f'Прогноз на следующий месяц: {next_prediction} кВт / час')
rolling_window_predictions = []
for i in range(1, 7):
prediction_data = np.array([60+i]).reshape(-1, 1)
prediction = model.predict(prediction_data)
rolling_window_predictions.append(prediction[0][0])
print(f'Прогнозы на следующие 6 месяцев: {rolling_window_predictions}')
print('Прогнозы на следующие 6 месяцев:')
for prediction in rolling_window_predictions:
print(prediction)
predictions_valid = model.predict(X)
rolling_window_predictions = []
for i in range(1, 13):
prediction_data = np.array([60 + i]).reshape(-1, 1)
prediction = model.predict(prediction_data)
rolling_window_predictions.append(prediction[0][0])
print(f'Прогнозы на следующие 12 месяцев: {rolling_window_predictions}')
print('Прогнозы на следующие 12 месяцев:')
for prediction in rolling_window_predictions:
print(prediction)
#добавляем 12 пустых значений
extended_y = np.pad(y.flatten(), (0, 12), 'constant', constant_values=(0,))
#объединение всех предсказанных значений
all_predictions = np.concatenate([predictions_valid.flatten(), np.array(rolling_window_predictions).flatten()])
plt.figure(figsize=(12, 6))
plt.plot(np.arange(1, 73), extended_y, label='Данные')
plt.plot(np.arange(1, 73), all_predictions, label='Предсказание', linestyle='dashed')
plt.xlabel('Месяц')
plt.ylabel('Объём выработки электроэнергии')
plt.title('Предсказание объёма выработки электроэнергии')
plt.legend()
plt.show()