"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Construindo um agente de xadrez usando DQN

Construindo um agente de xadrez usando DQN

Postado em 2025-03-24
Navegar:728

Recentemente, tentei implementar um agente de xadrez baseado em DQN.

Agora, quem sabe como os DQNs e o xadrez funcionam diria que é uma ideia idiota.

E ... foi, mas como iniciante eu gostei, no entanto. Neste artigo, compartilharei as idéias que aprendi enquanto trabalho nisso.


Compreender o ambiente.

Antes de começar a implementar o próprio agente, tive que me familiarizar com o ambiente que vou usar e fazer um invólucro personalizado em cima dele para que ele possa interagir com o agente durante o treinamento.

  • usei o ambiente de xadrez da biblioteca Kaggle_environments.

     from kaggle_environments import make
     env = make("chess", debug=True)
    
  • Eu também usei o Chessnut, que é uma biblioteca Python leve que ajuda a analisar e validar jogos de xadrez.

     from Chessnut import Game
     initial_fen = env.state[0]['observation']['board']
     game=Game(env.state[0]['observation']['board'])
    

Nesse ambiente, o estado do conselho é armazenado no formato Fen.

Building a Chess Agent using DQN

fornece uma maneira compacta de representar todas as peças da placa e o jogador atualmente ativo. No entanto, como planejei alimentar a entrada de uma rede neural, tive que modificar a representação do estado.


Convertendo o formato Fen em Matrix

Building a Chess Agent using DQN

Como existem 12 tipos diferentes de peças em uma placa, criei 12 canais de grades 8x8 para representar o estado de cada um desses tipos na placa.


Criando um invólucro para o ambiente

class EnvCust:
    def __init__(self):
        self.env = make("chess", debug=True)
        self.game=Game(env.state[0]['observation']['board'])
        print(self.env.state[0]['observation']['board'])
        self.action_space=game.get_moves();
        self.obs_space=(self.env.state[0]['observation']['board'])

    def get_action(self):
        return Game(self.env.state[0]['observation']['board']).get_moves();


    def get_obs_space(self):
        return fen_to_board(self.env.state[0]['observation']['board'])

    def step(self,action):
        reward=0
        g=Game(self.env.state[0]['observation']['board']);
        if(g.board.get_piece(Game.xy2i(action[2:4]))=='q'):
            reward=7
        elif g.board.get_piece(Game.xy2i(action[2:4]))=='n' or g.board.get_piece(Game.xy2i(action[2:4]))=='b' or g.board.get_piece(Game.xy2i(action[2:4]))=='r':
            reward=4
        elif g.board.get_piece(Game.xy2i(action[2:4]))=='P':
            reward=2
        g=Game(self.env.state[0]['observation']['board']);
        g.apply_move(action)
        done=False
        if(g.status==2):
            done=True
            reward=10
        elif g.status == 1:  
            done = True
            reward = -5 
        self.env.step([action,'None'])
        self.action_space=list(self.get_action())
        if(self.action_space==[]):
            done=True
        else:
            self.env.step(['None',random.choice(self.action_space)])
            g=Game(self.env.state[0]['observation']['board']);
            if g.status==2:
                reward=-10
                done=True

        self.action_space=list(self.get_action())
        return self.env.state[0]['observation']['board'],reward,done

O ponto deste invólucro era fornecer uma política de recompensa para o agente e uma função de etapa que é usada para interagir com o ambiente durante o treinamento.

chessnut foi útil para obter informações como os movimentos legais possíveis no estado atual do conselho e também para reconhecer colegas de seleção durante o jogo.

Tentei criar uma política de recompensa para dar pontos positivos para os colegas e tirar peças inimigas, enquanto pontos negativos para perder o jogo.


Criando um buffer de repetição

Building a Chess Agent using DQN

O buffer de replay é usado durante o período de treinamento para salvar a saída (estado, ação, recompensa, próximo estado) pela rede Q e posteriormente usada aleatoriamente para retropagem da rede de destino


Funções auxiliares

Building a Chess Agent using DQN

Building a Chess Agent using DQN

chessnut retorna ação legal no formato UCI, que se parece com 'A2A3', no entanto, para interagir com a rede neural, converti cada ação em um índice distinto usando um padrão básico. Existem 64 quadrados totais, então decidi ter 64*64 índices exclusivos para cada movimento.
eu sei que nem todos os 64*64 movimentos seriam legais, mas eu poderia lidar com a legalidade usando o chessnut e o padrão era simples o suficiente.


Estrutura da rede neural

import torch
import torch.nn as nn
import torch.optim as optim

class DQN(nn.Module):
    def __init__(self):  
        super(DQN, self).__init__()
        self.conv_layers = nn.Sequential(
            nn.Conv2d(12, 32, kernel_size=3, stride=1, padding=
            nn.ReLU(),  
            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),  
            nn.ReLU()
        )
        self.fc_layers = nn.Sequential(
            nn.Flatten(),
            nn.Linear(64 * 8 * 8, 256),
            nn.ReLU(), 
            nn.Linear(256, 128),
            nn.ReLU(), 
            nn.Linear(128, 4096)
        )

    def forward(self, x):
        x = x.unsqueeze(0)
        x = self.conv_layers(x)  
        x = self.fc_layers(x)  
        return x

    def predict(self, state, valid_action_indices):
        with torch.no_grad(): 
            q_values = self.forward(state) 
            q_values = q_values.squeeze(0)  


            valid_q_values = q_values[valid_action_indices]


            best_action_relative_index = valid_q_values.argmax().item()  
            max_q_value=valid_q_values.argmax()
            best_action_index = valid_action_indices[best_action_relative_index] 

            return max_q_value, best_action_index

Esta rede neural usa as camadas convolucionais para obter a entrada de 12 canais e também usa os índices de ação válidos para filtrar a previsão da saída de recompensa.


Implementando o agente

model = DQN().to(device)  # The current Q-network
target_network = DQN().to(device)  # The target Q-network
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
replay_buffer = ReplayBuffer(buffer_size=10000)
epsilon = 0.5  
gamma = 0.99 
batch_size=15
def train(episodes):
    for ep in range(1,episodes 1):
        print('Episode Number:',ep)
        myenv=EnvCust()
        done=False
        state=myenv.obs_space
        i=0
        while not done and i batch_size:
                mini_batch = replay_buffer.sample(batch_size)
                for e in mini_batch:
                    state, action, reward, next_state, done = e
                    g=Game(next_state)
                    act=g.get_moves();
                    ind_a=action_index(act)
                    input_state=torch.tensor(fen_to_board(next_state), dtype=torch.float32, requires_grad=True).to(device)
                    tpred,_=target_network.predict(input_state,ind_a)
                    target = reward   gamma * tpred * (1 - done)

                    act_ind=uci_to_action_index(action)
                    input_state2=torch.tensor(fen_to_board(state), dtype=torch.float32, requires_grad=True).to(device)
                    current_q_value =model(input_state2)[0,act_ind]

                    loss = (current_q_value - target) ** 2
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()
            if ep % 5 == 0:
                target_network.load_state_dict(model.state_dict())



esse era obviamente um modelo muito básico que não teve chance de realmente ter um bom desempenho (e não foi), mas me ajudou a entender como os DQNs funcionam um pouco melhor.

Building a Chess Agent using DQN

Declaração de lançamento Este artigo é reproduzido em: https://dev.to/ankit_upadhyay_1c38e52c0/building-a-chess-agent-using-dqn-40po?1 Se houver alguma infração, entre em contato com [email protected] para excluí-lo.
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3