[PYTHON] Écrire Reversi AI avec Keras + DQN

Étude gratuite des vacances d'hiver Il y a aussi Demo

Motivation

-J'ai lu cet article et j'ai manqué de faire la même chose quand j'étais étudiant.

Nous visons une IA purement forte plutôt que d'apprendre les règles de la réversion. Dépôt

Sujets avant DQN

Surface de la planche

La planche est de 6x6. À l'origine, je le faisais avec 8x8, mais comme le modèle et les données d'entraînement seront de taille raisonnable, environ 6x6 était parfait pour l'essai. ~~ Ou plutôt, cela s'est passé bien avec 6x6 et je l'ai compris ~~

Préparer l'IA

Je veux générer une grande quantité de musique pour apprendre, donc je vais créer une IA appropriée. Aujourd'hui, nous allons faire une exploration d'arbres de Monte Carlo complètement aléatoire. Et le résultat est ici. Cet article montre l'IA de l'exploration d'arbres de Monte Carlo avec n playouts dans MTS (n).

Génération d'échecs

[Ici](http://qiita.com/Ugo-Nama/items/08c6a5f6a571335972d5#%E9%96%A2%E6%95%B0%E8%BF%91%E4%BC%BC%E3%81%AB % E3% 83% 8B% E3% 83% A5% E3% 83% BC% E3% 83% A9% E3% 83% AB% E3% 83% 8D% E3% 83% 83% E3% 83% 88% E3 % 83% AF% E3% 83% BC% E3% 82% AF% E3% 82% 92% E4% BD% BF% E3% 81% 86) Apprenez avec quelque chose comme Neural Fitted Q Itération Alors je vais faire un score. Nous avons enregistré le tableau et la progression du tour sur la partition, et préparé environ 200 000 stations pour le moment. Avec DQN, vous n'avez pas à préparer une bonne partition, c'est donc très facile. Vous pouvez le faire simplement en le tournant complètement au hasard pendant des dizaines de minutes.

Sujet DQN

Voir cet article pour les bases.

contribution

DQN prend l'état «s» et l'action «a» comme entrée. Cette fois, l'état est le plateau, le tour et le plateau après avoir agi. Dans les jeux Atari, qui sont courants dans DQN, des facteurs autres que les actions (tels que le mouvement des ennemis) affectent l'état suivant, de sorte que les actions ne peuvent être effectuées que par une entrée clé. D'un autre côté, dans Reversi, mes actions déterminent complètement l'état suivant, alors j'ai essayé ceci.

Récompense et rendement

DQN définit une récompense «r» pour chaque action. Cette fois, c'était le résultat final de l'action, +1 pour la victoire, -1 pour la défaite et 0 pour les nuls et avant la finale. Cela garantit que le score intermédiaire est toujours entre [-1, 1] et que la sortie peut être "tanh". De plus, en supposant un jeu à somme nulle, black score = -white score est établi, et R décrit plus tard Il sera possible de l'utiliser pour calculer la valeur estimée de. À propos, la propagation de la valeur Q est également facile à voir.

Calcul de la valeur estimée R

Utilisez r pour calculer la récompense totale R, qui est le signal de l'enseignant ([Reference](http://qiita.com/Ugo-Nama/items/08c6a5f6a571335972d5#deep%E3%81%98%E3%] 82% 83% E3% 81% AA% E3% 81% 84q-réseauq% E5% AD% A6% E7% BF% 92 -% E9% 96% A2% E6% 95% B0% E8% BF% 91% E4% BC% BC)).

Q_\theta(s, a) = r + \gamma*\max_{a'}Q_\theta(s',a')

C'est la formule pour le signal de l'enseignant, mais dans le cas de reversi, le noir et le blanc alternent, donc la valeur que vous voulez est la valeur que vous voulez en copiant simplement cette formule parce que le tour de s et le tour de s' sont différents. Ne sortira pas. Ici, en utilisant l'hypothèse de somme nulle mentionnée ci-dessus, réécrivez comme suit.

Q_\theta(s, a) = \left\{
\begin{array}{ll}
 r + \gamma*\max_{a'}Q_\theta(s',a') & (s et s'Et le tour est le même)\\
 r - \gamma*\max_{a'}Q_\theta(s',a') & (s et s'Le tournant est différent)
\end{array}
\right.

Si le tour est différent, l'inversion de code du score de l'adversaire sera le propre score de l'hypothèse de la somme nulle, donc cette formule est utilisée. La méthode minimax fait la même chose, donc je l'ai inventée naturellement, mais je ne sais pas si elle correspond. En outre, étant donné que la surface de la carte de Reversi est considérée comme ayant la même surface de carte diagonale biaxiale et tournée à 180 degrés, l'idée d'augmenter la vitesse de propagation en prenant «max» parmi ces quatre types a également été introduite.

Le code sera this, mais pour l'accélération max Le «prédire» pour le calcul est fait en une seule fois, et le code ε-gourmand est mélangé, ce qui le rend terriblement difficile à lire. (Post-scriptum 2017/1/1: j'ai remarqué en considérant 8 plates-formes, mais NFQ ne semble pas avoir besoin d'ε-gourmand.)

modèle

Profitant de Keras, j'ai réalisé le modèle suivant.

def create_model6():

    board_input = Input(shape=[6, 6])
    action_input = Input(shape=[6, 6])
    color_input = Input(shape=[1])

    model_v = Sequential([
        InputLayer([6, 6]),
        Reshape([6, 6, 1]),
        Conv2D(64, 6, 1), # 1x6
        ELU(),
        Conv2D(64, 1, 1),
        ELU(),
        Flatten()
    ])

    model_h = Sequential([
        InputLayer([6, 6]),
        Reshape([6, 6, 1]),
        Conv2D(64, 1, 6), # 6x1
        ELU(),
        Conv2D(64, 1, 1),
        ELU(),
        Flatten()
    ])

    model_dr = Sequential([
        InputLayer([6, 6]),
        Reshape([6*6, 1]),
        ZeroPadding1D(3),
        Reshape([6, 7, 1]),
        LocallyConnected2D(64, 6, 1),
        ELU(),
        LocallyConnected2D(64, 1, 1),
        ELU(),
        Flatten()
    ])

    model_dl = Sequential([
        InputLayer([6, 6]),
        Reshape([6*6, 1]),
        ZeroPadding1D(2),
        Reshape([8, 5, 1]),
        LocallyConnected2D(64, 8, 1),
        ELU(),
        LocallyConnected2D(64, 1, 1),
        ELU(),
        Flatten()
    ])

    color_model = Sequential([
        InputLayer([1]),
        Dense(256),
        ELU(),
        Dense(1024),
        ELU()
    ])

    merge_layer = merge([
        model_v(board_input),
        model_h(board_input),
        model_dl(board_input),
        model_dr(board_input),
        color_model(color_input),
        model_v(action_input),
        model_h(action_input),
        model_dl(action_input),
        model_dr(action_input),
    ], mode="concat", concat_axis=-1) 

    x = Dense(2048)(merge_layer)
    x = BatchNormalization()(x)
    x = ELU()(x)
    x = Dense(512)(x)
    x = BatchNormalization()(x)
    x = ELU()(x)
    x = Dense(128)(x)
    x = BatchNormalization()(x)
    x = ELU()(x)
    output = Dense(1, activation="tanh")(x)

    model = Model(input=[board_input, color_input, action_input], output=[output])

    adam = Adam(lr=1e-4)
    model.compile(optimizer=adam, loss="mse")

    return model

Tout d'abord, il y a deux cartes, présentes et post-action, qui sont entrées dans quatre types de réseaux de partage de poids. model_v et model_h sont pliés en 1x1 après la convolution 6x1, 1x6 que j'ai vue. Cela vous permet de calculer en ne regardant qu'une seule ligne verticale et une seule ligne horizontale. Les autres model_dl et model_dr sont des calculs de colonnes diagonales. Tout d'abord, utilisez «ZeroPadding» et «Remodeler» pour aligner les colonnes diagonales dans une colonne verticale et l'appliquer au 6x1 «2D connecté localement». Par exemple, dans model_dr, les colonnes diagonales sont alignées comme indiqué dans la figure ci-dessous. スクリーンショット 2016-12-27 15.46.43.png J'utilise LocallyConnected2D parce que ces colonnes montrent des choses différentes. Je veux vraiment le séparer, mais je l'ai sauté. Après cela, le tour est également augmenté de manière appropriée et devient une couche entièrement connectée après avoir connecté toutes les sorties.

Keras a un haut degré de liberté dans la conception de modèles, mais je suis assez désemparé car il peut sembler que «Model, Sequence» et «Layer» peuvent être utilisés sans distinction. La zone autour de la dernière couche entièrement connectée est le produit de cette souffrance. De plus, dans cet article, j'ai découvert ʻInputLayer` et j'ai progressé, donc j'espère qu'il sera plus apprécié.

Confirmation de la progression de l'apprentissage

J'ai utilisé deux méthodes pour vérifier les progrès.

Battons-nous réellement

J'ai fait des centaines de batailles avec une IA aléatoire pour chaque nombre approprié d'itérations et j'ai vu quel était le taux de victoire. En fait, l'implémentation était boguée au début, et quand je l'ai remarqué et corrigé et commencé la suite, le taux de gain était supérieur à 99% à ce moment-là, donc ce n'est pas très utile. Je l'ai utilisé pour laisser le modèle avec le meilleur taux de victoire dans le processus d'apprentissage.

Donnez les données du jeu proches des meilleures

Voyons quel type de valeur sera obtenu en donnant à l'entrée le score d'échecs joué entre MTS (5000). DQN estime le score lorsque vous continuez à pointer vers le meilleur coup, donc l'idée est de donner un score qui continue de pointer vers le meilleur coup avec MTS avec un grand nombre de playouts. Le résultat à la fin de l'apprentissage était le suivant.

 0: B: [-0.02196666 -0.02230018 -0.0303785  -0.03168077]
 1: W: [-0.09994178 -0.10080269 -0.09473281 -0.09523395]
 2: B: [-0.05049421 -0.0613905  -0.05865757 -0.0515893 ]
 3: W: [-0.10307723 -0.11034401 -0.1078812  -0.11545543]
 4: B: [-0.02195507 -0.01722838 -0.00687013 -0.00869585]
 5: W: [-0.128447   -0.12213746 -0.14925914 -0.14207964]
 6: B: [-0.22107203 -0.21318831 -0.1865633  -0.18185341]
 7: W: [ 0.06178221  0.08316899  0.05964577  0.03900897]
 8: B: [-0.22808655 -0.20577276 -0.16608836 -0.18835764]
 9: W: [ 0.0713096   0.08927093  0.05861793  0.0417437 ]
10: B: [-0.25330806 -0.2539109  -0.22571792 -0.20664638]
11: W: [ 0.05460038  0.07116394  0.07360842  0.01370821]
12: B: [-0.24553944 -0.22967289 -0.22448763 -0.2255006 ]
13: W: [ 0.08806669  0.11078909  0.11152182  0.0635582 ]
14: B: [-0.45493153 -0.45988095 -0.46441916 -0.41323128]
15: W: [ 0.37723741  0.37333494  0.36738792  0.32914931]
16: B: [-0.46461144 -0.44231483 -0.42101949 -0.38848421]
17: W: [ 0.17253573  0.21936594  0.20173906  0.16213408]
18: B: [-0.50654161 -0.52144158 -0.50978303 -0.51221204]
19: W: [ 0.42853072  0.47864962  0.42829457  0.39107552]
20: B: [-0.68370593 -0.69842124 -0.69973147 -0.70182347]
21: W: [ 0.39964256  0.50497115  0.51084852  0.49810672]
22: B: [-0.71973562 -0.70337516 -0.62852156 -0.67204589]
23: W: [ 0.37252051  0.49400631  0.34360072  0.35528785]
24: B: [-0.81641883 -0.84098679 -0.79452062 -0.82713711]
25: W: [ 0.80729294  0.81642532  0.79480326  0.78571904]
26: B: [-0.916417   -0.9247427  -0.90268892 -0.89786631]
27: W: [ 0.93264407  0.93837488  0.93335259  0.9382773 ]
28: W: [ 0.93243909  0.93243909  0.9183923   0.9183923 ]

Les scores du premier mouvement, du deuxième mouvement, et ainsi de suite à partir du haut sont les mêmes dans le sens horizontal, l'axe diagonal de l'action est inversé et la rotation est de 180 degrés. On peut lire que le score en fin de partie est élevé et que le signe s'inverse en raison du changement de tour. Le fait que les valeurs dans le sens horizontal soient à peu près les mêmes semble indiquer leur égalité. La valeur Q n'est-elle pas propagée dans les premiers stades ou est-elle dans un état indéfini en premier lieu? Il semble que le taux d'actualisation γ ne soit pas très efficace ...

Résultat d'apprentissage

Je l'ai tourné pendant environ 3 jours avec la sensation ci-dessus. Quand j'ai acheté un nouveau livre de Made in Abyss et que je suis revenu, toutes les sorties étaient «nan» et j'avais froid et en sueur. Par-dessus tout, je veux que vous soyez plein de choses. Heureusement, j'ai essayé d'évaluer le taux de gain en utilisant le modèle restant.

--995/1000 avec un adversaire aléatoire -95 / 100 avec MTS (30) --MTS (100) 6/10 avec adversaire --2/10 avec MTS (1000)

Hmm subtil? Les adversaires aléatoires devraient pouvoir gagner s'ils ne sont bons que dans la tactique de la seconde mi-temps, alors j'ai pensé qu'il serait plus facile d'augmenter le taux de victoire avec DQN qui se propage à partir de la seconde mi-temps, mais c'était un peu que je pourrais gagner contre des adversaires MTS qui devraient être plus forts en seconde mi-temps J'ai été surpris. Avez-vous pris le dessus à l'étape intermédiaire? Sans nan, je sens que je peux aller plus loin et devenir plus fort.

démo

J'ai toujours voulu utiliser GCP, alors j'ai essayé d'utiliser le cadre gratuit. S'il ne tombe pas, je pense que cela fonctionnera pendant les vacances de fin d'année et de nouvel an. http://104.155.201.107:8888/ Sélectionnez DQN dans la case de sélection ci-dessous pour obtenir DQN.

Considération

À propos du modèle

Puisqu'il est réversible, j'ai conçu un modèle qui peut considérer vertical, horizontal et diagonal. Je ne sais pas si j'ai appris les règles de la prise en sandwich, mais puis-je voir le degré d'ouverture? En fait, la valeur de l'action semble être comprise uniquement du conseil d'administration après l'action, donc j'estime qu'il n'était pas nécessaire d'inclure le conseil dans l'État. Si le résultat de l'action est le même quel que soit l'état, ces scores doivent être identiques. Je pense que le modèle que j'ai fait correctement a bien fonctionné, donc je n'ai pas suffisamment réfléchi. Cependant, il est assez difficile de prendre plusieurs jours pour chaque étude.

À propos de la partition

Le score vers la fin était inversé à chaque tour, il semblait donc que l'apprentissage progressait. Par contre, la valeur absolue du score devait être sous la forme de «γ ^ n», mais cela semblait être loin de là. Qu'arrivera-t-il à la vraie valeur de «R» en premier lieu ... Il semble que ce soit avantageux pour le second coup, alors le noir sera-t-il moins et le blanc sera plus dès le premier coup?

TODO

That's it folks!

Recommended Posts

Écrire Reversi AI avec Keras + DQN
Ecrire DCGAN avec Keras
Reconnaissance d'image avec keras
3. 3. Programmation IA avec Python
Jouer avec Othello (Reversi)
Visualisez les réclamations avec l'IA
Créez le moteur de prédiction Keras AI en 1 heure avec GCP
Tutoriel CIFAR-10 avec Keras
LSTM multivarié avec Keras
Installation de Keras (utilisée par Anaconda)
Analyse de régression multiple avec Keras
Notes AutoEncodder avec Keras
Écrivez facilement if-elif avec lambda
Implémentation de word2vec avec Theano + Keras
Génération de phrases avec GRU (keras)
Réglage des paramètres Keras avec Keras Tuner
Créez Puyopuyo AI avec Python
Écrivons python avec cinema4d.
Créez facilement des CNN avec Keras
Implémentation d'un GAN efficace avec keras
Écrivez un test unitaire flexible avec PyHamcrest!
Reconnaissance d'image avec Keras + OpenCV