А в качестве бонуса стать богатым! Шучу, бро.

В этом посте мы построим модель LSTM для прогнозирования цен на акции Apple, используя Tensorflow!

Прогнозирование цен на акции — очень интересная область машинного обучения. Лично у меня всегда есть интерес к приложениям в этой области.

Машинное обучение стало очень полезным для прогнозирования фондового рынка за последние годы, и сегодня многие инвестиционные компании используют машинное обучение для принятия решений в Фондовый рынок.

И, вопреки тому, что многие думают, нам не нужна потрясающая Модель машинного обучения, чтобы действительно зарабатывать деньги.

Предупреждение. Этот пост имеет целью только исследовать и показать, как модели машинного обучения работают на фондовом рынке, это не рекомендации по инвестициям! Фондовый рынок меняется быстро и не рекомендуется новичкам без опыта!

Теперь мы можем продолжить!

Как работает LSTM?

По сути, модели LSTM могут хранить информацию с течением времени. Это очень полезно, когда мы хотим работать с временными рядами или последовательными данными.

Модели LSTM очень похожи на человеческий мозг. Когда кто-то говорит тебе:

"Марк и Джейн играют в футбол на улице"

Вы уже знаете, что такое футбол, кто такие Марк и Джейн и что такое улица, поэтому вам будет легче обрабатывать и понимать информацию.

Предположим, вы ничего не знали, это было бы очень сложно и, возможно, вы не поняли бы информацию с первого раза.

LSTM работает так: после сохранения информации они могут решать более сложные проблемы, где важна предыдущая информация.

Применив это к проблеме этого поста, когда мы хотим спрогнозировать цену, нам понадобится предыдущая информация. Вот почему LSTM очень полезен!

Другая важная особенность LSTM заключается в том, что мы можем решить, какая информация будет храниться, а какую можно отбросить. Мы делаем это с помощью вентилей, и это помогает нам избежать таких проблем, как Проблема исчезающего градиента.

На изображении ниже у нас есть архитектура ячейки LSTM и ее функции:

По сути, в этих функциях происходит магия забывания, обновления и сохранения информации.

Если вы хотите узнать больше о LSTM, я рекомендую прочитать это.

Теперь давайте перейдем к нашей проблеме!

Понимание проблемы

Как вы могли видеть ранее, прогнозирование цены акций связано с использованием последовательных данных, где прошлые данные имеют значение и влияют непосредственно на наши прогнозы.

Это пример последовательных данных о ценах на акции:

Что мы хотим сделать, так это: дать нашей модели историю цен на акции Apple, он будет работать с этими данными, чтобы выявить закономерности и сделать много вычислений, чтобы потом дать нам прогнозы!

И почему я выбрал акции Apple?

Итак, сначала нам нужно загрузить наши данные. Для этого проекта я использовал набор данных, экспортированный напрямую из NASDAQ, вы можете скачать эти данные здесь.

Мы используем нейронные сети, поэтому чем больше данных, тем лучше, я использовал цены за последние 5 лет, они нам пригодятся.

После загрузки данных мы хотим сделать худшую часть любого специалиста по данным или инженеру по машинному обучению — адаптации!

Уже отформатированные данные находятся в репозитории этого поста, в конце этого поста.

Но сначала адаптируйте наши Данные, нам нужно посмотреть, что мы будем адаптировать и форматировать. Если мы посмотрим на данные, это выглядит так:

Теперь мы хотим знать, есть ли в нашем наборе данных нулевые значения. Хороший способ сделать это — использовать heatmap() от Seaborn для его визуализации.

Но, как вы могли видеть ранее, в нашем столбце «Дата» используется «/», и это может помешать нашей работе, поэтому нам нужно отформатировать его!

На самом деле, в нашей модели мы просто хотим использовать столбец «Открыть», но было бы неплохо отформатировать столбцы «Дата», чтобы мы могли использовать их позже в другом проекте с теми же данными.

Чтобы отформатировать наш столбец «Дата», мы можем использовать to_datetime() от Pandas:

data[‘Date’] = pd.to_datetime(data.Date)

Теперь наш столбец «Дата» имеет формат «Дата-время»!

Теперь нам нужно отформатировать наши цены, они в формате String. Это легко сделать, мы можем использовать replace() из класса String.

data[‘Open’] = data[‘Open’].replace({‘\$’:’’}, regex=True).astype(float)
data[‘High’] = data[‘High’].replace({‘\$’: ‘’}, regex=True).astype(float)
data[‘Close/Last’] = data[‘Close/Last’].replace({‘\$’: ‘’}, regex=True).astype(float)
data[‘Low’] = data[‘Low’].replace({‘\$’: ‘’}, regex=True).astype(float)

И последнее, что нужно изменить в наших данных, это удалить пробел в имени столбцов, мы можем сделать это с помощью rename() от Pandas.

data.rename(columns={‘ Close/Last’: ‘Close/Last’, ‘ Volume’: ‘Volume’,
 ‘ Open’: ‘Open’, ‘ High’: ‘High’, ‘ Low’: ‘Low’},
 inplace=True)

Теперь наш набор данных отформатирован и готов к разделению.

В нашем наборе данных 1258, мы хотим использовать 1000 строк для поезда и 258 для теста:

# Split into train and test:
data_to_train = data[:1000]
data_to_test = data[1000:]

Теперь мы можем сохранить 2 CSV-файла, Train и Test.

data_to_train.to_csv(‘train_data.csv’)
data_to_test.to_csv(‘test_data.csv’)

Пришло время заняться машинным обучением, детка!

Создание нашей модели

Эта архитектура была основана на Модели Деррика Мвити, которую я тестировал, и результаты были слишком хорошими!

Мы хотим использовать столбец «Открыть» в нашей модели, поэтому мы можем использовать iloc для получения его значений.

training_set = train_data.iloc[: , 3:4].values

И мы хотим определить переменную как real_stock_price для хранения наших реальных данных для последующего сравнения с прогнозами нашей модели!

real_stock_price = test_data.iloc[: , 3:4].values

После получения значений из столбца «Открыть» нам нужно их масштабировать. Благодаря этому наша Модель работает лучше!

Чтобы масштабировать значения, мы можем использовать sklearn!

# Normalizing data, scale between 0 and 1:
from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range=(0, 1))
training_data_scaled = sc.fit_transform(training_set)

После масштабирования данных обучения нам нужно отформатировать их в 3D-массив для ввода в нашу модель LSTM. Мы делаем это, создавая 60 меток времени.

X_train = []
y_train = []
for i in range(60, 1000):
  X_train.append(training_data_scaled[i-60:i, 0])
  y_train.append(training_data_scaled[i, 0])
X_train, y_train = np.array(X_train), np.array(y_train)

После этого наши данные готовы для ввода в нашу модель!

Наша Модель будет использовать следующую архитектуру:

# Building Model:
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.LSTM(units=50, return_sequences=True,
input_shape=(X_train.shape[1], 1)))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.LSTM(units=50, return_sequences=True))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.LSTM(units=50, return_sequences=True))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.LSTM(units=50))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.Dense(units=1))
model.summary()

Мы используем слои Dropout, чтобы избежать проблем переобучения, и, кроме того, мы используем параметр return_sequences, чтобы определить, будет ли слой возвращать последовательность, совместимую с LSTM. Мы используем “return_sequences=True”, когда у нас есть слой LSTM после!

После сборки нашей модели мы хотим скомпилировать ее с помощью:

Теперь пришло время подогнать нашу модель!

modelo = model.fit(X_train, y_train, epochs=100, batch_size=32)

После обучения нашей модели мы можем построить график потери, чтобы визуализировать, насколько она хороша:

Составление прогнозов

Чтобы делать прогнозы, нам нужно использовать наш тестовый набор данных и отформатировать его, как мы делали это раньше в наборе данных поезда.

dataset_total = pd.concat([train_data[‘Open’], test_data[‘Open’]], axis=0)
inputs = dataset_total[len(dataset_total) — len(test_data) — 60:].values
inputs = inputs.reshape(-1,1)
inputs = sc.transform(inputs)
X_test = []
for i in range(60, 259):
   X_test.append(inputs[i-60:i, 0])
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))

После форматирования тестовых данных мы можем делать прогнозы в нашем X_test.

predicted_stock_price = model.predict(X_test)

Но перед построением наших прогнозов нам нужно сделать inverse_transform()в массиве прогнозов, потому что мы делаем прогнозы с использованием шкалы, поэтому наши прогнозы находятся в диапазоне от 0 до 1.

predicted_stock_price = model.predict(X_test)

Теперь пришло время построить прогнозы и посмотреть, как наша модель работает по сравнению с реальными ценами на акции.

Как видите, наша модель показала себя слишком хорошо!

Вы можете использовать тот же подход из этой статьи в любом прогнозировании цен, давайте делать деньги, детка!

Вы можете получить доступ к репозиторию этого сообщения в здесь.

На данный момент это все!

Увидимся в следующий раз!

Мои социальные сети:

Linkedin:https://www.linkedin.com/in/gabriel-mayer-779b5a162/

GitHub: https://github.com/gabrielmayers

Instagram: https://www.instagram.com/gabrielmayerl/

использованная литература

[1] Деррик Мвити, Данные и записная книжка для учебного пособия по прогнозированию цен на акции (2018), Github