7.1~7.4 policy.py
Compte tenu de la couche d'entrée, il y a 104 diagrammes de phase 9x9 (images) (= 104ch). Le nombre de filtres est de 194. Utilisez le premier filtre pour filtrer une image 9x9 par rapport à une image. Faites ceci pour 104 canaux et obtenez 104 images. Combinez 104 images en une seule image. C'est 1ch. Faites de même avec le deuxième filtre. Faites de même pour le 194e filtre. Cela donne 194 images. Autrement dit, le nombre de canaux de sortie est de 194 canaux.
pointwise convolution Le but est de réduire le nombre de dimensions Image du filtre allongé de "1 pixel x 1 pixel x nombre de couches" https://www.robotech-note.com/entry/2017/12/24/191936 Entrée: 1 pixel pour chaque canal de 1 à 192, sortie: 1 valeur de pixel Ceci est effectué pour tous les pixels afin d'obtenir une image à un écran. Faites ceci pour le nombre de canaux de sortie en modifiant les paramètres. Obtenez des images de sortie pour le nombre de canaux de sortie. Après tout, la taille de filtre des 194 filtres ci-dessus n'est que de 1x1 et c'est la même chose.
python-dlshogi\pydlshogi\network\policy.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from chainer import Chain
import chainer.functions as F
import chainer.links as L
from pydlshogi.common import *
ch = 192
class PolicyNetwork(Chain):
#Entrée 104ch
#L'entrée est de 104 diagrammes de phase 9x9.
#Nombre de filtres 194.
#Les valeurs 9x9 filtrées pour chaque canal d'entrée sont ajoutées par les canaux d'entrée et émises comme 1 canal.
#Le nombre de filtres étant de 194, le nombre de canaux de sortie est de 194.
def __init__(self):
super(PolicyNetwork, self).__init__()
with self.init_scope():
self.l1 = L.Convolution2D(in_channels = 104, out_channels = ch, ksize = 3, pad = 1)
self.l2 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l3 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l4 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l5 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l6 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l7 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l8 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l9 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l10 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l11 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l12 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.l13 = L.Convolution2D(in_channels = ch, out_channels = MOVE_DIRECTION_LABEL_NUM,
ksize = 1, nobias = True)
#Taille de filtre 1x1 (ksize)=1)Sens de
#Entrée: 1 pixel pour chaque canal de 1 à 192, sortie: 1 valeur de pixel
#Ceci est effectué pour tous les pixels afin d'obtenir une image sur un seul écran.
#Faites ceci pour le nombre de canaux de sortie en modifiant les paramètres.
#Obtenez des images de sortie pour le nombre de canaux de sortie.
self.l13_bias = L.Bias(shape=(9*9*MOVE_DIRECTION_LABEL_NUM))
# MOVE_DIRECTION_LABEL_NUM=27. Affiche 20 directions de mouvement et 7 pièces.
def __call__(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
h3 = F.relu(self.l3(h2))
h4 = F.relu(self.l4(h3))
h5 = F.relu(self.l5(h4))
h6 = F.relu(self.l6(h5))
h7 = F.relu(self.l7(h6))
h8 = F.relu(self.l8(h7))
h9 = F.relu(self.l9(h8))
h10 = F.relu(self.l10(h9))
h11 = F.relu(self.l11(h10))
h12 = F.relu(self.l12(h11))
h13 = self.l13(h12)
return self.l13_bias(F.reshape(h13,(-1, 9*9*MOVE_DIRECTION_LABEL_NUM)))
#La raison pour laquelle la fonction softmax n'est pas décrite dans la sortie est
#F lors de l'apprentissage.softmax_cross_Pour utiliser la fonction d'entropie.
#Cette fonction calcule la fonction softmax et l'erreur d'entropie croisée en même temps.
common.py bb_rotate180() Argument: nombre binaire à 81 chiffres. (Un élément de piece_bb et occupé, c'est-à-dire qu'une carte de bits est incluse) Sortie: Inverse 81 chiffres et sorties.
python-dlshogi\pydlshogi\common.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import shogi
#Constante de mouvement
# UP=0、UP_LEFT=1、、、、UP_RIGHT_PROMOTE=Il est défini comme 19.
#Lors de l'utilisation, par exemple, 〇〇=S'il est UP, 0 est affecté à la variable 〇〇.
MOVE_DIRECTION = [
UP, UP_LEFT, UP_RIGHT, LEFT, RIGHT, DOWN, DOWN_LEFT, DOWN_RIGHT,
UP2_LEFT, UP2_RIGHT,
UP_PROMOTE, UP_LEFT_PROMOTE, UP_RIGHT_PROMOTE, LEFT_PROMOTE, RIGHT_PROMOTE,
DOWN_PROMOTE, DOWN_LEFT_PROMOTE, DOWN_RIGHT_PROMOTE,
UP2_LEFT_PROMOTE, UP2_RIGHT_PROMOTE
] = range(20)
#Table de conversion
# **_La variable nommée PROMOTE est MOVE_Prédéfini dans DIRECTION.
# UP_PROMOTE=10,・ ・ ・,UP_RIGHT_PROMOTE=Il est défini comme 19.
MOVE_DIRECTION_PROMOTED = [
UP_PROMOTE, UP_LEFT_PROMOTE, UP_RIGHT_PROMOTE, LEFT_PROMOTE, RIGHT_PROMOTE,
DOWN_PROMOTE, DOWN_LEFT_PROMOTE, DOWN_RIGHT_PROMOTE,
UP2_LEFT_PROMOTE, UP2_RIGHT_PROMOTE
]
#Nombre d'étiquettes représentant les mouvements
MOVE_DIRECTION_LABEL_NUM = len(MOVE_DIRECTION) + 7 #7 est le type de pièce
# rotate 180degree
# shogi.I1 est 80, ..., shogi.A9 est égal à 0. En d'autres termes, SQUARES_R180 = [80, 79,・ ・ ・, 1, 0]
SQUARES_R180 = [
shogi.I1, shogi.I2, shogi.I3, shogi.I4, shogi.I5, shogi.I6, shogi.I7, shogi.I8, shogi.I9,
shogi.H1, shogi.H2, shogi.H3, shogi.H4, shogi.H5, shogi.H6, shogi.H7, shogi.H8, shogi.H9,
shogi.G1, shogi.G2, shogi.G3, shogi.G4, shogi.G5, shogi.G6, shogi.G7, shogi.G8, shogi.G9,
shogi.F1, shogi.F2, shogi.F3, shogi.F4, shogi.F5, shogi.F6, shogi.F7, shogi.F8, shogi.F9,
shogi.E1, shogi.E2, shogi.E3, shogi.E4, shogi.E5, shogi.E6, shogi.E7, shogi.E8, shogi.E9,
shogi.D1, shogi.D2, shogi.D3, shogi.D4, shogi.D5, shogi.D6, shogi.D7, shogi.D8, shogi.D9,
shogi.C1, shogi.C2, shogi.C3, shogi.C4, shogi.C5, shogi.C6, shogi.C7, shogi.C8, shogi.C9,
shogi.B1, shogi.B2, shogi.B3, shogi.B4, shogi.B5, shogi.B6, shogi.B7, shogi.B8, shogi.B9,
shogi.A1, shogi.A2, shogi.A3, shogi.A4, shogi.A5, shogi.A6, shogi.A7, shogi.A8, shogi.A9,
]
def bb_rotate_180(bb):
#C'est morceau pour entrer bb_Un élément de bb et un élément d'occupé. Autrement dit, un nombre binaire à 81 chiffres.
bb_r180 = 0
for pos in shogi.SQUARES: #SQUARES est la gamme(0, 81)Cette
if bb & shogi.BB_SQUARES[pos] > 0:
# BB_LES CARRÉS[0b000 ・ ・ ・ 0001,0b000 ・ ・ ・ 0010,0b000 ・ ・ ・ 0100,・ ・ ・,0b100 ・ ・ ・ 0000].. 81 éléments.
# &Est l'opérateur de bits AND.
bb_r180 += 1 << SQUARES_R180[pos]
# a<<b est un opérateur qui décale le bit de a vers la gauche de b chiffres.
return bb_r180
features.py make_input_features() Arguments: piece_bb, occupé, pieces_in_hand Sortie: où se trouve la première pièce, la première pièce, la deuxième pièce, la deuxième pièce [(Matrice 9x9), (Matrice 9x9), ... (18 + 4 + 4 + 4 + 4 + 2 + 2), (Matrice 9x9), (Matrice 9x9), ... (18 + 4 + 4 + 4 + 4 + 2 + 2)]
make_input_features_from_board() Sortez piece_bb, busy, pieces_in_hand, tournez avec board comme argument et effectuez make_input_features.
make_output_label() Arguments: move (move_from et move_to), color (first ou second) La couleur est utilisée pour permettre à move_direction d'être utilisé à la fois en premier et en second.
Sortie: move_direction (81 chiffres) + move_to (1 chiffre) Image 81-aire. move_direction est de 81 chiffres, move_to est de 1 chiffre. 81 chiffres ... 27 1 chiffre ・ ・ ・ 9x9
En d'autres termes, le déplacement est converti en une valeur numérique et une sortie. À propos, la valeur numérique de cette sortie est également l'indice de la sortie de NN. Il est utilisé lorsque vous souhaitez extraire l'élément souhaité de la sortie de NN.
make_features() Retirez piece_bb, busy, pieces_in_hand avec position comme argument et effectuez make_input_features.
python-dlshogi\pydlshogi\features.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import shogi
import copy
from pydlshogi.common import *
def make_input_features(piece_bb, occupied, pieces_in_hand):
features = []
for color in shogi.COLORS:
# board pieces
for piece_type in shogi.PIECE_TYPES_WITH_NONE[1:]: #PIECE_TYPES_WITH_NONE est la plage(0, 16)Cette
bb = piece_bb[piece_type] & occupied[color] #Obtenir la position de la pièce côté tour pour chaque pièce (&Est un peu opérateur)
feature = np.zeros(9*9)
for pos in shogi.SQUARES: #SQUARES est la gamme(0, 81)Cette
if bb & shogi.BB_SQUARES[pos] > 0: #BB_LES CARRÉS[0b1, 0b10, 0b100,・ ・ ・,0b1 ・ ・ ・ 0].. 81 éléments.
feature[pos] = 1 #Chaque bit de la carte de bits est décomposé en éléments. Par exemple, 1010 ...[1,0,1,0,・ ・ ・]Démonté en.
features.append(feature.reshape((9, 9))) #Chaque bit de la carte de bits est décomposé en éléments et renvoyé sous forme de matrice 9x9.
# pieces in hand
for piece_type in range(1, 8):
for n in range(shogi.MAX_PIECES_IN_HAND[piece_type]):
#shogi.MAX_PIECES_IN_HAND est le nombre de pièces dont vous disposez. Index 1~7 ressemble probablement à ceci:
#shogi.MAX_PIECES_IN_HAND[1] =18: Ayumu
#shogi.MAX_PIECES_IN_HAND[2] =4: voiture d'encens
#shogi.MAX_PIECES_IN_HAND[3] =4: Katsura
#shogi.MAX_PIECES_IN_HAND[4] =4: Argent
#shogi.MAX_PIECES_IN_HAND[5] =4: ven
#shogi.MAX_PIECES_IN_HAND[6] =2: Coin
#shogi.MAX_PIECES_IN_HAND[7] =2: voiture volante
if piece_type in pieces_in_hand[color] and n < pieces_in_hand[color][piece_type]:
feature = np.ones(9*9)
else:
feature = np.zeros(9*9)
features.append(feature.reshape((9, 9)))
return features
#Sortie: où se trouve la première pièce, la première pièce, la deuxième pièce, la deuxième pièce
# [(Matrice 9x9),
# (Matrice 9x9),... est (18 + 4 + 4 + 4 + 4 + 2 + 2),
# (Matrice 9x9),
# (Matrice 9x9),... est (18 + 4 + 4 + 4 + 4 + 2 + 2)]
def make_input_features_from_board(board): #faire avec le conseil comme argument_input_Faites des fonctionnalités.
if board.turn == shogi.BLACK:
piece_bb = board.piece_bb
occupied = (board.occupied[shogi.BLACK], board.occupied[shogi.WHITE])
pieces_in_hand = (board.pieces_in_hand[shogi.BLACK], board.pieces_in_hand[shogi.WHITE])
else:
piece_bb = [bb_rotate_180(bb) for bb in board.piece_bb]
occupied = (bb_rotate_180(board.occupied[shogi.WHITE]), bb_rotate_180(board.occupied[shogi.BLACK]))
pieces_in_hand = (board.pieces_in_hand[shogi.WHITE], board.pieces_in_hand[shogi.BLACK])
return make_input_features(piece_bb, occupied, pieces_in_hand)
def make_output_label(move, color):
move_to = move.to_square
move_from = move.from_square
#■ Déplacer la classe
# from_variable carrée: valeur de la source de mouvement lorsque la surface de la planche est représentée par une valeur numérique comprise entre 0 et 80.
#Le quotient divisé par 9 est la coordonnée y et le reste est la coordonnée x. La coordonnée xy est 0 origine.
# to_variable carrée: comme ci-dessus (destination).
#
#coordonnée x
# 0 1 2 3 4 5 6 7 8
#
#0 1 2 3 4 5 6 7 8 0 coordonnées y
# 9 10 11 12 13 14 15 16 17 1
# 18 19 20 21 22 23 24 25 26 2
# 27 28 29 30 31 32 33 34 35 3
# 36 37 38 39 40 41 42 43 44 4
# 45 46 47 48 49 50 51 52 53 5
# 54 55 56 57 58 59 60 61 62 6
# 63 64 65 66 67 68 69 70 71 7
# 72 73 74 75 76 77 78 79 80 8
#S'il est blanc, faites pivoter le tableau
if color == shogi.WHITE:
move_to = SQUARES_R180[move_to]
if move_from is not None: #Lorsque vous déplacez une pièce sur le plateau au lieu de la pièce que vous avez
move_from = SQUARES_R180[move_from]
# move direction
if move_from is not None: #Lorsque vous déplacez une pièce sur le plateau au lieu de la pièce que vous avez
to_y, to_x = divmod(move_to, 9)
from_y, from_x = divmod(move_from, 9)
dir_x = to_x - from_x
dir_y = to_y - from_y
if dir_y < 0 and dir_x == 0:
move_direction = UP
elif dir_y == -2 and dir_x == -1:
move_direction = UP2_LEFT
elif dir_y == -2 and dir_x == 1:
move_direction = UP2_RIGHT
elif dir_y < 0 and dir_x < 0:
move_direction = UP_LEFT
elif dir_y < 0 and dir_x > 0:
move_direction = UP_RIGHT
elif dir_y == 0 and dir_x < 0:
move_direction = LEFT
elif dir_y == 0 and dir_x > 0:
move_direction = RIGHT
elif dir_y > 0 and dir_x == 0:
move_direction = DOWN
elif dir_y > 0 and dir_x < 0:
move_direction = DOWN_LEFT
elif dir_y > 0 and dir_x > 0:
move_direction = DOWN_RIGHT
# promote
if move.promotion:
move_direction = MOVE_DIRECTION_PROMOTED[move_direction]
else:
#Propre pièce
# len(MOVE_DIRECTION)Est 20
# move.drop_piece_Le type est-il le type de pièce que vous avez placé?
# -Est-ce que 1 est le nombre?
move_direction = len(MOVE_DIRECTION) + move.drop_piece_type - 1
move_label = 9 * 9 * move_direction + move_to
#Image 81-aire. bouge toi_la direction est de 81 chiffres, déplacer_to est un chiffre de 1.
#81 chiffres ... 27
#1 chiffre ・ ・ ・ 9x9
return move_label
def make_features(position):
piece_bb, occupied, pieces_in_hand, move, win = position
features = make_input_features(piece_bb, occupied, pieces_in_hand)
return(features, move, win)
Recommended Posts