Краткое изложение того, как сети RNN-LSTM можно использовать для точного прогнозирования цены биткойнов (BTC).

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

В этом блоге я реализовал модель RNN-LSTM для прогнозирования и фиксации движения биткойнов (BTC) с начала 2022 года.

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

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

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

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim

Извлечение годовых данных

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

data_2021=data.loc[data['Date'].str[:4]=="2021"]
data_2020=data.loc[data['Date'].str[:4]=="2020"]
data_2022=data.loc[data['Date'].str[:4]=="2022"]

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

Для моделирования и прогнозирования использовалась только цена Close.

Данные за 2021 год использовались для обучения модели и прогнозирования цен на 2022 год (~2 месяца)

train=data_2021['Close'].values
test=data_2022['Close'].values

Масштабирование функций

Масштабирование признаков является важным шагом в обучении моделей RNN-LSTM, поскольку обучающие данные (Цена закрытия) могут варьироваться в различных пределах и, следовательно, должны быть приведены к общему масштабу, который может интерпретировать модель.

Для вышеуказанной цели использовался класс MinMaxScaler из пакета sklearn.

in_scaler=MinMaxScaler(feature_range=(-1,1))
train=in_scaler.fit_transform(train.reshape(-1,1))
test=in_scaler.transform(test.reshape(-1,1))

Создание окон

Уникальной особенностью RNN является то, что он предсказывает предстоящие значения, обрабатывая определенное количество значений перед ним. Количество значений, предварительно обработанных моделью для прогнозирования следующего значения, называется размером окна/длиной последовательности. См. диаграмму ниже —

А ниже код (размер окна = 9)

ws=9 #window size = 9
def data_loader(train, test):
    train_seq=[]
    train_tar=[]
    test_seq=[]
    test_tar=[]
    
    for i in range(len(train)-ws):
        train_seq.append(train[i:i+ws])
        train_tar.append(train[i+ws:i+ws+1])
    for i in range(len(test)-ws):
        test_seq.append(test[i:i+ws])
        test_tar.append(test[i+ws:i+ws+1])
    return [train_seq, train_tar, test_seq, test_tar]

train_seq,train_tar, test_seq, test_tar=data_loader(train, test)
'''
Converting the arrays to Tensors
'''
train_seq=torch.Tensor(np.array(train_seq))
train_tar=torch.Tensor(np.array(train_tar)) 
test_seq=torch.Tensor(np.array(test_seq))
test_tar=torch.Tensor(np.array(test_tar))

Архитектура модели LSTM

'''
Defining hyperparameters
'''
input_size=1
hidden_dim1=1500
num_layers=2
output_size=1
'''
Defining the class
'''
class LSTM(nn.Module):
    def __init__(self, input_size, hidden_dim1, num_layers, output_size):
        super(LSTM, self).__init__()
        self.hidden_dim1=hidden_dim1
        self.num_layers=num_layers
        self.lstm1=nn.LSTM(input_size, hidden_dim1, num_layers, batch_first=True)
        self.l1=nn.Linear(hidden_dim1, output_size)
        self.relu=nn.ReLU()
        
    def forward(self, x):
        h0=torch.zeros(self.num_layers, x.size(0), self.hidden_dim1).requires_grad_() #hidden_state
        c0=torch.zeros(self.num_layers, x.size(0), self.hidden_dim1).requires_grad_() #hidden_cell
        
        
        lstm_out1,(hn,cn)=self.lstm1(x,(h0.detach(), c0.detach()))
        output=self.l1(lstm_out1[:,-1,:])
        return output


model=LSTM(input_size=input_size, hidden_dim1=hidden_dim1, num_layers=num_layers,output_size=output_size)
criterion=nn.MSELoss()
optimizer=optim.Adam(model.parameters(), lr=0.001)

MSELoss — это функция потерь для расчета потерь для каждой итерации во время обучения.

Адам используется в качестве функции оптимизатора для минимизации потерь во время обучения.

Обучение

Модель была обучена на 300 эпохах с MSELoss в качестве функции потерь и Адамом в качестве оптимизатора.

epochs=300
e_loss=[]
for epoch in range(epochs):
 
 y_pred=model(train_seq)
 loss=criterion(y_pred, train_tar)
 optimizer.zero_grad()
 loss.backward()
 optimizer.step()
 e_loss.append(loss.item())
 print('Epoch [{}/{}] Loss: {}'.format(epoch+1, epochs, loss.item()))

Тестирование

Модель была протестирована на 41 значении, все из которых соответствуют 1 января 2022 года. Ниже приведен график сравнения фактических и прогнозируемых цен.

Metricwise: оценка R2 составила 0,7551.

Заключение

Хотя модель может показаться не совсем точной (низкий показатель R2), она все же может отражать тенденцию постоянно растущего волатильного актива, что, я считаю, имеет гораздо большее значение, чем первое.

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

Счастливый мл.