Jaringan saraf yang mendalam telah menjadi semakin populer selama bertahun-tahun dan menunjukkan kemampuan yang kuat untuk memecahkan masalah yang tidak dapat diselesaikan di masa lalu di banyak bidang. Dalam peramalan urutan waktu, harga jaringan saraf yang umum digunakan adalah RNN, karena RNN tidak hanya memiliki input data saat ini, tetapi juga input data historis, tentu saja, ketika kita berbicara tentang RNN memprediksi harga, kita sering berbicara tentang jenis RNN: LSTM. Artikel ini akan didasarkan pada pytorch, membangun model untuk memprediksi harga Bitcoin. Tutorial ini disediakan oleh FMZ, pencipta platform perdagangan kuantitatif mata uang digital.www.fmz.comDi sini, saya akan berbagi beberapa tips yang bisa Anda manfaatkan untuk memulai sebuah bisnis.
Salah satu contoh yang terkait dengan prediksi harga:https://yq.aliyun.com/articles/538484Untuk lebih jelasnya tentang model RNN:https://zhuanlan.zhihu.com/p/27485750Memahami input dan output RNN:https://www.zhihu.com/question/41949741/answer/318771336Tentang pytorch: Dokumen Resmihttps://pytorch.org/docsUntuk informasi lebih lanjut, cari sendiri. Selain itu, untuk membaca artikel ini, Anda juga perlu memiliki beberapa pengetahuan sebelumnya, seperti panda / reptil / pemrosesan data, tetapi tidak masalah.
Parameter LSTM:
Ketika saya pertama kali melihat parameter-parameter yang sangat rumit di dokumen, saya berkata:Jika Anda membaca secara perlahan, Anda mungkin mengerti.
input_size
: ukuran karakteristik vektor input x, jika harga penutupan diprediksi dengan harga penutupan, maka input_size=1; jika harga penutupan diprediksi dengan harga penutupan dengan harga penutupan tinggi dan rendah, maka input_size=4hidden_size
Ukuran lapisan tersirat:num_layers
: Jumlah lapisan RNNbatch_first
: Jika untuk True, parameter pertama yang harus dimasukkan adalah batch_size, parameter ini juga bisa membingungkan, dan akan dijelaskan secara lebih rinci di bawah ini.
Parameter input data:
input
: data yang dimasukkan secara spesifik, adalah sebuah tensor tiga dimensi, dengan bentuk spesifik: ((seq_len, batch, input_size) ); di antaranya, panjang baris indeks seq_len, yaitu LSTM perlu dipertimbangkan berapa lama data historis, perhatikan bahwa ini hanya mengacu pada format data, bukan struktur dalam LSTM, model LSTM yang sama dapat memasukkan data seq_len yang berbeda, semua dapat memberikan hasil yang diprediksi; ukuran batch, mewakili berapa banyak kelompok data yang berbeda; input_size adalah input_size sebelumnya.h_0
: Keadaan hidden awal, berbentuk ((num_layers * num_directions, batch, hidden_size), jika pada saat jaringan dua arah num_directions=2c_0
: Status sel awal, bentuknya sama, tidak dapat ditentukan.
Parameter output:
output
: bentuk output (seq_len, batch, num_directions * hidden_size), perhatian terkait dengan parameter model batch_firsth_n
: t = keadaan h pada saat seq_len, bentuknya sama dengan h_0c_n
: t = keadaan c pada saat seq_len, bentuknya sama dengan c_0
Pertama, impor paket yang Anda butuhkan.
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
Mendefinisikan 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]]])
Jadi bentuk x adalah ((3, 4, 5) karena kita sudah mendefinisikan sebelumnya.batch_first=True
, ukuran batch_size saat ini adalah 3, sqe_len adalah 4, input_size adalah 5; x[0] mewakili batch pertama.
Jika tidak didefinisikan batch_first, default false, maka representasi data pada saat ini sama sekali berbeda, batch size adalah 4, sqe_len adalah 3, input_size adalah 5; saat ini x[0] mewakili semua batch data pada saat t = 0, dengan demikian, asumsi. Individu merasa pengaturan ini tidak sesuai dengan intuisi, sehingga parameter ditambahkan.batch_first=True
.
Di sisi lain, Google juga telah merilis beberapa situs web yang menawarkan berbagai macam layanan dan layanan.x.permute(1,0,2)
Input dan output
Bentuk input dan output LSTM mudah membingungkan, dan gambar berikut dapat membantu memahami:
Sumber: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 pengamatan, sesuai dengan interpretasi parameter sebelumnya. Perhatikan bahwa nilai kedua darihn.size (()) adalah 3, dan ukuran batch_size konsisten, menunjukkan bahwa dihn tidak menyimpan keadaan tengah, hanya langkah terakhir yang disimpan. Karena jaringan LSTM kami memiliki dua lapisan, output lapisan terakhir adalah nilai output, dan output berbentuk [3, 4, 10], menyimpan hasil t = 0, 1, 2, 3 untuk semua waktu, 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]
Dengan banyaknya informasi yang telah disebutkan di atas, sangat penting untuk memahami input dan output LSTM, karena jika tidak, maka mudah untuk membuat kesalahan dengan mengutip kode dari internet. Karena kemampuan kuat LSTM pada urutan waktu, bahkan jika modelnya salah, akhirnya hasil yang baik dapat diperoleh.
Mendapatkan data
Data yang digunakan adalah data pasar dari BTC_USD yang diperdagangkan 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 sebagai berikut:
Pemrosesan 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
Metode standarisasi data yang sangat kasar dan akan memiliki beberapa masalah, hanya demonstrasi, dapat digunakan untuk standarisasi data seperti tingkat laba.
Persiapkan data pelatihan
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 masing-masing adalah: torch.Size (([800, 10, 5]), torch.Size (([800, 10, 1]) ). Karena model kami adalah memprediksi harga penutupan siklus berikutnya berdasarkan data 10 siklus, secara teoritis 800 batch, selama ada 800 harga penutupan yang diprediksi, akan berhasil. Tetapi tren_y memiliki 10 data dalam setiap batch, dan sebenarnya hasil tengah dari setiap batch yang diprediksi dipertahankan, bukan hanya yang terakhir.
Perhatikan bahwa saat mempersiapkan data pelatihan, pergerakan jendela adalah melompat, data yang sudah digunakan tidak lagi digunakan, dan tentu saja jendela juga dapat bergerak secara individual, sehingga hasil pelatihan berkumpul banyak. Tetapi merasa data batch yang berdekatan terlalu berulang, maka metode saat ini digunakan.
Model yang akhirnya dibangun adalah sebagai berikut, yang berisi dua lapisan LSTM, 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.
Pada saat yang sama, saya pun mulai berlatih, dan kode yang saya gunakan adalah:
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 pelatihan adalah sebagai berikut:
Perkiraan 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, kesamaan data pelatihan (sebelum 800) sangat tinggi, tetapi harga Bitcoin naik sangat tinggi di akhir, model tidak melihat data ini, dan prediksi tidak sesuai.
Meskipun harga yang diprediksi tidak selalu akurat, bagaimana dengan harga yang diprediksi jatuh?
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% akurasi dalam memprediksi penurunan, atau lebih dari yang saya harapkan.
Tentu saja, model ini tidak memiliki nilai nyata, tetapi sederhana dan mudah dimengerti, hanya untuk memulai, dan akan ada lebih banyak kursus pengantar untuk aplikasi pengantar jejaring saraf dalam kuantitas mata uang digital di masa depan.
JackmaApakah data pelatihan sama dengan data tes?
a838899Apa yang dimaksud dengan data 800 hari, atau data 800 hari ke depan?
Orion1708Bagaimana mungkin model ini tidak memiliki nilai nyata?