def train_model(self, sars, done):
        (state, action, reward, next_state) = sars

        state = u.t_float32(state)
        action = u.t_float32(action)
        reward = u.t_float32(reward)
        next_state = u.t_float32(next_state)

        value = self.critic(state)
        next_value = self.critic(next_state)

        if done:
            advantage = reward - value
            target = reward
        else:
            advantage = (reward + self.discount_factor * next_value) - value
            target = reward + self.discount_factor * next_value

        self.actor_optimizer.zero_grad()
        probs = self.actor(state)
        actor_loss = -Categorical(probs).log_prob(action) * advantage
        actor_loss.backward()
        self.actor_optimizer.step()

        self.critic_optimizer.zero_grad()
        critic_loss = torch.mean((target.detach() - self.critic(state))**2)
        critic_loss.backward()
        self.critic_optimizer.step()

        if done:
            TrainerMetadata().log(critic_loss, 'critic_loss')
            TrainerMetadata().log(actor_loss, 'actor_loss')
Example #2
0
    def train_model(self, i_episode, current_step, current_sars, current_done):
        s, a, ext_reward, next_s = current_sars
        TrainerMetadata().log(ext_reward,
                              'ext_reward',
                              show_only_last=True,
                              compute_maxmin=True)

        int_reward = 0
        if self.use_intrinsic:
            int_reward = self.algorithm_im.get_reward(i_episode, current_step,
                                                      current_sars,
                                                      current_done)
            TrainerMetadata().log(int_reward,
                                  'int_reward',
                                  show_only_last=True,
                                  compute_maxmin=True)

        if current_done:
            self.algorithm_im.scale_annealing()

        int_ext_reward, weighted_int, weighted_ext = self.algorithm_im.weighted_reward(
            int_reward, ext_reward)
        TrainerMetadata().log(int_ext_reward,
                              'int_ext_reward',
                              show_only_last=True,
                              compute_maxmin=True)

        current_sars = (s, a, int_ext_reward, next_s)
        self.algorithm_rl.train_model(current_sars, current_done)
Example #3
0
    def get_weighted_reward(self, i_epoch, current_step, current_sars,
                            current_done):
        current_state, current_action, ext_reward, next_state = current_sars
        TrainerMetadata().log(ext_reward,
                              'ext_reward',
                              show_only_last=True,
                              compute_maxmin=True)

        int_reward = 0
        if self.use_intrinsic:
            int_reward = self.algorithm_im.get_reward(i_epoch, current_step,
                                                      current_sars,
                                                      current_done)
            TrainerMetadata().log(int_reward,
                                  'int_reward',
                                  show_only_last=True,
                                  compute_maxmin=True)

        if current_done:
            self.algorithm_im.scale_annealing()

        int_ext_reward, weighted_int, weighted_ext = self.algorithm_im.weighted_reward(
            int_reward, ext_reward)
        TrainerMetadata().log(int_ext_reward,
                              'int_ext_reward',
                              show_only_last=True,
                              compute_maxmin=True)

        return int_ext_reward
    def train_model(self):
        # 메모리에서 일정 크기만큼 기억을 불러온다
        # 그 후 기억을 모아 각 변수별로 모은다. (즉, 전치행렬)
        transitions = self.memory.sample(self.batch_size)
        batch = self.transition_structure(*zip(*transitions))

        # 텐서의 집합에서 고차원 텐서로
        # tuple(tensor, ...) -> tensor()
        state_batch = torch.cat(batch.state).to(device)
        action_batch = torch.cat(batch.action).to(device)
        reward_batch = torch.cat(batch.reward).to(device)
        next_state_batch = torch.cat(batch.next_state).to(device)

        # <평가망 최적화>
        # (무엇을, 어디서, 어떻게, 왜)
        # 각각의 기억에 대해, 타겟 정책망에, 다음 상태를 넣어서, 다음 타겟 액션을 구한다.
        # 각각의 기억에 대해, 타겟 평가망에, 다음 상태와 타겟 액션을 넣어서, 다음 타겟 보상을 구한다.
        target_actions = self.target_actor(next_state_batch)
        target_rewards = self.target_critic(next_state_batch, target_actions)
        # 현재 보상에 타겟 보상을 더해서 예측한 보상을 구한다.
        expected_rewards = reward_batch.unsqueeze(
            dim=1) + self.discount_factor * target_rewards
        predicted_rewards = self.critic(state_batch, action_batch)

        # 평가망의 예측 보상과 타겟 평가망의 예측 보상을 MSE 비교 후 업데이트
        self.critic_optimizer.zero_grad()
        critic_loss = nn.MSELoss().to(device)
        critic_loss = critic_loss(expected_rewards, predicted_rewards)
        critic_loss.backward()
        self.critic_optimizer.step()

        # <정책망 최적화>
        self.actor_optimizer.zero_grad()
        predicted_actions = self.actor(state_batch)
        q_output = self.critic(state_batch, predicted_actions)
        # actor_loss = -1*torch.sum(q_output).to(device)
        # sum 이 아니라 mean 인 이유
        # -> sum이든 mean이든 똑같으나 (N은 같으므로)
        # -> sum 했을 때 값이 많이 커지니까 그냥 보기 좋게 mean으로..
        actor_loss = -1 * torch.mean(q_output).to(device)

        # 정책망의 예측 보상을 정책 그라디언트로 업데이트
        actor_loss.backward()
        self.actor_optimizer.step()

        # 현재 평가망, 정책망의 가중치를 타겟 평가망에다 덮어쓰기
        u.soft_update_from_to(src_nn=self.critic,
                              dst_nn=self.target_critic,
                              tau=self.soft_target_update_tau)
        u.soft_update_from_to(src_nn=self.actor,
                              dst_nn=self.target_actor,
                              tau=self.soft_target_update_tau)

        TrainerMetadata().log(critic_loss, 'critic_loss')
        TrainerMetadata().log(actor_loss, 'actor_loss')
Example #5
0
    def _line_search(self, old_loss, loss_grad, step_vector_x, advantage_batch,
                     s_batch, old_policy, a_batch):
        old_actor = copy.deepcopy(self.actor)

        actor_flat_params = parameters_to_vector(self.actor.parameters())
        expected_improve = (loss_grad * step_vector_x).sum(0, keepdim=True)
        expected_improve = expected_improve.cpu().numpy()

        i, line_search_succeed = -1, False
        for i in range(self.backtrack_iters):
            # 라인 서치로 정책 업데이트
            backtrack_ratio = self.backtrack_coeff**i
            constraint_params = actor_flat_params + backtrack_ratio * step_vector_x
            vector_to_parameters(constraint_params, self.actor.parameters())

            # 바꾼 actor를 기반으로 다시 평균(log정책(a|s)*A) 구해봄
            meow, logstd, std = self.actor(s_batch)
            new_policy = self._log_density(a_batch, meow, std, logstd)
            constraint_loss = self._surrogate_loss(
                old_policy=old_policy,
                new_policy=new_policy,
                advantage_batch=advantage_batch)
            loss_improve = (constraint_loss - old_loss).detach().cpu().numpy()
            weighted_expected_improve = backtrack_ratio * expected_improve
            kl = kl_divergence(new_actor=self.actor,
                               old_actor=old_actor,
                               s_batch=s_batch)
            kl = kl.mean()

            TrainerMetadata().log(kl, 'KL', 'current_kl', compute_maxmin=True)
            TrainerMetadata().log(self.max_kl, 'KL', 'max_kl')
            TrainerMetadata().log(loss_improve / weighted_expected_improve,
                                  'real / expected (improve)',
                                  'real_ratio',
                                  compute_maxmin=True)
            TrainerMetadata().log(0.5, 'real / expected (improve)',
                                  'threshold ')
            # TrainerMetadata().log(expected_improve, 'expected_improve', compute_maxmin=True)

            # see https://en.wikipedia.org/wiki/Backtracking_line_search
            # TODO: 0.5 인 이유? 1.0 보다 커야 개선된 것 아닌가
            # 일단 Armijo used ​1⁄2 for both c and tau in a paper he published in 1966
            if kl < self.max_kl and (loss_improve /
                                     weighted_expected_improve) > 0.5:
                line_search_succeed = True
                break

        TrainerMetadata().console_log('KL_iter', i)

        if not line_search_succeed:
            self.actor = copy.deepcopy(old_actor)
            print('policy update does not impove the surrogate')
Example #6
0
    def train_model(self, i_episode, step, done):
        # 메모리에서 일정 크기만큼 기억을 불러온다
        # 그 후 기억을 모아 각 변수별로 모은다. (즉, 전치행렬)
        # TODO: random과 zip func 글카에서 하기
        transitions = self.memory.sample(self.batch_size)
        # SARS = State, Action, Reward, next State
        sars_batch = self.transition_structure(*zip(*transitions))

        # TODO: 이거 튜플로 묶으면 다시 GPU에서 CPU로 오나?
        # 텐서의 집합에서 고차원 텐서로
        # tuple(tensor, ...) -> tensor()
        s = torch.cat(sars_batch.state).to(self.device)
        a = torch.cat(sars_batch.action).to(self.device)
        ext_r = torch.cat(sars_batch.reward).to(self.device)
        next_s = torch.cat(sars_batch.next_state).to(self.device)

        # int_r = self.algorithm_im.get_reward(i_episode, step, s, a, next_s)
        int_r = self.im.get_reward(i_episode, step, transitions, s, a, next_s)
        ext_r = self.im.weighted_reward_batch(int_r, ext_r)

        critic_loss, actor_loss = self.ddpg.train_model(s, a, ext_r, next_s)

        if done:
            TrainerMetadata().log(critic_loss, 'critic_loss')
            TrainerMetadata().log(actor_loss, 'actor_loss')
            TrainerMetadata().log(torch.max(int_r), 'int_reward', 'max')
            TrainerMetadata().log(torch.mean(int_r), 'int_reward', 'mean')
            TrainerMetadata().log(torch.min(int_r), 'int_reward', 'min')
            TrainerMetadata().log(torch.max(ext_r), 'ext_reward', 'max')
            TrainerMetadata().log(torch.mean(ext_r), 'ext_reward', 'mean')
            TrainerMetadata().log(torch.min(ext_r), 'ext_reward', 'min')
    def __init__(self, state_size, action_size):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size, self.action_size = state_size, action_size
        self.value_size = 1

        # 모델 빌드
        self.actor = Actor(self.state_size, self.action_size).to(self.device)
        self.critic = Critic(self.state_size, self.value_size).to(self.device)

        # Optimizer
        self.actor_optimizer = optim.Adam(self.actor.parameters(),
                                          lr=self.learning_rate_actor)
        # critic 에만 L2 weight decay 넣음
        self.critic_optimizer = optim.Adam(self.critic.parameters(),
                                           lr=self.learning_rate_critic)

        self.register_serializable([
            'self.actor',
            'self.critic',
            'self.actor_optimizer',
            'self.critic_optimizer',
        ])
Example #8
0
    def __init__(self,
                 algorithm_im,
                 algorithm_rl,
                 state_size,
                 action_size,
                 action_range,
                 use_intrinsic=True):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size, self.action_size = state_size, action_size
        # TODO: 정규화된 입력인지 검사 문구 넣고 range 빼기
        self.action_low, self.action_high = action_range

        self.algorithm_im, self.algorithm_rl = algorithm_im, algorithm_rl
        self.use_intrinsic = use_intrinsic
        if self.use_intrinsic is False:
            self.algorithm_im.intrinsic_reward_ratio = 0

        self.register_serializable([
            'algorithm_im',
            'algorithm_rl',
        ])
Example #9
0
    def __init__(self, state_size, action_size):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size, self.action_size = state_size, action_size

        # 모델 빌드
        self.actor = Actor(self.state_size, self.action_size).to(self.device)
        self.critic = Critic(self.state_size).to(self.device)

        # Optimizer
        # critic 에만 L2 weight decay 넣음
        self.critic_optimizer = optim.Adam(self.critic.parameters(),
                                           lr=self.learning_rate_critic,
                                           weight_decay=self.l2_weight_decay)

        self.transition_structure = Transition
        self.memory = list()

        self.gae = GAE(gamma=self.gamma)

        self.register_serializable([
            'self.actor',
            'self.critic',
            'self.critic_optimizer',
        ])
def conjugate_gradient(func_Ax, s_batch, loss_grad_data, cg_iters=10, residual_tol=1e-10):
    """
    Demmel p 312

    공역 구배법 = 켤레 기울기법
    == 설명 (from 위키피디아 한국어판) ==
    Ax = b 를 풀고 싶다고 하자. 이 때 A는 (대칭행렬)이며 (대칭행렬의 이차형식 > 0)이어야 한다.
    켤레 벡터 뜻은 대충 A의 이차형식을 0으로 만드는 두 벡터임..

    아무튼 정답벡터 x를 (x = α*켤레벡터들의 합)으로 나타낼 수 있다고 하면
    어찌어찌 잘 하면 α = <p, b> / |p|^2 으로 나타낼 수 있다고 함

    근데 차원이 커지면 이거 풀기 귀찮으니까 대충 때려 맞추고 점점 해답에 접근하는 방법을 씀
    즉 r0 = b - Ax0 라 하고 이걸로 α 구함
    이 α를 기준으로 x와 r을 다시 나타냄
    다시 나타낸 r로 잘 구함... (반복)

    대충 이런 개념

    z = Ax
    v =  r*r
        -----
        p*(Ax)

    new_x = old_x + v * p
    new_r = old_r + v * Ax
    meow = new_r * new_r
           -------------
               r * r
    new_p = r + (meow * p)
    """
    device = TrainerMetadata().device

    p = loss_grad_data.clone().to(device)
    r = loss_grad_data.clone().to(device)
    x = torch.zeros_like(loss_grad_data).to(device)
    dot_rr = torch.dot(r, r).to(device)

    for i in range(cg_iters):
        # 원래 여기서 z = Ax를 계산해야 한다
        # 그런데 A를 갖고 있기 힘드니깐 대충 Ax 예상해서 던져주는 놈을 사용할 것이다
        # z = A * p
        # z = func_Ap
        z = func_Ax((p, s_batch))
        alpha = dot_rr / torch.dot(p, z).to(device)
        x += alpha * p
        r -= alpha * z
        new_dot_rr = torch.dot(r, r).to(device)
        meow = new_dot_rr / dot_rr
        p = r + (meow * p)

        dot_rr = new_dot_rr
        if dot_rr < residual_tol:
            break

    return x
    def __init__(self, state_size, action_size):
        super(Actor, self).__init__()
        self.device = TrainerMetadata().device
        self.layer_sizes = [state_size, 24, action_size]

        self.linear1 = nn.Linear(self.layer_sizes[0], self.layer_sizes[1])
        self.linear2 = nn.Linear(self.layer_sizes[1], self.layer_sizes[2])
        self.head = nn.Softmax(dim=-1)
        u.fanin_init(self.linear1.weight)
        u.fanin_init(self.linear2.weight)
Example #12
0
    def __init__(self, state_size, action_size):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device
        self.region_head = Region(state_size, action_size)

        self.register_serializable([
            'self.region_head',
        ])
    def __init__(self, state_size, action_size, action_range=(-1, 1)):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size, self.action_size = state_size, action_size
        # TODO: 정규화된 입력인지 검사 문구 넣고 range 빼기
        self.action_low, self.action_high = action_range

        # 모델 빌드
        self.actor = Actor(self.state_size, self.action_size).to(self.device)
        self.critic = Critic(self.state_size, self.action_size).to(self.device)
        self.target_actor = Actor(self.state_size, self.action_size).to(self.device)
        self.target_critic = Critic(self.state_size, self.action_size).to(self.device)

        # 타겟 정책망, 타겟 평가망 가중치를 각각 정책망, 평가망 가중치로 초기화
        self.target_actor.load_state_dict(self.actor.state_dict())
        self.target_critic.load_state_dict(self.critic.state_dict())

        # 타겟망들은 오차계산 및 업데이트 안 하는 평가 전용모드임을 선언
        self.target_actor.eval()
        self.target_critic.eval()

        # Optimizer
        self.actor_optimizer = optim.Adam(
            self.actor.parameters(),
            lr=self.learning_rate_actor
        )
        # critic 에만 L2 weight decay 넣음
        self.critic_optimizer = optim.Adam(
            self.critic.parameters(),
            lr=self.learning_rate_critic,
            weight_decay=self.l2_weight_decay
        )

        # 리플레이 메모리
        # DQN, DDPG에서 제안하고 쓰는 개념이므로 정의는 따로 두더라도 인스턴스는 알고리즘 내부에서 갖고 있는다
        self.transition_structure = Transition
        self.memory = ReplayMemory(self.memory_maxlen, self.transition_structure)

        # 오른스타인-우렌벡 과정
        self.noise = OrnsteinUhlenbeckNoise(self.action_size)

        self.register_serializable([
            'self.actor',
            'self.critic',
            'self.target_actor',
            'self.target_critic',
            'self.actor_optimizer',
            'self.critic_optimizer',
            'self.memory',
            'self.noise',
        ])
    def __init__(self, state_size, value_size):
        super(Critic, self).__init__()
        self.device = TrainerMetadata().device
        self.layer_sizes = [state_size, 24, 24, value_size]

        self.linear1 = nn.Linear(self.layer_sizes[0], self.layer_sizes[1])
        self.linear2 = nn.Linear(self.layer_sizes[1], self.layer_sizes[2])
        self.head = nn.Linear(self.layer_sizes[2], self.layer_sizes[3])
        u.fanin_init(self.linear1.weight)
        u.fanin_init(self.linear2.weight)
        nn.init.uniform_(self.head.weight, a=-3 * 10e-4, b=3 * 10e-4)
    def __init__(self, state_size, action_size):
        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        self.state_size = state_size
        self.action_size = action_size
        self.value_size = 1

        self.actor = self.build_actor()
        self.critic = self.build_critic()
        self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=self.learning_rate_actor)
        self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=self.learning_rate_critic)
    def _surrogate_loss(self, old_policy, new_policy, advantage_batch):
        # CPI = Conservative Policy Iteration
        improve_ratio = self._improve_ratio(old_policy, new_policy)
        clipped_ratio = torch.clamp(improve_ratio, 1 - self.epsilon,
                                    1 + self.epsilon)

        TrainerMetadata().log(torch.max(improve_ratio),
                              'improve_ratio',
                              'max',
                              show_only_last=True,
                              compute_maxmin=True)
        TrainerMetadata().log(torch.min(improve_ratio),
                              'improve_ratio',
                              'min',
                              show_only_last=True,
                              compute_maxmin=True)
        # TODO: advantage 나중에 곱해보기?
        loss_cpi = improve_ratio * advantage_batch
        loss_clip = clipped_ratio * advantage_batch
        loss = torch.min(loss_cpi, loss_clip).mean()
        return loss.to(self.device)
Example #17
0
    def __init__(self, state_size, action_size):
        super().__init__()
        self.device = TrainerMetadata().device
        # 64, 64는 논문 저자 공식 레포지토리
        self.layer_sizes = [state_size, 64, 64, action_size]

        self.linear1 = nn.Linear(self.layer_sizes[0], self.layer_sizes[1])
        self.linear2 = nn.Linear(self.layer_sizes[1], self.layer_sizes[2])
        self.head = nn.Linear(self.layer_sizes[2], self.layer_sizes[3])

        # TODO: (개선) 초기화 이해 안 감 -> 공식 레포가 이렇지만 다른 초기화는?
        self.head.weight.data.mul_(0.1)
        self.head.bias.data.mul_(0.0)
    def __init__(self, state_size, action_size, action_range=(-1, 1)):
        super(DQNNetwork, self).__init__()
        self.device = TrainerMetadata().device
        self.layer_sizes = [state_size, 24, 24, action_size]

        # TODO: 정규화된 입력인지 검사 문구 넣고 range 빼기
        self.action_low, self.action_high = action_range
        self.linear1 = nn.Linear(self.layer_sizes[0], self.layer_sizes[1])
        self.linear2 = nn.Linear(self.layer_sizes[1], self.layer_sizes[2])
        self.head = nn.Linear(self.layer_sizes[2], self.layer_sizes[3])
        u.fanin_init(self.linear1.weight)
        u.fanin_init(self.linear2.weight)
        nn.init.uniform_(self.head.weight, a=-3 * 10e-3, b=3 * 10e-3)
Example #19
0
    def __init__(self, algorithm_rl, state_size, action_size):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size, self.action_size = state_size, action_size
        self.algorithm_rl = algorithm_rl

        self.register_serializable([
            'algorithm_rl',
        ])
    def train_model(self, sars, done):
        # 메모리에서 일정 크기만큼 기억을 불러온다
        # 그 후 기억을 모아 각 변수별로 모은다. (즉, 전치행렬)
        # TODO: random과 zip func 글카에서 하기
        transitions = self.memory.sample(self.batch_size)
        # SARS = State, Action, Reward, next State
        sars_batch = self.transition_structure(*zip(*transitions))

        # TODO: 이거 튜플로 묶으면 다시 GPU에서 CPU로 오나?
        # 텐서의 집합에서 고차원 텐서로
        # tuple(tensor, ...) -> tensor()
        s_batch = torch.stack(sars_batch.state).to(self.device)
        a_batch = torch.stack(sars_batch.action).to(self.device)
        r_batch = torch.stack(sars_batch.reward).to(self.device)
        next_s_batch = torch.stack(sars_batch.next_state).to(self.device)

        self.critic_optimizer.zero_grad()
        critic_loss = self.get_critic_loss(s_batch, a_batch, r_batch, next_s_batch)
        # 예측한 보상과 향후 기대하는 보상을 MSE 비교 후 업데이트
        #   ||r' - [r + (r+1)']|| = 0
        # ∴ ||r' - (r+1)'      || = r  (현재 Q함수와 다음 Q함수 차이가 딱 실제 보상이 되도록 학습)
        critic_loss.backward()
        self.critic_optimizer.step()

        self.actor_optimizer.zero_grad()
        actor_loss = self.get_actor_loss(s_batch)
        # 정책망의 예측 보상을 정책 그라디언트로 업데이트
        # ∇θµ[Q(s,a|θ)] ∇θµ[µ(s|θµ)]
        actor_loss.backward()
        self.actor_optimizer.step()

        # 현재 평가망, 정책망의 가중치를 타겟 평가망에다 덮어쓰기
        u.soft_update_from_to(src_nn=self.critic, dst_nn=self.target_critic, tau=self.soft_target_update_tau)
        u.soft_update_from_to(src_nn=self.actor, dst_nn=self.target_actor, tau=self.soft_target_update_tau)

        if done:
            TrainerMetadata().log(critic_loss, 'critic_loss', show_only_last=False)
            TrainerMetadata().log(actor_loss, 'actor_loss', show_only_last=False)
    def __init__(self, state_size, action_size):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        self.state_size, self.action_size = state_size, action_size

        self.register_serializable([
            'self.intrinsic_reward_ratio',
            'self.intrinsic_reward_ratio_annealing',
            'self.intrinsic_reward_ratio_decay',
            'self.intrinsic_reward_ratio_min',
        ])
    def train_model(self, sars, done):
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

        # 메모리에서 일정 크기만큼 기억을 불러온다
        # 그 후 기억을 모아 각 변수별로 모은다. (즉, 전치행렬)
        # TODO: random과 zip func 글카에서 하기
        transitions = self.memory.sample(self.batch_size)
        # SARS = State, Action, Reward, next State
        sars_batch = self.transition_structure(*zip(*transitions))

        # TODO: 이거 튜플로 묶으면 다시 GPU에서 CPU로 오나?
        # 텐서의 집합에서 고차원 텐서로
        # tuple(tensor, ...) -> tensor()
        s_batch = torch.stack(sars_batch.state).to(self.device)
        a_batch = torch.stack(sars_batch.action).to(self.device)
        r_batch = torch.stack(sars_batch.reward).to(self.device)
        next_s_batch = torch.stack(sars_batch.next_state).to(self.device)
        done_batch = torch.stack(sars_batch.done).to(self.device)

        # 정책망에 각각의 기억에 대해 상태를 넣어서 각각의 액션 보상을 구한다.
        # 그 다음에 선택한 액션 쪽의 보상을 가져온다.
        state_action_values = self.policy(s_batch).gather(1, a_batch)

        # 타겟망 예측에서, 아직 안 죽은 거에만 큐함수 추정을 더해주기 위해 마스크를 만들기
        # 어렵게 마스크를 만드는 이유? 한번에 모아서 신경망에 보내면 실행 속도가 빨라짐..
        # 안 죽었을 때의 상태들만 가져오기
        not_done = [not i for i in done_batch]
        non_final_mask = u.t_uint8(not_done).squeeze().to(self.device)
        non_final_next_states = torch.stack(
            list(compress(next_s_batch, not_done)))

        # 안 죽었을 때의 타겟망 보상 추정하기
        next_state_values = torch.zeros(len(s_batch), device=self.device)
        next_state_values[non_final_mask] = self.target_policy(
            non_final_next_states).max(1)[0].detach()
        next_state_values = next_state_values.unsqueeze(dim=1)
        # 기존 보상에 안 죽었을 때만 큐함수 추정을 더하기
        expected_state_action_values = r_batch + (self.discount_factor *
                                                  next_state_values)

        # 정책망의 예측 보상과 타겟망의 예측 보상을 MSE 비교
        self.policy_optimizer.zero_grad()
        loss = nn.MSELoss().to(self.device)
        loss = loss(state_action_values, expected_state_action_values)
        loss.backward()
        self.policy_optimizer.step()

        if done:
            TrainerMetadata().log(loss, 'policy_loss')
Example #23
0
def kl_divergence(new_actor, old_actor, s_batch):
    device = TrainerMetadata().device
    meow, logstd, std = new_actor(s_batch)
    meow_old, logstd_old, std_old = old_actor(s_batch)
    meow_old = meow_old.detach()
    std_old = std_old.detach()
    logstd_old = logstd_old.detach()

    # kl divergence between old policy and new policy : D( pi_old || pi_new )
    # pi_old -> mu0, logstd0, std0 / pi_new -> mu, logstd, std
    # be careful of calculating KL-divergence. It is not symmetric metric
    kl = logstd_old - logstd + (std_old.pow(2) + (meow_old - meow).pow(2)) / \
         (2.0 * std.pow(2)) - 0.5

    return kl.sum(1, keepdim=True)
Example #24
0
    def __init__(self, state_size):
        super().__init__()
        self.device = TrainerMetadata().device
        # 액션 크기는 안 받는 이유는? Q(s, a) 아닌가?
        # Q 함수 추정이 아니라 V (Value) 추정이다
        # 나중에 GAE 에서 이득(A) 계산할 때 V가 필요
        self.layer_sizes = [state_size, 64, 64, 1]

        self.linear1 = nn.Linear(self.layer_sizes[0], self.layer_sizes[1])
        self.linear2 = nn.Linear(self.layer_sizes[1], self.layer_sizes[2])
        self.head = nn.Linear(self.layer_sizes[2], self.layer_sizes[3])

        # TODO: 초기화 이해 안 감 -> 공식 레포가 이렇지만 다른 초기화는?
        self.head.weight.data.mul_(0.1)
        self.head.bias.data.mul_(0.0)
Example #25
0
    def __init__(self, state_size, action_size):
        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        self.state_size = state_size
        self.action_size = action_size

        self.policy_model = self.build_model()
        self.target_model = self.build_model()
        self.update_target_model()
        self.target_model.eval()

        self.policy_optimizer = optim.Adam(self.policy_model.parameters(),
                                           lr=self.learning_rate_dqn)

        self.transition_structure = Transition
        self.memory = ReplayMemory(self.memory_maxlen,
                                   self.transition_structure)
Example #26
0
    def train_model(self):
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

        # 메모리에서 일정 크기만큼 기억을 불러온다
        # 그 후 기억을 모아 각 변수별로 모은다. (즉, 전치행렬)
        transitions = self.memory.sample(self.batch_size)
        batch = self.transition_structure(*zip(*transitions))

        target = []
        target_val = []

        # 정책망에 각각의 기억에 대해 상태를 넣어서 각각의 액션 보상을 구한다.
        # 그 다음에 선택한 액션 쪽의 보상을 가져온다.
        for i in range(self.batch_size):
            state = batch.state[i]
            action = batch.action[i]
            target.append(self.policy_model(state).squeeze()[action])

        # 안 죽었을 때의 타겟망 보상 추정하기
        for i in range(self.batch_size):
            next_state = batch.next_state[i]
            target_val.append(self.target_model(next_state))

        # 기존 보상에 안 죽었을 때만 큐함수 추정을 더하기
        for i in range(self.batch_size):
            done = batch.done[i]
            reward = batch.reward[i]
            if done:
                target_val[i] = u.t_float32(reward).squeeze()
            else:
                target_val[i] = reward + self.discount_factor * torch.max(
                    target_val[i]).to(self.device)

        # 정책망의 예측 보상과 타겟망의 예측 보상을 MSE 비교
        self.policy_optimizer.zero_grad()
        loss = nn.MSELoss().to(self.device)
        loss = loss(torch.stack(target), torch.stack(target_val))
        loss.backward()
        self.policy_optimizer.step()

        TrainerMetadata().log(loss, 'policy_loss')
    def __init__(self, state_size, action_size, action_range=(-1, 1)):
        super().__init__()

        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size, self.action_size = state_size, action_size
        # TODO: 정규화된 입력인지 검사 문구 넣고 range 빼기
        self.action_low, self.action_high = action_range

        # 모델 빌드
        self.policy = DQNNetwork(self.state_size,
                                 self.action_size).to(self.device)
        self.target_policy = DQNNetwork(self.state_size,
                                        self.action_size).to(self.device)

        # 타겟 정책망을 정책망 가중치로 초기화
        self.target_policy.load_state_dict(self.policy.state_dict())

        # 타겟망은 오차계산 및 업데이트 안 하는 평가 전용모드임을 선언
        self.target_policy.eval()

        # Optimizer
        self.policy_optimizer = optim.Adam(self.policy.parameters(),
                                           lr=self.learning_rate_policy)

        # 리플레이 메모리
        # DQN, DDPG에서 제안하고 쓰는 개념이므로 정의는 따로 두더라도 인스턴스는 알고리즘 내부에서 갖고 있는다
        self.transition_structure = Transition
        self.memory = ReplayMemory(self.memory_maxlen,
                                   self.transition_structure)

        self.register_serializable([
            'self.policy',
            'self.target_policy',
            'self.policy_optimizer',
            'self.memory',
            'self.epsilon',
            'self.epsilon_decay',
            'self.epsilon_min',
        ])
Example #28
0
    def __init__(self, state_size, action_size, action_range=(-1, 1)):
        self._set_hyper_parameters()
        self.device = TrainerMetadata().device

        # 기본 설정
        self.state_size = state_size
        self.action_size = action_size

        # TODO: 정규화된 입력인지 검사 문구 넣고 range 빼기
        self.action_low, self.action_high = action_range

        self.ddpg = DDPG(self.state_size, self.action_size, action_range)
        self.im = PredictiveSurpriseMotivation(self.state_size,
                                               self.action_size)

        # TODO: 리플레이 메모리를 DDPG 알고리즘에서 분리해서 저장하는 게 아름다운가?
        # 리플레이 메모리
        self.transition_structure = Transition
        self.memory = ReplayMemory(self.memory_maxlen,
                                   self.transition_structure)
Example #29
0
    def draw_line(self, y, x=None, x_auto_increment=None, interval=None, env=None, win=None, variable=None):
        if x is None or x == 0:
            if x_auto_increment == 'global_step':
                x = TrainerMetadata().global_step
            elif x_auto_increment == 'per_variable_step':
                x = self.per_variable_step[win]
                self.per_variable_step[win] += 1

        interval = interval if interval else self.default_interval
        env = env if env else self.default_env
        win = win if win else self.default_win
        variable = variable if variable else self.default_variable

        if x % interval == 0:
            # Visdom은 numpy array를 입력으로 받음
            x = x if isinstance(x, np.ndarray) else np.array([x])
            y = y if isinstance(y, np.ndarray) else np.array([y])

            win = self._abbreviate_win_name(env, win)
            self.viz.line(X=np.array([x]), Y=np.array([y]), name=variable, win=win, update='append', opts={'title': win})
def execute(X, n_clusters, device=None, tol=1e-4):
    """lloyd algorithm_rl

        Args:
          X: n차원 Numpy 배열 (float 가정)
          n_clusters: 클러스터 갯수
          device: PyTorch device 오브젝트
          tol: 계산 도중 중심 이동 간격 최소 기대치
        Returns:
          choice_cluster: X가 속한 클러스터 인덱스 (0~n-1)
          initial_state: 초기 좌표
    """
    device = device if device else TrainerMetadata().device
    X = torch.from_numpy(X).float().to(device)

    initial_state = get_initial_state(X, n_clusters)

    while True:
        # Expectation
        dis = _pairwise_distance(X, initial_state)

        choice_cluster = torch.argmin(dis, dim=1)

        initial_state_pre = initial_state.clone()

        for index in range(n_clusters):
            selected = torch.nonzero(choice_cluster == index).squeeze()

            selected = torch.index_select(X, 0, selected)
            # Maximization
            initial_state[index] = selected.mean(dim=0)

        center_shift = torch.sum(torch.sqrt(torch.sum((initial_state - initial_state_pre) ** 2, dim=1)))

        if center_shift ** 2 < tol:
            break

    return choice_cluster, initial_state