Обучение с подкреплением (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! Дайте мне знать в комментарии, если можно сделать дальнейшие улучшения.

Ваше здоровье