Je veux faire du Deep Learning avec pylearn2. Mais je ne sais pas si je fais simplement de la discrimination d'image dans le didacticiel. Donc, je vais faire une IA pour la troisième ligne (soi-disant jeu ○ ×). Je voulais vraiment faire l'IA d'Othello, mais comme c'est la première fois que j'utilise pylearn2, j'ai choisi un jeu plus simple. Au fait, je suis un débutant en apprentissage automatique, pylearn2. Veuillez signaler toute erreur. Ignorez les étapes pour installer les packages requis tels que pylearn2 et numpy.
Puisqu'il s'agit d'une IA à trois yeux, numérotez d'abord les carrés sur la carte 3x3 pour indiquer l'état sur la carte.
L'entrée est un certain état de la carte 3x3, et la position de la main suivante est la sortie. Par conséquent, considérez le réseau suivant.
Les nombres sur les épaules des cercles d'entrée et de sortie sont les nombres des carrés sur le plateau. L'entrée est de 9 entrées, c'est-à-dire l'état de 9 carrés. La couche cachée est une couche et la fonction d'activation est la fonction sigmoïde. La sortie étant divisée en 9 classes, utilisez la fonction softmax. Ici, «diviser en 9 classes» signifie classer une certaine entrée (état du plateau) en fonction de la case du prochain coup. En d'autres termes, s'il est classé en 0, le coup suivant sera effectué sur la case 0.
L'IA créée cette fois ne recherche pas la force. Si vous pouvez continuer le jeu sans vous écarter des données d'enseignement, nous le diviserons en une lettre. Par conséquent, au lieu de collecter uniquement les données de combat qui font le mieux, préparez une grande quantité de données qui concourent simplement selon les règles. Afin de générer une grande quantité de données de combat, j'ai créé un script Ruby qui le place simplement dans un endroit où les premier et deuxième mouvements peuvent être placés au hasard. On vous dira peut-être pourquoi vous n'écrivez pas en python, mais cela ne veut pas dire grand-chose simplement parce que vous êtes fatigué d'écrire uniquement python ces derniers temps. Le premier mouvement est 〇 et le deuxième mouvement est ×. Vous pouvez créer un syllabaire en spécifiant le nombre de boucles dans l'argument et en l'exécutant. Ceci est utilisé comme données d'enseignement. Le nombre est le numéro de la case placée, et la victoire et la défaite à la fin indiquent la victoire ou la défaite de la première attaque.
tic_tac_toe.rb
#!/usr/bin/env ruby
#
# tic tac toe
#
# 0 : O (first)
# 1 : X (second)
# 2 : none
#
def show_board(array)
p array[0][0].to_s + "," + array[0][1].to_s + "," + array[0][2].to_s
p array[1][0].to_s + "," + array[1][1].to_s + "," + array[1][2].to_s
p array[2][0].to_s + "," + array[2][1].to_s + "," + array[2][2].to_s
p ""
end
def judge(array)
ret = 2
for stone in [0, 1] do
for i in [0 ,1, 2] do
if (array[i][0]==stone && array[i][1]==stone && array[i][2]==stone) ||
(array[0][i]==stone && array[1][i]==stone && array[2][i]==stone) then
ret = stone
end
end
if (array[0][0]==stone && array[1][1]==stone && array[2][2]==stone) ||
(array[0][2]==stone && array[1][1]==stone && array[2][0]==stone) then
ret = stone
end
end
return ret
end
loop_max = ARGV[0].to_i
#p "loop max=" + loop_max.to_s
cell_array = []
stone_array = []
loop_cnt = 0
until loop_cnt >= loop_max do
cell_array = Array.new(9)
stone_array = Array.new(3).map { Array.new(3, 2) }
9.times do |num|
cell_array[num] = num
end
i = 10
history = []
9.times do |num|
#p i
rnd = rand(i) - 1
if num % 2 == 0
stone_array[cell_array[rnd].divmod(3)[0]][cell_array[rnd].divmod(3)[1]] = 0
else
stone_array[cell_array[rnd].divmod(3)[0]][cell_array[rnd].divmod(3)[1]] = 1
end
history.push(cell_array[rnd])
#show_board(stone_array)
ret = judge(stone_array)
if ret == 0 then
history.push("win") # "O" is winner.
break
elsif ret == 1 then
history.push("lose") # "O" is loser.
break
end
cell_array.delete_at(rnd)
i -= 1
end
p history.join(",")
loop_cnt += 1
end
$ ruby tic_tac_toe.rb 500 | tee tic-tac-toe_records.log
"6,8,3,4,2,0,lose"
"7,1,4,5,0,2,8,win"
"6,2,3,0,5,8,1,7,4,win"
"3,8,4,2,6,5,lose"
"1,8,2,7,3,0,6,4,lose"
"8,0,3,6,7,4,1,2,lose"
"6,8,3,5,2,7,4,win"
"2,1,7,4,3,5,8,6,0"
"4,8,6,7,1,3,2,win"
"6,1,3,0,8,7,5,4,lose"
"8,2,7,1,4,3,0,win"
"8,6,1,2,7,0,3,4,lose"
"4,3,8,1,2,6,7,0,lose"
"8,6,3,4,1,5,7,2,lose"
"1,2,0,4,7,8,5,6,lose"
"0,5,2,3,6,7,8,4,lose"
"7,1,2,6,4,5,0,3,8,win"
"2,1,0,8,3,5,7,4,6,win"
"2,0,8,5,6,7,4,win"
...
Je traiterai ces données de score en csv afin qu'elles puissent être utilisées facilement comme entrée. Cette fois, afin de créer une IA qui décide de la deuxième attaque, seules celles remportées par la deuxième attaque sont extraites.
$ awk '{gsub("\"","");print $0;}' tic-tac-toe_records.log | grep lose | tee tic-tac-toe_records_lose.csv
Ce sera comme ça après le traitement.
tic-tac-toe_records_lose.csv
6,8,3,4,2,0,lose
3,8,4,2,6,5,lose
1,8,2,7,3,0,6,4,lose
8,0,3,6,7,4,1,2,lose
...
Maintenant, vous êtes prêt à partir.
Tout d'abord, le code source est affiché.
tic_tac_toe.py
#!/usr/bin/env python
# -*- cording: utf-8 -*-
import theano
from pylearn2.models import mlp
from pylearn2.training_algorithms import sgd
from pylearn2.termination_criteria import EpochCounter
from pylearn2.datasets.dense_design_matrix import DenseDesignMatrix
import numpy as np
import csv
class TicTacToe(DenseDesignMatrix):
def __init__(self):
X = []
y = []
X_temp = [0,0,0,0,0,0,0,0,0] # 3x3 board
y_temp = [0,0,0,0,0,0,0,0,0] # 3x3 board
# (1)
self.class_names = ['0', '3']
f = open("tic-tac-toe_records_lose.csv", "r")
reader = csv.reader(f)
# (2)
for row in reader:
for i, cell_index in enumerate(row):
if cell_index == "win" or cell_index == "lose":
X_temp = [0,0,0,0,0,0,0,0,0]
elif i % 2 == 0:
temp = []
X_temp[int(cell_index)] = 1
for x in X_temp:
temp.append(x)
#print " temp = " + str(temp)
X.append(temp)
else:
X_temp[int(cell_index)] = 2
y_temp[int(cell_index)] = 3
#print "y_temp = " + str(y_temp)
y.append(y_temp)
y_temp = [0,0,0,0,0,0,0,0,0]
X = np.array(X)
y = np.array(y)
super(TicTacToe, self).__init__(X=X, y=y)
# (3)
data_set = TicTacToe()
h0 = mlp.Sigmoid(layer_name='h0', dim=9, irange=.1, init_bias=1.)
out = mlp.Softmax(layer_name='out', n_classes=9, irange=0.)
trainer = sgd.SGD(learning_rate=.05, batch_size=200, termination_criterion=EpochCounter(5000))
layers = [h0, out]
ann = mlp.MLP(layers, nvis=9)
trainer.setup(ann, data_set)
# (4)
while True:
trainer.train(dataset=data_set)
ann.monitor.report_epoch()
ann.monitor()
if trainer.continue_learning(ann) == False:
break
# (5)-1
next_move = [0,0,0,0,0,0,0,0,0]
inputs = np.array([[0,0,1,0,0,0,0,0,0]])
output = ann.fprop(theano.shared(inputs, name='inputs')).eval()
print output[0]
for i in range(0,9):
if max(output[0]) == output[0][i]:
next_move[i] = 3
print next_move
# (5)-2
next_move = [0,0,0,0,0,0,0,0,0]
inputs = np.array([[1,0,2,1,0,0,0,1,2]])
output = ann.fprop(theano.shared(inputs, name='inputs')).eval()
print output[0]
for i in range(0,9):
if max(output[0]) == output[0][i]:
next_move[i] = 3
print next_move
Je vais vous expliquer un peu. Veuillez le lire en correspondance avec (1), (2) ... dans le code. En principe, 〇 est "1", × est "2" et la cellule vide est "0". (Il est différent du code ruby utilisé pour créer les données d'enseignement. Désolé pour l'incompréhension.)
(1) Réglage de la valeur de sortie La valeur à prendre comme valeur de sortie. J'utilise 0,1,2 pour l'entrée, j'ai donc décidé d'utiliser 3 pour la sortie. (2) Conversion d'échecs Correspond au score d'échecs lu à l'entrée et à la sortie du réseau neuronal. Par exemple, si l'entrée du score est "6,8,3,4,2,0, perdez", l'expansion sera la suivante.
La musique: 6,8,3,4,2,0,lose
X[n] = [0,0,0,0,0,0,1,0,0] : "6"Dans la position de"〇"C'est"1"Entrer
y[n] = [0,0,0,0,0,0,0,0,3] :Prochaine étape"8"Dans la position de"×"Alors"8"Dans la position de"3"Les sorties
X[n+1] = [0,0,0,1,0,0,1,0,2] : "8"Dans la position de"×"C'est"2",prochain"3"Dans la position de"〇"C'est"1"Entrer
y[n+1] = [0,0,0,0,3,0,0,0,0] :Prochaine étape"4"Dans la position de"×"Alors"4"Dans la position de"3"Les sorties
X[n+2] = [0,0,1,1,2,0,1,0,2] : "4"Dans la position de"×"C'est"2",prochain"2"Dans la position de"〇"C'est"1"Entrer
y[n+2] = [3,0,0,0,0,0,0,0,0] :Prochaine étape"0"Dans la position de"×"Alors"0"Dans la position de"3"Les sorties
(3) Description de la structure MLP La couche cachée h0 est générée avec dim (dimension) = 9 (nombre de carrés) en utilisant la fonction sigmoïde comme fonction d'activation. irange et init_bias conviennent. La couche de sortie out est générée avec n_classes (nombre de classifications) = 9 (nombre de cellules) en utilisant la fonction softmax comme fonction d'activation. irange convient. [Méthode de descente de gradient probabiliste](https://ja.wikipedia.org/wiki/%E7%A2%BA%E7%8E%87%E7%9A%84%E5%8B%BE%E9%85%8D Entraîner avec% E9% 99% 8D% E4% B8% 8B% E6% B3% 95). learning_rate et batch_size sont appropriés. terminaison_criterion spécifie quand terminer la formation.
ann = mlp.MLP(layers, nvis=9)
Ce qui précède spécifie la structure de MLP. nvis a une dimension d'entrée = 9 (nombre de carrés). (4) Formation C'est une boucle d'entraînement. Nous avons également un suivi des progrès. (5) Test Testez à quoi ressemble la sortie pour certaines entrées. La partie avec la probabilité la plus élevée (sortie [0]) de 9 classes est le prochain mouvement (next_move).
La sortie lorsque le programme est exécuté est la suivante.
$ python tic_tac_toe.py
Parameter and initial learning rate summary:
h0_W: 0.05
h0_b: 0.05
softmax_b: 0.05
softmax_W: 0.05
Compiling sgd_update...
Compiling sgd_update done. Time elapsed: 0.203131 seconds
compiling begin_record_entry...
compiling begin_record_entry done. Time elapsed: 0.003911 seconds
Monitored channels:
Compiling accum...
Compiling accum done. Time elapsed: 0.000039 seconds
Monitoring step:
Epochs seen: 1
Batches seen: 3
Examples seen: 542
Monitoring step:
Epochs seen: 2
Batches seen: 6
Examples seen: 1084
...
Monitoring step:
Epochs seen: 5000
Batches seen: 15000
Examples seen: 2710000
Monitoring step:
Epochs seen: 5001
Batches seen: 15003
Examples seen: 2710542
[ 0.07985083 0.10700001 0.00255253 0.15781951 0.08504663 0.16470689
0.11459433 0.12293593 0.16549335]
[0, 0, 0, 0, 0, 0, 0, 0, 3]
[ 2.56981722e-03 1.25923571e-01 2.05250923e-04 6.14268028e-04
1.85819252e-02 2.43921569e-02 8.27328217e-01 3.84348076e-04
4.45556802e-07]
[0, 0, 0, 0, 0, 0, 3, 0, 0]
De ce qui précède, Si l'entrée est [0,0,1,0,0,0,0,0,0], le mouvement suivant est [0,0,0,0,0,0,0,0,3]. En d'autres termes, l'IA frappe comme le montre la figure ci-dessous.
Si l'entrée est [1,0,2,1,0,0,0,1,2], le mouvement suivant est [0,0,0,0,0,0,3,0,0]. En d'autres termes, l'IA frappe comme le montre la figure ci-dessous.
Eh bien, si vous frappez "X" à la position "5", vous gagnez et vous avez terminé, mais vous allez arrêter la portée de "O". Eh bien, c'est correct pour le fait qu'il soit basé sur un score aléatoire.
C'est un peu ennuyeux parce que je dois jouer avec le code source à chaque fois, mais j'ai le prochain mouvement pour une entrée arbitraire.
À l'avenir, sur la base des résultats d'un entraînement, je faciliterai l'obtention du prochain coup pour n'importe quelle entrée et l'implémenterai dans un jeu à trois yeux. Tout d'abord, je dois créer un programme de jeu d'affilée. **J'ai fait. Veuillez consulter l'article suivant. ** ** Faisons une IA de troisième ordre avec Pylearn2 --Save and load model-
http://www.arngarden.com/2013/07/29/neural-network-example-using-pylearn2/ [http://sinhrks.hatenablog.com/entry/2014/11/30/085119] (http://sinhrks.hatenablog.com/entry/2014/11/30/085119) https://www.safaribooksonline.com/blog/2014/02/10/pylearn2-regression-3rd-party-data/
Recommended Posts