Вступление
Анализ временных рядов относится к анализу изменения тренда данных за определенный период времени. Анализ временных рядов имеет множество применений. Одним из таких приложений является прогнозирование будущей стоимости товара на основе его прошлых значений. Прогнозирование будущих цен акций, вероятно, является лучшим примером такого приложения. В этой статье мы увидим, как можно выполнить анализ временных рядов с помощью рекуррентной нейронной сети . Мы будем прогнозировать будущие цены акций компании Apple (AAPL), основываясь на ценах ее акций за последние 5 лет.
Набор данных
Данные, которые мы собираемся использовать для этой статьи, можно загрузить с сайта Yahoo Finance . Для обучения нашего алгоритма мы будем использовать цены акций Apple с 1 января 2013 года по 31 декабря 2017 года. Для прогнозирования мы будем использовать цены акций Apple за январь 2018 года. Поэтому для того, чтобы оценить эффективность алгоритма, загрузите также фактические цены акций за январь 2018 года.
Давайте теперь посмотрим, как выглядят наши данные. Откройте обучающий файл Apple stock price training, содержащий данные за пять лет. Вы увидите, что он содержит семь столбцов: Date, Open, High, Low, Close, Adj Close и Volume. Мы будем предсказывать цену открытия акций, поэтому нас не интересуют остальные столбцы.
Если вы построите график начальных цен акций относительно даты, то увидите следующий график:
Вы можете видеть, что тренд сильно нелинейен, и очень трудно уловить тренд, используя эту информацию. Именно здесь может быть использована сила LSTM . LSTM (Long Short-Term Memory network) – это тип рекуррентной нейронной сети, способной запоминать прошлую информацию и при прогнозировании будущих значений учитывать эту прошлую информацию.
Достаточно предварительных замечаний, давайте посмотрим, как LSTM можно использовать для анализа временных рядов.
Прогнозирование Будущих Цен На Акции
Прогнозирование цены акций аналогично любой другой задаче машинного обучения, где нам дается набор функций, и мы должны предсказать соответствующее значение. Мы будем выполнять те же действия, что и для решения любой задачи машинного обучения. Выполните следующие действия:
Импорт библиотек
Первым шагом, как всегда, является импорт необходимых библиотек. Для этого выполните следующий сценарий:
import numpy as np import matplotlib.pyplot as plt import pandas as pd
Импорт набора данных
Выполните следующий сценарий для импорта набора данных. Ради этой статьи данные были сохранены в папке Datasets, внутри диска “E”. Вы можете изменить путь соответственно.
apple_training_complete = pd.read_csv(r'E:\Datasets\apple_training.csv')
Как мы уже говорили ранее, нас интересует только цена открытия акции. Поэтому мы отфильтруем все данные из нашего обучающего набора и сохраним только значения для столбца Open . Выполните следующий сценарий:
apple_training_processed = apple_training_complete.iloc[:, 1:2].values
Нормализация данных
Как правило, всякий раз, когда вы используете нейронную сеть, вы должны нормализовать или масштабировать свои данные. Мы будем использовать класс MinMaxScaler
из библиотеки sklearn.preprocessing
для масштабирования наших данных между 0 и 1. Параметр feature_range
используется для указания диапазона масштабируемых данных. Выполните следующий сценарий:
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler(feature_range = (0, 1)) apple_training_scaled = scaler.fit_transform(apple_training_processed)
Преобразование обучающих данных в Правильную форму
Как я уже говорил ранее, в задачах временного ряда мы должны предсказать значение в момент времени T, основываясь на данных из дней T-N, где N может быть любым числом шагов. В этой статье мы собираемся предсказать цену открытия акций на основе данных, основанных на ценах открытия акций за последние 60 дней. Я пробовал и проверял различные числа и обнаружил, что наилучшие результаты получаются, когда используются последние 60 временных шагов. Вы можете попробовать разные числа и посмотреть, как работает ваш алгоритм.
Наш набор функций должен содержать значения начальной цены акций за последние 60 дней, в то время как метка или зависимая переменная должны быть ценой акций на 61-й день. Выполните следующий сценарий для создания набора объектов и меток.
features_set = [] labels = [] for i in range(60, 1260): features_set.append(apple_training_scaled[i-60:i, 0]) labels.append(apple_training_scaled[i, 0])
В приведенном выше скрипте мы создаем два списка: feature_set
и labels
. В данных обучения содержится 1260 записей. Мы выполняем цикл, который начинается с 61-й записи и сохраняет все предыдущие 60 записей в список feature_set
. 61-я запись хранится в списке labels
.
Нам нужно преобразовать как feature_set
, так и список labels
в массив numpy, прежде чем мы сможем использовать его для обучения. Выполните следующий сценарий:
features_set, labels = np.array(features_set), np.array(labels)
Чтобы обучить LSTM на наших данных, нам нужно преобразовать наши данные в форму, принятую LSTM. Нам нужно преобразовать наши данные в трехмерный формат. Первое измерение-это количество записей или строк в наборе данных, которое в нашем случае равно 1260. Второе измерение-это количество временных шагов, равное 60, а последнее измерение – количество индикаторов. Поскольку мы используем только одну функцию, то есть Open , количество индикаторов будет равно одному. Выполните следующий сценарий:
features_set = np.reshape(features_set, (features_set.shape[0], features_set.shape[1], 1))
Обучение LSTM
Мы предварительно обработали наши данные и преобразовали их в нужный формат. сейчас самое время создать наш LSTM. Модель LSTM, которую мы собираемся создать, будет последовательной моделью с несколькими слоями. Мы добавим к нашей модели четыре слоя LSTM, за которыми последует плотный слой, предсказывающий будущую цену акций.
Давайте сначала импортируем библиотеки, которые нам понадобятся для создания нашей модели:
from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM from keras.layers import Dropout
В приведенном выше скрипте мы импортировали класс Sequential
из библиотеки keras.models
и классы Dense
, ISM
и Dropout
из keras.слои
библиотека.
В качестве первого шага нам нужно создать экземпляр класса Sequential
. Это будет наш класс моделей, и мы добавим к этой модели LSTM, Dropout и плотные слои. Выполните следующий сценарий
model = Sequential()
Создание слоев LSTM и Dropout
Давайте добавим слой LSTM к модели, которую мы только что создали. Для этого выполните следующий сценарий:
model.add(LSTM(units=50, return_sequences=True, input_shape=(features_set.shape[1], 1)))
Для добавления слоя в последовательную модель используется метод add
. Внутри метода add
мы передали наш слой LSTM. Первый параметр слоя LSTM-это количество нейронов или узлов, которые нам нужны в слое. Второй параметр – return_sequences
, который имеет значение true, так как мы добавим в модель больше слоев. Первый параметр input_shape
– это количество временных шагов, а последний параметр-количество индикаторов.
Теперь давайте добавим слой отсева в нашу модель. Слой отсева добавляется, чтобы избежать переобучения, которое является феноменом, когда модель машинного обучения работает лучше на обучающих данных по сравнению с тестовыми данными. Выполните следующий сценарий, чтобы добавить выпадающий слой.
model.add(Dropout(0.2))
Давайте добавим в нашу модель еще три слоя LSTM и dropout. Запустите следующий сценарий.
model.add(LSTM(units=50, return_sequences=True)) model.add(Dropout(0.2)) model.add(LSTM(units=50, return_sequences=True)) model.add(Dropout(0.2)) model.add(LSTM(units=50)) model.add(Dropout(0.2))
Создание Плотного Слоя
Чтобы сделать нашу модель более надежной, мы добавляем плотный слой в конце модели. Число нейронов в плотном слое будет установлено равным 1, так как мы хотим предсказать одно значение на выходе.
model.add(Dense(units = 1))
Компиляция моделей
Наконец, нам нужно составить наш СПИСОК, прежде чем мы сможем обучить его на обучающих данных. Следующий скрипт компилирует нашу модель.
model.compile(optimizer = 'adam', loss = 'mean_squared_error')
Мы вызываем метод compile для последовательного объекта модели, который в нашем случае является “моделью”. Мы используем среднеквадратичную ошибку в качестве функции потерь, а для уменьшения потерь или оптимизации алгоритма используем оптимизатор adam .
Обучение алгоритму
Теперь настало время обучить модель, которую мы определили в предыдущих нескольких шагах. Для этого мы вызываем метод fit
на модели
и передаем ему наши обучающие функции и метки, как показано ниже:
model.fit(features_set, labels, epochs = 100, batch_size = 32)
В зависимости от вашего оборудования обучение модели может занять некоторое время.
Тестирование нашего LSTM
Мы успешно обучили наш LSTM, теперь самое время проверить работоспособность нашего алгоритма на тестовом наборе, предсказав цены открытия акций на январь 2018 года. Однако, как и в случае с обучающими данными, нам нужно преобразовать наши тестовые данные в правильный формат.
Давайте сначала импортируем наши тестовые данные. Выполните следующий сценарий:
apple_testing_complete = pd.read_csv(r'E:\Datasets\apple_testing.csv') apple_testing_processed = apple_testing_complete.iloc[:, 1:2].values
В приведенном выше сценарии мы импортируем наши тестовые данные и, как и в случае с обучающими данными, удаляем все столбцы из тестовых данных, кроме столбца, содержащего цены открытия акций.
Если начальные цены акций за январь 2018 года сопоставить с датами, то вы увидите следующий график.
Вы можете видеть, что тренд очень нелинейный. В целом цены на акции демонстрируют небольшой рост в начале месяца, за которым следует тенденция к снижению в конце месяца, с небольшим повышением и снижением цен на акции в промежутке между ними. Прогнозировать такую тенденцию крайне сложно. Давайте посмотрим, действительно ли обученный нами LSTM способен предсказать такую тенденцию.
Преобразование тестовых данных в Правильный формат
Для каждого дня января 2018 года мы хотим, чтобы наш набор функций содержал цены открытия акций за предыдущие 60 дней. На 1 января нам нужны цены акций за предыдущие 60 дней. Для этого нам нужно объединить наши обучающие данные и тестовые данные перед предварительной обработкой. Для этого выполните следующий сценарий:
apple_total = pd.concat((apple_training_complete['Open'], apple_testing_complete['Open']), axis=0)
Теперь давайте подготовим наши тестовые входы. Входные данные для каждого дня должны содержать начальные цены акций за предыдущие 60 дней. Это означает, что нам нужны начальные цены акций за 20 тестовых дней в январе 2018 года и 60 цен акций за последние 60 дней для тренировочного набора. Выполните следующий сценарий, чтобы получить эти 80 значений.
test_inputs = apple_total[len(apple_total) - len(apple_testing_complete) - 60:].values
Как и в случае с обучающим набором, нам нужно масштабировать наши тестовые данные. Выполните следующий сценарий:
test_inputs = test_inputs.reshape(-1,1) test_inputs = scaler.transform(test_inputs)
Мы масштабировали наши данные, теперь давайте подготовим наш окончательный тестовый входной набор, который будет содержать предыдущие 60 цен акций за январь. Выполните следующий сценарий:
test_features = [] for i in range(60, 80): test_features.append(test_inputs[i-60:i, 0])
Наконец, нам нужно преобразовать наши данные в трехмерный формат, который может быть использован в качестве входных данных для LSTM. Выполните следующий сценарий:
test_features = np.array(test_features) test_features = np.reshape(test_features, (test_features.shape[0], test_features.shape[1], 1))
Делать Прогнозы
Сейчас самое время увидеть магию. Мы предварительно обработали наши тестовые данные и теперь можем использовать их для прогнозирования. Для этого нам просто нужно вызвать метод predict
на модели, которую мы обучили. Выполните следующий сценарий:
predictions = model.predict(test_features)
Поскольку мы масштабировали наши данные, прогнозы, сделанные LSTM, также масштабируются. Нам нужно вернуть масштабированное предсказание обратно к их фактическим значениям. Для этого мы можем использовать методы inverse_transform
объекта scale, созданного нами во время обучения. Взгляните на следующий сценарий:
predictions = scaler.inverse_transform(predictions)
Наконец, давайте посмотрим, насколько хорошо наш алгоритм предсказал будущие цены акций. Выполните следующий сценарий:
plt.figure(figsize=(10,6)) plt.plot(apple_testing_processed, color='blue', label='Actual Apple Stock Price') plt.plot(predictions , color='red', label='Predicted Apple Stock Price') plt.title('Apple Stock Price Prediction') plt.xlabel('Date') plt.ylabel('Apple Stock Price') plt.legend() plt.show()
Вывод выглядит следующим образом:
В выходных данных синяя линия представляет фактические цены акций за январь 2018 года, в то время как красная линия представляет прогнозируемые цены акций. Вы можете ясно видеть, что наш алгоритм смог уловить общую тенденцию. Прогнозируемые цены также видят бычий тренд в начале, за которым следует медвежий или нисходящий тренд в конце. Удивительно, не правда ли?
Вывод
Long short-term memory network (LSTM) – одна из наиболее часто используемых нейронных сетей для анализа временных рядов. Способность LSTM запоминать предыдущую информацию делает его идеальным для таких задач. В этой статье мы увидели, как мы можем использовать LSTM для прогнозирования цены акций Apple. Я бы предложил вам загрузить акции какой-нибудь другой организации, например Google или Microsoft, из Yahoo Finance и посмотреть, способен ли ваш алгоритм фиксировать тенденции.