Мне трудно заставить агента Deep Q-Learning найти оптимальную политику. Вот как моя текущая модель выглядит в TensorFlow:
model = Sequential()
model.add(Dense(units=32, activation="relu", input_dim=self.env.state.size)),
model.add(Dense(units=self.env.allActionsKeys.size, activation="softmax"))
model.compile(loss="mse", optimizer=Adam(lr=0.00075), metrics=['accuracy'])
Для проблемы, над которой я сейчас работаю, self.env.state.size равно 6, а количество возможных действий ('self.env.allActionsKeys.size') равно 30.
Входной вектор состоит из битов, каждый из которых имеет разные диапазоны (впрочем, не слишком разные в этой задаче). Диапазон 2 бит составляет [0,3], для остальных 2 - [0,2] и для оставшихся [0,1]. Пожалуйста, обратите внимание, что это должна быть простая проблема, я также стремлюсь к более сложным, где размер ввода будет, например, 15, а диапазоны могут отличаться немного больше ([0,15], [0 , 3], ...).
Вот как выглядит мой метод поезда:
def train(self, terminal_state):
if len(self.replay_memory) < MIN_REPLAY_MEMORY_SIZE:
return
# Get MINIBATCH_SIZE random samples from replay_memory
minibatch = random.sample(self.replay_memory, MINIBATCH_SIZE)
# Transition: (current_state, action, reward, normalized_next_state, next_state, done)
current_states = np.array([transition[0] for transition in minibatch])
current_qs_minibatch = self.model.predict(current_states, batch_size=MINIBATCH_SIZE, use_multiprocessing=True)
next_states = np.array([transition[3] for transition in minibatch])
next_qs_minibatch = self.model.predict(next_states, batch_size=MINIBATCH_SIZE, use_multiprocessing=True)
env_get_legal_actions = self.env.get_legal_actions
np_max = np.max
X = []
y = []
for index, (current_state, action, reward, normalized_next_state, next_state, done) in enumerate(minibatch):
if not done:
legalActionsIds = env_get_legal_actions(next_state)
max_next_q = np_max(next_qs_minibatch[index][legalActionsIds])
new_q = reward + DISCOUNT * max_next_q
else:
new_q = reward
current_qs = current_qs_minibatch[index].copy()
current_qs[action] = new_q
X.append(current_state)
y.append(current_qs)
self.model.fit(np.array(X), np.array(y), batch_size=MINIBATCH_SIZE, verbose=0, shuffle=False)
, где DISCOUNT = 0,99 и MINIBATCH_SIZE = 64
Я читал это Рекомендуется нормализовать входной вектор, поэтому я протестировал 2 разных метода нормализации атрибутов: min-max norm. и Z-оценка нормы. И, поскольку диапазоны значений не сильно различаются, я также тестировал без нормализации. Ни один из этих методов не оказался лучше других.
Что происходит, так это то, что в начале, на этапе исследования, оценка со временем улучшается, что означает, что модель чему-то учится, но затем, во время фазы исследования фаза эксплуатации, когда значение эпсилон низкое и агент выполняет большую часть действий с жадностью, оценка резко уменьшается, что означает, что на самом деле он не изучил ничего хорошего.
Это мой алгоритм Deep Q-Learning:
epsilon = 1
for episode in range(1, EPISODES+1):
episode_reward = 0
step = 0
done = False
current_state = env_reset()
while not done:
normalized_current_state = env_normalize(current_state)
if np_random_number() > epsilon: # Take legal action greedily
actionsQValues = agent_get_qs(normalized_current_state)
legalActionsIds = env_get_legal_actions(current_state)
# Make the argmax selection among the legal actions
action = legalActionsIds[np_argmax(actionsQValues[legalActionsIds])]
else: # Take random legal action
action = env_sample()
new_state, reward, done = env_step(action)
episode_reward += reward
agent_update_replay_memory((normalized_current_state, action, reward, env_normalize(new_state), new_state, done))
agent_train(done)
current_state = new_state
step += 1
# Decay epsilon
if epsilon > MIN_EPSILON:
epsilon *= EPSILON_DECAY
, где EPISODES = 4000 и EPSILON_DECAY = 0.9995.
Я поигрался со всеми этими гиперпараметрами, но результаты очень похожи. Не знаю, что еще попробовать. Я что-то не так делаю с нормализацией? Есть ли другой более рекомендуемый метод нормализации? Может ли проблема быть в моей модели нейронной сети, которая недостаточно хороша?
Я думаю, не должно быть так сложно заставить ее работать для такой простой задачи, как эта, с размером ввода 6, выходной слой из 30 узлов и скрытый слой из 32.
Обратите внимание, что для той же проблемы я использовал другое представление состояния, используя двоичный массив размером 14, и он отлично работает с теми же гиперпараметрами. В чем тогда может быть проблема, когда я использую это другое представление?