«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Создание шахматного агента с использованием DQN

Создание шахматного агента с использованием DQN

Опубликовано в 2025-03-24
Просматривать:631

] Недавно я пытался реализовать шахматный агент на основе DQN.

]

] Теперь любой, кто знает, как работает DQN и шахматы, скажет вам, что это глупая идея.

]

] И ... это было, но как новичок мне нравился, тем не менее. В этой статье я поделюсь пониманием, которые я узнал, работая над этим.

]
]

] Понимание окружающей среды.

]

, прежде чем я начал реализовывать самого агента, мне пришлось ознакомиться с средой, которую я буду использовать, и сделать пользовательскую обертку поверх него, чтобы он мог взаимодействовать с агентом во время обучения.

]
    ]
  • ]

    Я использовал шахматную среду из библиотеки kaggle_environments.
    из Kaggle_environments Import Make env = make ("шахматы", отладка = true)
    ]

    ]
     from kaggle_environments import make
     env = make("chess", debug=True)
    
    ]
  • ]
я также использовал Chessnut, которая является легкой библиотекой Python, которая помогает анализировать и проверять шахматные игры.
  • ]
    из игры в импорт шахмата initial_fen = env.state [0] ['asperation'] ['alp'] Game = Game (Env.State [0] ['asmation'] ['alp'])
    ]

    ]
     from Chessnut import Game
     initial_fen = env.state[0]['observation']['board']
     game=Game(env.state[0]['observation']['board'])
    
    ] В этой среде состояние совета директоров хранится в формате FEN.
  • ]

Building a Chess Agent using DQN он обеспечивает компактный способ представить все части на доске и в настоящее время активного игрока. Однако, поскольку я планировал подавать ввод в нейронную сеть, мне пришлось изменить представление состояния.

] ] ] Преобразование FEN в формат матрицы

]

Building a Chess Agent using DQN, поскольку на доске есть 12 различных типов, я создал 12 каналов из 8x8 сетей, чтобы представлять состояние каждого из этих типов на доске.

] ] Создание обертки для среды


]

]
класс Envcust: def __init __ (self): self.env = make ("шахматы", отладка = true) self.game = game (env.state [0] ['наблюдение'] ['board']) print (self.env.state [0] ['Наблюдение'] ['alp']) self.action_space = game.get_moves (); self.obs_space = (self.env.state [0] ['Наблюдение'] ['alp']) def get_action (self): return game (self.env.state [0] ['assication'] ['board']). get_moves (); def get_obs_space (self): Вернуть fen_to_board (self.env.state [0] ['asperation'] ['alp']) def Step (Self, Action): награда = 0 g = game (self.env.state [0] ['asmanation'] ['alp']); if (g.board.get_piece (game.xy2i (action [2: 4])) == 'q'): награда = 7 elif g.board.get_piece (game.xy2i (action [2: 4])) == 'n' или g.board.get_piece (game.xy2i (action [2: 4])) == 'b' или g.board.get_piece (game.xy2i (Action [2: 4]) == 'r': награда = 4 elif g.board.get_piece (game.xy2i (action [2: 4])) == 'p': награда = 2 g = game (self.env.state [0] ['asmanation'] ['alp']); g.apply_move (action) Готово = ложь if (g.status == 2): выполнено = true награда = 10 elif g.status == 1: выполнено = true награда = -5 self.env.step ([action, 'none']) self.action_space = list (self.get_action ()) if (self.action_space == []): выполнено = true еще: self.env.step (['none', random.choice (self.action_space)])) g = game (self.env.state [0] ['asmanation'] ['alp']); Если g.status == 2: награда = -10 выполнено = true self.action_space = list (self.get_action ()) вернуть self.env.state [0] ['asmentation'] ['alp'], вознаграждение, сделано
]

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

]

я попытался создать политику вознаграждения, чтобы дать положительные очки для фиксаторов и извлекать кусочки противника, в то время как негативные очки за проигрыш в игре.

] ]

] Создание буфера воспроизведения

]


буфер воспроизведения используется в течение учебного периода для сохранения (состояние, действие, вознаграждение, следующее состояние) выводом Q-NetWork, а затем используется случайным образом для обратного распространения целевой сети

] Building a Chess Agent using DQN]

] Вспомогательные функции

]


Building a Chess Agent using DQN Chessnut возвращает юридические иски в формате UCI, который выглядит как «A2A3», однако для взаимодействия с нейронной сетью я преобразовал каждое действие в отдельный индекс, используя базовый шаблон. Всего насчитывается 64 квадрата, поэтому я решил иметь 64*64 уникальных индексов для каждого хода.

] Building a Chess Agent using DQN я знаю, что не все из 64*64 были бы законными, но я мог бы обрабатывать законность, используя шахматный, и шаблон был достаточно прост.

] ] ] Структура нейронной сети
] импорт факел импортировать Torch.nn как nn импортировать Torch.optim как оптимальный Класс DQN (NN.Module): def __init __ (self): Super (dqn, self) .__ init __ () self.conv_layers = nn.sextential ( 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.sextential ( 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) возврат x DEF PREDICT (SEFT, состояние, valive_action_indices): с Torch.no_Grad (): q_values ​​= self.forward (состояние) Q_VALUES = Q_VALUES.SQUEASE (0) valive_q_values ​​= q_values ​​[valid_action_indices] best_action_relative_index = viad_q_values.argmax (). item () MAX_Q_VALUE = vials_q_values.argmax () BEST_ACTION_INDEX = VALICE_ACTION_INDICE [BEST_ACTION_RELATION_INDEX] вернуть max_q_value, best_action_index ]


] Эта нейронная сеть использует сверточные слои для принятия 12 каналов, а также использует допустимые индексы действия, чтобы отфильтровать прогноз вывода вознаграждения.

]
 from Chessnut import Game
 initial_fen = env.state[0]['observation']['board']
 game=Game(env.state[0]['observation']['board'])
] Реализация агента

]

model = dqn (). target_network = dqn (). to (device) # целевая Q-сеть Optimizer = torch.optim.adam (model.parameters (), lr = 1e-4) Replay_buffer = Replaybuffer (buffer_size = 10000) Эпсилон = 0,5 Гамма = 0,99 batch_size = 15 def Train (эпизоды): Для EP в диапазоне (1, эпизоды 1): Print ('№ «Номер эпизода:», EP) myenv = invcust () Готово = ложь state = myenv.obs_space i = 0 Пока не закончил, а я batch_size: mini_batch = replay_buffer.sample (batch_size) для e в mini_batch: состояние, действие, вознаграждение, next_state, done = e g = игра (next_state) act = g.get_moves (); ind_a = action_index (act) input_state = torch.tensor (fen_to_board (next_state), dtype = torch.float32, tress_gradure = true) .to (device) tpred, _ = target_network.predict (input_state, ind_a) target = reward gamma * tpred * (1 - сделано) act_ind = uci_to_action_index (action) input_state2 = torch.tensor (fen_to_board (state), dtype = torch.float32, tress_grade = true) .to (device) current_q_value = model (input_state2) [0, act_ind] Потеря = (current_q_value - target) ** 2 Optimizer.zero_Grad () потеря.backward () Optimizer.step () Если EP % 5 == 0: target_network.load_state_dict (model.state_dict ())
]


] Это была очень базовая модель, которая не имела шансов на самом деле хорошо работать (и это не так), но она помогла мне понять, как работают DQN немного лучше.

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



] ]

Заявление о выпуске Эта статья воспроизводится по адресу: https://dev.to/ankit_upadhyay_1c38ae52c0/building-a-chess-agent-using-dqn-40po?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с исследованием[email protected], чтобы удалить его.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3