Type/to search
3
Follow
1504
Followers
Jaringan Saraf dan Seri Perdagangan Kuantitatif Mata Uang Digital (1) - LSTM Memprediksi Harga Bitcoin
Discussions
Created 2019-07-12 14:28:20  Updated 2024-12-19 20:58:01
 3
 8008

img

1. Pengantar Singkat

Jaringan saraf dalam telah menjadi semakin populer dalam beberapa tahun terakhir, memecahkan masalah yang sebelumnya tidak dapat dipecahkan di banyak bidang dan menunjukkan kemampuannya yang hebat. Dalam prediksi deret waktu, harga jaringan syaraf yang umum digunakan adalah RNN, karena RNN tidak hanya memiliki input data terkini, tetapi juga input data historis. Tentu saja, ketika kita berbicara tentang RNN yang memprediksi harga, kita sering berbicara tentang jenis RNN : LSTM . Artikel ini akan membangun model untuk memprediksi harga Bitcoin berdasarkan pytorch. Meskipun ada banyak informasi relevan di Internet, itu masih belum cukup menyeluruh, dan relatif sedikit orang yang menggunakan pytorch. Tetap perlu menulis artikel. Hasil akhirnya adalah menggunakan harga pembukaan, harga penutupan, harga tertinggi, harga terendah, dan volume transaksi pasar Bitcoin. untuk memprediksi harga penutupan berikutnya. Pengetahuan pribadi saya tentang jaringan saraf rata-rata, dan saya menyambut kritik dan koreksi Anda.
Tutorial ini dibuat oleh FMZ, penemu platform perdagangan kuantitatif mata uang digital (www.fmz.com). Selamat bergabung di grup QQ: 863946592 untuk komunikasi.

2. Data dan Referensi

Contoh prediksi harga terkait: https://yq.aliyun.com/articles/538484
Pengenalan terperinci tentang model RNN: https://zhuanlan.zhihu.com/p/27485750
Memahami input dan output RNN: https://www.zhihu.com/question/41949741/answer/318771336
Tentang pytorch: Dokumentasi resmi https://pytorch.org/docs Cari sendiri informasi lainnya.
Selain itu, diperlukan beberapa pengetahuan prasyarat untuk memahami artikel ini, seperti pandas/crawler/pemrosesan data, dll., tetapi tidak masalah jika Anda tidak mengetahuinya.

3. Parameter model LSTM pytorch

Parameter LSTM:

Ketika saya pertama kali melihat parameter yang padat ini pada dokumen, reaksi saya adalah:
img
Saat saya membaca perlahan, saya akhirnya memahaminya.

img

input_size: Ukuran fitur vektor input x. Jika harga penutupan digunakan untuk memprediksi harga penutupan, maka input_size=1; jika harga penutupan diprediksi oleh harga pembukaan tertinggi dan harga penutupan terendah, maka input_size=4
hidden_size: Ukuran lapisan tersembunyi
num_layers: Jumlah lapisan RNN
batch_first: Jika Benar, dimensi input pertama adalah batch_size. Parameter ini juga sangat membingungkan dan akan dijelaskan secara rinci di bawah ini.

Parameter data masukan:

img

input: Data masukan spesifik adalah tensor tiga dimensi dengan bentuk spesifik (seq_len, batch, input_size). Di antara mereka, seq_len mengacu pada panjang urutan, yaitu, seberapa panjang data historis yang perlu dipertimbangkan LSTM. Perhatikan bahwa ini hanya mengacu pada format data, bukan struktur internal LSTM. Model LSTM yang sama dapat data input dengan seq_len yang berbeda dan dapat memberikan prediksi. Hasil; batch mengacu pada ukuran batch, yang menunjukkan berapa banyak kelompok data yang berbeda; input_size adalah input_size sebelumnya.
h_0: Keadaan tersembunyi awal, bentuknya (num_layers * num_directions, batch, hidden_size), jika merupakan jaringan dua arah num_directions=2
c_0: Keadaan sel awal, bentuknya sama seperti di atas, dapat dibiarkan tidak ditentukan.

Parameter keluaran:

img

output: Bentuk keluaran (seq_len, batch, num_directions * hidden_size), perhatikan bahwa ini terkait dengan parameter model batch_first
h_n: h state pada waktu t = seq_len, bentuknya sama dengan h_0
c_n: c state pada waktu t = seq_len, bentuknya sama dengan c_0

4. Contoh sederhana input dan output LSTM

Pertama impor paket yang diperlukan

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

Mendefinisikan model LSTM

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

Mempersiapkan data masukan

python
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]]])

Bentuk x adalah (3,4,5), karena kita mendefinisikanbatch_first=True, saat ini, batch_size adalah 3, sqe_len adalah 4, dan input_size adalah 5. X[[0] mewakili kelompok pertama.

Jika batch_first tidak didefinisikan, nilainya akan menjadi False secara default, dan data direpresentasikan secara berbeda, dengan ukuran batch 4, sqe_len 3, dan input_size 5. Pada saat ini x[[0] mewakili data semua batch pada t=0, dan seterusnya. Saya pribadi merasa bahwa pengaturan ini tidak intuitif, jadi saya menambahkan parameterbatch_first=True.

Konversi data antara keduanya juga sangat nyaman:x.permute(1,0,2)

Masukan dan Keluaran

Bentuk input dan output LSTM mudah membingungkan, dengan bantuan gambar berikut untuk membantu pemahaman:
img
Sumber: https://www.zhihu.com/question/41949741/answer/318771336

python
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])

Amati hasil keluaran yang konsisten dengan penjelasan parameter sebelumnya. Perhatikan bahwa nilai kedua hn.size() adalah 3, yang konsisten dengan ukuran batch_size, yang menunjukkan bahwa tidak ada status peralihan yang disimpan dalam hn, hanya langkah terakhir.
Karena jaringan LSTM kita memiliki dua lapisan, output dari lapisan terakhir hn sebenarnya adalah nilai output, dan bentuk outputnya adalah[3, 4, 10], menyimpan hasil semua momen t=0,1,2,3, jadi:

python
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. Siapkan data pasar Bitcoin

Banyak hal yang telah saya katakan sebelumnya hanyalah pendahuluan. Sangat penting untuk memahami input dan output LSTM. Jika tidak, akan mudah membuat kesalahan jika Anda menyalin beberapa kode dari Internet secara acak. Karena kemampuan yang hebat dari LSTM dalam deret waktu, meskipun modelnya salah, Anda bisa mendapatkannya pada akhirnya. Hasil yang bagus.

Akuisisi Data

Data yang digunakan adalah data pasar pasangan perdagangan BTC_USD dari bursa Bitfinex.

python
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 datanya adalah sebagai berikut:
img

Prapemrosesan data

python
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 sangat kasar dan akan ada beberapa masalah. Ini hanya untuk demonstrasi. Anda dapat menggunakan standarisasi data seperti yield.

Mempersiapkan data pelatihan

python
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 akhir dari train_x dan train_y adalah: torch.Size([800, 10, 5]), torch.Size([800, 10, 1]). Karena model kami memprediksi harga penutupan periode berikutnya berdasarkan data dari 10 periode, secara teoritis, 800 batch hanya memerlukan 800 harga penutupan yang diprediksi. Namun train_y memiliki 10 data dalam setiap batch. Faktanya, hasil antara dari setiap prediksi batch dipertahankan, bukan hanya yang terakhir. Saat menghitung Kerugian akhir, semua 10 hasil prediksi dapat diperhitungkan dan dibandingkan dengan nilai aktual di train_y. Secara teoritis, hanya mungkin untuk menghitung Kerugian hasil prediksi terakhir. Saya menggambar diagram kasar untuk mengilustrasikan masalah ini. Karena model LSTM sebenarnya tidak berisi parameter seq_len, model tersebut dapat diterapkan pada panjang yang berbeda, dan hasil prediksi antara juga bermakna, jadi saya cenderung menggabungkan perhitungan Loss.
img

Perlu diperhatikan bahwa saat menyiapkan data pelatihan, pergerakan jendela akan tersendat-sendat, dan data yang telah digunakan tidak lagi digunakan. Tentu saja, jendela juga dapat dipindahkan satu per satu, sehingga set pelatihan yang diperoleh akan jauh lebih besar. . Tetapi saya merasa data batch yang berdekatan terlalu berulang, jadi saya mengadopsi metode saat ini.
img

6. Membangun model LSTM

Model akhir adalah sebagai berikut, yang mencakup LSTM dua lapis dan lapisan Linear.

python
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. Mulai melatih model

Akhirnya mulai pelatihan, kodenya adalah sebagai berikut:

python
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 pelatihannya adalah sebagai berikut:
img

8. Evaluasi Model

Nilai prediksi modelnya adalah:

python
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
Seperti yang terlihat pada gambar, tingkat kecocokan data pelatihan (sebelum 800) sangat tinggi, tetapi harga Bitcoin telah naik ke titik tertinggi baru kemudian, dan model belum melihat data ini, jadi prediksinya adalah tidak dapat bekerja dengan baik. Ini juga menunjukkan adanya masalah dalam standardisasi data sebelumnya.
Meskipun harga yang diprediksi mungkin tidak akurat, seberapa akurat prediksi kenaikan dan penurunannya? Lihatlah bagian data prediksi:

python
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)))

Akurasi prediksi naik turunnya mencapai 81,4%, melebihi ekspektasi saya. Saya tidak tahu apakah saya membuat kesalahan di suatu tempat.

Tentu saja, model ini tidak memiliki nilai riil, tetapi sederhana dan mudah dipahami. Gunakan saja ini sebagai titik awal. Akan ada lebih banyak kursus pengantar tentang penerapan jaringan saraf dalam kuantifikasi mata uang digital.

Related Recommendations
Comment
All comments (3)

    训练数据和测试数据一样?

    5 years ago

    什么意思 不是很明白啊 是用800天的数据,预测下一天的数据 还是下800天的数据

    6 years ago

    为什么说此模型没有什么实盘价值?

    7 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)