Sumber daya yang dimuat... Pemuatan...

Serial transaksi kuantitatif jaringan saraf dan mata uang digital ((1) LSTM memprediksi harga Bitcoin

Penulis:Rumput, Dibuat: 2019-07-12 14:28:20, Diperbarui: 2024-05-15 14:45:30

img

1.简单介绍

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.

2.数据和参考

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 dari model pytorch LSTM

Parameter LSTM:

Ketika saya pertama kali melihat parameter-parameter yang sangat rumit di dokumen, saya berkata:imgJika Anda membaca secara perlahan, Anda mungkin mengerti.

img

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_sizeUkuran 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:

img

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:

img

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

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

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:img
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]

5.准备比特币行情数据

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:img

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.img

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.img

6.构造LSTM模型

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.

7.开始训练模型

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:img

8.模型评价

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

img
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.


Berkaitan

Lebih banyak

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?