Прогнозировать цену биткоина в режиме реального времени с помощью ЛСТМ

Автор:Облака в матрице, Создано: 2020-05-20 15:45:23, Обновлено: 2020-05-20 15:46:37

img

Примечание: данный случай используется только для исследовательских целей и не является инвестиционным предложением.

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

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

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

Импорт библиотеки

import pandas as pd
import numpy as np

from sklearn.preprocessing import MinMaxScaler, LabelEncoder
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout

from matplotlib import pyplot as plt
%matplotlib inline

Анализ данных

Загрузка данных

Читать данные о дневном обороте BTC

data = pd.read_csv(filepath_or_buffer="btc_data_day")

В настоящее время данные находятся в 1380 строках, состоящих из столбцов Date, Open, High, Low, Close, Volume (BTC), Volume (Currency) и Weighted Price.

data.info()

Смотрите данные в первых 10 строках.

data.head(10)

img

Визуализация данных

Используя matplotlib, мы можем изобразить взвешенную цену и посмотреть на распределение и движение данных. На рисунке мы обнаружили часть данных 0, и нам нужно подтвердить, есть ли какие-либо отклонения в данных.

plt.plot(data['Weighted Price'], label='Price')
plt.ylabel('Price')
plt.legend()
plt.show()

img

Необычная обработка данных

Сначала посмотрим, есть ли в данных данные нана, и мы увидим, что в наших данных нет данных нана.

data.isnull().sum()

Date                 0
Open                 0
High                 0
Low                  0
Close                0
Volume (BTC)         0
Volume (Currency)    0
Weighted Price       0
dtype: int64

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

(data == 0).astype(int).any()

Date                 False
Open                  True
High                  True
Low                   True
Close                 True
Volume (BTC)          True
Volume (Currency)     True
Weighted Price        True
dtype: bool

data['Weighted Price'].replace(0, np.nan, inplace=True)
data['Weighted Price'].fillna(method='ffill', inplace=True)
data['Open'].replace(0, np.nan, inplace=True)
data['Open'].fillna(method='ffill', inplace=True)
data['High'].replace(0, np.nan, inplace=True)
data['High'].fillna(method='ffill', inplace=True)
data['Low'].replace(0, np.nan, inplace=True)
data['Low'].fillna(method='ffill', inplace=True)
data['Close'].replace(0, np.nan, inplace=True)
data['Close'].fillna(method='ffill', inplace=True)
data['Volume (BTC)'].replace(0, np.nan, inplace=True)
data['Volume (BTC)'].fillna(method='ffill', inplace=True)
data['Volume (Currency)'].replace(0, np.nan, inplace=True)
data['Volume (Currency)'].fillna(method='ffill', inplace=True)

(data == 0).astype(int).any()

Date                 False
Open                 False
High                 False
Low                  False
Close                False
Volume (BTC)         False
Volume (Currency)    False
Weighted Price       False
dtype: bool

И если мы посмотрим на распределение данных и на их движение, то кривая уже очень последовательна.

plt.plot(data['Weighted Price'], label='Price')
plt.ylabel('Price')
plt.legend()
plt.show()

img

Разделение учебных и тестовых наборов

Упорядочить данные до 0 - 1.

data_set = data.drop('Date', axis=1).values
data_set = data_set.astype('float32')
mms = MinMaxScaler(feature_range=(0, 1))
data_set = mms.fit_transform(data_set)

Разделяем тестовые и тренировочные наборы на 2:8.

ratio = 0.8
train_size = int(len(data_set) * ratio)
test_size = len(data_set) - train_size
train, test = data_set[0:train_size,:], data_set[train_size:len(data_set),:]

Создание тренировочных и тестовых наборов данных в течение одного дня как окна для создания наших тренировочных и тестовых наборов данных.

def create_dataset(data):
    window = 1
    label_index = 6
    x, y = [], []
    for i in range(len(data) - window):
        x.append(data[i:(i + window), :])
        y.append(data[i + window, label_index])
    return np.array(x), np.array(y)

train_x, train_y = create_dataset(train)
test_x, test_y = create_dataset(test)

Определение и обучение моделей

На этот раз мы используем простую модель, которая имеет следующую структуру: 1. LSTM2. Dense.

Здесь необходимо сделать пояснение в отношении формы ввода в LSTM. Вводная величина формы ввода - batch_size, time steps, features. В ней значение time steps - это интервал времени окна при вводе данных, здесь мы используем 1 день в качестве окна времени, и наши данные - это данные дня, поэтому здесь наши время шаги - 1.

Длинная краткосрочная память (англ. Long short-term memory, LSTM) - это особый вид РНН, который используется для решения проблем с исчезновением и взрывом на протяжении длинной последовательности тренировок.

img

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

Состояние клеток

Состояние клетки является ядром ЛСТМ. Он является темной линией, которая находится в верхней части диаграммы, и ниже этой черной линии есть несколько ворот, которые мы рассмотрим позже. Состояние клетки обновляется в зависимости от результатов каждой из ворот.

ЛСТМ-сеть может удалять или добавлять информацию о состоянии клетки через структуру, называемую воротами. Врата могут избирательно решать, какая информация должна проходить через них. Структура дверей - это комбинация сигмоидного слоя и операций с умножением точки.

Забытые двери

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

img

Мы можем видеть, что запоминающийся вход выводит вектор между 0 и 1 путем просмотра информации $h_{l-1}$ и $x_{t}$, где значение 0 и 1 означает, какая информация в состоянии $C_{t-1}$ сохраняется или отбрасывается. 0 означает, что не сохраняется, а 1 означает, что сохраняется.

Математическое выражение: $f_{t}=\sigma\left(W_{f} \cdot\left[h_{t-1}, x_{t}\right]+b_{f}\right) $

Входные двери

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

img

Мы видим, что сообщения $h_{l-1}$ и $x_{t}$ вновь помещаются в запоминающуюся дверь (sigmoid) и в входную дверь (tanh). Так как результат запоминаемой двери равен 0-1, то если запоминающая дверь выводит 0, то результат $C_{i}$ после ввода не будет добавлен в текущее состояние клетки, а если 1, то все будет добавлено в состояние клетки, поэтому роль запоминающей двери здесь заключается в выборочном добавлении результатов запоминающей двери в состояние клетки.

Формула: $C_{t}=f_{t} * C_{t-1} + i_{t} * \tilde{C}_{t}$

Выход

После обновления состояния клетки требуется определить, какие состояния клетки должны быть определены на основе суммы ввода $h_{l-1}$ и $x_{t}$. При этом ввод должен быть выполнен через сигмоидный слой, называемый выходной дверью, а затем через танх-слой.

img

def create_model():
    model = Sequential()
    model.add(LSTM(50, input_shape=(train_x.shape[1], train_x.shape[2])))
    model.add(Dense(1))
    model.compile(loss='mae', optimizer='adam')
    model.summary()
    return model

model = create_model()

img

history = model.fit(train_x, train_y, epochs=80, batch_size=64, validation_data=(test_x, test_y), verbose=1, shuffle=False)

plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='test')
plt.legend()
plt.show()

img

train_x, train_y = create_dataset(train)
test_x, test_y = create_dataset(test)

Прогноз

predict = model.predict(test_x)
plt.plot(predict, label='predict')
plt.plot(test_y, label='ground true')
plt.legend()
plt.show()

img

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


Больше