Policy Gradient 기반 정규 분포 DQN 강화학습 원리 및 정리 - Whitmem
Policy Gradient 기반 정규 분포 DQN 강화학습 원리 및 정리
AI Development Study
2025-04-17 23:43 게시 b23c92cfb705bd70d35a

0
0
31
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
금일은 집에서 DQN 강화 학습에 대해 조금 익혀보았다. 과거 오목 게임을 개발하기 위해 DQN 기법을 사용한 적이 있다. 이 때 기억으로는 제법 학습이 되지 않았는데, 일반 모델 DQN의 한계인 듯 싶다. 따라서 보통 오목 게임을 개발 할 때에는 DQN 생으로 사용하지 않고, 몬테 카를로 기법을 응용하여 신경망을 학습한다고 한다.
아무튼, 상기 오목 게임에 사용된 DQN 은 행동 기반, Q-learning 알고리즘을 사용해 신경망을 학습하였는데, 이번에는 Policy Gradient 기반 학습 방법을 익혀보았다.
Q-learning 기법에서는, 해당 행위가 유도 되기를 바라는 액션 Output 의 정답 부분을 다음 Max Q 와 합하여 보상 점수를 주는 방법을 이용한다.
하지만 Policy Gradient 는 애초 처음부터 정책 신경망을 원하는 방향으로 기울기를 주어 학습을 시키는 방법이다.
하지만 해당 학습 방법이 약간 잘못 된것인지, 제대로 동작하지는 않는다. 해당 오류 부분을 조만간 찾아서 다시 리뷰할 예정이다.
우선 결론부터 말하자면, 신경망의 아웃풋으로 Normal Mean 과 Normal Sigma 를 예측하는 방법이다. 원하는 Mean 과 Sigma 가 나올 수 있도록 기울기를 제시하여 학습할 수 있다.
norm = torch.distributions.Normal(0, 1) v = norm.sample() print(v)
Pytorch 에서는 기본적으로 Normal 클래스를 제공한다. 인자로 Mean 과 Sigma 를 기입하면 해당 평균과 표준 편차를 따르는 정규 분포를 생성할 수 있다. 위는 0, 1 표준 정규 분포를 생성하여 임의 sample 즉 값을 뽑아 출력한 것이다. 샘플을 뽑을 때 마다 랜덤으로 출력된다.
log_percent= norm.log_prob(torch.Tensor([0])) pcnt = torch.exp(log_percent) print(pcnt)
0 이라는 어떤 값에 대해 PDF 즉 확률 밀도 함수에 넣어 어느 정도의 확률이 되는지 가져온다. 표준 정규 분포에서 0 지점의 밀도 함수의 확률 값은 대략 0.4가 안된다. 아무튼 평균에 가까울수록 확률 값이 높아지고 표준 편차만큼 떨어질 수록 확률이 떨어진다. 평균을 중심으로 대칭이다. 이는 모두 고등 수학에서 배웠던 내용이다.
아무튼, Policy Gradient DQN 의 아이디어는, 어떤 수치를 뽑아내야할 때 어떤 확률 분포에서 뽑아내는 것이 좋은지를 위주로 학습하는 것이다. 즉 어떤 평균, 어떤 표준 편차에서 샘플을 뽑아야 보상을 최대화하할 수 있을지를 바탕으로 학습한다.
class Net(torch.nn.Module): def __init__(self): super().__init__(); self.x1 = torch.nn.Linear(50, 100) self.x2 = torch.nn.Linear(100, 300) self.x3 = torch.nn.Linear(300, 100) self.mean = torch.nn.Linear(100, 1) self.sigma = torch.nn.Linear(100, 1) pass
위 코드는 임의로 구성한 신경망을 나타낸 것이다. 최종 출력은 mean, sigma 를 출력하는 것을 목표로 한다. 반면 sigma 는 음수가 나올 수 없기 때문에 연속적인 미분 가능한 형태로 취하기 위해 EXP 해준다.
def forward(self, x): x = self.x1(x) x = self.x2(x) x = self.x3(x) mean = self.mean(x) sigma = torch.exp(self.sigma(x))
학습 할 때는 별도 Loss 가 존재하지 않는다. 값을 추론한 뒤에, 보상 점수를 정한다. 보상 점수가 정해지면, 해당 추론한 정규 분포의 mean 값과 sigma 값으로 임의 샘플을 하나 뽑는다.
result = net(input_now) print("나온 결과 :", result) mean = result[0][0] sigma = result[1][0] norm = torch.distributions.Normal(mean,sigma) v = norm.sample()
아무튼 위에서 뽑아진 하나의 샘플은 확률 밀도가 높은 부분에서 자주 발생했을 것이고, 또는 우연히 확률 밀도가 낮은 곳에서 뽑아진 샘플일 수도 있다. 해당 샘플에 대해서 보상 점수를 매겨주면 된다. 보상 점수를 매긴 뒤에, 이 값에 대한 확률을 올려야 하는지, 내려야 하는지를 경사 하강법을 위한 함수 식으로 정의 해주면 된다.
loss = -norm.log_prob(v) * reward
위 샘플을 log_prob 하면 내부적으로 미분 가능한 형태로 확률 밀도 함수에 넣어 확률 정도를 구해준다. 이 확률 값은 우리가 평소아는 정규 분포 모양을 따르기 때문에 위로 갈 수록 확률이 높은 것이다.
정규 분포를 아주 대충 그려본 것이다......... 사실 정규 분포가 저렇게 생기면 안되지만, 볼록하다는 것을 보여주기 위해 그린 것이다. 아무튼 제일 볼록한 부분이 확률이 제일 높은 것이고, 현재 샘플 뽑은 위치를 빨간 지점이라 가정하자.
그러면 신경망은 빨간색 지점에 대해 보상 점수에 따라 확률을 더 올릴 것인지 낮출 것인지로 즉 정규 분포의 평균 및 표준 편차 범위를 옮겨야 한다.
이런식으로 말이다. 위 예시는 해당 빨간 지점에 대해 양수의 보상 점수를 준 예시이다. 그러면 보상 점수가 양수일 때 해당 지점으로 경사 하강되게 하기 위해서는 로스 함수가 필요한다. 별도 로스 함수는 존재하지 않는다. 이 정규 분포 확률 밀도 함수가 로스 함수 역할을 해야한다. 그러기 위해서는, 확률이 높아지게끔 유도하기 위해,이 그래프를 뒤집어야 한다. 왜냐하면 optimizer 은 경사 하강을 목표로 하기 때문이다.
뒤집어주고 보상 점수를 곱해주면 해당 기울기가 더 커질 것이고, 빠르게 경사 하강 될 것이다. 반대로 보상 점수가 음수 인 경우 다시 뒤집어져 원상 복귀 될 것이고, 경사 하강되지 않을 것이다. (오히려 다른 위치로 하강될 것이다.) 따라서 다음과 같은 식이 나오는 것이다.
loss = -norm.log_prob(v) * reward
이제 이 loss 로 역전파 한 뒤에 옵티마이저로 스텝 해주면 된다.
댓글 0개
댓글은 일회용 패스워드가 발급되며 사이트 이용 약관에 동의로 간주됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.