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'])
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.
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.
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.
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
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.
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.
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.
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