Schooling Flappy Bird: Tutorial Pembelajaran Penguatan

Diterbitkan: 2022-03-11

Dalam pemrograman klasik, instruksi perangkat lunak secara eksplisit dibuat oleh programmer dan tidak ada yang dipelajari dari data sama sekali. Sebaliknya, pembelajaran mesin adalah bidang ilmu komputer yang menggunakan metode statistik untuk memungkinkan komputer belajar dan mengekstrak pengetahuan dari data tanpa diprogram secara eksplisit.

Dalam tutorial pembelajaran penguatan ini, saya akan menunjukkan bagaimana kita dapat menggunakan PyTorch untuk mengajarkan jaringan saraf pembelajaran penguatan cara bermain Flappy Bird. Tapi pertama-tama, kita perlu membahas sejumlah blok bangunan.

Algoritme pembelajaran mesin secara kasar dapat dibagi menjadi dua bagian: Algoritme pembelajaran tradisional dan algoritme pembelajaran mendalam. Algoritme pembelajaran tradisional biasanya memiliki lebih sedikit parameter yang dapat dipelajari daripada algoritme pembelajaran mendalam dan memiliki kapasitas belajar yang jauh lebih sedikit.

Juga, algoritma pembelajaran tradisional tidak dapat melakukan ekstraksi fitur : Spesialis kecerdasan buatan perlu mencari representasi data yang baik yang kemudian dikirim ke algoritma pembelajaran. Contoh teknik pembelajaran mesin tradisional termasuk SVM, hutan acak, pohon keputusan, dan $k$-means, sedangkan algoritme sentral dalam pembelajaran mendalam adalah jaringan saraf dalam .

Masukan ke jaringan saraf dalam dapat berupa gambar mentah, dan spesialis kecerdasan buatan tidak perlu menemukan representasi data apa pun—jaringan saraf menemukan representasi terbaik selama proses pelatihan.

Banyak teknik pembelajaran mendalam telah dikenal sejak lama, tetapi kemajuan terbaru dalam perangkat keras dengan cepat mendorong penelitian dan pengembangan pembelajaran mendalam. Nvidia bertanggung jawab atas perluasan bidang karena GPU-nya telah memungkinkan eksperimen pembelajaran mendalam yang cepat.

Parameter dan Hyperparameter yang Dapat Dipelajari

Algoritma pembelajaran mesin terdiri dari parameter yang dapat dipelajari yang disetel dalam proses pelatihan dan parameter yang tidak dapat dipelajari yang ditetapkan sebelum proses pelatihan. Parameter yang ditetapkan sebelum pembelajaran disebut hyperparameters .

Pencarian grid adalah metode umum untuk menemukan hyperparameter yang optimal. Ini adalah metode brute force: Ini berarti mencoba semua kemungkinan kombinasi hyperparameter pada rentang yang ditentukan dan memilih kombinasi yang memaksimalkan metrik yang telah ditentukan.

Algoritma Pembelajaran Diawasi, Tanpa Pengawasan, dan Penguatan

Salah satu cara untuk mengklasifikasikan algoritma pembelajaran adalah menarik garis antara algoritma diawasi dan tidak diawasi. (Tapi itu tidak selalu langsung: Pembelajaran penguatan terletak di antara kedua jenis ini.)

Ketika kita berbicara tentang pembelajaran yang diawasi, kita melihat pasangan $ (x_i, y_i) $. $ x_i $ adalah input algoritma dan $ y_i $ adalah outputnya. Tugas kita adalah menemukan fungsi yang akan melakukan pemetaan yang benar dari $x_i $ ke $y_i $.

Untuk menyetel parameter yang dapat dipelajari sehingga mereka mendefinisikan fungsi yang memetakan $ x_i $ ke $ y_i $, fungsi kerugian dan pengoptimal perlu didefinisikan. Pengoptimal meminimalkan fungsi kerugian. Salah satu contoh fungsi kerugian adalah mean squared error (MSE):

\[MSE = \sum_{i=1}^{n} (y_i - \widehat{y_i} )^2\]

Di sini, $ y_i $ adalah label kebenaran dasar dan $ \widehat{y_i} $ adalah label prediksi. Salah satu pengoptimal yang sangat populer dalam pembelajaran mendalam adalah penurunan gradien stokastik . Ada banyak variasi yang mencoba untuk memperbaiki metode penurunan gradien stokastik: Adam, Adadelta, Adagrad, dan sebagainya.

Algoritme tanpa pengawasan mencoba menemukan struktur dalam data tanpa diberi label secara eksplisit. $k$-means adalah salah satu contoh algoritma unsupervised yang mencoba menemukan cluster optimal dalam data. Di bawah ini adalah gambar dengan 300 titik data. $k$-means algoritma menemukan struktur dalam data dan menetapkan label cluster untuk setiap titik data. Setiap cluster memiliki warna tersendiri.

Cluster titik data yang terbagi warna. Cluster ditemukan oleh algoritma yang tidak diawasi

Pembelajaran penguatan menggunakan penghargaan: Label yang jarang dan tertunda waktu. Seorang agen mengambil tindakan, yang mengubah lingkungan, dari mana ia bisa mendapatkan pengamatan dan penghargaan baru. Observasi adalah stimulus yang dirasakan agen dari lingkungan. Bisa berupa apa yang dilihat, didengar, dicium oleh agen, dan sebagainya.

Hadiah diberikan kepada agen saat melakukan tindakan. Ini memberi tahu agen seberapa bagus tindakannya. Dengan mengamati pengamatan dan penghargaan, seorang agen belajar bagaimana berperilaku optimal di lingkungan. Saya akan membahasnya lebih detail di bawah ini.

Pembelajaran Penguatan Aktif, Pasif, dan Terbalik

Ada beberapa pendekatan berbeda untuk teknik ini. Pertama-tama, ada pembelajaran penguatan aktif, yang kami gunakan di sini. Sebaliknya, ada pembelajaran penguatan pasif, di mana penghargaan hanyalah jenis pengamatan lain, dan keputusan dibuat sesuai dengan kebijakan tetap.

Akhirnya, pembelajaran penguatan terbalik mencoba merekonstruksi fungsi penghargaan mengingat sejarah tindakan dan imbalannya di berbagai keadaan.

Generalisasi, Overfitting, dan Underfitting

Setiap instance tetap dari parameter dan hyperparameter disebut model. Eksperimen pembelajaran mesin biasanya terdiri dari dua bagian: Pelatihan dan pengujian.

Selama proses pelatihan, parameter yang dapat dipelajari disetel menggunakan data pelatihan. Dalam proses pengujian, parameter yang dapat dipelajari dibekukan, dan tugasnya adalah memeriksa seberapa baik model membuat prediksi pada data yang sebelumnya tidak terlihat. Generalisasi adalah kemampuan mesin pembelajaran untuk melakukan secara akurat pada contoh atau tugas baru yang tidak terlihat setelah mengalami kumpulan data pembelajaran.

Jika model terlalu sederhana dalam kaitannya dengan data, model tersebut tidak akan dapat menyesuaikan dengan data pelatihan dan akan berkinerja buruk baik pada dataset pelatihan maupun dataset pengujian. Dalam hal ini, kita katakan modelnya kurang pas .

Jika model pembelajaran mesin berperforma baik pada set data pelatihan, tetapi buruk pada set data pengujian, kami mengatakan bahwa model tersebut overfitting . Overfitting adalah situasi di mana model terlalu kompleks sehubungan dengan data. Ini dapat dengan sempurna menyesuaikan data pelatihan, tetapi sangat disesuaikan dengan dataset pelatihan sehingga kinerjanya buruk pada data pengujian—yaitu, tidak digeneralisasikan.

Di bawah ini adalah gambar yang menunjukkan underfitting dan overfitting dibandingkan dengan situasi yang seimbang antara data keseluruhan dan fungsi prediksi.

Grafik underfitting, balance, dan overfitting. Fungsi yang seimbang mengikuti tren umum dari titik data dengan cukup baik, tanpa terlalu melekat pada titik data individual

Skalabilitas

Data sangat penting dalam membangun model pembelajaran mesin. Biasanya, algoritma pembelajaran tradisional tidak memerlukan terlalu banyak data. Namun karena kapasitasnya yang terbatas, kinerjanya juga terbatas. Di bawah ini adalah plot yang menunjukkan seberapa baik skala metode pembelajaran mendalam dibandingkan dengan algoritme pembelajaran mesin tradisional.

Performa vs. kuantitas data untuk pembelajaran mendalam dan algoritme tradisional. Jaringan saraf berperforma lebih baik dalam skala.

Jaringan Saraf

Jaringan saraf terdiri dari beberapa lapisan. Gambar di bawah menunjukkan jaringan saraf sederhana dengan empat lapisan. Lapisan pertama adalah lapisan input, dan lapisan terakhir adalah lapisan output. Dua lapisan antara lapisan input dan output adalah lapisan tersembunyi.

Grafik jaringan saraf, menunjukkan setiap simpul dari lapisan input yang dipetakan ke setiap simpul Lapisan Tersembunyi 1, pada gilirannya dipetakan ke setiap simpul Lapisan Tersembunyi 2, dan akhirnya dipetakan ke lapisan keluaran, yang terdiri dari satu simpul

Jika jaringan saraf memiliki lebih dari satu lapisan tersembunyi, kami menyebutnya jaringan saraf dalam. Set input $ X $ diberikan ke jaringan saraf dan output $ y $ diperoleh. Pembelajaran dilakukan dengan menggunakan algoritma backpropagation yang menggabungkan fungsi loss dan pengoptimal.

Backpropagation terdiri dari dua bagian: umpan maju dan umpan mundur. Dalam forward pass, data input diletakkan pada input jaringan saraf dan output diperoleh. Kehilangan antara kebenaran dasar dan prediksi dihitung, dan kemudian dalam lintasan mundur, parameter jaringan saraf disetel sehubungan dengan kehilangan.

Jaringan Saraf Konvolusional

Salah satu variasi jaringan syaraf tiruan adalah jaringan syaraf convolutional . Ini terutama digunakan untuk tugas visi komputer.

Lapisan yang paling penting dalam jaringan saraf convolutional adalah lapisan convolutional (oleh karena itu namanya). Parameternya terbuat dari filter yang dapat dipelajari, juga disebut kernel. Lapisan konvolusi menerapkan operasi konvolusi ke input, meneruskan hasilnya ke lapisan berikutnya. Operasi konvolusi mengurangi jumlah parameter yang dapat dipelajari, berfungsi sebagai semacam heuristik dan membuat jaringan saraf lebih mudah untuk dilatih.

Di bawah ini adalah cara kerja satu kernel convolutional dalam convolutional layer. Kernel diterapkan ke gambar dan fitur berbelit-belit diperoleh.

Animasi yang menyoroti kernel dan operasinya sebagai gambar diproses, dan output fitur yang berbelit-belit yang sesuai

Lapisan ReLU digunakan untuk memperkenalkan non-linearitas dalam jaringan saraf. Non-linearitas penting karena dengannya kita dapat memodelkan semua jenis fungsi, tidak hanya yang linier, menjadikan jaringan saraf sebagai aproksimator fungsi universal. Ini membuat fungsi ReLU didefinisikan seperti ini:

\[ReLU = \max(0, x)\]

ReLU adalah salah satu contoh dari apa yang disebut fungsi aktivasi yang digunakan untuk memperkenalkan non-linearitas dalam jaringan saraf. Contoh fungsi aktivasi lainnya termasuk fungsi sigmoid dan hyper-tangent. ReLU adalah fungsi aktivasi yang paling populer karena terbukti membuat pelatihan jaringan saraf lebih efisien dibandingkan dengan fungsi aktivasi lainnya.

Di bawah ini adalah plot dari fungsi ReLU.

Fungsi ReLU, mirip dengan diagonal sederhana dari grafik y=x, tetapi dengan semua nilai x negatif dipetakan ke nol

Seperti yang Anda lihat, fungsi ReLU ini hanya mengubah nilai negatif menjadi nol. Ini membantu mencegah masalah gradien yang hilang. Jika gradien menghilang, itu tidak akan berdampak besar dalam menyetel bobot jaringan saraf.

Sebuah jaringan saraf convolutional terdiri dari beberapa lapisan: lapisan Convolutional, lapisan ReLU, dan lapisan yang terhubung penuh. Lapisan yang terhubung penuh menghubungkan setiap neuron dalam satu lapisan ke setiap neuron di lapisan lain, seperti yang terlihat dengan dua lapisan tersembunyi pada gambar di awal bagian ini. Lapisan terakhir yang terhubung sepenuhnya memetakan output dari lapisan sebelumnya ke, dalam hal ini, nilai number_of_actions .

Aplikasi

Pembelajaran mendalam berhasil dan mengungguli algoritme pembelajaran mesin klasik di beberapa subbidang pembelajaran mesin, termasuk visi komputer, pengenalan ucapan, dan pembelajaran penguatan. Bidang pembelajaran mendalam ini diterapkan di berbagai domain dunia nyata: Keuangan, kedokteran, hiburan, dll.

Pembelajaran Penguatan

Pembelajaran penguatan didasarkan pada agen . Seorang agen mengambil tindakan dalam suatu lingkungan dan mendapatkan pengamatan dan penghargaan darinya. Seorang agen perlu dilatih untuk memaksimalkan imbalan kumulatif. Seperti disebutkan dalam pendahuluan, dengan algoritme pembelajaran mesin klasik, insinyur pembelajaran mesin perlu melakukan ekstraksi fitur, yaitu, membuat fitur bagus yang mewakili lingkungan dengan baik dan yang dimasukkan ke dalam algoritme pembelajaran mesin.

Dengan menggunakan pembelajaran mendalam, dimungkinkan untuk membuat sistem ujung ke ujung yang mengambil input berdimensi tinggi—misalnya video—dan darinya, sistem mempelajari strategi optimal bagi agen untuk mengambil tindakan yang baik.

Pada tahun 2013, startup AI London DeepMind menciptakan terobosan besar dalam belajar mengontrol agen langsung dari input sensorik dimensi tinggi. Mereka menerbitkan sebuah makalah, Playing Atari with Deep Reinforcement Learning , di mana mereka menunjukkan bagaimana mereka mengajarkan jaringan saraf tiruan untuk memainkan game Atari hanya dengan melihat layar. Mereka diakuisisi oleh Google, dan kemudian menerbitkan makalah baru di Nature dengan beberapa perbaikan: Kontrol tingkat manusia melalui pembelajaran penguatan mendalam .

Berbeda dengan paradigma pembelajaran mesin lainnya, pembelajaran penguatan tidak memiliki pengawas, hanya sinyal hadiah. Umpan balik tertunda: Ini tidak instan seperti dalam algoritma pembelajaran yang diawasi. Data berurutan dan tindakan agen memengaruhi data berikutnya yang diterimanya.

Sekarang, seorang agen terletak di lingkungannya, yang berada dalam keadaan tertentu. Untuk menggambarkan ini secara lebih rinci, kami menggunakan proses keputusan Markov, yang merupakan cara formal untuk memodelkan lingkungan belajar penguatan ini. Ini terdiri dari satu set negara, satu set tindakan yang mungkin, dan aturan (misalnya, probabilitas) untuk transisi dari satu negara ke negara lain.

Grafik proses keputusan Markov: Negara (ditandai 'S') mengambil tindakan (ditandai 'a') yang kemudian memiliki berbagai probabilitas untuk negara mana agen berakhir berikutnya; beberapa jalur yang diikuti juga menunjukkan hadiah

Agen mampu melakukan tindakan, mengubah lingkungan. Kami menyebutnya hadiah $ R_t $. Ini adalah sinyal umpan balik skalar yang menunjukkan seberapa baik kinerja agen pada langkah $t$.

Agen jaringan saraf memutuskan tindakan mana yang harus diambil pada setiap langkah berdasarkan pengamatan dan penghargaan.

Untuk kinerja jangka panjang yang baik, tidak hanya imbalan langsung tetapi juga imbalan di masa depan harus diperhitungkan. Hadiah total untuk satu episode dari langkah waktu $t$ adalah $ R_t = r_t + r_{t+1} + r_{t+2} + \ldots + r_n $. Masa depan tidak pasti dan semakin jauh kita melangkah di masa depan, semakin banyak prediksi masa depan yang mungkin berbeda. Karena itu, hadiah masa depan yang didiskon digunakan: $ R_t = r_t +\gamma r_{t+1} + \gamma^2r_{t+2} + \ldots + \gamma^{nt}r_n = r_t + \gamma R_{t+1} $. Agen harus memilih tindakan yang memaksimalkan imbalan masa depan yang didiskon.

Pembelajaran Q yang mendalam

Fungsi $ Q(s, a) $ mewakili hadiah masa depan yang didiskon maksimum ketika tindakan $ a $ dilakukan dalam keadaan $ s $:

\[Q(s_t, a_t) = \max R_{t+1}\]

Estimasi imbalan masa depan diberikan oleh persamaan Bellman: $ Q(s, a) = r + \gamma \max_{a'}Q(s', a') $ . Dengan kata lain, hadiah masa depan maksimum yang diberikan suatu keadaan $ s $ dan suatu tindakan $ a $ adalah hadiah langsung ditambah hadiah masa depan maksimum untuk keadaan berikutnya.

Perkiraan nilai-Q menggunakan fungsi non-linier (jaringan saraf) tidak terlalu stabil. Karena itu, experience replay digunakan untuk stabilitas. Pengalaman selama episode dalam sesi pelatihan disimpan dalam memori replay. Mini-batch acak dari memori replay digunakan alih-alih menggunakan transisi terbaru. Ini mematahkan kesamaan sampel pelatihan berikutnya yang sebaliknya akan mendorong jaringan saraf ke minimum lokal.

Ada dua aspek yang lebih penting untuk disebutkan tentang Q-learning yang mendalam: Eksplorasi dan eksploitasi. Dengan eksploitasi, keputusan terbaik yang diberikan informasi saat ini dibuat. Eksplorasi mengumpulkan lebih banyak informasi.

Ketika algoritme melakukan tindakan yang diusulkan oleh jaringan saraf, ia melakukan eksploitasi: Ia mengeksploitasi pengetahuan yang dipelajari jaringan saraf. Sebaliknya, suatu algoritma dapat mengambil tindakan acak, mengeksplorasi kemungkinan baru dan memperkenalkan potensi pengetahuan baru ke jaringan saraf.

“Algoritme pembelajaran Q dalam dengan Pemutaran Ulang Pengalaman” dari makalah DeepMind, Bermain Atari dengan Pembelajaran Penguatan Dalam, ditunjukkan di bawah ini.

Deep Q-learning dengan algoritma Experience Replay dalam pseudocode

DeepMind mengacu pada jaringan konvolusi yang dilatih dengan pendekatan mereka sebagai Deep Q-networks (DQN).

Contoh Deep Q-learning Menggunakan Flappy Bird

Flappy Bird adalah game mobile populer yang awalnya dikembangkan oleh seniman video game Vietnam dan programmer Dong Nguyen. Di dalamnya, pemain mengendalikan seekor burung dan mencoba terbang di antara pipa hijau tanpa menabraknya.

Di bawah ini adalah screenshot dari klon Flappy Bird yang dikodekan menggunakan PyGame:

Tangkapan layar dari FlapPyBird, klon Flappy Bird yang dikodekan menggunakan PyGame

Klon tersebut telah bercabang dan dimodifikasi: Latar belakang, suara, dan gaya burung dan pipa yang berbeda telah dihapus dan kodenya telah disesuaikan sehingga dapat dengan mudah digunakan dengan kerangka kerja pembelajaran penguatan sederhana. Mesin game yang dimodifikasi diambil dari proyek TensorFlow ini:

Tangkapan layar DeepLearningFlappyBird, garpu klon dengan grafik yang disederhanakan

Namun alih-alih menggunakan TensorFlow, saya telah membangun kerangka kerja pembelajaran penguatan mendalam menggunakan PyTorch. PyTorch adalah kerangka kerja pembelajaran mendalam untuk eksperimen yang cepat dan fleksibel. Ini menyediakan tensor dan jaringan saraf dinamis di Python dengan akselerasi GPU yang kuat.

Arsitektur jaringan saraf sama dengan DeepMind yang digunakan dalam makalah Kontrol tingkat manusia melalui pembelajaran penguatan mendalam .

Lapisan Memasukkan Ukuran saringan Melangkah Jumlah filter Pengaktifan Keluaran
konv1 84x84x4 8x8 4 32 ReLU 20x20x32
konv2 20x20x32 4x4 2 64 ReLU 9x9x64
konv3 9x9x64 3x3 1 64 ReLU 7x7x64
fc4 7x7x64 512 ReLU 512
fc5 512 2 Linier 2

Ada tiga lapisan konvolusi dan dua lapisan yang terhubung penuh. Setiap lapisan menggunakan aktivasi ReLU, kecuali yang terakhir, yang menggunakan aktivasi linier. Jaringan saraf mengeluarkan dua nilai yang mewakili satu-satunya tindakan yang mungkin dilakukan pemain: "Terbang" dan "tidak melakukan apa-apa".

Input terdiri dari empat gambar hitam-putih 84x84 berurutan. Di bawah ini adalah contoh dari empat gambar yang diumpankan ke jaringan saraf.

Anda akan melihat bahwa gambar diputar. Itu karena output dari mesin game klon diputar. Tetapi jika jaringan saraf tersebut diajarkan dan kemudian diuji menggunakan gambar tersebut, tidak akan mempengaruhi kinerjanya.

Empat bingkai hitam-putih berurutan dari klon Flappy Bird, yang diumpankan langsung ke jaringan saraf

Anda mungkin juga memperhatikan bahwa gambar dipotong sehingga lantai dihilangkan, karena tidak relevan untuk tugas ini. Semua piksel yang mewakili pipa dan burung berwarna putih dan semua piksel yang mewakili latar belakang berwarna hitam.

Ini adalah bagian dari kode yang mendefinisikan jaringan saraf. Bobot jaringan saraf diinisialisasi untuk mengikuti distribusi seragam $\mathcal{U}(-0,01, 0,01)$. Bagian bias dari parameter jaringan saraf diatur ke 0,01. Beberapa inisialisasi yang berbeda telah dicoba (Xavier uniform, Xavier normal, Kaiming uniform, Kaiming normal, uniform, dan normal), tetapi inisialisasi di atas membuat jaringan saraf konvergen dan melatih tercepat. Ukuran jaringan saraf adalah 6,8 MB.

 class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() self.number_of_actions = 2 self.gamma = 0.99 self.final_epsilon = 0.0001 self.initial_epsilon = 0.1 self.number_of_iterations = 2000000 self.replay_memory_size = 10000 self.minibatch_size = 32 self.conv1 = nn.Conv2d(4, 32, 8, 4) self.relu1 = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(32, 64, 4, 2) self.relu2 = nn.ReLU(inplace=True) self.conv3 = nn.Conv2d(64, 64, 3, 1) self.relu3 = nn.ReLU(inplace=True) self.fc4 = nn.Linear(3136, 512) self.relu4 = nn.ReLU(inplace=True) self.fc5 = nn.Linear(512, self.number_of_actions) def forward(self, x): out = self.conv1(x) out = self.relu1(out) out = self.conv2(out) out = self.relu2(out) out = self.conv3(out) out = self.relu3(out) out = out.view(out.size()[0], -1) out = self.fc4(out) out = self.relu4(out) out = self.fc5(out) return out

Di konstruktor, Anda akan melihat bahwa ada hyperparameter yang ditentukan. Optimalisasi hyperparameter tidak dilakukan untuk tujuan posting blog ini. Sebaliknya, hyperparameters sebagian besar digunakan dari makalah DeepMind. Di sini, beberapa hyperparameter diskalakan menjadi lebih rendah daripada di makalah DeepMind, karena Flappy Bird kurang kompleks daripada game Atari yang mereka gunakan untuk tuning.

Juga, epsilon diubah menjadi jauh lebih masuk akal untuk game ini. DeepMind menggunakan epsilon satu, tetapi di sini kami menggunakan 0.1. Hal ini karena epsilon yang lebih tinggi memaksa burung untuk mengepak banyak, yang mendorong burung ke arah batas atas layar, selalu akhirnya mengakibatkan burung menabrak pipa.

Kode pembelajaran penguatan memiliki dua mode: Latih dan uji. Selama fase pengujian, kita dapat melihat seberapa baik algoritma pembelajaran penguatan telah belajar bermain game. Tapi pertama-tama, jaringan saraf perlu dilatih. Kita perlu mendefinisikan fungsi kerugian yang akan diminimalkan dan pengoptimal yang akan meminimalkan fungsi kerugian. Kami akan menggunakan metode optimasi Adam dan kesalahan kuadrat rata-rata untuk fungsi kerugian:

 optimizer = optim.Adam(model.parameters(), lr=1e-6) criterion = nn.MSELoss()

Permainan harus dipakai:

 game_state = GameState()

Memori replay didefinisikan sebagai daftar Python:

 replay_memory = []

Sekarang kita perlu menginisialisasi keadaan pertama. Suatu aksi adalah tensor dua dimensi:

  • [1, 0] mewakili "tidak melakukan apa-apa"
  • [0, 1] mewakili "terbang"

Metode frame_step memberi kita layar, hadiah, dan informasi berikutnya apakah status berikutnya adalah terminal. Hadiahnya adalah 0.1 untuk setiap gerakan burung tanpa mati saat tidak melewati pipa, 1 jika burung berhasil melewati pipa dan -1 jika burung menabrak.

Fungsi resize_and_bgr2gray lantai, mengubah ukuran layar menjadi gambar 84x84, dan mengubah ruang warna dari BGR menjadi hitam-putih. Fungsi image_to_tensor mengonversi gambar menjadi tensor PyTorch dan memasukkannya ke memori GPU jika CUDA tersedia. Akhirnya, empat layar sekuensial terakhir digabungkan bersama dan siap dikirim ke jaringan saraf.

 action = torch.zeros([model.number_of_actions], dtype=torch.float32) action[0] = 1 image_data, reward, terminal = game_state.frame_step(action) image_data = resize_and_bgr2gray(image_data) image_data = image_to_tensor(image_data) state = torch.cat((image_data, image_data, image_data, image_data)).unsqueeze(0)

Epsilon awal diatur menggunakan baris kode ini:

 epsilon = model.initial_epsilon

Loop tak terbatas utama mengikuti. Komentar ditulis dalam kode dan Anda dapat membandingkan kode dengan Deep Q-learning dengan algoritma Experience Replay yang ditulis di atas.

Algoritme mengambil sampel mini-batch dari memori replay dan memperbarui parameter jaringan saraf. Tindakan dieksekusi menggunakan eksplorasi serakah epsilon . Epsilon sedang dianil dari waktu ke waktu. Fungsi kerugian yang diminimalkan adalah $ L = \frac{1}{2}\left[\max_{a'}Q(s', a') - Q(s, a)\right]^2 $ . $ Q(s, a) $ adalah nilai kebenaran dasar yang dihitung menggunakan persamaan Bellman dan $ \max_{a'}Q(s', a') $ diperoleh dari jaringan saraf. Jaringan saraf memberikan dua nilai-Q untuk dua kemungkinan tindakan dan algoritme mengambil tindakan dengan nilai-Q tertinggi.

 while iteration < model.number_of_iterations: # get output from the neural network output = model(state)[0] # initialize action action = torch.zeros([model.number_of_actions], dtype=torch.float32) if torch.cuda.is_available(): # put on GPU if CUDA is available action = action.cuda() # epsilon greedy exploration random_action = random.random() <= epsilon if random_action: print("Performed random action!") action_index = [torch.randint(model.number_of_actions, torch.Size([]), dtype=torch.int) if random_action else torch.argmax(output)][0] if torch.cuda.is_available(): # put on GPU if CUDA is available action_index = action_index.cuda() action[action_index] = 1 # get next state and reward image_data_1, reward, terminal = game_state.frame_step(action) image_data_1 = resize_and_bgr2gray(image_data_1) image_data_1 = image_to_tensor(image_data_1) state_1 = torch.cat((state.squeeze(0)[1:, :, :], image_data_1)).unsqueeze(0) action = action.unsqueeze(0) reward = torch.from_numpy(np.array([reward], dtype=np.float32)).unsqueeze(0) # save transition to replay memory replay_memory.append((state, action, reward, state_1, terminal)) # if replay memory is full, remove the oldest transition if len(replay_memory) > model.replay_memory_size: replay_memory.pop(0) # epsilon annealing epsilon = epsilon_decrements[iteration] # sample random minibatch minibatch = random.sample(replay_memory, min(len(replay_memory), model.minibatch_size)) # unpack minibatch state_batch = torch.cat(tuple(d[0] for d in minibatch)) action_batch = torch.cat(tuple(d[1] for d in minibatch)) reward_batch = torch.cat(tuple(d[2] for d in minibatch)) state_1_batch = torch.cat(tuple(d[3] for d in minibatch)) if torch.cuda.is_available(): # put on GPU if CUDA is available state_batch = state_batch.cuda() action_batch = action_batch.cuda() reward_batch = reward_batch.cuda() state_1_batch = state_1_batch.cuda() # get output for the next state output_1_batch = model(state_1_batch) # set y_j to r_j for terminal state, otherwise to r_j + gamma*max(Q) y_batch = torch.cat(tuple(reward_batch[i] if minibatch[i][4] else reward_batch[i] + model.gamma * torch.max(output_1_batch[i]) for i in range(len(minibatch)))) # extract Q-value q_value = torch.sum(model(state_batch) * action_batch, dim=1) # PyTorch accumulates gradients by default, so they need to be reset in each pass optimizer.zero_grad() # returns a new Tensor, detached from the current graph, the result will never require gradient y_batch = y_batch.detach() # calculate loss loss = criterion(q_value, y_batch) # do backward pass loss.backward() optimizer.step() # set state to be state_1 state = state_1

Sekarang setelah semua bagian berada di tempatnya, inilah ikhtisar tingkat tinggi dari aliran data menggunakan jaringan saraf kami:

Gambaran akhir tingkat tinggi aliran data menggunakan jaringan saraf kami: Status input terdiri dari empat layar berurutan. Dari sana, jaringan saraf memberikan dua nilai-Q untuk dua kemungkinan tindakan ("tidak melakukan apa-apa" dan "melayang")

Berikut adalah satu urutan pendek dengan jaringan saraf terlatih.

Animasi klon Flappy Bird yang dimainkan oleh jaringan saraf terlatih yang dihasilkan

Jaringan saraf yang ditunjukkan di atas dilatih menggunakan GPU Nvidia GTX 1080 kelas atas selama beberapa jam; menggunakan solusi berbasis CPU sebagai gantinya, tugas khusus ini akan memakan waktu beberapa hari. FPS mesin game disetel ke jumlah yang sangat besar selama pelatihan: 999…999—dengan kata lain, sebanyak mungkin frame per detik. Pada tahap pengujian, FPS diatur ke 30.

Di bawah ini adalah bagan yang menunjukkan bagaimana nilai Q maksimum berubah selama iterasi. Setiap 10.000 iterasi ditampilkan. Lonjakan ke bawah berarti bahwa untuk bingkai tertentu (satu iterasi menjadi satu bingkai) jaringan saraf memprediksi burung itu akan mendapatkan hadiah yang sangat rendah di masa depan—yaitu, ia akan segera mogok.

Bagan yang menunjukkan bagaimana nilai Q maksimum berubah selama iterasi. Mulai dari nol dan dengan beberapa lonjakan ke bawah, ini menunjukkan tren keseluruhan menuju nilai Q maksimum sekitar 12 atau 13 setelah sekitar satu juta iterasi.

Kode lengkap dan model pra-pelatihan tersedia di sini.

Pembelajaran Penguatan Mendalam: 2D, 3D, dan Bahkan Kehidupan Nyata

Dalam tutorial pembelajaran penguatan PyTorch ini, saya menunjukkan bagaimana komputer dapat belajar bermain Flappy Bird tanpa pengetahuan sebelumnya tentang permainan, hanya menggunakan pendekatan coba-coba seperti yang dilakukan manusia saat pertama kali menghadapi permainan.

Sangat menarik bahwa algoritme dapat diimplementasikan dalam beberapa baris kode menggunakan kerangka kerja PyTorch. Makalah yang menjadi dasar metode di blog ini relatif lama, dan banyak makalah baru dengan berbagai modifikasi yang memungkinkan konvergensi lebih cepat tersedia. Sejak itu, pembelajaran penguatan mendalam telah digunakan untuk bermain game 3D dan dalam sistem robot dunia nyata.

Perusahaan seperti DeepMind, Maluuba, dan Vicarious bekerja secara intensif dalam pembelajaran penguatan yang mendalam. Teknologi tersebut digunakan di AlphaGo, yang mengalahkan Lee Sedol, salah satu pemain terbaik dunia di Go. Pada saat itu, diperkirakan akan memakan waktu setidaknya sepuluh tahun sampai mesin bisa mengalahkan pemain terbaik di Go.

Membanjirnya minat dan investasi dalam pembelajaran penguatan mendalam (dan kecerdasan buatan secara umum) bahkan mungkin mengarah pada potensi kecerdasan umum buatan (AGI)—kecerdasan tingkat manusia (atau bahkan lebih) yang dapat diekspresikan dalam bentuk algoritme dan disimulasikan pada komputer. Tapi AGI harus menjadi subjek artikel lain.


Referensi:

  • Demystifying Deep Reinforcement Learning
  • Pembelajaran Penguatan Mendalam untuk Flappy Bird
  • "Jaringan saraf konvolusi" di Wikipedia
  • "Pembelajaran penguatan" di Wikipedia
  • "Proses keputusan Markov" di Wikipedia
  • Kursus University College London di RL
Terkait: Tutorial Pembelajaran Mendalam: Dari Perceptrons ke Jaringan Dalam