Обучение с подкреплением (RL) — это мощный класс машинного обучения, который, в отличие от обучения с учителем (еще один мощный класс), не требует помеченных данных для обучения машины/агента принятию разумных решений. RL вращается только вокруг двух элементов:
- Окружающая среда: мир (симуляция), с которым взаимодействует актер/машина (т.е. агент).
- Агент: действующее лицо (например, робот, вычислительная машина и т. д.), обученное алгоритмом RL вести себя независимо и разумно.
Большинство ресурсов, относящихся к RL, чрезмерно (и в большинстве случаев исключительно) говорят о методах обучения агентов RL (взаимодействии агента и среды). Эти ресурсы практически не уделяют внимания развитию окружающей среды. Это также имеет смысл, потому что разработка алгоритма RL является ГЛАВНОЙ целью в конце дня. Такие методы, как динамическое программирование, Q-обучение, SARSA, Монте-Карло, глубокое Q-обучение и т. д. сосредоточены исключительно на обучении агента (часто называемого RL-агентом).
RL-AGENT учится вести себя разумно, когда он взаимодействует с СРЕДОЙ, и получает ВОЗНАГРАЖДЕНИЕ или ШТРАФ за его ДЕЙСТВИЕ. Но как мы можем обучить агента, если у нас нет среды? В большинстве практических приложений программисту (программистам) может потребоваться разработать собственную обучающую среду.
В этом блоге мы узнаем, как разработать простую среду RL, Hello-World RL, среду Grid World Environment!
Но сначала давайте узнаем некоторые основы об окружающей среде.
Основы среды RL
Ниже приведены требования к среде RL:
- Набор состояний/наблюдений для среды.
- Награда или штраф от среды к агенту.
- Набор действий для агента в пределах среды.
Проще говоря, среда RL содержит информацию обо всех возможных действиях, которые может предпринять агент, о состояниях, которых агент может достичь после этих действий, а также о вознаграждении или штрафе (отрицательном вознаграждении), которое среда дает агенту в ответ на взаимодействие.
Среда Grid-World
Ниже приведена иллюстрация среды мира сетки, в которой агент (то есть робот) начинает с начального местоположения (0,0) и пытается достичь целевого местоположения (3,3), шаг за шагом.
В приведенном выше мире сетки 4x4 робот может случайным образом выбирать любое действие из набора {Влево, Вверх, Вправо, Вниз} на каждом шаге. Агент получает награду -1, когда он переходит из одного состояния в другое после совершения действия. Это отрицательное вознаграждение (то есть штраф) заставляет агента завершить путешествие и достичь конечного состояния за минимальное количество шагов.
Если агент хочет выбежать за пределы сетки, он получает штраф -2. Например, если агент выполняет ЛЕВОЕ действие из любого из состояний (0, 0), (0, 1), (0, 2),
(0, 3), он получает штраф -2.
Когда агент переходит из любого из состояний (2, 3), (3, 2) в Конечное состояние (3, 3), он получает награду 0.
Реализация
Мы реализуем мир сетки как класс Python. Скелет окружения приведен ниже. У нас есть конструктор и четыре метода в классе GridWorld_Env. Позже мы покажем, как заполнить эти методы и добавить дополнительный метод по дополнительной причине. Большая часть кода говорит сама за себя, поэтому мы не будем добавлять много деталей. Тем не менее, пожалуйста, дайте мне знать в разделе комментариев, если необходимы дополнительные пояснения или среда может быть улучшена.
class GridWorld_Env: def __init__(self): pass # reset the agent when an episode begins def reset(self): pass # Agent takes the step, i.e. take action to interact with the environment def step(self, action): pass # Action reward given to the agent def get_reward(self): pass # Actual action that agent takes. def take_action(self): pass
Вот оно!
Это все, что нужно для создания окружения!
Теперь давайте заполним класс среды. Запомните набор действий {Влево, Вверх, Вправо, Вниз}, награды 0, -1, -2 и состояния (x, y): (0,0) → (3,3)
class GridWorld_Env: ''' Important paramenters --> self.x, self.y : x,y coordinate for the grid agent. --> self.done : Flag variable which turns True when (i) either episode ends, or (ii) maximum number of steps (200) are acheived in the episode. --> self.MAX_HOR_VAL, self.MAX_VER_VAL : Maximuma Horizontal and Vertical grid size of the environment. ''' # Constructor for GridWorld_Env Object, i.e. our agent def __init__(self, hor, ver): self.actions = ["left", "up", "right", "down"] self.x = 0 self.y = 0 self.MAX_HOR_VAL = hor-1 self.MAX_VER_VAL = ver-1 self.done = False self.episode_length = 0 self.state_observation = [self.x, self.y] # Reset the agent at the start of each episode def reset(self): self.done = False self.episode_length = 0 self.x, self.y = 0, 0 self.state_observation = [self.x, self.y] return [self.x, self.y] # Returns the number of actions in the action set def action_space(self): return self.actions # Agent takes the step, i.e. take action to interact with the environment def step(self, action): # If agent is at terminal state, end the episode, set self.done to be True if self.state_observation == [self.MAX_HOR_VAL, self.MAX_VER_VAL]: self.done = True return np.array(self.state_observation), self.reward, self.done, self.episode_length elif self.episode_length > 200: self.done = True return np.array(self.state_observation), self.reward, self.done,self.episode_length self.action = action self.reward = self.get_reward() self.state_observation = self.take_action() self.episode_length += 1 if(self.episode_length >= 200): self.done = True return np.array(self.state_observation), self.reward, self.done, self.episode_length def get_reward(self): # If agent tries to run out of the grid, penalize -2 if (self.x == 0 and self.action == "left") or (self.x == self.MAX_HOR_VAL and self.action == "right" ): return -2 elif (self.y == 0 and self.action == "down") or (self.y == self.MAX_VER_VAL and self.action == "up" ): return -2 # If agent reached Terminal state, reward = 0 elif (self.x, self.y) == (self.MAX_HOR_VAL-1, self.MAX_VER_VAL) and self.action == "right": return 0 elif (self.x, self.y) == (self.MAX_HOR_VAL, self.MAX_VER_VAL-1) and self.action == "up": return 0 # For all other states, penalize agent with -1 else: return -1 # Method to take action, remain in the same box if agent tries to run outside the grid, otherwise move one box in the direction of the action def take_action(self): if self.x > -1 and self.x <= self.MAX_HOR_VAL: if (self.action == "left" and self.x == 0) or (self.action == "right" and self.x == self.MAX_HOR_VAL): self.x = self.x elif(self.action == "left"): self.x -= 1 elif(self.action == "right"): self.x += 1 else: self.x = self.x if self.y > -1 and self.y <= self.MAX_VER_VAL: if (self.action == "down" and self.y == 0) or (self.action == "up" and self.y == self.MAX_HOR_VAL): self.y = self.y elif(self.action == "down"): self.y -= 1 elif(self.action == "up"): self.y += 1 else: self.y = self.y return [self.x, self.y]
Эту среду можно протестировать с любым алгоритмом RL. Мы протестировали его с помощью Q-Learning. Полный код (с тестом на Q-обучение) можно найти здесь.
Однако далее мы просто покажем, как агент может вызываться как объект класса GridWorld_Env.
# Since we have 3x3 grid, hence, we define following parameters EPISODES = 100 MAX_HOR_LENGTH = 3 MAX_HOR_LENGTH = 3 agent = GridWorld_Env(MAX_HOR_LENGTH, MAX_VER_LENGTH) ... ... for ep in EPISODES: # Reset the state of agent in the beginning of each episode current_state = agent.reset() done = False ... ... while not done: ... ... # Select action using, for example Q-Learning and take step. next_state, reward, done, _ = agent.step(action_space[action]) ...
Удачи в обучении агента алгоритмам RL! Дайте мне знать в комментарии, если можно сделать дальнейшие улучшения.
Ваше здоровье