Meningkatkan agen Q-Learning berbasis saham dengan menambahkan perulangan dan penghargaan

Pengingat


Halo, Habr! Saya memberi perhatian Anda terjemahan lain dari artikel baru saya dari media .

Terakhir kali ( artikel pertama ) ( Habr ), kami menciptakan agen menggunakan teknologi Q-Learning, yang melakukan transaksi pada rangkaian waktu simulasi dan pertukaran riil dan mencoba memeriksa apakah bidang tugas ini cocok untuk pembelajaran yang diperkuat.

Kali ini kami akan menambahkan layer LSTM untuk memperhitungkan dependensi waktu akun dalam lintasan dan melakukan teknik pembentukan hadiah berdasarkan presentasi.

gambar

Biarkan saya mengingatkan Anda bahwa untuk memverifikasi konsep, kami menggunakan data sintetis berikut:

gambar

Data sintetis: sinus dengan noise putih.

Fungsi sinus adalah titik awal pertama. Dua kurva mensimulasikan harga pembelian dan penjualan suatu aset, di mana spread adalah biaya transaksi minimum.

Namun, kali ini kami ingin menyulitkan tugas sederhana ini dengan memperluas jalur penugasan kredit:

gambar

Data sintetis: sinus dengan noise putih.

Fase sinus digandakan.

Ini berarti bahwa hadiah jarang yang kami gunakan harus tersebar di lintasan yang lebih panjang. Selain itu, kami secara signifikan mengurangi kemungkinan menerima hadiah positif, karena agen harus melakukan serangkaian tindakan yang benar 2 kali lebih lama untuk mengatasi biaya transaksi. Kedua faktor tersebut sangat menyulitkan tugas RL bahkan dalam kondisi sederhana seperti gelombang sinus.

Selain itu, kami ingat bahwa kami menggunakan arsitektur jaringan saraf ini:

gambar

Apa yang ditambahkan dan mengapa


Lstm


Pertama-tama, kami ingin memberi agen lebih banyak pemahaman tentang dinamika perubahan dalam lintasan. Sederhananya, agen harus lebih memahami perilakunya sendiri: apa yang dia lakukan sekarang dan untuk beberapa waktu di masa lalu, dan bagaimana distribusi tindakan negara, serta imbalan yang diterima, dikembangkan. Menggunakan layer perulangan dapat memecahkan masalah ini dengan tepat. Selamat datang di arsitektur baru yang digunakan untuk meluncurkan serangkaian eksperimen baru:

gambar

Harap perhatikan bahwa deskripsi saya sedikit ditingkatkan. Satu-satunya perbedaan dari NN lama adalah lapisan LSTM pertama yang tersembunyi dan bukan yang sepenuhnya terikat.

Harap dicatat bahwa dengan LSTM dalam pekerjaan, kita harus mengubah pemilihan contoh reproduksi pengalaman untuk pelatihan: sekarang kita membutuhkan urutan transisi daripada contoh yang terpisah. Begini cara kerjanya (ini adalah salah satu algoritma). Kami menggunakan point sampling sebelum:

gambar

Skema fiktif dari buffer pemutaran.

Kami menggunakan skema ini dengan LSTM:

gambar

Sekarang urutan dipilih (yang panjangnya kita tentukan secara empiris).

Seperti sebelumnya, dan sekarang sampel diatur oleh algoritma prioritas berdasarkan kesalahan pembelajaran temporal-temporal.

Level rekurensi LSTM memungkinkan penyebaran informasi secara langsung dari deret waktu untuk mencegat sinyal tambahan yang tersembunyi di jeda waktu lalu. Rangkaian waktu bersama kami adalah tensor dua dimensi dengan ukuran: panjang urutan pada representasi tindakan negara kami.

Presentasi


Rekayasa pemenang penghargaan, Potential Based Reward Shaping (PBRS), berdasarkan potensi, adalah alat yang ampuh yang memungkinkan Anda untuk meningkatkan kecepatan, stabilitas dan tidak melanggar optimalitas proses pencarian kebijakan untuk menyelesaikan masalah lingkungan kita. Saya sarankan membaca setidaknya dokumen asli ini dengan topik:

people.eecs.berkeley.edu/~russell/papers/ml99-shaping.ps

Potensi menentukan seberapa baik keadaan kita saat ini relatif terhadap keadaan target yang ingin kita masukkan. Pandangan skematis tentang cara kerjanya:

gambar

Ada beberapa opsi dan kesulitan yang bisa Anda pahami setelah coba-coba, dan kami menghilangkan detail ini, meninggalkan Anda dengan pekerjaan rumah Anda.

Perlu disebutkan satu hal lagi, yaitu PBRS dapat dibenarkan menggunakan presentasi, yang merupakan bentuk pengetahuan ahli (atau simulasi) tentang perilaku agen yang hampir optimal di lingkungan. Ada cara untuk menemukan presentasi seperti itu untuk tugas kami menggunakan skema optimisasi. Kami menghilangkan detail pencarian.

Potensi hadiah berupa: (persamaan 1):

r '= r + gamma * F (s') - F (s)

di mana F adalah potensi negara, dan r adalah hadiah awal, gamma adalah faktor diskon (0: 1).

Dengan pemikiran ini, kami beralih ke pengkodean.

Implementasi dalam R
Berikut adalah kode jaringan saraf berdasarkan API Keras:

Kode
# configure critic NN — — — — — — library('keras') library('R6') state_names_length <- 12 # just for example lstm_seq_length <- 4 learning_rate <- 1e-3 a_CustomLayer <- R6::R6Class( “CustomLayer” , inherit = KerasLayer , public = list( call = function(x, mask = NULL) { x — k_mean(x, axis = 2, keepdims = T) } ) ) a_normalize_layer <- function(object) { create_layer(a_CustomLayer, object, list(name = 'a_normalize_layer')) } v_CustomLayer <- R6::R6Class( “CustomLayer” , inherit = KerasLayer , public = list( call = function(x, mask = NULL) { k_concatenate(list(x, x, x), axis = 2) } , compute_output_shape = function(input_shape) { output_shape = input_shape output_shape[[2]] <- input_shape[[2]] * 3L output_shape } ) ) v_normalize_layer <- function(object) { create_layer(v_CustomLayer, object, list(name = 'v_normalize_layer')) } noise_CustomLayer <- R6::R6Class( “CustomLayer” , inherit = KerasLayer , lock_objects = FALSE , public = list( initialize = function(output_dim) { self$output_dim <- output_dim } , build = function(input_shape) { self$input_dim <- input_shape[[2]] sqr_inputs <- self$input_dim ** (1/2) self$sigma_initializer <- initializer_constant(.5 / sqr_inputs) self$mu_initializer <- initializer_random_uniform(minval = (-1 / sqr_inputs), maxval = (1 / sqr_inputs)) self$mu_weight <- self$add_weight( name = 'mu_weight', shape = list(self$input_dim, self$output_dim), initializer = self$mu_initializer, trainable = TRUE ) self$sigma_weight <- self$add_weight( name = 'sigma_weight', shape = list(self$input_dim, self$output_dim), initializer = self$sigma_initializer, trainable = TRUE ) self$mu_bias <- self$add_weight( name = 'mu_bias', shape = list(self$output_dim), initializer = self$mu_initializer, trainable = TRUE ) self$sigma_bias <- self$add_weight( name = 'sigma_bias', shape = list(self$output_dim), initializer = self$sigma_initializer, trainable = TRUE ) } , call = function(x, mask = NULL) { #sample from noise distribution e_i = k_random_normal(shape = list(self$input_dim, self$output_dim)) e_j = k_random_normal(shape = list(self$output_dim)) #We use the factorized Gaussian noise variant from Section 3 of Fortunato et al. eW = k_sign(e_i) * (k_sqrt(k_abs(e_i))) * k_sign(e_j) * (k_sqrt(k_abs(e_j))) eB = k_sign(e_j) * (k_abs(e_j) ** (1/2)) #See section 3 of Fortunato et al. noise_injected_weights = k_dot(x, self$mu_weight + (self$sigma_weight * eW)) noise_injected_bias = self$mu_bias + (self$sigma_bias * eB) output = k_bias_add(noise_injected_weights, noise_injected_bias) output } , compute_output_shape = function(input_shape) { output_shape <- input_shape output_shape[[2]] <- self$output_dim output_shape } ) ) noise_add_layer <- function(object, output_dim) { create_layer( noise_CustomLayer , object , list( name = 'noise_add_layer' , output_dim = as.integer(output_dim) , trainable = T ) ) } critic_input <- layer_input( shape = list(NULL, as.integer(state_names_length)) , name = 'critic_input' ) common_lstm_layer <- layer_lstm( units = 20 , activation = “tanh” , recurrent_activation = “hard_sigmoid” , use_bias = T , return_sequences = F , stateful = F , name = 'lstm1' ) critic_layer_dense_v_1 <- layer_dense( units = 10 , activation = “tanh” ) critic_layer_dense_v_2 <- layer_dense( units = 5 , activation = “tanh” ) critic_layer_dense_v_3 <- layer_dense( units = 1 , name = 'critic_layer_dense_v_3' ) critic_layer_dense_a_1 <- layer_dense( units = 10 , activation = “tanh” ) # critic_layer_dense_a_2 <- layer_dense( # units = 5 # , activation = “tanh” # ) critic_layer_dense_a_3 <- layer_dense( units = length(actions) , name = 'critic_layer_dense_a_3' ) critic_model_v <- critic_input %>% common_lstm_layer %>% critic_layer_dense_v_1 %>% critic_layer_dense_v_2 %>% critic_layer_dense_v_3 %>% v_normalize_layer critic_model_a <- critic_input %>% common_lstm_layer %>% critic_layer_dense_a_1 %>% #critic_layer_dense_a_2 %>% noise_add_layer(output_dim = 5) %>% critic_layer_dense_a_3 %>% a_normalize_layer critic_output <- layer_add( list( critic_model_v , critic_model_a ) , name = 'critic_output' ) critic_model_1 <- keras_model( inputs = critic_input , outputs = critic_output ) critic_optimizer = optimizer_adam(lr = learning_rate) keras::compile( critic_model_1 , optimizer = critic_optimizer , loss = 'mse' , metrics = 'mse' ) train.x <- array_reshape(rnorm(10 * lstm_seq_length * state_names_length) , dim = c(10, lstm_seq_length, state_names_length) , order = 'C') predict(critic_model_1, train.x) layer_name <- 'noise_add_layer' intermediate_layer_model <- keras_model(inputs = critic_model_1$input, outputs = get_layer(critic_model_1, layer_name)$output) predict(intermediate_layer_model, train.x)[1,] critic_model_2 <- critic_model_1 


Men-debug keputusan Anda berdasarkan hati nurani Anda ...

Hasil dan Perbandingan


Mari selami hasil akhirnya. Catatan: semua hasil adalah estimasi titik dan mungkin berbeda pada beberapa kali berjalan dengan berbagai sids seed acak.

Perbandingan meliputi:

  • versi sebelumnya tanpa LSTM dan presentasi
  • LSTM 2-elemen sederhana
  • LSTM 4-elemen
  • LSTM 4 sel dengan imbalan PBRS yang dihasilkan

gambar

Pengembalian rata-rata per episode rata-rata lebih dari 1000 episode.

gambar

Total episode kembali.

Bagan untuk agen paling sukses:

gambar

gambar

Kinerja agen.

Yah, cukup jelas bahwa agen dalam bentuk PBRS bertemu begitu cepat dan stabil dibandingkan dengan upaya sebelumnya sehingga dapat diterima sebagai hasil yang signifikan. Kecepatannya sekitar 4-5 kali lebih tinggi daripada tanpa presentasi. Stabilitas luar biasa.

Ketika menggunakan LSTM, 4 sel memiliki kinerja lebih baik dari 2 sel. LSTM 2 sel tampil lebih baik daripada versi non-LSTM (namun, mungkin ini adalah ilusi dari satu percobaan).

Kata-kata terakhir


Kita telah melihat bahwa penghargaan yang berulang dan pembangunan kapasitas membantu. Saya terutama menyukai kinerja PBRS yang sangat tinggi.

Jangan percaya siapa pun yang membuat saya mengatakan bahwa mudah untuk membuat agen RL yang menyatu dengan baik, karena itu bohong. Setiap komponen baru yang ditambahkan ke sistem membuatnya berpotensi kurang stabil dan membutuhkan banyak konfigurasi dan debugging.

Namun demikian, ada bukti jelas bahwa solusi untuk masalah tersebut dapat diperbaiki hanya dengan meningkatkan metode yang digunakan (data tetap utuh). Adalah fakta bahwa untuk tugas apa pun sejumlah parameter tertentu berfungsi lebih baik daripada yang lain. Dengan pemikiran ini, Anda memulai jalur pembelajaran yang sukses.

Terima kasih

Source: https://habr.com/ru/post/id436628/


All Articles