Полный обзор реального приложения машинного обучения с использованием нейронных сетей LSTM.

Популярность криптовалют резко возросла в 2017 году из-за нескольких месяцев подряд экспоненциального роста их рыночной капитализации. Пик цен составил более 800 миллиардов долларов в январе 2018 года.

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

В этом блоге я расскажу о четырехэтапном процессе прогнозирования цен на криптовалюту:

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

Соревнование

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

Данные

Набор данных можно загрузить с веб-сайта CryptoCompare, который находится здесь.

Набор данных содержит всего 5 функций. Детали для них следующие:

  1. Цена закрытия - это рыночная цена закрытия валюты в конкретный день.
  2. Высокая цена - это самая высокая цена валюты за день.
  3. Низкая цена - это самая низкая цена на валюту на текущий день.
  4. Цена открытия - это рыночная цена открытия валюты на данный день.
  5. Объем - объем валюты, который находится в торговле в этот день.

Где код?

Без лишних слов, давайте начнем с кода. Полный проект на GitHub можно найти здесь.

Я начал с загрузки всех необходимых библиотек и зависимостей.

import json
import requests
from keras.models import Sequential
from keras.layers import Activation, Dense, Dropout, LSTM
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.metrics import mean_absolute_error
%matplotlib inline

Я использовал обменный курс доллара и сохранил данные в реальном времени во фрейме данных pandas. Я использовал метод to_datetime () для преобразования строки Date time в объект времени Python Date. Это необходимо, поскольку объекты даты и времени в файле читаются как строковый объект. Выполнение таких операций, как разница во времени со строкой, а не с объектом Date Time, очень просто.

endpoint = 'https://min-api.cryptocompare.com/data/histoday'
res = requests.get(endpoint + '?fsym=BTC&tsym=USD&limit=2000')
hist = pd.DataFrame(json.loads(res.content)['Data'])
hist = hist.set_index('time')
hist.index = pd.to_datetime(hist.index, unit='s')
target_col = 'close'

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

hist

Затем я разделил данные на два набора - обучающий набор и тестовый набор с 80% и 20% данных соответственно. Решение, принятое здесь, предназначено только для целей этого руководства. В реальных проектах вы всегда должны разделять свои данные на обучение, проверку и тестирование (например, 60%, 20%, 20%).

def train_test_split(df, test_size=0.2):
    split_row = len(df) - int(test_size * len(df))
    train_data = df.iloc[:split_row]
    test_data = df.iloc[split_row:]
    return train_data, test_data
train, test = train_test_split(hist, test_size=0.2)

Теперь давайте построим график цен на криптовалюту в долларах как функцию времени, используя приведенный ниже код:

def line_plot(line1, line2, label1=None, label2=None, title='', lw=2):
    fig, ax = plt.subplots(1, figsize=(13, 7))
    ax.plot(line1, label=label1, linewidth=lw)
    ax.plot(line2, label=label2, linewidth=lw)
    ax.set_ylabel('price [CAD]', fontsize=14)
    ax.set_title(title, fontsize=16)
    ax.legend(loc='best', fontsize=16)
line_plot(train[target_col], test[target_col], 'training', 'test', title='')

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

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

def normalise_zero_base(df):
    return df / df.iloc[0] - 1
def normalise_min_max(df):
    return (df - df.min()) / (data.max() - df.min())

Затем я создал функцию для извлечения данных из окон размером 5 каждое, как показано в приведенном ниже коде:

def extract_window_data(df, window_len=5, zero_base=True):
    window_data = []
    for idx in range(len(df) - window_len):
        tmp = df[idx: (idx + window_len)].copy()
        if zero_base:
            tmp = normalise_zero_base(tmp)
        window_data.append(tmp.values)
    
    return np.array(window_data)

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

def prepare_data(df, target_col, window_len=10, zero_base=True, test_size=0.2):
    train_data, test_data = train_test_split(df, test_size=test_size)
    X_train = extract_window_data(train_data, window_len, zero_base)
    X_test = extract_window_data(test_data, window_len, zero_base)
    y_train = train_data[target_col][window_len:].values
    y_test = test_data[target_col][window_len:].values
    if zero_base:
        y_train = y_train / train_data[target_col][:-window_len].values - 1
        y_test = y_test / test_data[target_col][:-window_len].values - 1
    return train_data, test_data, X_train, X_test, y_train, y_test

LSTM

Он работает с использованием специальных ворот, позволяющих каждому слою LSTM получать информацию как из предыдущих, так и из текущего слоя. Данные проходят через несколько шлюзов (например, ворота забывания, входные ворота и т. Д.) И различные функции активации (например, функция tanh, функция relu) и проходят через ячейки LSTM. Основное преимущество этого заключается в том, что он позволяет каждой ячейке LSTM запоминать шаблоны в течение определенного времени. Следует отметить, что LSTM может запоминать важную информацию и в то же время забывать несущественную информацию. Архитектура LSTM показана ниже:

Теперь давайте построим модель. Последовательная модель используется для наложения всех слоев (входных, скрытых и выходных). Нейронная сеть состоит из слоя LSTM, за которым следует 20% -ный слой Dropout и плотный слой с линейной функцией активации. Я выполнил модель, используя Адама в качестве оптимизатора и среднеквадратичную ошибку в качестве функции потерь.

def build_lstm_model(input_data, output_size, neurons=100, activ_func='linear', dropout=0.2, loss='mse', optimizer='adam'):
    model = Sequential()
    model.add(LSTM(neurons, input_shape =(input_data.shape[1],input_data.shape[2])))
    model.add(Dropout(dropout))
    model.add(Dense(units=output_size))
    model.add(Activation(activ_func))
    model.compile(loss=loss, optimizer=optimizer)
    
    return model

Затем я установил некоторые параметры, которые будут использоваться позже. Эти параметры: начальное число случайных чисел, длина окна, размер набора тестов, количество нейронов в слое LSTM, эпохи, размер пакета, потери, выпадения и оптимизатор.

np.random.seed(42)
window_len = 5
test_size = 0.2
zero_base = True
lstm_neurons = 100
epochs = 20
batch_size = 32
loss = 'mse'
dropout = 0.2
optimizer = 'adam'

Теперь давайте обучим модель, используя входные данные x_train и метки y_train.

train, test, X_train, X_test, y_train, y_test = prepare_data(hist, target_col, window_len=window_len, zero_base=zero_base, test_size=test_size)
model = build_lstm_model(X_train, output_size=1, neurons=lstm_neurons, dropout=dropout, loss=loss,optimizer=optimizer)
history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, verbose=1, shuffle=True)

Я использовал среднюю абсолютную ошибку (MAE) в качестве метрики оценки. Причина выбора MAE вместо среднеквадратичной ошибки (RMSE) заключается в том, что MAE более интерпретируема. RMSE не описывает только среднюю ошибку, и, следовательно, ее гораздо труднее понять. Поскольку мы хотим, чтобы модель была легко объяснена даже для нетехнической аудитории, MAE выглядит лучшим выбором.

Средняя абсолютная ошибка

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

Значение MAE 0,029311972877135727 выглядит неплохо. Наконец, давайте построим график фактических и прогнозируемых цен, используя приведенный ниже код:

preds = test[target_col].values[:-window_len] * (preds + 1)
line_plot(targets, preds, 'actual', 'prediction', lw=3)
preds = pd.Series(index=targets.index, data=preds)

Выводы

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

Также прочтите