지금까지 우리는 MC와 TD를
이용해 에이전트가 환경에서 어떻게 학습하고, 어떻게 정책을 바꾸는지 살펴보았다. 이 두 방법은 공통적으로 정책을 평가하고 제어할 때 모두 같은 정책을 사용했다. 이렇게 같은 정책으로 학습하고 같은 정책으로 행동하는 방식을 온 폴리시(On-Policy)
라고 부른다.
하지만 이 방식에는 한 가지 한계가 있다. 바로 모델에 대한 정보를
전혀 모르는 상태, 즉 모델 프리(Model Free) 환경에서는
다음 상태가 무엇인지 미리 알 수 없기 때문에 상태가치함수(V함수)만으로는
최적의 정책을 구하기 어렵다는 점이다.
이때 유용하게 사용할 수 있는 것이 행동가치함수, 즉 Q함수이다.
Q함수는 어떤 상태에서 어떤 행동을 했을 때의 기대 가치를 알려주는
함수이다. 즉, 다음 상태를 몰라도 현재 상태에서 가능한
모든 행동의 가치를 비교해서 가장 좋은 행동을 선택할 수 있게 해준다.
그래서 MC나 TD에서도
정책을 제어할 때는 Q함수를 사용한다고 앞에서 설명했다.
그리고 이 아이디어를 한 단계 발전시킨 것이 바로 SARSA이다.
SARSA는 TD 방식에
기반을 두되, 상태가치함수 대신 Q함수를 사용해서 정책을
평가한다.
왜냐하면, 실제로 에이전트는 매 순간 하나의 행동만 선택하고 경험하기
때문에, Q함수를 사용하는 것이 더 현실적이고 정확하기 때문이다.
SARSA도 마찬가지로 정책을 평가할 때나 제어할 때나 같은 정책을
사용하므로 온 폴리시 학습 방식에 속한다.
여기까지가 우리가 지금까지 배운 내용이다.
이제부터는 한 걸음 더 나아가, 정책을 따르지 않고도 더 효율적으로
학습할 수 있는 방법, 즉 오프 폴리시(Off-policy) 학습
방식인 큐러닝(Q-Learning)에 대해 살펴볼
것이다.
큐러닝은 현재까지 학습한 것보다 훨씬 더 강력한 방법으로, 에이전트가
더 빠르고 안정적으로 최적의 정책을 학습할 수 있도록 도와준다.
Q러닝에서
샘플링
SARSA에서 경험을 쌓을 때 다음 행동을 결정하는 방식은 정책(π)을 따라서 Q값을 계산하는 것이다. 하지만 Q러닝에서 경험을 쌓을 때 다음 행동은 정책을 따라가는 것이
아니라 Q값을 max로 만드는 행동을 선택한다. 이것이 SARSA와 Q러닝의
차이점이다.
Q러닝은 중요도 샘플링(Importance
Sampling)을 사용하지는 않지만 정책을 평가할 때 사용하는 정책(max)과 정책을
제어(π)할 때 사용하는 정책이 다르기 때문에 오프 폴리시 방법이라 할 수 있다. 일반적으로 Q러닝이 SARSA보다
보다 좋은 성능을 보여준다.
지금까지 계속 설명한 정책평가와 정책제어 문제를 Q러닝에서 살펴보자. SARSA 알고리즘에서 정책평가는 Q함수를 계산하는 것이었다. 고정된 정책에 따라 행동을 선택하면서 가치를 계산하고 Q함수를 업데이트한다. 정책제어는 정책평가를 통해 계산한 Q함수 중 가장 큰 Q함수를 가지고 있는 행동을 선택하도록 정책을 수정하는 방식으로 진행한다.
Q러닝에서는 별도의 고정된 정책을 사용하지 않는다. 정책평가 과정에서 Q함수가 가장 큰 행동을 선택해서 그 행동을 통해서
계산한 Q값을 가지고 Q함수를 업데이트한다. 고정된 정책을 사용하지 않기 때문에 정책제어 과정이 별도로 존재하지 않는다.
Q러닝에서는 정책평가와 정책제어가 동시에 이루어진다.
5.3.4 Q러닝 예제
import numpy as np
import random
# (1) 상태 및 행동 정의
states = ['S', 'R1', 'R2', 'R3', 'F']
state_to_index = {
'S': 0,
'R1': 1,
'R2': 2,
'R3': 3,
'F': 4
}
# (2) 상태 전이 및 보상 정의
transitions = {
'S': [('R1', 0), ('R2', 0)],
'R1': [('R2', 0), ('R3', 0), ('F', 1)],
'R2': [('R3', 0), ('F', 1)],
'R3': [('F', 1)],
'F': []
}
# (3) Q 테이블 초기화
Q = {}
for s in states:
Q[s] = {}
for (s_next, _) in transitions[s]:
Q[s][s_next] = 0.0
# (4) 학습 파라미터
alpha = 0.1
gamma = 0.9
epsilon = 0.1
episodes = 500
# (5) Q-Learning 학습 루프
for ep in range(episodes):
state = 'S'
while state != 'F':
# (6) ε-greedy 방식으로 행동 선택
if random.random() < epsilon:
action = random.choice(list(Q[state].keys()))
else:
action = max(Q[state], key=Q[state].get)
# (7) 다음 상태 및 보상 확인
next_state = action
reward = 0
for (s_next, r) in transitions[state]:
if s_next == next_state:
reward = r
break
# (8) Q-Learning 업데이트
if next_state != 'F':
max_q_next = max(Q[next_state].values())
td_target = reward + gamma * max_q_next
else:
td_target = reward
Q[state][action] += alpha * (td_target - Q[state][action])
# (9) 다음 상태로 이동
state = next_state
# (10) 결과 출력
print("행동 가치 함수 Q(s, a):")
for s in Q:
for a in Q[s]:
print(f"Q({s}, {a}) = {Q[s][a]:.2f}")
행동 가치 함수 Q(s, a):
Q(S, R1) = 0.90
Q(S, R2) = 0.63
Q(R1, R2) = 0.53
Q(R1, R3) = 0.77
Q(R1, F) = 1.00
Q(R2, R3) = 0.87
Q(R2, F) = 0.19
Q(R3, F) = 1.00
Q러닝
대부분 코드가 SARSA와 비슷하므로, 특징적인 부분만 살펴보자.
(6) 에피소드가 시작되면 현재 상태에서 다음 행동을 선택한다. ε-greedy 방식을 사용하여 일정 확률로는 무작위 행동을, 그
외에는 현재 Q값이 가장 높은 행동을 선택한다. 이 방식은
탐험과 활용 사이의 균형을 맞추기 위한 전략이다.
(7) 선택한 행동에 따라 다음 상태로 이동하고, 해당 전이에 대한 보상을 확인한다. 보상은 경로 중 대부분은 0이며, 목표 상태인 F에
도달하면 1의 보상이 주어진다.
(8) Q-Learning 방식의 핵심인 Q값 업데이트가 이뤄지는 단계다. Q-Learning은 다음 상태에서
가능한 모든 행동 중 가장 큰 Q값을 사용하여 현재 상태의 Q값을
갱신한다. 이 방식은 향후 최적의 행동만을 기준으로 학습을 진행하기 때문에 정책 평가와 정책 개선이
동시에 이뤄진다.
(9) 다음 상태로 이동하고, 그
상태가 종료 상태가 아니면 다시 행동을 선택해 루프를 이어간다. 종료 상태에 도달하면 하나의 에피소드가
끝나며 다음 에피소드로 넘어간다.
(10) 학습이 모두 끝나면 각 상태에서 가능한 행동에 대한 Q값을 출력한다. 이 출력 결과는 에이전트가 어떤 상태에서 어떤 행동을
하는 것이 더 나은지를 수치적으로 보여주는 지표가 된다.
SARSA 예제와
Q-Learning 예제는 전체 구조는 거의 동일하지만 핵심적인 차이점은 Q값을 업데이트할
때 '어떤 방식으로 다음 상태의 가치를 계산하느냐'에 있다. 아래에 두 코드의 차이점 중심 비교를 정리해보았다:
Q값 업데이트 방식의 차이
SARSA (온-폴리시: 현재
사용하는 정책을 그대로 따름)는 다음 상태에서 ε-greedy 정책에
따라 실제로 선택한 다음 행동의 Q값을 사용한다. 즉, Q(next_state, next_action)을 사용한다.
Q-Learning은 다음 상태에서 가장 Q값이 큰 행동(탐욕적 행동)의 Q값을
사용한다. 즉, max_a Q(next_state, a)를
사용한다.
다음
행동 선택 시점의 차이
SARSA는 다음 상태로 이동한 후 다음 행동도 선택하고, 그 선택한
행동의 Q값으로 업데이트한다.
Q-Learning은 다음 상태에 도달했을 때 가장 Q값이 높은 행동의 Q값만 참조하고, 행동은 따로 선택하지 않는다.
상태-행동 |
SARSA |
Q러닝 |
차이 및 해석 |
Q(S, R1) |
0.77 |
0.90 |
Q러닝이 더 높음. 최적 행동(R1→F)을 고려함 |
Q(S, R2) |
0.57 |
0.63 |
Q러닝이 더 높음. 미래 보상을
조금 더 반영 |
Q(R1, R2) |
0.61 |
0.53 |
SARSA가 더 높음. 실제 경험 중심의
경로 반영 |
Q(R1, R3) |
0.90 |
0.77 |
SARSA가 더 높음. 중간 경로 탐험
경험 반영 |
Q(R1, F) |
0.65 |
1.00 |
Q러닝이 더 높음. 즉시 보상
경로를 최적 경로로 간주 |
Q(R2, R3) |
0.88 |
0.87 |
거의 유사함 |
Q(R2, F) |
0.10 |
0.19 |
Q러닝이 더 높음. 직접 연결
가치 반영 |
Q(R3, F) |
1.00 |
1.00 |
종료 상태. 두 알고리즘 모두
동일 |
SARSA와 Q러닝 행동 가치 함수 비교
Q러닝은 최대 보상 경로를 기준으로 학습하는 경향이 강해 빠르게 종료
상태에 도달하는 경로를 더 선호한다. 반면 SARSA는 실제
정책을 따라 학습하므로 평균적인 경험을 더 반영하며, 더 보수적인 정책을 만든다. 이러한 차이는 문제의 성격과 요구사항에 따라 적절한 알고리즘을 선택할 수 있도록 도와준다.
지금까지 공부한 것이 강화학습 기본 알고리즘 이론이다. 다이나믹 프로그래밍, MC, TD, Q러닝이 실무에서 사용되는 사례는 많지 않다. 앞으로
살펴볼 DQN부터 실무적으로 많이 사용되는 알고리즘이다. 하지만
초기에 나온 강화학습 알고리즘에 대해 반드시 이해하고 넘어가야 한다. 이 장에서 공부한 기초 알고리즘을
이해하지 못하고 고급 알고리즘을 바로 이해하는 거의 불가능하기 때문이다.
다음 장부터는 인공신경망 개념에 대해 알아보고 코드를 직접 구현하면서 좀 더 개선된 강화학습 알고리즘을 공부해 보도록 하자.