Tief-Neural-Netzwerke sind in den letzten Jahren immer beliebter geworden und haben in vielen Bereichen eine starke Fähigkeit gezeigt, Schwierigkeiten zu lösen, die in der Vergangenheit nicht gelöst werden konnten. Bei der Vorhersage von Zeitreihen ist der gebräuchliche Neural-Netzwerkpreis RNN, da RNN nicht nur aktuelle Dateneingaben, sondern auch historische Dateneingaben enthält. Natürlich wird oft von einer Art von RNN gesprochen, wenn wir über RNN-Preisvorhersagen sprechen: LSTM. Dieses Tutorial wird von FMZ, der Erfinder der digitalen Währung, zur Verfügung gestellt.www.fmz.comSie können sich auch an die Seite der QQ-Gruppe 863946592 wenden.
Ein Beispiel für eine entsprechende Preisvorhersage:https://yq.aliyun.com/articles/538484Ein weiteres Detail zum RNN-Modell:https://zhuanlan.zhihu.com/p/27485750Die Eingaben und Ausgänge von RNN zu verstehen:https://www.zhihu.com/question/41949741/answer/318771336Über pytorch: offizielle Dokumentationhttps://pytorch.org/docsSie können sich selbst nach weiteren Informationen umsehen. Außerdem benötigen Sie einige Vorkenntnisse, wie Pandas/Reptilien/Datenverarbeitung, aber das ist nicht wichtig.
Die Parameter des LSTM:
Als ich zum ersten Mal diese verblendeten Parameter in der Dokumentation sah, sagte ich:Wenn man es langsam liest, dann versteht man es wahrscheinlich.
input_size
: Eigenschaftsgröße des Eingabevektors x, wenn der Schlusspreis mit dem Schlusspreis prognostiziert wird, dann input_size=1; wenn der Schlusspreis mit dem Schlusspreis mit dem Schlusspreis mit dem Schlusspreis mit dem Schlusspreis mit dem Schlusspreis mit dem Schlusspreis prognostiziert wird, dann input_size=4hidden_size
Die Größe der impliziten Schichten:num_layers
: Anzahl der Schichten der RNNbatch_first
: ist auch verwirrend, wenn die erste Dimension, die für True eingegeben wird, batch_size ist, was im Folgenden erläutert wird.
Einfüge Datenparameter:
input
: die spezifischen Eingabedaten sind ein dreidimensionaler Tensor, die spezifischen Formen sind: ((seq_len, batch, input_size) ). Hierbei ist die Länge der Seq_len-Indexreihe, d.h. LSTM, zu berücksichtigen, wie lange die historischen Daten sind. Beachten Sie, dass dies nur das Format der Daten und nicht die Struktur des LSTM ist.h_0
: der ursprüngliche Hidden-Zustand, mit der Form ((num_layers * num_directions, batch, hidden_size), wenn das BIP-Netzwerk num_directions=2 istc_0
: Anfangs-Zell-Zustand, gleiche Form, kann nicht angegeben werden.
Ausgabeparameter:
output
: Ausgabe der Form (seq_len, batch, num_directions * hidden_size), die mit dem Modellparameter batch_first verbunden isth_n
: t = seq_len Moment h-Zustand, in der gleichen Form wie h_0c_n
: t = Zustand c im Augenblick seq_len, in der gleichen Form wie c_0
Zuerst importieren Sie die Pakete, die Sie benötigen.
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
Definition des LSTM-Modells
LSTM = nn.LSTM(input_size=5, hidden_size=10, num_layers=2, batch_first=True)
Daten bereit zur Eingabe
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]]])
Und das ist die Form von x, die wir definiert haben, wie wir es definiert haben.batch_first=True
, die Batch_size ist 3, sqe_len 4, input_size 5; x[0] stellt das erste Batch dar.
Wenn batch_first nicht definiert ist, ist der Standardfall False, dann ist die Repräsentation der Daten in diesem Fall völlig anders, die Batch-Größe ist 4, sqe_len ist 3, input_size ist 5; x[0] repräsentiert alle Batches bei t=0 Daten, also in der Reihenfolge.batch_first=True
.
Es ist auch sehr einfach, Daten zwischen beiden zu wechseln:x.permute(1,0,2)
Eingabe und Ausgabe
Die Form der LSTM-Eingabe-Ausgabe kann leicht verwirrend sein.
Quelle:https://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])
Die Ergebnisse der beobachteten Ausgabe stimmen mit der Erklärung der vorherigen Parameter überein. Beachten Sie, dass der zweite Wert vonhn.size ((() 3 ist und die Batch_size-Größe übereinstimmt, was bedeutet, dass kein Zwischenstand in hn gespeichert wird, sondern nur der letzte Schritt. Da unser LSTM-Netzwerk zwei Ebenen hat, ist die Ausgabe der letzten Ebene ein Wert des Outputs, der in der Form [3, 4, 10] ist und die Ergebnisse von t = 0, 1, 2, 3 für alle Zeiten speichert, also:
hn[-1][0] == output[0][-1] #第一个batch在hn最后一层的输出等于第一个batch在t=3时output的结果
hn[-1][1] == output[1][-1]
hn[-1][2] == output[2][-1]
Es ist wichtig, die Eingaben und Ausgänge von LSTM zu verstehen, da es aufgrund der starken Fähigkeiten von LSTM in Bezug auf die Zeitreihen möglich ist, auch wenn das Modell falsch ist, schließlich gute Ergebnisse zu erzielen.
Die Datenerfassung
Die Daten werden von der Börse Bitfinex für das BTC_USD-Paar verwendet.
import requests
import json
resp = requests.get('https://q.fmz.com/chart/history?symbol=bitfinex.btc_usd&resolution=15&from=0&to=0&from=1525622626&to=1562658565')
data = resp.json()
df = pd.DataFrame(data,columns = ['t','o','h','l','c','v'])
print(df.head(5))
Die Daten sind in folgenden Formaten:
Vorbearbeitung der Daten
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
Die Methode zur Standardisierung der Daten ist sehr grob, es gibt einige Probleme, nur eine Demonstration, die mit der Standardisierung von Daten wie Ertragsraten durchgeführt werden kann.
Bereitstellung von Trainingsdaten
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))
Die Formen der endgültigen train_x und train_y sind: torch.Size (([800, 10, 5]), torch.Size (([800, 10, 1]) ). Weil unser Modell die Schlusspreise für den nächsten Zyklus mit Daten aus 10 Zyklen prognostiziert, sind theoretisch 800 Batches möglich, solange es 800 prognostizierte Schlusspreise gibt. Aber train_y hat 10 Daten pro Batch und in der Tat ist das mittlere Ergebnis der Prognose für jede Batch behalten, nicht nur das letzte.
Beachten Sie, dass bei der Vorbereitung der Trainingsdaten die Bewegung der Fenster sprunghaft ist, dass die Daten, die bereits verwendet wurden, nicht mehr verwendet werden, und dass die Fenster natürlich auch einzeln bewegt werden können.
Die endgültig gebaute Modell besteht aus einer zweischichtigen LSTM und einer Linear-Schicht.
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.
Ich habe mich in meinem eigenen Land niedergelassen, wo ich in den USA lebte, und ich habe mich in den USA niedergelassen.
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()))
Die Ergebnisse der Ausbildung sind folgende:
Das Modell prognostiziert:
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()
Wie man anhand der Abbildung sehen kann, ist die Übereinstimmung der Trainingsdaten (vor 800) sehr hoch, aber der Bitcoin-Preis stieg in letzter Zeit, das Modell hat diese Daten nicht gesehen und die Prognose ist nicht zufriedenstellend.
Obwohl die prognostizierten Preise nicht unbedingt korrekt sind, wie ist die Prognose für einen Einbruch der Preise?
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)))
Das Ergebnis war 81,4 Prozent genauer als erwartet. Ich weiß nicht, ob ich etwas falsch gemacht habe.
Natürlich ist dieses Modell nicht von praktischem Wert, aber es ist einfach zu verstehen, und nur damit werden weitere Einführungskurse in Quantitative Neural Networks für digitale Währungen angeboten.
JackmaDie Daten aus dem Training sind die gleichen wie die Daten aus dem Test.
a838899Was das bedeutet, ist nicht ganz klar, ob man die Daten von 800 Tagen benutzt, um die nächsten Tage vorherzusagen, oder die nächsten 800 Tage.
Orion 1708Wie kann man sagen, dass dieses Modell keinen tatsächlichen Wert hat?