Rangkaian neural yang mendalam telah menjadi semakin popular pada tahun-tahun ini dan menunjukkan keupayaan yang kuat untuk menyelesaikan masalah yang tidak dapat diselesaikan pada masa lalu di banyak bidang. Dalam ramalan urutan masa, harga rangkaian neural yang biasa digunakan adalah RNN, kerana RNN tidak hanya mempunyai input data semasa, tetapi juga input data sejarah. Sudah tentu, ketika kita bercakap tentang ramalan harga RNN, kita sering bercakap tentang jenis RNN: LSTM. Tutorial ini disediakan oleh penerbit FMZ, platform perdagangan kuantiti mata wang digital.www.fmz.com), selamat datang ke kumpulan QQ: 863946592.
Contoh ramalan harga yang berkaitan:https://yq.aliyun.com/articles/538484Maklumat lanjut mengenai model RNN:https://zhuanlan.zhihu.com/p/27485750Memahami input dan output RNN:https://www.zhihu.com/question/41949741/answer/318771336Mengenai pytorch: Dokumen Rasmihttps://pytorch.org/docsUntuk maklumat lanjut, cari sendiri. Untuk membaca artikel ini, anda juga memerlukan pengetahuan terlebih dahulu, seperti panda / reptil / pemprosesan data, tetapi tidak mengapa.
Parameter LSTM:
Apabila saya mula melihat parameter-parameter yang sangat rumit di dalam dokumen, saya berkata:Jika anda membaca dengan perlahan, anda akan dapat memahami.
input_size
: saiz ciri vektor input x, jika harga penutupan diramalkan dengan harga penutupan, maka input_size=1; jika harga penutupan diramalkan dengan harga penutupan tinggi dan rendah, maka input_size=4hidden_size
Ukuran lapisan tersirat:num_layers
: Jumlah lapisan RNNbatch_first
: Jika untuk True, parameter ini juga membingungkan jika dimensi pertama yang dimasukkan adalah batch_size, yang akan dijelaskan secara terperinci di bawah.
Parameter data input:
input
: data input tertentu, adalah tensor tiga dimensi, bentuk tertentu adalah: ((seq_len, batch, input_size)); di antaranya, panjang barisan indeks seq_len, iaitu LSTM perlu dipertimbangkan berapa lama data sejarah, perhatikan ini hanya merujuk kepada format data, bukan struktur dalaman LSTM, model LSTM yang sama boleh memasukkan data seq_len yang berbeza, semua boleh memberikan hasil yang diramalkan; ukuran batch, mewakili berapa banyak kumpulan data yang berbeza; input_size adalah input_size sebelumnya.h_0
: keadaan tersembunyi awal, berbentuk ((num_layers * num_directions, batch, hidden_size), jika pada masa kedua-dua arah rangkaian num_directions=2c_0
: Keadaan sel awal, bentuk sama, boleh tidak ditentukan.
Parameter output:
output
: bentuk output (seq_len, batch, num_directions * hidden_size), perhatian berkaitan dengan parameter model batch_firsth_n
: t = keadaan h pada saat seq_len, bentuk sama dengan h_0c_n
: t = keadaan c pada saat seq_len, bentuk sama dengan c_0
Mulakan dengan mengimport pakej yang anda perlukan
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
Menentukan model LSTM
LSTM = nn.LSTM(input_size=5, hidden_size=10, num_layers=2, batch_first=True)
Data siap untuk dimasukkan
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]]])
x mempunyai bentuk seperti ((3, 4, 5) kerana kita telah tentukan sebelum inibatch_first=True
, pada masa ini, saiz batch_size adalah 3, sqe_len adalah 4, input_size adalah 5; x[0] mewakili batch pertama.
Jika batch_first tidak ditakrifkan, dengan lalai False, maka wakil data pada masa ini adalah berbeza, saiz batch adalah 4, sqe_len adalah 3, input_size adalah 5; pada masa ini x[0] mewakili semua batch pada t = 0 data, dengan urutan yang sama. Individu merasakan bahawa tetapan ini tidak sesuai dengan intuisi, jadi parameter ditambahkan.batch_first=True
.
Pertukaran data antara kedua-duanya juga mudah:x.permute(1,0,2)
Input dan Output
Bentuk input dan output LSTM mudah keliru, dan gambar berikut dapat membantu memahami:
Sumbernya: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])
Hasil hasil yang dilihat, selaras dengan penjelasan parameter sebelumnya. Perhatikan bahawa nilai kedua untukhn.size (()) adalah 3, dan saiz batch_size selaras, menunjukkan bahawa tiada keadaan pertengahan disimpan dalamhn, hanya langkah terakhir disimpan. Oleh kerana rangkaian LSTM kami mempunyai dua lapisan, output pada lapisan terakhir adalah nilai output, output berbentuk [3, 4, 10], menyimpan hasil t = 0, 1, 2, 3 pada semua masa, jadi:
hn[-1][0] == output[0][-1] #第一个batch在hn最后一层的输出等于第一个batch在t=3时output的结果
hn[-1][1] == output[1][-1]
hn[-1][2] == output[2][-1]
Banyak perkara yang telah diceritakan di atas adalah sekadar pembukaan, memahami input dan output LSTM sangat penting, jika tidak, mudah untuk membuat kesilapan dengan mengambil beberapa kod secara rawak dari internet, kerana kemampuan kuat LSTM pada urutan masa, walaupun modelnya salah, akhirnya dapat menghasilkan hasil yang baik.
Pengambilan data
Data yang digunakan adalah data pasaran bagi pasangan dagangan BTC_USD di bursa Bitfinex.
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))
Format data adalah seperti berikut:
Pemprosesan Data
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
Pendekatan standardisasi data sangat kasar dan akan mempunyai beberapa masalah, hanya demonstrasi, standardisasi data seperti kadar pulangan boleh digunakan.
Persediaan data latihan
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))
Bentuk tren_x dan tren_y ialah: torch.Size (([800, 10, 5]), torch.Size (([800, 10, 1]) ). Oleh kerana model kami adalah untuk meramalkan harga penutupan kitaran seterusnya berdasarkan data 10 kitaran, secara teori 800 batch, selagi terdapat 800 harga penutupan yang diramalkan adalah sesuai. Tetapi tren_y mempunyai 10 data dalam setiap batch, dan sebenarnya hasil pertengahan dari setiap batch yang diramalkan dikekalkan, bukan hanya yang terakhir.
Perhatikan bahawa pergerakan tetingkap adalah melompat semasa menyediakan data latihan, data yang telah digunakan tidak lagi digunakan, dan tentu saja tetingkap juga boleh dipindahkan secara individu, yang menghasilkan kumpulan latihan yang lebih besar. Tetapi perasaan bahawa data batch berdekatan terlalu berulang, maka kaedah semasa digunakan.
Model yang akhirnya dibina adalah seperti berikut, yang mengandungi satu lapisan LSTM dua, satu lapisan 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.
Akhirnya, saya mula berlatih, kodnya seperti ini:
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()))
Hasil latihan adalah sebagai berikut:
Nilai ramalan model:
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()
Menurut grafik, kesesuaian data latihan ((sebelum 800) sangat tinggi, tetapi harga Bitcoin naik tinggi pada akhir, model tidak melihat data ini, ramalan tidak berusaha.
Walaupun harga yang diramalkan tidak semestinya tepat, bagaimana dengan keakuratannya untuk meramalkan kejatuhan?
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)))
Hasilnya adalah 81.4% atau lebih baik daripada jangkaan saya.
Sudah tentu, model ini tidak mempunyai nilai sebenar, tetapi mudah difahami, hanya dengan itu, akan ada lebih banyak kursus pengenalan aplikasi perisian neural network untuk kuantiti mata wang digital.
JackmaAdakah data latihan sama dengan data ujian?
a838899Apa yang dimaksudkan dengan data 800 hari, atau ramalan hari depan atau 800 hari akan datang?
Orion1708Bagaimana boleh model ini tidak mempunyai nilai sebenar?