Rede neural e quantificação de transações de moedas digitais série ((1) LSTM prevê o preço do Bitcoin

Autora:Ervas daninhas, Criado: 2019-07-12 14:28:20, Atualizado: 2023-10-24 21:42:00

img

1.简单介绍

As redes neurais profundas têm sido cada vez mais populares nos últimos anos e mostram poderosas capacidades para resolver problemas que não poderiam ser resolvidos no passado em muitos campos. Na previsão de séries temporais, o preço da rede neural mais comum é o RNN, porque o RNN tem não apenas a entrada de dados atuais, mas também a entrada de dados históricos. Claro, quando falamos de previsão de preços da RNN, geralmente se fala de um tipo de RNN: LSTM. Este tutorial é oferecido pela plataforma de negociação de moeda digital de quantificação FMZ.www.fmz.comO blogueiro também escreveu sobre o assunto:

2.数据和参考

Os dados do preço do Bitcoin são provenientes da plataforma de negociação quantitativa FMZ inventor:https://www.quantinfo.com/Tools/View/4.htmlO que é um exemplo de previsão de preços:https://yq.aliyun.com/articles/538484Para mais informações sobre o modelo RNN:https://zhuanlan.zhihu.com/p/27485750Compreender as entradas e saídas do RNN:https://www.zhihu.com/question/41949741/answer/318771336Sobre o pytorch: Documentos oficiaishttps://pytorch.org/docsPara mais informações, procure por conta própria. Além disso, para ler este artigo, é necessário ter algum conhecimento prévio, como pandas / répteis / processamento de dados, mas não importa.

3. Parâmetros do modelo pytorch LSTM

Parâmetros do LSTM:

A primeira vez que vi esses parâmetros no documento, minha reação foi:imgE se você lê devagar, você provavelmente entende.

img

input_size: tamanho da característica do vetor x, se o preço de fechamento for previsto no preço de fechamento, então input_size=1; se o preço de fechamento for previsto no preço de fechamento no preço de fechamento, então input_size=4hidden_sizeTamanho da camada implícita:num_layersNúmero de camadas do RNN:batch_firstSe for verdade, o primeiro parâmetro a ser inserido é batch_size, o que também pode ser confuso.

Parâmetros de entrada de dados:

img

inputOs dados especificamente inseridos são um tensor tridimensional, com a forma específica de: ((seq_len, batch, input_size) ). Dentre eles, o comprimento da seqüência de sequências seq_len, ou seja, o LSTM, precisa considerar o tempo de dados históricos. Note que isso se refere apenas ao formato dos dados, não à estrutura interna do LSTM. O mesmo modelo LSTM pode inserir dados diferentes seq_len e dar os resultados previstos.h_0: estado oculto inicial, com a forma ((num_layers * num_directions, batch, hidden_size), se a rede bidirecional num_directions=2c_0: estado inicial da célula, forma idêntica, pode não ser especificado.

Parâmetros de saída:

img

output: a forma de saída (seq_len, batch, num_directions * hidden_size), atenção e relacionada com o parâmetro do modelo batch_firsth_n: t = estado h no momento seq_len, com a mesma forma h_0c_n: t = estado c do momento seq_len, com a mesma forma de c_0

4.LSTM输入输出的简单例子

Primeiro, importa o pacote necessário.

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

Definição do modelo LSTM

LSTM = nn.LSTM(input_size=5, hidden_size=10, num_layers=2, batch_first=True)

Dados prontos para entrada

x = torch.randn(3,4,5)
# x的值为:
tensor([[[ 0.4657,  1.4398, -0.3479,  0.2685,  1.6903],
         [ 1.0738,  0.6283, -1.3682, -0.1002, -1.7200],
         [ 0.2836,  0.3013, -0.3373, -0.3271,  0.0375],
         [-0.8852,  1.8098, -1.7099, -0.5992, -0.1143]],

        [[ 0.6970,  0.6124, -0.1679,  0.8537, -0.1116],
         [ 0.1997, -0.1041, -0.4871,  0.8724,  1.2750],
         [ 1.9647, -0.3489,  0.7340,  1.3713,  0.3762],
         [ 0.4603, -1.6203, -0.6294, -0.1459, -0.0317]],

        [[-0.5309,  0.1540, -0.4613, -0.6425, -0.1957],
         [-1.9796, -0.1186, -0.2930, -0.2619, -0.4039],
         [-0.4453,  0.1987, -1.0775,  1.3212,  1.3577],
         [-0.5488,  0.6669, -0.2151,  0.9337, -1.1805]]])

A forma de x é ((3, 4, 5)), como definimos anteriormente.batch_first=TrueO tamanho do batch_size é 3, o sqe_len é 4 e o input_size é 5; x[0] representa o primeiro batch.

Se o batch_first não for definido, o padrão é Falso, então a representação dos dados neste momento é completamente diferente, o tamanho do batch é 4, o sqe_len é 3 e o input_size é 5; neste momento, x[0] representa todos os batches quando t=0 dados, em ordem de ordem.batch_first=True.

A conversão de dados entre os dois também é fácil:x.permute(1,0,2)

Importação e exportação

A forma das entradas e saídas do LSTM é facilmente confusa, e pode ser ajudada a entender com o seguinte gráfico:img
Fonte: Acompanhe o vídeohttps://www.zhihu.com/question/41949741/answer/318771336

x = torch.randn(3,4,5)
h0 = torch.randn(2, 3, 10)
c0 = torch.randn(2, 3, 10)
output, (hn, cn) = LSTM(x, (h0, c0))
print(output.size()) #在这里思考一下,如果batch_first=False输出的大小会是多少?
print(hn.size())
print(cn.size())
#结果
torch.Size([3, 4, 10])
torch.Size([2, 3, 10])
torch.Size([2, 3, 10])

Observe que o resultado da observação é consistente com a explicação do parâmetro anterior. Observe que o segundo valor dehn.size (()) é 3, e o tamanho do batch_size é consistente, indicando que não se guarda o estado intermediário nohn, apenas o último passo. Uma vez que a nossa rede LSTM tem duas camadas, a última camada de saída é o valor da saída, que tem a forma de [3, 4, 10], e guarda o resultado de t = 0, 1, 2, 3 em todos os momentos, então:

hn[-1][0] == output[0][-1] #第一个batch在hn最后一层的输出等于第一个batch在t=3时output的结果
hn[-1][1] == output[1][-1]
hn[-1][2] == output[2][-1]

5.准备比特币行情数据

O que foi dito antes é apenas um passo, e é importante entender a entrada e saída do LSTM, caso contrário, é fácil errar ao extrair qualquer código da internet, porque o LSTM tem uma capacidade poderosa na sequência de tempo, mesmo que o modelo esteja errado, pode resultar em bons resultados.

Obtenção de dados

Os dados usados são dados de mercado do par BTC_USD da Bitfinex.

import requests
import json

resp = requests.get('https://www.quantinfo.com/API/m/chart/history?symbol=BTC_USD_BITFINEX&resolution=60&from=1525622626&to=1562658565')
data = resp.json()
df = pd.DataFrame(data,columns = ['t','o','h','l','c','v'])
print(df.head(5))

O formato de dados é o seguinte:img

Preprocessamento de dados

df.index = df['t'] # index设为时间戳
df = (df-df.mean())/df.std() # 数据的标准化,否则模型的Loss会非常大,不利于收敛
df['n'] = df['c'].shift(-1) # n为下一个周期的收盘价,是我们预测的目标
df = df.dropna()
df = df.astype(np.float32) # 改变下数据格式适应pytorch

O método de padronização de dados é muito grosseiro e pode ter alguns problemas, mas apenas uma demonstração pode ser usada para padronizar dados como o rendimento.

Preparação de dados de treinamento

seq_len = 10 # 输入10个周期的数据
train_size = 800 # 训练集batch_size
def create_dataset(data, seq_len):
    dataX, dataY=[], []
    for i in range(0,len(data)-seq_len, seq_len):
        dataX.append(data[['o','h','l','c','v']][i:i+seq_len].values)
        dataY.append(data['n'][i:i+seq_len].values)
    return np.array(dataX), np.array(dataY)
data_X, data_Y = create_dataset(df, seq_len)
train_x = torch.from_numpy(data_X[:train_size].reshape(-1,seq_len,5)) #变化形状,-1代表的值会自动计算
train_y = torch.from_numpy(data_Y[:train_size].reshape(-1,seq_len,1))

Os modelos final train_x e train_y têm as seguintes formas: torch.Size (([800, 10, 5]), torch.Size (([800, 10, 1]) ). Como o nosso modelo prevê o preço de fechamento do próximo ciclo com base em 10 ciclos de dados, 800 lotes, teoricamente, são suficientes para 800 preços de fechamento previstos. Mas o train_y tem 10 dados em cada lote, e na verdade, o resultado intermediário da previsão de cada lote é reservado, não apenas o último. No cálculo do final Loss, todos os 10 resultados de previsão podem ser considerados e comparados com o valor real no train_y.img

Observe que a movimentação das janelas é salto quando se prepara os dados de treinamento, os dados já usados não são mais usados, e, claro, as janelas também podem ser movidas individualmente, o que resulta em um grande conjunto de treinamentos.img

6.构造LSTM模型

O modelo final foi construído da seguinte forma, contendo uma camada LSTM de duas camadas e uma camada Linear.

class LSTM(nn.Module):
    def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):
        super(LSTM, self).__init__()
        self.rnn = nn.LSTM(input_size,hidden_size,num_layers,batch_first=True)
        self.reg = nn.Linear(hidden_size,output_size) # 线性层,把LSTM的结果输出成一个值

    def forward(self, x):
        x, _ = self.rnn(x) # 如果不理解前向传播中数据维度的变化,可单独调试
        x = self.reg(x)
        return x
        
net = LSTM(5, 10) # input_size为5,代表了高开低收和交易量. 隐含层为10.

7.开始训练模型

A partir de então, o treinamento começou e o código é o seguinte:

criterion = nn.MSELoss() # 使用了简单的均方差损失函数
optimizer = torch.optim.Adam(net.parameters(),lr=0.01) # 优化函数,lr可调
for epoch in range(600): # 由于速度很快,这里的epoch多一些
    out = net(train_x) # 由于数据量很小, 直接拿全量数据计算
    loss = criterion(out, train_y)
    optimizer.zero_grad()
    loss.backward() # 反向传播损失
    optimizer.step() # 更新参数
    print('Epoch: {:<3}, Loss:{:.6f}'.format(epoch+1, loss.item()))

Os resultados do treinamento são os seguintes:img

8.模型评价

O modelo prevê:

p = net(torch.from_numpy(data_X))[:,-1,0] # 这里只取最后一个预测值作为比较
plt.figure(figsize=(12,8))
plt.plot(p.data.numpy(), label= 'predict')
plt.plot(data_Y[:,-1], label = 'real')
plt.legend()
plt.show()

img
Como pode ser visto no gráfico, os dados de treinamento (antes de 800) têm uma grande coincidência, mas o preço do Bitcoin subiu muito no final, o modelo não viu esses dados e a previsão não foi tomada em consideração. Isso também mostra que há problemas na padronização dos dados anteriores. A previsão de preços não é sempre exata, mas o que acontece com a previsão de um declínio?

r = data_Y[:,-1][800:1000]
y = p.data.numpy()[800:1000]
r_change = np.array([1 if i > 0 else 0 for i in r[1:200] - r[:199]])
y_change = np.array([1 if i > 0 else 0 for i in y[1:200] - r[:199]])
print((r_change == y_change).sum()/float(len(r_change)))

O resultado foi de 81,4% de precisão na previsão da queda, ou melhor do que eu esperava.

É claro que este modelo não tem nenhum valor real, mas é simples e fácil de entender, apenas para introduzir, em seguida, mais cursos de introdução a aplicações de redes neurais para quantificação de moeda digital.


Relacionados

Mais.

JackmaOs dados do treinamento são os mesmos que os dados do teste?

a838899O que isso significa não é muito claro, se você está usando dados de 800 dias para prever os dados do dia seguinte ou os próximos 800 dias.

Orion1708Como é que o modelo não tem valor real?