
- Kali ini game "Snake" dipilih.
- Perpustakaan untuk jaringan Go telah dibuat.
- Prinsip pembelajaran, tergantung pada "kedalaman" ingatan, ditemukan.
- Server ditulis untuk permainan antar pengembang.
Inti dari permainan
Mungkin banyak orang mengingat permainan "Snake", yang merupakan aplikasi standar pada ponsel Nokia. Esensinya adalah ini: ular bergerak melintasi lapangan, yang berkurang jika tidak menemukan makanan, atau bertambah jika ditemukan. Jika seekor ular menabrak rintangan, maka ia mati.
Saya sedikit mengubah aturan: ular tidak mati jika jatuh, tetapi berhenti begitu saja, terus berkurang. Selain itu, ular dapat dibagi dua. Jika ular memiliki satu sel tersisa di tubuhnya dan dia tidak dapat menemukan makanan dalam 10 gerakan, maka dia mati, berubah menjadi makanan.
Kami akan melatih bot yang mengendalikan ular. Jika ular terbelah, maka bot akan menerima ular lain yang memegang kendali, yang pada gilirannya juga dapat membelah.
Percobaan dengan ular dari ahli biologi maya Mikhail Tsarkov diambil sebagai dasar.
Jaringan saraf
Sebagai bagian dari tugas, perpustakaan untuk jaringan saraf ditulis dalam bahasa Go. Mempelajari karya jaringan saraf, saya menggunakan video diary
foo52ru dan buku Tariq Rashid - Buat jaringan saraf.
Fungsi
CreateLayer(L []int)
membuat jaringan saraf dengan jumlah lapisan yang diperlukan dan ukurannya. Pada setiap lapisan, kecuali yang terakhir, neuron perpindahan ditambahkan. Kami mengumpankan data ke lapisan pertama, dan kami mendapatkan hasilnya dari lapisan terakhir.
Contoh:
CreateLayer([]int{9, 57, 3, 1})
Di sini kami membuat jaringan saraf dengan sembilan input. Dua lapisan tersembunyi dari 57 dan 3 neuron dan satu neuron untuk mendapatkan hasilnya. Neuron-neuron pemindahan secara otomatis ditambahkan oleh plus ke yang kita atur.
Perpustakaan memungkinkan Anda untuk:
- Kirim data ke input jaringan.
- Dapatkan hasilnya dengan mengakses lapisan terakhir.
- Tanyakan jawaban yang benar dan lakukan pelatihan dengan menyesuaikan bobot ikatan.
Bobot ikatan awal diberikan oleh nilai acak mendekati nol. Untuk aktivasi, kami menggunakan fungsi logistik.
Pelatihan bot
Bot menerima bidang 9x9 persegi di pintu masuk, di tengahnya adalah kepala ular. Dengan demikian, jaringan saraf kita akan memiliki 81 input. Urutan sel yang dimasukkan ke input tidak masalah. Selama pelatihan, jaringan "akan mencari tahu" sendiri, di mana apa yang berada.
Untuk mengindikasikan rintangan dan ular lainnya, saya menggunakan nilai dari -1 hingga 0 (tidak termasuk). Sel-sel kosong ditunjuk dengan nilai 0,01, dan makanan 0,99.
Pada output dari jaringan saraf, 5 neuron digunakan untuk tindakan:
- bergerak ke kiri di sepanjang sumbu X;
- di sebelah kanan;
- atas sumbu y;
- bawah;
- terbelah dua.
Gerakan bot ditentukan oleh neuron, yang memiliki nilai terbesar pada output.
Langkah 0. Pengacak
Pertama, pengacak bot telah dibuat. Jadi saya sebut bot yang berjalan secara acak. Perlu untuk memverifikasi efektivitas jaringan saraf. Dengan pelatihan yang tepat, jaringan saraf harus dengan mudah mengalahkannya.
Langkah 1. Belajar tanpa ingatan
Setelah setiap gerakan, kami menyesuaikan bobot ikatan untuk neuron output yang menunjukkan nilai tertinggi. Kami tidak menyentuh neuron keluaran lainnya.
Nilai-nilai berikut diberikan untuk pelatihan:
- makanan yang ditemukan: 0,99
- membuat gerakan ke segala arah: 0,5
- kehilangan sel tubuh tanpa menemukan makanan (10 langkah diberikan untuk ini): 0,2
- berdiri diam (menabrak rintangan atau macet): 0,1
- berdiri diam, memiliki satu sel tubuh: 0,01
Setelah pelatihan seperti itu, bot dengan cepat mulai mengalahkan pengacak, dan saya mengatur tugas: untuk membuat bot yang akan mengalahkan ini.
Pengujian A / B
Untuk menyelesaikan tugas ini, sebuah program dibuat yang membagi ular menjadi dua bagian, tergantung pada konfigurasi jaringan saraf. Di lapangan, 20 ular dari setiap konfigurasi diproduksi.
Semua ular yang dikendalikan oleh satu bot memiliki jaringan saraf yang sama. Semakin banyak ular dalam manajemennya dan semakin sering mereka menghadapi tugas yang berbeda, semakin cepat pelatihan berlangsung. Jika, misalnya, satu ular belajar menghindari kebuntuan atau terbelah dua ketika mencapai jalan buntu, maka secara otomatis semua ular dari bot ini memperoleh keterampilan ini.
Dengan mengubah konfigurasi jaringan saraf, Anda bisa mendapatkan hasil yang baik, tetapi ini tidak cukup. Untuk lebih meningkatkan algoritma, saya memutuskan untuk menggunakan memori untuk beberapa gerakan.
Langkah 2. Belajar dengan memori
Untuk setiap bot, saya membuat memori untuk 8 gerakan. Keadaan lapangan dan gerakan yang disarankan bot dicatat dalam memori. Setelah itu, saya membuat penyesuaian bobot untuk semua delapan negara yang mendahului langkah. Untuk ini, saya menggunakan faktor koreksi tunggal, terlepas dari kedalaman perjalanan. Dengan demikian, setiap gerakan menyebabkan penyesuaian bobot tidak hanya sekali, tetapi delapan.
Seperti yang diharapkan, bot memori mulai dengan cepat mengalahkan bot yang dilatih tanpa memori.
Langkah 3. Kurangi koefisien koreksi tergantung pada kedalaman memori
Selanjutnya, saya mencoba mengurangi faktor koreksi, tergantung pada kedalaman memori. Untuk langkah terakhir yang dibuat, koefisien terbesar untuk menyesuaikan bobot ditetapkan. Dalam perjalanan yang mendahuluinya, faktor koreksi menurun dan seterusnya di seluruh memori.

Penurunan linear dalam koefisien koreksi tergantung pada kedalaman memori menyebabkan fakta bahwa bot baru mulai mengalahkan mereka yang menggunakan koefisien tunggal.
Selanjutnya, saya mencoba menggunakan pengurangan faktor koreksi logaritmik. Koefisien berkurang setengahnya, tergantung pada kedalaman memori untuk setiap gerakan. Dengan demikian, gerakan yang dibuat "dahulu" memiliki dampak yang jauh lebih kecil pada pembelajaran daripada gerakan "segar".
Bot dengan pengurangan logaritmik dalam koefisien koreksi mulai mengalahkan bot dengan hubungan linier.
Server untuk bot
Ternyata, meningkatkan tingkat bot "memompa" bisa tak terbatas. Dan saya memutuskan untuk membuat server di mana pengembang dapat bersaing satu sama lain (terlepas dari bahasa pemrograman) dalam menulis algoritma yang efektif untuk Ular.
Protokol
Untuk otorisasi, Anda harus mengirim permintaan GET ke direktori "game" dan menentukan nama pengguna, misalnya:
.../game/?user=masterdak
Alih-alih "..." Anda harus menentukan alamat situs dan port tempat server digunakan.
Selanjutnya, server akan mengeluarkan respons dalam format JSON yang menunjukkan sesi:
{"answer":"Hellow, masterdak!","session":"f4f559d1d2ed97e0616023fb4a84f984"}
Setelah itu, Anda dapat meminta peta dan koordinat ular di lapangan, menambahkan sesi ke permintaan:
.../game/?user=masterdak&session=f4f559d1d2ed97e0616023fb4a84f984
Server akan menampilkan sesuatu seperti ini:
{ "answer": "Sent game data.", "data": { "area": [ ["... ..."] ], "snakes": [ { "num": 0, "body": [ { "x": 19, "y": 24 }, { "x": 19, "y": 24 }, { "x": 19, "y": 24 } ], "energe": 4, "dead": false } ] } }
Bidang
area akan menunjukkan keadaan bidang bermain dengan nilai-nilai berikut:
0
Ini akan diikuti oleh array dengan ular yang ada di kendali Anda.
Tubuh ular ada di dalam susunan
tubuh . Seperti yang dapat Anda lihat seluruh tubuh ular (termasuk kepala - sel pertama) di awal berada pada posisi yang sama "x": 19, "y": 24. Hal ini disebabkan oleh kenyataan bahwa pada awal permainan ular keluar dari lubang, yang ditentukan oleh satu sel di lapangan . Selanjutnya, koordinat tubuh dan kepala akan berbeda.
Struktur berikut (contoh dalam Go) mendefinisikan semua opsi respons server:
type respData struct { Answer string Session string Data struct { Area [][]int Snakes []struct { Num int Body []Cell Energe int Dead bool } } } type Cell struct { X int Y int }
Selanjutnya, Anda perlu mengirim langkah yang dibuat ular dengan menambahkan
langkah ke permintaan GET, misalnya:
...&move=u
u - berarti memerintah;
d - turun;
l - ke kiri;
r - ke kanan;
/ - mengurangi separuh.
Perintah untuk beberapa ular (misalnya, untuk tujuh) akan terlihat seperti ini:
...&move=ud/urld
Satu karakter - satu tim. Jawabannya harus berisi perintah untuk semua ular yang berada di bawah kendali Anda. Jika tidak, beberapa ular mungkin tidak menerima perintah dan akan melanjutkan tindakan lama.
Bidang diperbarui pada interval 150 ms. Jika tidak ada perintah yang diterima dalam 60 detik, server akan menutup koneksi.
Referensi
Untuk menghindari kebiasaan itu, bagi mereka yang tertarik untuk melihatnya, kirimkan saya pesan. Sebagai tanggapan, saya akan mengirim alamat ip server saya. Atau Anda dapat menggunakan server Anda menggunakan kode sumber program.
Saya bukan spesialis dalam pemrograman atau dalam jaringan saraf. Karena itu, saya bisa membuat kesalahan. Saya menyebarkan kode "sebagaimana adanya". Saya akan senang jika pengembang yang lebih berpengalaman akan menunjukkan kesalahan yang dibuat.
- Perpustakaan untuk jaringan saraf bersama dengan permainan "Tic Tac Toe"
- Master Ular - Server
- Master Ular - Bot
- Snakeworld2
UPDUnggah sementara
alamat IP server . Sekarang hanya satu bot pengacak (SnakeBot0) diluncurkan di sana. Saya harap server crash tidak begitu cepat.