Q-обучение с опытом воспроизведения, а не обучения - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь реализовать опыт воспроизведения (ER) в среде OpenAI taxi-v2.Предполагается, что конвергенция ускорится, но, кажется, агент не учится, когда я включаю воспроизведение опыта.Из литературы предполагается, что ER ускоряет конвергенцию, что означает, что в моей реализации должна быть ошибка кодирования.Я тестирую базовый агент (один без ER) и тот, который использует ER параллельно, чтобы увидеть изменения в производительности.Базовый агент, кажется, учится, как и ожидалось.Я потратил больше времени, чтобы это взяло на себя, и я все еще в замешательстве.Я был бы признателен, если бы кто-нибудь взглянул на код и увидел, где я допустил ошибку в кодировании, и указал мне правильное направление.

Думаю, проблема в функции play_and_train_with_replay.Вот код:

env = gym.make("Taxi-v2")
n_actions = env.action_space.n
replay = ReplayBuffer(1000)
agent = QLearningAgent(alpha=0.5, epsilon=0.25, discount=0.99,
                   get_legal_actions = lambda s: range(n_actions))
# QLearningAgent is a class that implements q-learning.


def play_and_train_with_replay(env, agent, replay=None, 
                           t_max=10**4, replay_batch_size=32):
"""
This function should 
- run a full game, actions given by agent.getAction(s)
- train agent using agent.update(...) whenever possible
- return total reward
:param replay: ReplayBuffer where agent can store and sample (s,a,r,s',done) tuples.
    If None, do not use experience replay
"""
total_reward = 0.0
s = env.reset()


for t in range(t_max):
    # get agent to pick action given state s
    a = agent.get_action(s)
    next_s, r, done, _ = env.step(a)
    agent.update(s,a,r,next_s) # update agent using q-learning

    if replay is not None: # code for agent-experienceReplay
        # store current <s,a,r,s'> transition in buffer
        replay.add(s,a,r,next_s,done)

        # sample replay_batch_size random transitions from replay, 
        slist,alist,rlist,next_slist,donelist = replay.sample(replay_batch_size) # randomly sample a batch of <s,a,r,s',done>


        # then update agent on each of them in a loop

        for indx in range(replay_batch_size): 
            s = slist[indx]
            a = alist[indx]
            r = rlist[indx]
            next_s = next_slist[indx]
            done = donelist[indx]
            agent.update(s,a,r,next_s) 


    s = next_s
    total_reward +=r

    if done:break

return total_reward

Предполагается, что общее вознаграждение будет увеличиваться (и становиться положительным) с каждой итерацией, но с включенным воспроизведением опыта оно выравнивается до диапазона от -40 до -15.

Если вы хотите увидеть, как я реализовал функции replay.add и replay.sample, код приведен ниже.Я не уверен, что где-то там спрятана ошибка, но раньше я ошибался.Этот код ниже прошел все предварительные тесты.

import random
#from collections import OrderedDict, deque
class ReplayBuffer(object):
   def __init__(self, size):
    """
    Create Replay buffer.
    Parameters
    ----------
    size: int
        Max number of transitions to store in the buffer. When the buffer
        overflows the old memories are dropped.


    """
    #self._storage = deque()
    self._storage = []
    self._maxsize = size
    self._next_index = 0

def __len__(self):
    return len(self._storage)

def add(self, obs_t, action, reward, obs_tp1, done):
    '''
    Make sure, _storage will not exceed _maxsize. 
    Make sure, FIFO rule is being followed: the oldest examples has to be removed earlier
    '''
    '''
    data = [OrderedDict({'s':obs_t,
           'a':action,
           'r': reward,
           's_prime': obs_tp1,
           'is_done': done})]

    # add data to storage
    if self.__len__() >= self._maxsize:    
        diff = abs(self._maxsize - self.__len__())
        for _ in range(diff+1): 
            self._storage.popleft()

        self._storage.extend(data)   
    #elif self.__len__()==0: 
    #    self._storage.extend(data)   
    else: 
        self._storage.extend(data)
    '''
    data = (obs_t, action, reward, obs_tp1, done)

    if  self._next_index >= self.__len__():    
        #diff = abs(self._maxsize - self.__len__())
        #for _ in range(diff+1): 
        #    self._storage.pop(0)
        self._storage.append(data)   
    else: 
        self._storage[self._next_index] = data # overrides the first entered data
    self._next_index = (self._next_index + 1)% self._maxsize # checks if the remainder is > 0 when compared to maxsize.


def sample(self, batch_size):
    """Sample a batch of experiences.
    Parameters
    ----------
    batch_size: int
        How many transitions to sample.
    Returns
    -------
    obs_batch: np.array
        batch of observations
    act_batch: np.array
        batch of actions executed given obs_batch
    rew_batch: np.array
        rewards received as results of executing act_batch
    next_obs_batch: np.array
        next set of observations seen after executing act_batch
    done_mask: np.array
        done_mask[i] = 1 if executing act_batch[i] resulted in
        the end of an episode and 0 otherwise.
    """

    #idxes = <randomly generate batch_size integers to be used as indexes of samples            
    _indxs = random.choices(range(self.__len__()), k= batch_size)

    obs_batch, act_batch, rew_batch, next_obs_batch, done_mask = [],[],[],[],[]

    # collect <s,a,r,s',done> for each index            
    '''
    for i in _indxs:    
        obs_batch.append(self._storage[i]['s'])
        act_batch.append(self._storage[i]['a'])
        rew_batch.append(self._storage[i]['r'])
        next_obs_batch.append(self._storage[i]['s_prime'])
        done_mask.append(self._storage[i]['is_done'])

    '''
    for i in _indxs:    
        data = self._storage[i]
        obs_t, action, reward, obs_tp1, done = data
        obs_batch.append(np.array(obs_t, copy=False))
        act_batch.append(np.array(action, copy=False))
        rew_batch.append(np.array(reward, copy=False))
        next_obs_batch.append(np.array(obs_tp1, copy=False))
        done_mask.append(np.array(done, copy=False))

    return np.array(obs_batch), np.array(act_batch), np.array(rew_batch), np.array(next_obs_batch), np.array(done_mask)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...