Я пытаюсь создать агента Deep Q-Network (DQN), который может научиться играть в игру 2048 .Я ориентируюсь на другие программы и статьи, основанные на игре Snake, и она работала хорошо (, в частности, эта ).
В качестве состояния ввода я использую только сетку сЯ использую (newScore-oldScore-1) тайлы как ноль-массив и в качестве награды, чтобы штрафовать ходы, которые вообще не дают очков.Я знаю, что это не может быть оптимальным, так как можно было бы вознаграждать, оставаясь в живых как можно дольше, но это будет хорошо для первого шага, верно?Тем не менее, я не получаю никаких хороших результатов.
Я пытался настроить макет модели, количество нейронов и слоев, оптимизатор, гамму, скорость обучения, награды, и т. Д. .Я также пытался закончить игру после 5 ходов и оптимизировать только для тех первых пяти ходов, но независимо от того, что я делаю, я не получаю заметного улучшения.Я запускаю его для тысяч игр, и он просто не становится лучше.На самом деле, иногда я получаю худшие результаты, чем полностью случайный алгоритм, поскольку иногда он просто возвращает один и тот же результат для любого ввода и застревает.
Итак, мой вопрос, если я делаю что-то принципиально неправильное?У меня где-то есть маленькая глупая ошибка?Это неправильный подход полностью?(Я знаю, что игру, возможно, довольно легко решить без ИИ, но это выглядело как маленький забавный проект)
Здесь можно увидеть мой ноутбук Jupyter Github .Извините за плохое качество кода, я все еще начинающий, и я знаю, что мне нужно начинать создавать документацию даже для забавных маленьких проектов.
Некоторые фрагменты кода:
Ввод отформатирован как 1, 16 numpy array, также пытался нормализовать значения или использовать только 1 и 0 для занятых и пустых ячеек, но это тоже не помогло.Вот почему я предположил, что это, возможно, скорее концептуальная проблема?
def get_board(self):
grid = self.driver.execute_script("return myGM.grid.cells;")
mygrid = []
for line in grid:
a = [x['value'] if x != None else 0 for x in line]
#a = [1 if x != None else 0 for x in line]
mygrid.append(a)
return np.array(mygrid).reshape(1,16)
Вывод представляет собой индекс {0,3}, представляющий действия вверх, вниз, влево или вправо, и это просто значение свысокий прогнозируемый балл.
prediction = agent.model.predict(old_state)
predicted_move = np.argmax(prediction)
Я пробовал много разных архитектур моделей, но остановился на более простой сети, так как я прочитал, что ненужные сложные структуры часто являются проблемой и ненужной.Однако я не смог найти надежного источника для метода, как получить оптимальный макет, кроме экспериментов, поэтому я был бы рад получить еще несколько предложений там.
model = models.Sequential()
model.add(Dense(16, activation='relu', input_dim=16))
#model.add(Dropout(0.15))
#model.add(Dense(50, activation='relu'))
#model.add(Dropout(0.15))
model.add(Dense(20, activation='relu'))
#model.add(Dropout(0.15))
#model.add(Dense(30, input_dim=16, activation='relu'))
#model.add(Dropout(0.15))
#model.add(Dense(30, activation='relu'))
#model.add(Dropout(0.15))
#model.add(Dense(8, activation='relu'))
#model.add(Dropout(0.15))
model.add(Dense(4, activation='linear'))
opt = Adam(lr=self.learning_rate)
model.compile(loss='mse', optimizer=opt)