2주차 Value-Based Reinforcement Learning 방식
[핵심 목표]
Q 함수(Q-value)를 통해 상태-행동 쌍의 가치를 정의하고, 벨만 방정식을 사용하여 Q 함수를 업데이트하는 개념을 이해
PyTorch로 Q 함수를 근사하는 Neural Network 모델을 구현 준비
[Value-Based Reinforcement Learning (Value-based Approach)]
정책을 직접 파라미터화하지 않고, Value Function 또는 Q 함수를 학습
1. 함수 -
상태 s에서 행동 a를 취했을 때 앞으로 얻을 수 있는 예상 누적 보상 (Expected Return)
“상태 s에서 행동 a를 하면 얼마나 좋은가?”를 정량화 Q 함수를 정확히 알면 각 상태에서 가치가 가장 높은 행동을 선택하는 정책을 쉽게 생성 가능
2. -러닝 (-learning)
벨만 최적 방정식 (Bellman Optimality Equation)을 사용하여 Q 함수를 업데이트
- : 다음 상태
- : 보상
- : 할인율 (0 ~ 1)
- : 다음 상태에서 가장 높은 Q값을 주는 행동 선택
-러닝: 벨만 최적 방정식을 사용하여 Q 함수를 갱신하는 오프폴리시(Off-policy) 알고리즘
- 업데이트 규칙
- : 학습률 (Learning rate)
- : 경험 샘플
- 업데이트 규칙
3. PyTorch Neural Network 모델 구현 준비
- Q 함수를 딥뉴럴넷으로 근사하여 복잡한 환경에서도 확장성을 확보
- 다음 단계로 경험 리플레이(Replay Buffer), 타겟 네트워크(Target Network) 등의 개념을 도입하여 DQN 알고리즘을 구현하고, Q 함수를 실제로 학습시키는 과정 진행 예정
[Q-러닝 실습 예제: Q-러닝으로 미로 탈출하기]
1. 환경 설정
미로 정의
5x5 크기의 미로를 numpy 배열로 표현
- 0: 길
- 1: 벽
- 2: 시작
- 3: 목표
import numpy as np
# 5x5 미로 환경 설정 (0: 길, 1: 벽, 2: 시작, 3: 목표)
maze = np.array([
[2, 0, 0, 0, 0],
[0, 1, 1, 0, 0],
[0, 0, 0, 1, 0],
[1, 1, 0, 1, 0],
[0, 1, 0, 3, 0]
])행동 정의
에이전트가 취할 수 있는 행동을 정의
- 0: 위
- 1: 아래
- 2: 왼쪽
- 3: 오른쪽
# 0: 위로 1칸 이동(-1,0)
# 1: 아래로 1칸 이동(1,0)
# 2: 왼쪽으로 1칸 이동(0,-1)
# 3: 오른쪽으로 1칸 이동(0,1))
actions = [(-1, 0), (1, 0), (0, -1), (0, 1)]Q테이블 초기화
Q테이블을 0으로 초기화 (5x5x4개행동)
q_table = np.zeros((5, 5, 4))하이퍼파라미터 설정
학습에 필요한 하이퍼파라미터를 설정
learning_rate: 학습률discount_factor: 할인율epsilon: 탐험 비율episodes: 에피소드 수
learning_rate = 0.1
discount_factor = 0.9
epsilon = 0.1 # 탐험 비율
episodes = 10002. Q-러닝 알고리즘
다음 상태 얻기
현재 상태와 행동을 입력받아 다음 상태를 반환하는 함수
def get_next_state(state, action):
next_state = (state[0] + actions[action][0], state[1] + actions[action][1])
# 경계 확인 및 벽 충돌 감지
if 0 <= next_state[0] < 5 and 0 <= next_state[1] < 5 and maze[next_state[0], next_state[1]] != 1:
return next_state
else:
return state보상 얻기
현재 상태를 입력받아 보상을 반환하는 함수
- 목표 상태: 10
- 그 외: -1
def get_reward(state):
if maze[state[0], state[1]] == 3:
return 10
else:
return -1Q-러닝 학습
Q-러닝 알고리즘을 사용하여 Q-테이블을 업데이트
# Q-러닝 알고리즘
for episode in range(episodes):
state = (0, 0) # 시작 위치
while maze[state[0], state[1]] != 3 :
if np.random.rand() < epsilon:
action = np.random.randint(4)
else:
action = np.argmax(q_table[state[0], state[1], :])
next_state = get_next_state(state, action)
reward = get_reward(next_state)
q_table[state[0], state[1], action] += learning_rate * (
reward + discount_factor * np.max(q_table[next_state[0], next_state[1], :])
- q_table[state[0], state[1], action]
)
state = next_state
# 중간 프로그래스 출력 (예시: 100번째 에피소드마다 출력)
if (episode + 1) % 100 == 0:
print(f"Episode {episode + 1} 완료")Episode 100 완료 Episode 200 완료 Episode 300 완료 Episode 400 완료 Episode 500 완료 Episode 600 완료 Episode 700 완료 Episode 800 완료 Episode 900 완료 Episode 1000 완료
Q-값 업데이트 수식
- : 상태 에서 행동 의 Q-값
- : 학습률
- : 보상
- : 할인율
- : 다음 상태 에서 최대 Q-값
3. 결과 확인
최종 경로 찾기
학습된 Q-테이블을 사용하여 시작 상태에서 목표 상태까지의 최적 경로를 찾기
# 최종 경로 찾기
state = (0, 0)
path = [state]
while maze[state[0], state[1]] != 3:
action = np.argmax(q_table[state[0], state[1], :])
state = get_next_state(state, action)
path.append(state)경로 시각화
찾은 경로를 text로 시각화하여 출력
# 경로 시각화
print("미로 탈출 경로:")
for i in range(5):
for j in range(5):
if (i, j) == (0, 0):
print("S", end=" ")
elif (i,j) == (4,3):
print("G", end=" ")
elif (i,j) in path:
print("*", end=" ") # 지나간 경로
elif maze[i, j] == 1:
print("#", end=" ") # 벽 표시
else:
print(" ", end=" ")
print()미로 탈출 경로: S * # # * * * # # # * # # * G