Фондовый рынок — это мост между экономикой страны и гражданами конкретной страны. Состояние фондового рынка связано со здоровьем экономики страны, но в то же время позволяет простому человеку принять участие в этом рынке. Фондовый рынок содержит акции больших и малых компаний, которые находятся в определенной стране, и граждане могут вести бизнес, покупая акции по низкой цене и продавая их с прибылью, когда цена акций растет. Однако вот в чем загвоздка: огромные убытки возникают, когда цены на акции резко падают. Поэтому неудивительно, что люди, инвестирующие в фондовый рынок, проводят десятки расчетов, прежде чем потратить хоть копейку. Однако, к счастью, появление ИИ привело к решению этой проблемы, поскольку ИИ работает исключительно хорошо с меньшим участием человека. Мало того, методы искусственного интеллекта, такие как рекуррентные нейронные сети (RNN), могут делать прогнозы, используя данные за десятилетия. Чтобы проиллюстрировать это, в этой статье RNN используются для прогнозирования акций Schlumberger (нефтегазовой сервисной компании) с 2010 по 2019 год.
Отказ от ответственности: это статья об искусственном интеллекте от среднего до продвинутого уровня. Обязательно знание нейронных сетей, RNN и языка Python.
Что такое RNN?
RNN — это тип нейронных сетей, которые, в свою очередь, являются подмножеством методов машинного обучения. В отличие от простых нейронных сетей, RNN учитывают прошлое состояние, а также текущее состояние конкретного нейрона. Проще говоря, RNN учится не только на текущих данных, но и на прошлых данных. Если RNN является двунаправленной, сеть учится на настоящих, прошлых и будущих данных. Термины используются здесь свободно для простоты. Читателям рекомендуется узнать больше о RNN из других источников, таких как специализация Эндрю Нг по глубокому обучению.
Существует несколько типов RNN. Самые известные из них — GRU и LSTM. Хотя однозначного вердикта о том, какой из них лучше, нет, оба они широко используются сегодня. Для нашего приложения мы будем использовать LSTM.
Реализация
Первым шагом является сбор данных. Я собрал данные фондового рынка за 10 лет с официального сайта Nasdaq. Данные представлены в формате csv, а код для визуализации показан ниже:
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt import csv time_step = [] temps = [] with open('HistoricalQuotes(1).csv') as csvfile: reader = csv.reader(csvfile, delimiter=',') next(reader) step=0 for row in reader: val=row[1] temps.append(float(val[2:])) time_step.append(step) step = step + 1 series = np.array(temps) time = np.array(time_step) plt.figure(figsize=(10, 6)) plot_series(time, series)
HistoryQuotes(1).csv содержит данные фондового рынка. Читатель разделяет каждую строку везде, где есть запятая. Второе значение (то есть первый индекс) — это цена закрытия акции. Первый символ, который является знаком доллара, опускается при использовании val[2:]. Функция plot_series показана ниже:
def plot_series(time, series, format="-", start=0, end=None): plt.plot(time[start:end], series[start:end], format) plt.xlabel("Time") plt.ylabel("Value") plt.grid(True) plt.show()
Данные показаны ниже:
Данные разделены на набор для обучения и проверки. Данные разделены на отметке 1800-го временного шага.
split_time = 1800 time_train = time[:split_time] x_train = series[:split_time] time_valid = time[split_time:] x_valid = series[split_time:]
Входные данные для RNN представлены в виде оконных рядов. Это необходимо для того, чтобы сеть видела часть данных, а не только одну точку данных.
def windowed_dataset(series, window_size, batch_size, shuffle_buffer): series = tf.expand_dims(series, axis=-1) ds = tf.data.Dataset.from_tensor_slices(series) ds = ds.window(window_size + 1, shift=1, drop_remainder=True) ds = ds.flat_map(lambda w: w.batch(window_size + 1)) ds = ds.shuffle(shuffle_buffer) ds = ds.map(lambda w: (w[:-1], w[1:])) return ds.batch(batch_size).prefetch(1) def model_forecast(model, series, window_size): ds = tf.data.Dataset.from_tensor_slices(series) ds = ds.window(window_size, shift=1, drop_remainder=True) ds = ds.flat_map(lambda w: w.batch(window_size)) ds = ds.batch(32).prefetch(1) forecast = model.predict(ds) return forecast tf.keras.backend.clear_session() np.random.seed(51) window_size = 64 batch_size = 256 shuffle_buffer_size=1000 train_set = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
До сих пор мы подготовили данные. Следующим шагом является подготовка модели. Используемая нами модель имеет следующую последовательность:
Conv2d -> LSTM -> LSTM -> Плотный -> Плотный -> Плотный -> Лямбда
model = tf.keras.models.Sequential([ tf.keras.layers.Conv1D(filters=60, kernel_size=5, strides=1, padding="causal", activation="relu", input_shape=[None, 1]), tf.keras.layers.LSTM(60, return_sequences=True), tf.keras.layers.LSTM(60, return_sequences=True), tf.keras.layers.Dense(30, activation="relu"), tf.keras.layers.Dense(10, activation="relu"), tf.keras.layers.Dense(1), tf.keras.layers.Lambda(lambda x: x * 400) ])
Мы будем использовать стохастический градиентный спуск (SGD) с импульсом в качестве нашего оптимизатора и Хубера в качестве нашей функции потерь, обученной на 100 эпохах. Метрикой является средняя абсолютная ошибка (MAE).
optimizer = tf.keras.optimizers.SGD(lr=1e-6, momentum=0.9) model.compile(loss=tf.keras.losses.Huber(), optimizer=optimizer, metrics=["mae"]) history = model.fit(train_set,epochs=100)
Модель обучается в течение 100 эпох, а затем на проверочном наборе делаются прогнозы. Истинные значения (синяя линия) и прогнозируемые значения (оранжевая линия) показаны на одном графике для сравнения.
MAE составляет всего 1,49, что является отличным результатом, учитывая спорадический и непостоянный характер нефтегазовой отрасли.
Этот код был вдохновлен специализацией Tensorflow от Deeplearning.ai