„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Erstellen eines Schachagenten mit DQN

Erstellen eines Schachagenten mit DQN

Gepostet am 2025-03-24
Durchsuche:268

Ich habe kürzlich versucht, einen DQN -basierten Schachagenten zu implementieren.

Jetzt würde jeder, der weiß, wie DQNs und Chess funktionieren, Ihnen sagen, dass dies eine dumme Idee ist.

Und ... es war es, aber als Anfänger habe ich es trotzdem genossen. In diesem Artikel werde ich die Erkenntnisse teilen, die ich beim Arbeiten daran gelernt habe.


Die Umwelt verstehen.

Bevor ich mit der Implementierung des Agenten selbst begann, musste ich mich mit der Umgebung vertraut machen, die ich verwenden werde, und eine benutzerdefinierte Wrapper darüber erstellen, damit er während des Trainings mit dem Agenten interagieren kann.

  • Ich habe die Schachumgebung aus der Bibliothek kaggle_environments verwendet.

     from kaggle_environments import make
     env = make("chess", debug=True)
    
  • Ich habe auch Schachnuss verwendet, eine leichte Python -Bibliothek, die Schachspiele analysiert und validiert.

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

In dieser Umgebung wird der Vorstand im Fen -Format gespeichert.

Building a Chess Agent using DQN

Es bietet eine kompakte Möglichkeit, alle Teile auf der Tafel und den aktuell aktiven Spieler darzustellen. Da ich jedoch vorhatte, die Eingabe in ein neuronales Netzwerk zu füttern, musste ich die Darstellung des Staates ändern.


Konvertieren des Fens in Matrixformat

Building a Chess Agent using DQN

Da es 12 verschiedene Arten von Teilen auf einer Tafel gibt, habe ich 12 Kanäle von 8x8 -Grids erstellt, um den Zustand jedes dieser Typen auf der Tafel darzustellen.


Erstellen einer Wrapper für die Umgebung

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

Der Punkt dieses Wrappers bestand darin, dem Agenten eine Belohnungsrichtlinie zu liefern, und eine Schrittfunktion, mit der während des Trainings mit der Umgebung interagiert wird.

chessnut war nützlich, um Informationen wie die gesetzlichen Schritte zu erhalten, die im aktuellen Zustand des Boards möglich sind und auch Checkmates während des Spiels erkennen.

Ich habe versucht, eine Belohnungsrichtlinie zu erstellen, um positive Punkte für Scheckte zu geben und feindliche Teile herauszunehmen, während negative Punkte für den Verlust des Spiels ausgegeben werden.


Erstellen eines Wiederholungspuffers

Building a Chess Agent using DQN

Wiederholungspuffer wird während der Schulungsperiode verwendet, um die Ausgabe (Status, Aktion, Belohnung, Nächster Zustand) nach dem Q-Network zu speichern und später zufällig für die Rückpropagation des Zielnetzwerks


Hilfsfunktionen

Building a Chess Agent using DQN

Building a Chess Agent using DQN

Schachnuss gibt rechtliche Schritte im UCI -Format zurück, das wie "A2A3" aussieht, um jedoch mit dem neuronalen Netzwerk zu interagieren. Ich habe jede Aktion mit einem grundlegenden Muster in einen bestimmten Index konvertiert. Es gibt insgesamt 64 Quadrate, also habe ich beschlossen, 64*64 eindeutige Indizes für jeden Zug zu haben.
Ich weiß, dass nicht alle 64 Moves legal wären, aber ich könnte die Legalität unter Verwendung von ChessNut und dem Muster einfach genug bewältigen.


Neuronale Netzwerkstruktur

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

Dieses neuronale Netzwerk verwendet die Faltungsschichten, um die 12 -Kanaleingabe in Anspruch zu nehmen, und auch die gültigen Aktionsindizes, um die Vorhersage der Belohnungsausgabe herauszufiltern.


Implementieren der Agent

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())



Dies war offensichtlich ein sehr grundlegendes Modell, das keine Chance hatte, tatsächlich gut abzuschneiden (und es tat es nicht), aber es half mir zu verstehen, wie DQNs ein wenig besser funktionieren.

Building a Chess Agent using DQN

Freigabeerklärung Dieser Artikel wird unter: https://dev.to/ankit_upadhyay_1c38ae52c0/building-a-chess-agent-using-dqn-40po?1 reproduziert.
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3