Обучаем double DQN играть в простейшую игру где нужно отбивать мяч.
Для экспериментов над входными данными, функцией reward, было принято решение написать свою
игру, а не брать готовую например из Gym.
state.shape = (210, 160, 3)
reward - +1 за удар по мячу, -1 за промах.
Сам метод DQN реализован в dqn_agent так же в dqn_agent добавлена обрезка градиента (-1, 1). Добавлен Multi step - стакает несколько шагов при формировании батча для обучения. И Double_DQN.
Важные фитчи, без которых ничего не работало находятся в wrapper.
- MaxAndSkipEnv - получает n фреймов каждый фрейм переводит в градиент серого и уменьшает до 84х84 и вибирает 1 максимальный
- FrameStack - Просто собирает n фреймов в deque список и возвращает LazyFrames от этого списка
- LazyFrames - Конкатинирует фреймы (в моем случае к=4 и выходной размер 1х84Х336)
Какой можно сделать вывод:
Самое важное оказалось именно в файле wrapper, т.к. до этого было проверено очень много подходов в том числе разные функции реварда, разные входные данные, разные модели и ничего не работало. В итоге сейчас код стал ужасен т.к. добавлено много, как оказалось, не самых нужных фитч.
Думаю здесь больше сработал уклон к человеческому восприятию, что мы не обрабатываем каждый кадр, мы "тормозим". Для нейросети это оказалось полезным, если частота кадров высокая, то соседние кадры несут в себе приблизительно одинаковую информацию и логично их скипать, тем самым уменьшая к-во кадров и бесполеных данных для тренировки