- Published on
강화학습(Reinforcement Learning) 완벽 가이드: 이론부터 최신 알고리즘, 실전 구현까지
- Authors
- Name
- 1. 강화학습 개요
- 2. 수학적 기초
- 3. 고전적 알고리즘
- 4. Deep RL 혁명
- 5. Model-based RL
- 6. RLHF: Reinforcement Learning from Human Feedback
- 7. 주요 응용 사례
- 8. PyTorch 코드 예제
- 9. 주요 논문 레퍼런스
- 10. RL의 현재 한계와 미래 전망
- 마무리
1. 강화학습 개요
강화학습(Reinforcement Learning, RL)은 머신러닝의 세 축 중 하나로, 지도학습(Supervised Learning)이나 비지도학습(Unsupervised Learning)과는 근본적으로 다른 패러다임이다. 지도학습이 정답 레이블이 있는 데이터에서 패턴을 학습하고, 비지도학습이 레이블 없이 데이터의 구조를 파악한다면, 강화학습은 환경과의 상호작용을 통해 시행착오(trial and error)로 최적의 행동 전략을 학습한다.
인간이 자전거 타기를 배우는 과정을 떠올려 보자. 누군가가 "핸들을 37도 왼쪽으로 돌리고 페달을 초당 1.2회 밟아라"라고 알려주지 않는다. 대신 넘어지면 고통이라는 벌을 받고, 균형을 잡으면 앞으로 나아간다는 보상을 받으면서, 스스로 최적의 균형 전략을 터득한다. 이것이 바로 강화학습의 본질이다.
1.1 핵심 구성 요소
강화학습 시스템은 다음과 같은 핵심 요소들로 구성된다.
Agent (에이전트): 환경 속에서 행동을 수행하는 학습 주체다. 게임에서의 플레이어, 로봇, 자율주행 차량 등이 에이전트에 해당한다.
Environment (환경): 에이전트가 상호작용하는 외부 세계다. 게임 보드, 물리 시뮬레이션 공간, 실제 도로 환경 등이 이에 해당한다. 환경은 에이전트의 행동에 대해 다음 상태와 보상을 돌려준다.
State (): 현재 환경의 상태를 나타내는 정보다. 체스에서의 보드 배치, 로봇의 관절 각도, 주가 차트의 현재 패턴 등이 상태가 된다. 상태 공간(State Space) 는 가능한 모든 상태의 집합이다.
Action (): 에이전트가 각 상태에서 선택할 수 있는 행동이다. 게임에서 조이스틱 방향, 로봇 팔의 토크 값 등이 행동이다. 행동 공간(Action Space) 는 이산적(discrete)일 수도, 연속적(continuous)일 수도 있다.
Reward (): 에이전트가 특정 상태에서 특정 행동을 취했을 때 환경으로부터 받는 스칼라 피드백 신호다. 강화학습의 목표는 장기 누적 보상(cumulative reward)을 최대화하는 것이지, 즉각적 보상을 최대화하는 것이 아니다.
Policy (): 에이전트의 행동 전략이다. 상태를 입력받아 행동(또는 행동 확률분포)을 출력하는 함수로, 강화학습의 궁극적 학습 대상이다.
- Deterministic Policy:
- Stochastic Policy:
Value Function (): 상태 에서 정책 를 따랐을 때 기대되는 누적 보상이다. "이 상태가 얼마나 좋은가"를 수치화한다.
Action-Value Function (): 상태 에서 행동 를 취한 후 정책 를 따랐을 때 기대되는 누적 보상이다. "이 상태에서 이 행동이 얼마나 좋은가"를 수치화한다.
Discount Factor (): 미래 보상의 현재 가치를 결정하는 할인율이다. 이면 에이전트는 즉각적 보상만 고려하고, 에 가까울수록 먼 미래의 보상도 현재와 비슷한 가치를 둔다.
1.2 강화학습의 상호작용 루프
강화학습의 핵심 구조는 다음과 같은 반복적 상호작용 루프로 이루어진다.
시점 t:
1. 에이전트가 현재 상태 s_t를 관측
2. 정책 π에 따라 행동 a_t를 선택
3. 환경이 행동을 수행하고, 보상 r_{t+1}과 다음 상태 s_{t+1}을 반환
4. 에이전트가 (s_t, a_t, r_{t+1}, s_{t+1}) 경험을 바탕으로 정책을 갱신
5. t ← t + 1, 반복
이 루프에서 생성되는 경험의 시퀀스 를 Trajectory 또는 Episode라 부르며, 이것이 강화학습 에이전트의 학습 데이터가 된다.
1.3 강화학습 알고리즘의 분류
강화학습 알고리즘은 여러 기준으로 분류할 수 있다.
| 분류 기준 | 유형 | 설명 | 대표 알고리즘 |
|---|---|---|---|
| 학습 대상 | Value-based | 가치 함수를 학습하여 행동 결정 | Q-Learning, DQN |
| Policy-based | 정책을 직접 학습 | REINFORCE, PPO | |
| Actor-Critic | 가치 함수와 정책을 동시에 학습 | A2C, A3C, SAC | |
| 환경 모델 | Model-free | 환경 모델 없이 직접 경험으로 학습 | DQN, PPO, SAC |
| Model-based | 환경 모델을 학습하여 계획(planning)에 활용 | MuZero, Dreamer | |
| 데이터 활용 | On-policy | 현재 정책이 생성한 데이터만 사용 | SARSA, PPO |
| Off-policy | 다른 정책이 생성한 데이터도 사용 가능 | Q-Learning, DQN, SAC |
2. 수학적 기초
2.1 Markov Decision Process (MDP)
강화학습의 수학적 프레임워크는 **Markov Decision Process (MDP)**다. MDP는 순차적 의사결정 문제를 형식화하는 수학적 모델로, 다음 5-tuple로 정의된다.
- : 상태 공간 (State Space)
- : 행동 공간 (Action Space)
- : 상태 전이 확률 (Transition Probability) — 상태 에서 행동 를 취했을 때 상태 로 전이될 확률
- : 보상 함수 (Reward Function) — 전이 에 대한 즉각적 보상
- : 할인율 (Discount Factor)
MDP의 핵심은 Markov Property(마르코프 성질)다. 미래 상태는 현재 상태와 현재 행동에만 의존하며, 과거의 모든 상태와 행동 이력과는 독립적이다.
이 성질 덕분에 현재 상태 만으로 의사결정에 필요한 모든 정보를 담을 수 있다고 가정하며, 이것이 강화학습을 수학적으로 다룰 수 있게 해주는 근본적인 기반이다.
2.2 Return과 가치 함수 정의
에이전트의 목표는 Return(수익)을 최대화하는 것이다. Return은 시점 부터의 할인된 누적 보상으로 정의된다.
Return의 중요한 재귀적 성질은 다음과 같다.
이 재귀 관계가 이후 Bellman 방정식의 기초가 된다.
State-Value Function: 정책 를 따를 때, 상태 에서 시작하여 기대할 수 있는 Return이다.
Action-Value Function: 정책 를 따를 때, 상태 에서 행동 를 먼저 취한 후 기대할 수 있는 Return이다.
두 함수 사이의 관계는 다음과 같다.
2.3 Bellman Equation 유도
Bellman Equation은 강화학습의 가장 핵심적인 수학적 도구다. Return의 재귀적 성질을 이용하여 가치 함수를 재귀적으로 표현한다.
State-Value Function의 Bellman Equation 유도:
Return의 재귀 관계 을 대입하면:
기댓값의 선형성을 이용하여 전개하면:
여기서 행동 는 정책 에 따라, 다음 상태 는 전이 확률 에 따라 결정되므로, 전체 기댓값을 이중 합으로 풀면:
이것이 **Bellman Expectation Equation for **다. 현재 상태의 가치가 즉각적 보상과 할인된 다음 상태의 가치의 기댓값으로 표현된다.
Action-Value Function의 Bellman Equation:
동일한 방식으로 에 대해서도 유도할 수 있다.
2.4 Bellman Optimality Equation
최적 정책 는 모든 상태에서 가장 높은 가치를 달성하는 정책이다.
최적 가치 함수 와 는 다음과 같이 정의된다.
Bellman Optimality Equation for 유도:
최적 정책 하에서는, 에이전트가 각 상태에서 최적의 행동을 선택한다. 따라서 정책에 의한 기댓값 대신 **최대화(max)**를 사용한다.
의 Bellman 방정식을 대입하면:
Bellman Optimality Equation for :
이 방정식의 핵심적 의미는 다음과 같다. 최적 행동-가치 함수 를 알면, 각 상태에서 를 최대화하는 행동을 선택하기만 하면 최적 정책을 얻을 수 있다.
2.5 Advantage Function
나중에 Policy Gradient 계열에서 핵심적으로 사용될 Advantage Function 를 여기서 정의한다.
Advantage Function은 "상태 에서 행동 를 취하는 것이 평균적으로 행동하는 것보다 얼마나 더 좋은가"를 나타낸다. 이면 평균 이상, 이면 평균 이하의 행동이다. 모든 행동에 대한 Advantage의 기댓값은 0이다.
3. 고전적 알고리즘
3.1 Dynamic Programming (DP)
Dynamic Programming은 환경의 완전한 모델(전이 확률 와 보상 함수 )을 알고 있을 때 사용할 수 있는 방법이다. 현실적으로 환경 모델을 정확히 아는 경우는 드물지만, DP는 다른 모든 RL 알고리즘의 이론적 기반이 된다.
Policy Evaluation (정책 평가): 주어진 정책 의 가치 함수 를 계산한다. Bellman Expectation Equation을 반복 적용하여 수렴시킨다.
Policy Improvement (정책 개선): 현재 가치 함수에 대해 greedy 정책을 구한다.
Policy Iteration: Policy Evaluation과 Policy Improvement를 번갈아 수행하여 최적 정책에 수렴시킨다.
Value Iteration: Bellman Optimality Equation을 직접 반복 적용한다.
수렴 후 최적 정책을 추출한다. Value Iteration은 Policy Iteration에서 Policy Evaluation을 한 번의 sweep만 수행하는 것으로 볼 수 있다.
3.2 Monte Carlo (MC) Methods
환경 모델을 모르는 Model-free 상황에서, Monte Carlo 방법은 실제 경험(에피소드)을 통해 가치 함수를 추정한다. 핵심 아이디어는 간단하다: 여러 에피소드를 실행하고, 각 상태(또는 상태-행동 쌍)에서 관측된 Return의 평균을 가치 함수의 추정값으로 사용한다.
여기서 는 상태 가 방문된 횟수, 는 번째 방문에서의 실제 Return이다.
MC의 장점: 환경 모델이 필요 없고, 편향(bias)이 없는 추정값을 제공한다.
MC의 단점: 에피소드가 끝나야만 학습이 가능하고(episodic tasks에만 적용 가능), Return의 분산(variance)이 크다.
3.3 Temporal-Difference (TD) Learning
TD Learning은 DP와 MC의 장점을 결합한다. 환경 모델 없이도 학습 가능하면서(MC처럼), 에피소드가 끝나기 전에 매 시점(step)마다 업데이트할 수 있다(DP처럼).
TD(0) — 가장 기본적인 TD 방법:
여기서 를 TD Error라 부른다. 실제 보상 에 다음 상태의 추정 가치를 더한 TD Target ()과 현재 추정 가치의 차이만큼 업데이트한다. 이것을 Bootstrapping이라 한다 — 다른 추정값을 이용하여 추정값을 갱신하는 것이다.
MC vs. TD 비교:
| 특성 | Monte Carlo | TD Learning |
|---|---|---|
| 업데이트 시점 | 에피소드 종료 후 | 매 시점(step)마다 |
| 타깃 | 실제 Return | TD Target |
| 편향 (Bias) | 없음 (unbiased) | 있음 (biased, bootstrapping으로 인해) |
| 분산 (Variance) | 높음 | 낮음 |
| 환경 모델 | 불필요 | 불필요 |
| 연속 환경 | 적용 불가 | 적용 가능 |
TD(): MC와 TD(0) 사이를 보간하는 방법이다. 이면 TD(0), 이면 MC와 동등해진다. -Return을 다음과 같이 정의한다.
여기서 은 -step Return이다.
3.4 SARSA (On-Policy TD Control)
SARSA는 on-policy TD 제어 알고리즘으로, 이름이 업데이트에 사용되는 경험 튜플 에서 유래했다.
SARSA는 실제로 수행한 다음 행동 의 Q-값을 사용하여 업데이트한다. 이는 현재 정책(보통 -greedy)이 실제로 취할 행동의 가치를 반영하므로, 탐색(exploration) 중의 위험한 행동도 고려하게 된다.
3.5 Q-Learning (Off-Policy TD Control)
Q-Learning은 Watkins(1989)가 제안한 off-policy TD 제어 알고리즘으로, 강화학습 역사상 가장 중요한 알고리즘 중 하나다.
SARSA와의 결정적 차이점은, 다음 상태에서 실제로 취한 행동이 아닌 최대 Q-값을 주는 행동(greedy action)을 사용한다는 점이다. 이 때문에 Q-Learning은 off-policy다 — 에이전트가 탐색을 위해 어떤 행동을 취하든, 항상 최적 Q-값을 향해 수렴한다.
# Q-Learning 의사 코드
import numpy as np
def q_learning(env, num_episodes, alpha=0.1, gamma=0.99, epsilon=0.1):
Q = np.zeros((env.observation_space.n, env.action_space.n))
for episode in range(num_episodes):
state = env.reset()
done = False
while not done:
# ε-greedy 행동 선택
if np.random.random() < epsilon:
action = env.action_space.sample() # 탐색(exploration)
else:
action = np.argmax(Q[state]) # 활용(exploitation)
next_state, reward, done, _ = env.step(action)
# Q-Learning 업데이트: max over next actions
td_target = reward + gamma * np.max(Q[next_state]) * (1 - done)
td_error = td_target - Q[state, action]
Q[state, action] += alpha * td_error
state = next_state
return Q
Q-Learning 수렴 조건: 모든 상태-행동 쌍이 무한히 많이 방문되고, 학습률이 Robbins-Monro 조건 (, )을 만족하면, Q-Learning은 에 수렴함이 증명되어 있다.
4. Deep RL 혁명
고전적 RL 알고리즘은 테이블 형태의 가치 함수를 사용하므로, 상태 공간이 큰 문제에는 적용이 불가능하다. Atari 게임만 해도 화면 픽셀이 상태가 되므로 상태 공간이 으로 천문학적이다. 이 문제를 해결하기 위해 딥 뉴럴 네트워크를 함수 근사기(Function Approximator)로 사용하는 Deep RL이 등장했다.
4.1 DQN: Deep Q-Network (2013/2015)
논문: "Playing Atari with Deep Reinforcement Learning" (Mnih et al., 2013), "Human-level control through deep reinforcement learning" (Mnih et al., 2015, Nature)
DQN은 Deep RL 시대를 연 기념비적인 논문이다. Q-Learning의 Q-테이블을 CNN(Convolutional Neural Network)으로 대체하여, 원시 픽셀 입력으로부터 직접 행동 가치를 추정한다.
여기서 는 네트워크 파라미터다. 학습 목표는 다음 손실 함수를 최소화하는 것이다.
하지만 단순히 뉴럴 네트워크로 Q-함수를 근사하면 학습이 극도로 불안정했다. DQN이 이를 해결한 두 가지 핵심 혁신이 있다.
혁신 1: Experience Replay
연속적인 경험 은 시간적으로 강한 상관관계가 있다. 이는 확률적 경사 하강법(SGD)이 가정하는 i.i.d.(독립 동일 분포) 조건을 위반한다. Experience Replay는 경험을 Replay Buffer 에 저장한 후, 학습 시 무작위 미니배치를 추출하여 사용함으로써 데이터 간 상관관계를 깨뜨린다.
from collections import deque
import random
class ReplayBuffer:
def __init__(self, capacity):
self.buffer = deque(maxlen=capacity)
def push(self, state, action, reward, next_state, done):
self.buffer.append((state, action, reward, next_state, done))
def sample(self, batch_size):
batch = random.sample(self.buffer, batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
return states, actions, rewards, next_states, dones
def __len__(self):
return len(self.buffer)
혁신 2: Target Network
Q-값을 업데이트할 때, 타깃()과 예측()이 같은 네트워크의 파라미터 에 의존하면, 타깃이 계속 움직여서 학습이 발산할 수 있다. Target Network는 별도의 파라미터 를 가진 복제 네트워크를 만들고, 주기적으로(예: 매 10,000 step) 메인 네트워크의 파라미터를 복사하여 타깃을 안정시킨다.
또는 soft update 방식도 사용된다:
Atari 결과: DQN은 49개 Atari 2600 게임 중 29개에서 인간 수준 이상의 성능을 달성했다. 특히 Breakout, Pong 같은 게임에서 놀라운 전략을 스스로 학습했다.
4.2 DQN 개선 변형들
DQN 이후 수많은 개선이 이루어졌다. 주요 변형들을 살펴보자.
Double DQN (van Hasselt et al., 2016): 표준 DQN은 max 연산자로 인해 Q-값을 **과대추정(overestimation)**하는 경향이 있다. Double DQN은 행동 선택과 행동 평가를 분리하여 이를 해결한다.
행동 선택은 온라인 네트워크()로, 행동 평가는 타깃 네트워크()로 수행한다.
Dueling DQN (Wang et al., 2016): 네트워크 아키텍처를 변경하여 Q-함수를 State-Value 와 Advantage 로 분해한다.
이 분해 덕분에, 행동 선택이 중요하지 않은 상태에서는 만 정확히 학습하면 되므로 더 효율적이다.
Prioritized Experience Replay (Schaul et al., 2016): 모든 경험을 동일한 확률로 샘플링하는 대신, TD Error가 큰 경험을 더 자주 샘플링한다. 학습에 더 유용한 경험에 우선순위를 두는 것이다.
Importance sampling weight를 사용하여 편향을 보정한다:
Noisy DQN (Fortunato et al., 2018): -greedy 대신 네트워크 가중치에 학습 가능한 노이즈를 추가하여 탐색한다.
Categorical DQN / C51 (Bellemare et al., 2017): Q-값의 기댓값 대신 전체 Return 분포를 학습하는 Distributional RL 접근이다.
Rainbow (Hessel et al., 2018): 위의 6가지 개선을 모두 결합한 에이전트다. 개별 기법보다 월등히 우수한 성능을 보였다.
| 구성 요소 | 기여 |
|---|---|
| Double DQN | Q-값 과대추정 제거 |
| Prioritized Replay | 중요 경험 우선 학습 |
| Dueling Architecture | V와 A의 효율적 분리 |
| Multi-step Returns | 더 긴 시간 범위 학습 |
| Distributional RL (C51) | Return 분포 학습 |
| Noisy Nets | 파라미터 공간에서의 탐색 |
4.3 Policy Gradient: REINFORCE
Value-based 방법들(DQN 등)은 Q-함수를 학습한 후 greedy하게 행동을 선택한다. 하지만 이 접근에는 한계가 있다.
- **연속 행동 공간(Continuous Action Space)**에서는 를 구하기 어렵다.
- **확률적 정책(Stochastic Policy)**을 직접 표현할 수 없다.
- Q-함수의 작은 변화가 정책의 급격한 변화를 초래할 수 있다.
Policy Gradient 방법은 정책 를 직접 파라미터화하고, 정책의 파라미터 를 직접 최적화한다.
Policy Gradient Theorem 유도:
목적 함수를 다음과 같이 정의한다.
여기서 는 trajectory이고 는 trajectory의 총 return이다.
의 기울기를 구하기 위해, trajectory의 확률을 다음과 같이 표현한다.
기울기를 구하면:
여기서 Log-Derivative Trick 을 적용하면:
를 전개하면:
환경 역학 와 는 에 의존하지 않으므로, 기울기 연산 시 사라진다.
따라서 Policy Gradient Theorem은 다음과 같다.
이 결과의 핵심적 의미는: 환경 모델(전이 확률 )을 몰라도 정책의 기울기를 추정할 수 있다는 것이다.
REINFORCE 알고리즘 (Williams, 1992):
Policy Gradient Theorem의 가장 직접적인 구현체가 REINFORCE다. Monte Carlo 방식으로 trajectory를 수집하고, 관측된 Return으로 기울기를 추정한다.
Baseline을 이용한 분산 감소:
REINFORCE의 가장 큰 문제는 높은 분산이다. Return 에서 baseline 를 빼도 기울기의 기댓값(편향)은 변하지 않지만, 분산을 크게 줄일 수 있다.
가장 흔히 사용되는 baseline은 상태 가치 함수 이며, 이 경우 는 Advantage Function의 추정치가 된다.
4.4 Actor-Critic: A2C, A3C
Actor-Critic 방법은 Policy Gradient(Actor)와 Value Function(Critic)을 동시에 학습한다.
- Actor: 정책 를 학습 — 행동을 결정
- Critic: 가치 함수 를 학습 — 행동을 평가
REINFORCE는 에피소드가 끝나야 학습할 수 있고, Return의 분산이 크다는 문제가 있었다. Actor-Critic은 Critic이 제공하는 가치 추정치를 baseline으로 사용하여, 매 시점마다 업데이트하면서도 분산을 줄인다.
Actor 업데이트:
여기서 Advantage는 TD Error로 추정한다:
Critic 업데이트:
A3C: Asynchronous Advantage Actor-Critic (Mnih et al., 2016)
A3C는 병렬화를 통해 학습 안정성과 속도를 크게 향상시켰다. 핵심 아이디어는:
- 다수의 Worker가 각자의 환경 복사본에서 독립적으로 경험을 수집한다.
- 각 Worker가 자신의 경험으로 기울기를 계산하고, 글로벌 파라미터를 비동기적으로 업데이트한다.
- 비동기적 업데이트가 자연스러운 탐색 다양성을 제공하여, Experience Replay 없이도 데이터 상관관계 문제를 완화한다.
A2C: Advantage Actor-Critic
A2C는 A3C의 동기적(synchronous) 버전이다. 모든 Worker가 동시에 경험을 수집한 후, 기울기를 합산하여 한 번에 업데이트한다. 비동기 업데이트로 인한 stale gradient 문제가 없어서, 실제로는 A2C가 A3C와 비슷하거나 더 나은 성능을 보이는 경우가 많다.
4.5 TRPO와 PPO
Policy Gradient의 핵심 문제는 학습률(step size) 설정이 어렵다는 것이다. 너무 크면 정책이 급격히 변해서 성능이 붕괴하고, 너무 작으면 학습이 느리다. TRPO와 PPO는 이 문제를 해결하기 위한 핵심 알고리즘이다.
TRPO: Trust Region Policy Optimization (Schulman et al., 2015)
TRPO는 정책 업데이트의 크기를 명시적으로 제한한다. KL Divergence를 사용하여 이전 정책과 새 정책 사이의 거리를 제한하는 Trust Region 안에서만 업데이트를 수행한다.
TRPO는 이론적으로 단조로운 성능 개선을 보장하지만, 제약 최적화 문제를 풀기 위해 Conjugate Gradient와 Line Search가 필요하여 구현이 매우 복잡하다.
PPO: Proximal Policy Optimization (Schulman et al., 2017)
PPO는 TRPO의 안정성을 유지하면서 구현이 훨씬 간단한 알고리즘이다. 오늘날 가장 널리 사용되는 Policy Gradient 알고리즘으로, OpenAI의 ChatGPT 학습에도 사용되었다.
PPO-Clip 목적 함수 유도:
정책 비율을 정의한다.
TRPO의 surrogate objective는 이다. 이 목적 함수를 제약 없이 최대화하면, 비율 가 과도하게 커져서 정책이 급격히 변할 수 있다.
PPO의 핵심 아이디어는, 비율을 범위로 클리핑하여 정책 변화를 제한하는 것이다. (는 보통 0.1~0.2)
이 목적 함수가 어떻게 작동하는지 경우를 나누어 분석하면:
Case 1: (좋은 행동):
- 이면 (새 정책이 이 행동을 훨씬 더 많이 선택): 클리핑되어 로 제한. 더 이상의 정책 이동에 대한 인센티브를 제거.
- 이면: 클리핑 없이 사용.
Case 2: (나쁜 행동):
- 이면 (새 정책이 이 행동을 훨씬 덜 선택): 클리핑되어 로 제한.
- 이면: 클리핑 없이 사용.
두 경우 모두, 정책이 이미 올바른 방향으로 충분히 이동했으면 더 이상의 인센티브를 차단한다. 이것이 PPO의 안정성의 핵심이다.
PPO의 전체 목적 함수:
실제 구현에서는 Policy Loss, Value Loss, Entropy Bonus를 결합한다.
- : Value Function의 MSE Loss
- : 정책의 Entropy (탐색을 장려)
- : 가중치 계수
GAE (Generalized Advantage Estimation):
PPO는 보통 GAE(Schulman et al., 2016)를 사용하여 Advantage를 추정한다. GAE는 TD()의 Advantage 버전이다.
여기서 는 TD Error다. 이면 1-step TD 추정, 이면 MC 추정이 된다.
4.6 SAC: Soft Actor-Critic
논문: "Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor" (Haarnoja et al., 2018)
SAC는 Maximum Entropy RL 프레임워크에 기반한 off-policy actor-critic 알고리즘이다. 연속 행동 공간에서 가장 성공적인 알고리즘 중 하나로, 로보틱스 분야에서 특히 높은 성능을 보인다.
Maximum Entropy 목적 함수:
표준 RL이 Return만 최대화하는 것과 달리, SAC는 Return과 Entropy를 동시에 최대화한다.
여기서 는 정책의 Entropy이고, 는 Entropy의 중요도를 조절하는 Temperature 파라미터다.
Entropy 정규화의 이점은 다음과 같다.
- 탐색 촉진: 정책이 가능한 한 랜덤하게 행동하면서도 보상을 최대화하도록 학습하므로, 지역 최적해에 빠지는 것을 방지.
- 로버스트한 정책: 여러 최적에 가까운 행동을 유지하므로, 환경 변화에 강건함.
- 더 빠른 학습: 초기에 넓은 탐색을 수행하여 유용한 행동을 더 빨리 발견.
Soft Bellman Equation:
SAC의 세 네트워크:
- Soft Q-Function : 두 개의 Q-네트워크를 사용하여 과대추정을 방지 (Clipped Double Q)
- Policy : Gaussian 정책 (평균과 분산을 출력)
- Temperature : 자동 조절 (entropy constraint 방식)
Q-함수 업데이트:
여기서 이다.
정책 업데이트:
Reparameterization Trick을 사용하여 미분 가능하게 만든다: , 여기서 .
Temperature 자동 조절:
여기서 는 목표 Entropy (보통 )다.
4.7 DDPG와 TD3: 연속 행동 공간
DDPG: Deep Deterministic Policy Gradient (Lillicrap et al., 2015)
DQN은 이산 행동 공간에만 적용 가능하다. DDPG는 DQN의 아이디어를 연속 행동 공간으로 확장한 off-policy actor-critic 알고리즘이다. "Continuous control with DQN"이라고 볼 수 있다.
- Deterministic Actor: 가 연속 행동을 직접 출력
- Critic: 가 행동 가치를 평가
- DQN의 Experience Replay와 Target Network를 그대로 사용
- 탐색을 위해 Ornstein-Uhlenbeck 노이즈를 행동에 추가
Actor 업데이트 (Deterministic Policy Gradient):
TD3: Twin Delayed DDPG (Fujimoto et al., 2018)
DDPG는 Q-값 과대추정과 학습 불안정성 문제가 있었다. TD3는 세 가지 기법으로 이를 해결한다.
- Twin Q-networks: 두 개의 Q-네트워크 중 작은 값을 타깃으로 사용 → 과대추정 완화
Delayed Policy Updates: Actor를 Critic보다 덜 자주 업데이트 (예: Critic 2번당 Actor 1번) → 더 정확한 Q-값을 바탕으로 정책 업데이트
Target Policy Smoothing: 타깃 행동에 클리핑된 노이즈를 추가 → 타깃 Q-값 평활화
5. Model-based RL
지금까지 다룬 알고리즘들은 모두 Model-free 방법이다 — 환경 모델을 모르는 채로 직접 경험을 통해 학습한다. Model-based RL은 환경의 동역학 모델을 학습하고, 이를 이용하여 더 효율적으로 학습한다.
5.1 Model-based의 장점과 도전
장점:
- 샘플 효율성 (Sample Efficiency): 실제 환경 상호작용 횟수를 크게 줄일 수 있다. 학습된 모델 안에서 시뮬레이션("imagination")을 통해 대량의 가상 경험을 생성할 수 있기 때문이다.
- Planning: 행동하기 전에 미래를 "시뮬레이션"하여 최적의 행동 시퀀스를 탐색할 수 있다.
- Transfer: 학습된 모델을 다양한 태스크에 재사용할 수 있다.
도전:
- 모델이 부정확하면 (Model Error), 이 오류가 계획(planning) 과정에서 누적되어 성능이 크게 저하된다.
- 복잡한 환경의 동역학을 정확히 학습하는 것 자체가 어렵다.
5.2 World Models (Ha & Schmidhuber, 2018)
World Models는 환경을 **VAE(Variational Autoencoder)로 압축된 잠재 공간(Latent Space)**에서 모델링하는 선구적 연구다.
- Vision Model (V): VAE로 고차원 관측을 저차원 잠재 벡터 로 인코딩
- Memory Model (M): RNN(MDN-RNN)으로 잠재 공간에서의 동역학을 예측:
- Controller (C): 단순한 선형 모델로, 와 를 입력받아 행동 결정
핵심 혁신은 Controller를 "꿈" 속에서 학습할 수 있다는 것이다. V와 M이 학습한 세계 모델 안에서 가상 에피소드를 생성하고, Controller는 이 가상 경험으로 학습한다.
5.3 MuZero (Schrittwieser et al., 2020)
MuZero는 DeepMind의 AlphaZero를 계승하면서, 환경의 규칙을 몰라도 학습할 수 있게 확장한 model-based RL 알고리즘이다.
AlphaZero는 게임 규칙(완벽한 시뮬레이터)을 알고 있어야 했다. MuZero는 다음 세 함수를 학습한다.
- Representation Function : 관측 를 잠재 상태 로 매핑:
- Dynamics Function : 잠재 상태에서의 전이를 예측:
- Prediction Function : 잠재 상태에서 정책과 가치를 예측:
이 세 함수를 사용하여 **Monte Carlo Tree Search (MCTS)**를 잠재 공간에서 수행한다. 환경의 실제 전이 규칙을 모르더라도, 학습된 동역학 함수로 미래를 시뮬레이션할 수 있다.
MuZero는 Go, Chess, Shogi에서 AlphaZero와 동등한 성능을 달성하면서, 추가로 Atari 게임에서도 SOTA 성능을 보였다.
5.4 Dreamer (Hafner et al., 2020, 2021, 2023)
Dreamer 시리즈는 잠재 공간에서의 세계 모델(World Model)을 학습하고, 이 모델 안에서 상상(imagination)을 통해 정책을 학습하는 접근이다.
Dreamer v3 (Hafner et al., 2023) 는 하나의 알고리즘과 하이퍼파라미터 세트로 150개 이상의 다양한 태스크(Atari, DMC, Minecraft 등)를 성공적으로 학습하는 범용성을 보여주었다.
핵심 구성 요소:
- RSSM (Recurrent State Space Model): 결정적 상태와 확률적 상태를 결합한 세계 모델
- Actor-Critic in Imagination: 학습된 세계 모델 안에서 trajectory를 "상상"하고, 이 상상 속에서 actor-critic 학습 수행
- Symlog Predictions: 보상의 스케일에 무관하게 학습하기 위한 정규화 기법
5.5 자율 알고리즘 발견: DiscoRL (2025)
2025년 Nature에 발표된 DeepMind의 연구는 RL의 새로운 패러다임을 열었다. 기계가 스스로 SOTA RL 알고리즘을 발견할 수 있음을 보여주었다. DiscoRL(Discovered RL)이라 명명된 이 발견된 규칙은 뉴럴 네트워크로 표현되며, 기존 수학적 방정식 형태의 알고리즘보다 더 유연하고, 다양한 벤치마크에서 수동 설계된 알고리즘을 능가했다.
6. RLHF: Reinforcement Learning from Human Feedback
RLHF는 강화학습의 가장 임팩트 있는 최신 응용이다. ChatGPT, Claude, Gemini 등 현대 LLM의 핵심 학습 파이프라인으로, 인간의 선호도를 보상 신호로 사용하여 모델을 정렬(Alignment)한다.
6.1 RLHF 파이프라인
RLHF 파이프라인은 세 단계로 이루어진다.
Stage 1: Supervised Fine-Tuning (SFT)
Pre-trained LLM을 인간이 작성한 고품질 대화 데이터로 Fine-tuning한다. 이 단계에서 모델은 지시를 따르는 기본 능력을 갖추게 된다.
Stage 2: Reward Model (RM) Training
동일한 프롬프트에 대해 SFT 모델이 여러 응답을 생성하고, 인간 라벨러가 이를 비교하여 선호도 순위를 매긴다. 이 선호도 데이터로 보상 모델을 학습한다.
선호도 쌍 에 대해 (여기서 이 보다 선호됨), Bradley-Terry 모델에 기반한 손실 함수를 사용한다.
여기서 는 보상 모델, 는 시그모이드 함수다.
Stage 3: RL Optimization (PPO Fine-tuning)
학습된 보상 모델을 보상 함수로 사용하여, PPO 알고리즘으로 LLM 정책을 최적화한다. SFT 모델로부터 너무 멀어지지 않도록 KL Penalty를 추가한다.
여기서 는 KL 페널티의 강도를 조절하는 계수다. 이 KL 항이 없으면, 모델이 보상 모델을 "해킹"하여 부자연스러운 출력을 생성할 수 있다 (Reward Hacking).
6.2 DPO: Direct Preference Optimization
논문: "Direct Preference Optimization: Your Language Model is Secretly a Reward Model" (Rafailov et al., 2023)
DPO는 RLHF의 복잡성을 대폭 줄인 혁신적 접근이다. 핵심 통찰은 보상 모델을 별도로 학습하고 RL을 수행하는 두 단계를 하나로 통합할 수 있다는 것이다.
KL-제약 최적화 문제의 최적 정책을 유도하면:
이를 에 대해 역으로 풀면:
이 관계를 Bradley-Terry 모델에 대입하면 (분배 상수 는 소거됨):
DPO의 장점:
- 별도의 보상 모델 학습이 불필요
- 복잡한 PPO 학습 루프가 불필요
- 구현이 단순하고 학습이 안정적
- 메모리와 계산 비용이 크게 절감
6.3 GRPO: Group Relative Policy Optimization
논문: DeepSeek-R1에서 처음 사용된 GRPO는 2025~2026년 가장 주목받는 RL 정렬 기법이다.
GRPO는 PPO의 핵심적 비효율성인 **Value Network(Critic)**를 제거한다. 대신, 하나의 프롬프트에 대해 그룹 단위로 여러 응답을 생성하고, 그룹 내 상대적인 보상 통계로 Advantage를 추정한다.
여기서 는 그룹 크기, 는 번째 응답의 보상이다. 이 방식의 장점은:
- Value Network의 메모리와 계산 오버헤드를 완전히 제거
- 그룹 내 상대적 비교가 보상 스케일에 무관한 학습을 가능케 함
- 수학, 코딩 등 정답이 검증 가능한(Verifiable Rewards) 태스크에서 특히 효과적
RLVR (Reinforcement Learning with Verifiable Rewards):
DeepSeek-R1의 성공 이후, RLVR 패러다임이 급부상했다. 인간의 주관적 선호도 대신, 수학 문제의 정답 여부, 코드의 테스트 통과 여부 등 객관적으로 검증 가능한 보상을 사용한다. 이 접근은 능력 대비 비용 비율이 매우 높아, 수학과 코딩 이외의 도메인(화학, 생물학 등)으로도 확장되고 있다.
6.4 LLM 정렬 최신 동향 (2025~2026)
2025~2026년의 주요 LLM 정렬 발전은 다음과 같다.
- OpenAI GPT-5 (2025년 8월): RLHF 정제를 통해 환각(hallucination)을 크게 줄이고 사실 정확도를 향상
- Anthropic Claude Opus 4.5 (2025년 11월): Constitutional AI와 RLHF의 결합으로 학습, 80페이지 분량의 상세한 헌법(Constitution) 공개
- RLAIF (RL from AI Feedback): 인간 대신 AI가 선호도 피드백을 제공하는 방식으로, 확장성이 크게 향상
- Hybrid 접근: PPO + DPO + GRPO를 태스크에 따라 선택적으로 조합하는 트렌드
7. 주요 응용 사례
7.1 AlphaGo / AlphaZero / AlphaFold
AlphaGo (Silver et al., 2016):
바둑에서 인간 세계 챔피언 이세돌을 4:1로 이긴 AlphaGo는 강화학습의 가능성을 전 세계에 알렸다. 바둑의 상태 공간은 약 으로, 우주의 원자 수()보다 훨씬 많다.
AlphaGo의 학습 파이프라인:
- SL Policy Network: 인간 기보 16만 건으로 지도학습 (57% → 프로 수준)
- RL Policy Network: 자기 자신과의 대국(Self-play)으로 강화학습
- Value Network: 게임 결과를 예측하여 위치 평가
- Monte Carlo Tree Search (MCTS): Policy Network와 Value Network를 결합하여 탐색
AlphaGo Zero (Silver et al., 2017):
인간 기보를 전혀 사용하지 않고, 순수하게 Self-play RL만으로 3일 만에 AlphaGo를 100:0으로 이겼다. 이것은 RL의 잠재력을 극적으로 보여준 결과다.
AlphaZero (Silver et al., 2018):
AlphaGo Zero의 범용 버전으로, 동일한 알고리즘이 바둑, 체스, 장기(Shogi) 모두에서 기존 최고 프로그램을 능가했다. 핵심 구성은 단 두 가지다: Deep Neural Network + MCTS.
AlphaFold (Jumper et al., 2021) / AlphaFold 3 (Abramson et al., 2024):
직접적인 RL은 아니지만, RL의 탐색 전략에서 영감을 받은 단백질 3D 구조 예측 시스템으로, 생물학 50년 난제를 해결했다. AlphaFold 3는 단백질뿐 아니라 DNA, RNA, 리간드 등 모든 생체분자의 상호작용 구조를 예측한다.
7.2 로보틱스
강화학습은 로보틱스 분야에서 혁신적 성과를 만들어내고 있다.
Sim-to-Real Transfer: 시뮬레이션 환경에서 RL로 학습한 정책을 실제 로봇에 전이하는 기법이다. Domain Randomization으로 시뮬레이션 환경의 물리 파라미터를 무작위로 변화시켜, 실제 환경에서도 작동하는 로버스트한 정책을 학습한다.
주요 성과:
- OpenAI Rubik's Cube (2019): 로봇 손으로 루빅스 큐브를 푸는 것에 성공
- Quadruped Locomotion: 4족 보행 로봇이 다양한 지형에서 안정적으로 이동
- Dexterous Manipulation: 인간 수준의 물체 조작 기술 학습
- Google DeepMind Gemini Robotics (2025): RL 기반 로봇 조작 모델 출시, 물리 세계와의 상호작용 능력을 크게 향상
7.3 게임 AI
강화학습은 게임 분야에서 가장 극적인 성과를 보여왔다.
- Atari Games (DQN, 2015): 49개 게임에서 인간 수준 달성
- StarCraft II (AlphaStar, 2019): 99.8% 이상의 인간 플레이어보다 우수한 성적
- Dota 2 (OpenAI Five, 2019): 세계 챔피언 팀을 2:0으로 승리
- Gran Turismo (GT Sophy, 2022): 레이싱 게임에서 프로 드라이버급 성능
- Minecraft (Dreamer v3, 2023): 처음으로 다이아몬드 채굴에 성공
7.4 추천 시스템과 기타 응용
추천 시스템: 사용자의 장기적 만족도를 최대화하는 순차적 추천을 학습한다. Netflix, YouTube, TikTok 등에서 활용되며, 단기적 클릭률보다 장기적 사용자 참여(engagement)를 최적화한다.
금융: 포트폴리오 최적화, 고빈도 트레이딩, 최적 주문 실행 등에 RL이 활용된다.
자율주행: Waymo, Tesla 등에서 의사결정 모듈에 RL 기반 접근을 탐색하고 있다.
헬스케어: 만성 질환의 동적 치료 계획(Dynamic Treatment Regimes), 약물 발견 가속화, 리소스 할당 최적화 등에 RL이 연구되고 있다.
네트워크/시스템 최적화: 데이터 센터 냉각 최적화(Google), 네트워크 라우팅, 칩 설계(Google TPU 배치 최적화) 등에서 실전 성과를 거두고 있다.
8. PyTorch 코드 예제
8.1 DQN 구현 (CartPole)
CartPole 환경에서 DQN을 구현하는 전체 코드다. Experience Replay, Target Network, -greedy 탐색을 모두 포함한다.
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import gymnasium as gym
from collections import deque
import random
# ============================================================
# Q-Network 정의
# ============================================================
class QNetwork(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=128):
super(QNetwork, self).__init__()
self.network = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, action_dim)
)
def forward(self, x):
return self.network(x)
# ============================================================
# Replay Buffer
# ============================================================
class ReplayBuffer:
def __init__(self, capacity=10000):
self.buffer = deque(maxlen=capacity)
def push(self, state, action, reward, next_state, done):
self.buffer.append((state, action, reward, next_state, done))
def sample(self, batch_size):
batch = random.sample(self.buffer, batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
return (
np.array(states),
np.array(actions),
np.array(rewards, dtype=np.float32),
np.array(next_states),
np.array(dones, dtype=np.float32)
)
def __len__(self):
return len(self.buffer)
# ============================================================
# DQN Agent
# ============================================================
class DQNAgent:
def __init__(self, state_dim, action_dim, lr=1e-3, gamma=0.99,
epsilon_start=1.0, epsilon_end=0.01, epsilon_decay=500,
target_update=10, buffer_size=10000, batch_size=64):
self.action_dim = action_dim
self.gamma = gamma
self.epsilon_start = epsilon_start
self.epsilon_end = epsilon_end
self.epsilon_decay = epsilon_decay
self.target_update = target_update
self.batch_size = batch_size
self.steps_done = 0
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 메인 네트워크와 타깃 네트워크
self.q_network = QNetwork(state_dim, action_dim).to(self.device)
self.target_network = QNetwork(state_dim, action_dim).to(self.device)
self.target_network.load_state_dict(self.q_network.state_dict())
self.target_network.eval()
self.optimizer = optim.Adam(self.q_network.parameters(), lr=lr)
self.buffer = ReplayBuffer(buffer_size)
def get_epsilon(self):
"""Exponential decay로 epsilon 감소"""
eps = self.epsilon_end + (self.epsilon_start - self.epsilon_end) * \
np.exp(-1.0 * self.steps_done / self.epsilon_decay)
return eps
def select_action(self, state):
"""ε-greedy 행동 선택"""
self.steps_done += 1
epsilon = self.get_epsilon()
if random.random() < epsilon:
return random.randrange(self.action_dim) # 탐색
else:
state_t = torch.FloatTensor(state).unsqueeze(0).to(self.device)
with torch.no_grad():
q_values = self.q_network(state_t)
return q_values.argmax(dim=1).item() # 활용
def update(self):
"""Experience Replay로부터 미니배치를 샘플링하여 Q-Network 업데이트"""
if len(self.buffer) < self.batch_size:
return
states, actions, rewards, next_states, dones = self.buffer.sample(self.batch_size)
states_t = torch.FloatTensor(states).to(self.device)
actions_t = torch.LongTensor(actions).to(self.device)
rewards_t = torch.FloatTensor(rewards).to(self.device)
next_states_t = torch.FloatTensor(next_states).to(self.device)
dones_t = torch.FloatTensor(dones).to(self.device)
# 현재 Q-값: Q(s, a; θ)
current_q = self.q_network(states_t).gather(1, actions_t.unsqueeze(1)).squeeze(1)
# 타깃 Q-값: r + γ * max_a' Q(s', a'; θ⁻)
with torch.no_grad():
next_q = self.target_network(next_states_t).max(dim=1)[0]
target_q = rewards_t + self.gamma * next_q * (1 - dones_t)
# 손실 계산 및 역전파
loss = nn.MSELoss()(current_q, target_q)
self.optimizer.zero_grad()
loss.backward()
# Gradient Clipping으로 안정성 향상
nn.utils.clip_grad_norm_(self.q_network.parameters(), max_norm=1.0)
self.optimizer.step()
return loss.item()
def update_target_network(self):
"""타깃 네트워크를 메인 네트워크의 파라미터로 동기화"""
self.target_network.load_state_dict(self.q_network.state_dict())
# ============================================================
# 학습 루프
# ============================================================
def train_dqn(num_episodes=500, render=False):
env = gym.make("CartPole-v1")
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.n
agent = DQNAgent(state_dim, action_dim)
episode_rewards = []
for episode in range(num_episodes):
state, _ = env.reset()
total_reward = 0
done = False
while not done:
action = agent.select_action(state)
next_state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
agent.buffer.push(state, action, reward, next_state, done)
agent.update()
state = next_state
total_reward += reward
# 주기적 타깃 네트워크 업데이트
if episode % agent.target_update == 0:
agent.update_target_network()
episode_rewards.append(total_reward)
if (episode + 1) % 50 == 0:
avg_reward = np.mean(episode_rewards[-50:])
print(f"Episode {episode+1}, Avg Reward (last 50): {avg_reward:.1f}, "
f"Epsilon: {agent.get_epsilon():.3f}")
env.close()
return agent, episode_rewards
if __name__ == "__main__":
agent, rewards = train_dqn()
8.2 PPO 구현 (CartPole)
PPO-Clip 알고리즘의 전체 구현이다. Actor-Critic 네트워크, GAE, Clipped Surrogate Objective를 포함한다.
import torch
import torch.nn as nn
import torch.optim as optim
from torch.distributions import Categorical
import numpy as np
import gymnasium as gym
# ============================================================
# Actor-Critic 네트워크
# ============================================================
class ActorCritic(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=64):
super(ActorCritic, self).__init__()
# Actor (정책 네트워크)
self.actor = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, action_dim),
nn.Softmax(dim=-1)
)
# Critic (가치 네트워크)
self.critic = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, 1)
)
def forward(self, state):
action_probs = self.actor(state)
state_value = self.critic(state)
return action_probs, state_value
def act(self, state):
"""행동 선택 (샘플링)"""
action_probs, state_value = self.forward(state)
dist = Categorical(action_probs)
action = dist.sample()
return action.item(), dist.log_prob(action), state_value
def evaluate(self, states, actions):
"""저장된 경험 배치를 평가"""
action_probs, state_values = self.forward(states)
dist = Categorical(action_probs)
log_probs = dist.log_prob(actions)
entropy = dist.entropy()
return log_probs, state_values.squeeze(-1), entropy
# ============================================================
# PPO Agent
# ============================================================
class PPOAgent:
def __init__(self, state_dim, action_dim, lr=3e-4, gamma=0.99,
lam=0.95, clip_epsilon=0.2, epochs=10, batch_size=64,
entropy_coef=0.01, value_coef=0.5):
self.gamma = gamma
self.lam = lam
self.clip_epsilon = clip_epsilon
self.epochs = epochs
self.batch_size = batch_size
self.entropy_coef = entropy_coef
self.value_coef = value_coef
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.policy = ActorCritic(state_dim, action_dim).to(self.device)
self.optimizer = optim.Adam(self.policy.parameters(), lr=lr)
# 경험 저장소
self.states = []
self.actions = []
self.log_probs = []
self.rewards = []
self.dones = []
self.values = []
def select_action(self, state):
state_t = torch.FloatTensor(state).to(self.device)
with torch.no_grad():
action, log_prob, value = self.policy.act(state_t)
return action, log_prob.item(), value.item()
def store_transition(self, state, action, log_prob, reward, done, value):
self.states.append(state)
self.actions.append(action)
self.log_probs.append(log_prob)
self.rewards.append(reward)
self.dones.append(done)
self.values.append(value)
def compute_gae(self, next_value):
"""Generalized Advantage Estimation (GAE) 계산"""
advantages = []
gae = 0
values = self.values + [next_value]
for t in reversed(range(len(self.rewards))):
delta = self.rewards[t] + self.gamma * values[t + 1] * (1 - self.dones[t]) - values[t]
gae = delta + self.gamma * self.lam * (1 - self.dones[t]) * gae
advantages.insert(0, gae)
advantages = torch.FloatTensor(advantages).to(self.device)
returns = advantages + torch.FloatTensor(self.values).to(self.device)
return advantages, returns
def update(self, next_value):
"""PPO-Clip 업데이트 수행"""
advantages, returns = self.compute_gae(next_value)
# 텐서 변환
states_t = torch.FloatTensor(np.array(self.states)).to(self.device)
actions_t = torch.LongTensor(self.actions).to(self.device)
old_log_probs_t = torch.FloatTensor(self.log_probs).to(self.device)
# Advantage 정규화 (분산 감소)
advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8)
# PPO 에폭 반복
for _ in range(self.epochs):
# 전체 데이터로 미니배치 학습
indices = np.arange(len(self.states))
np.random.shuffle(indices)
for start in range(0, len(self.states), self.batch_size):
end = start + self.batch_size
batch_idx = indices[start:end]
# 현재 정책으로 재평가
new_log_probs, values, entropy = self.policy.evaluate(
states_t[batch_idx], actions_t[batch_idx]
)
# 정책 비율: r_t(θ) = π_θ(a|s) / π_θ_old(a|s)
ratio = torch.exp(new_log_probs - old_log_probs_t[batch_idx])
# PPO-Clip 목적 함수
surr1 = ratio * advantages[batch_idx]
surr2 = torch.clamp(ratio, 1 - self.clip_epsilon,
1 + self.clip_epsilon) * advantages[batch_idx]
policy_loss = -torch.min(surr1, surr2).mean()
# Value Loss (MSE)
value_loss = nn.MSELoss()(values, returns[batch_idx])
# Entropy Bonus (탐색 장려)
entropy_loss = -entropy.mean()
# 전체 손실
loss = (policy_loss
+ self.value_coef * value_loss
+ self.entropy_coef * entropy_loss)
self.optimizer.zero_grad()
loss.backward()
nn.utils.clip_grad_norm_(self.policy.parameters(), max_norm=0.5)
self.optimizer.step()
# 경험 버퍼 초기화
self.states.clear()
self.actions.clear()
self.log_probs.clear()
self.rewards.clear()
self.dones.clear()
self.values.clear()
# ============================================================
# 학습 루프
# ============================================================
def train_ppo(num_episodes=500, update_interval=2048):
env = gym.make("CartPole-v1")
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.n
agent = PPOAgent(state_dim, action_dim)
episode_rewards = []
total_steps = 0
state, _ = env.reset()
current_episode_reward = 0
for step in range(1, 200001):
action, log_prob, value = agent.select_action(state)
next_state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
agent.store_transition(state, action, log_prob, reward, done, value)
current_episode_reward += reward
total_steps += 1
if done:
episode_rewards.append(current_episode_reward)
current_episode_reward = 0
state, _ = env.reset()
if len(episode_rewards) % 50 == 0:
avg = np.mean(episode_rewards[-50:])
print(f"Episode {len(episode_rewards)}, "
f"Avg Reward (last 50): {avg:.1f}, "
f"Total Steps: {total_steps}")
else:
state = next_state
# 일정 스텝마다 PPO 업데이트
if step % update_interval == 0:
with torch.no_grad():
state_t = torch.FloatTensor(state).to(agent.device)
_, next_value = agent.policy(state_t)
next_value = next_value.item()
agent.update(next_value)
env.close()
return agent, episode_rewards
if __name__ == "__main__":
agent, rewards = train_ppo()
9. 주요 논문 레퍼런스
강화학습의 발전을 이끈 핵심 논문들을 연대순으로 정리한다.
| 연도 | 논문/알고리즘 | 저자 | 핵심 기여 | 링크 |
|---|---|---|---|---|
| 1989 | Q-Learning | Watkins | Off-policy TD Control의 시초 | — |
| 1992 | REINFORCE | Williams | Policy Gradient의 시초 | — |
| 2013 | DQN (Atari) | Mnih et al. | Deep RL의 시작, Experience Replay | arXiv:1312.5602 |
| 2015 | DQN (Nature) | Mnih et al. | Target Network, 인간 수준 Atari | Nature |
| 2015 | DDPG | Lillicrap et al. | 연속 행동 공간 DQN 확장 | arXiv:1509.02971 |
| 2015 | TRPO | Schulman et al. | Trust Region으로 안정적 정책 업데이트 | arXiv:1502.05477 |
| 2016 | Double DQN | van Hasselt et al. | Q-값 과대추정 해결 | arXiv:1509.06461 |
| 2016 | Dueling DQN | Wang et al. | V와 A의 아키텍처 분리 | arXiv:1511.06581 |
| 2016 | Prioritized ER | Schaul et al. | TD Error 기반 우선순위 샘플링 | arXiv:1511.05952 |
| 2016 | A3C | Mnih et al. | 비동기 Actor-Critic | arXiv:1602.01783 |
| 2016 | AlphaGo | Silver et al. | RL + MCTS로 바둑 정복 | Nature |
| 2016 | GAE | Schulman et al. | Advantage 추정의 편향-분산 균형 | arXiv:1506.02438 |
| 2017 | PPO | Schulman et al. | Clipped Surrogate로 간단하고 안정적 | arXiv:1707.06347 |
| 2017 | AlphaGo Zero | Silver et al. | 인간 지식 없이 Self-play만으로 학습 | Nature |
| 2017 | C51 (Distributional) | Bellemare et al. | Return 분포 학습 | arXiv:1707.06887 |
| 2018 | SAC | Haarnoja et al. | Maximum Entropy Off-policy AC | arXiv:1801.01290 |
| 2018 | TD3 | Fujimoto et al. | Twin Q + Delayed Updates + Smoothing | arXiv:1802.09477 |
| 2018 | Rainbow | Hessel et al. | 6가지 DQN 개선 통합 | arXiv:1710.02298 |
| 2018 | World Models | Ha & Schmidhuber | 잠재 공간에서의 세계 모델 | arXiv:1803.10122 |
| 2018 | AlphaZero | Silver et al. | 범용 Self-play 알고리즘 | Science |
| 2020 | MuZero | Schrittwieser et al. | 규칙 없이 학습하는 Model-based RL | Nature |
| 2020 | Dreamer | Hafner et al. | 잠재 공간 상상을 통한 학습 | arXiv:1912.01603 |
| 2023 | DPO | Rafailov et al. | 보상 모델 없는 직접 선호도 최적화 | arXiv:2305.18290 |
| 2023 | Dreamer v3 | Hafner et al. | 범용 World Model 에이전트 | arXiv:2301.04104 |
| 2025 | GRPO (DeepSeek-R1) | DeepSeek | Critic 없는 그룹 상대적 정책 최적화 | arXiv:2501.12948 |
| 2025 | DiscoRL | Lu et al. | 자율 SOTA RL 알고리즘 발견 | Nature |
10. RL의 현재 한계와 미래 전망
10.1 현재 한계
샘플 비효율성 (Sample Inefficiency):
Model-free RL은 여전히 천문학적인 양의 환경 상호작용을 필요로 한다. Atari 게임에서 DQN은 약 2억 프레임(약 900시간의 게임 플레이)이 필요했다. 인간은 10분 정도면 기본적인 전략을 학습한다. Model-based 접근이 이를 개선하고 있지만, 아직 범용적 해결책은 없다.
보상 설계의 어려움 (Reward Engineering):
적절한 보상 함수를 설계하는 것은 RL 응용의 가장 큰 실무적 과제다. 보상이 잘못 설계되면 Reward Hacking — 의도하지 않은 방식으로 보상을 최대화하는 현상 — 이 발생한다. 예를 들어, "경주에서 빨리 달리기"라는 보상을 주면 에이전트가 원을 그리며 도는 것을 학습할 수 있다.
Sim-to-Real Gap:
시뮬레이션에서 학습한 정책이 현실 세계에서 작동하지 않는 문제다. 물리 시뮬레이션의 부정확성, 센서 노이즈, 시각적 차이 등이 원인이다. Domain Randomization과 같은 기법이 이를 완화하지만, 근본적 해결은 아니다.
안전성 (Safety):
실제 환경에서의 RL 학습은 위험할 수 있다. 로봇이 학습 중 자신이나 환경을 손상시킬 수 있고, 자율주행차가 학습 중 사고를 일으킬 수 있다. Safe RL — 안전 제약 조건 하에서 학습하는 연구 — 이 활발하지만, 아직 초기 단계다.
확장성 (Scalability):
상태 공간과 행동 공간이 극도로 크거나 무한한 경우, 전통적 RL 방법은 계산 복잡성 때문에 적용이 어렵다. 2026년 발표된 연구에서는 이를 단순화된 도메인으로 변환하고, 스펙트럼 수렴 보장이 있는 계층적 알고리즘을 통해 해결하는 접근이 제안되었다.
탐색-활용 딜레마 (Exploration-Exploitation Dilemma):
특히 보상이 희소한(sparse reward) 환경에서, 유용한 보상 신호를 찾기 위한 효과적인 탐색 전략이 여전히 미해결 과제다. 호기심 기반 탐색(Curiosity-driven Exploration), 개수 기반 탐색(Count-based Exploration) 등이 연구되고 있다.
10.2 미래 전망
Foundation Models + RL:
20252026년의 가장 강력한 트렌드는 Large Language Models와 RL의 융합이다. RLHF/DPO/GRPO를 통한 LLM 정렬은 이미 산업 표준이 되었고, LLM의 추론 능력을 RL로 강화하는 연구(예: OpenAI의 o1/o3, DeepSeek-R1)가 폭발적으로 성장하고 있다. 나아가, Vision-Language Models의 시각적 콘텐츠 생성에도 RL이 적용되어, 20192020년 13편에서 2024~2025년 91편으로 관련 논문이 급증했다.
자율 알고리즘 발견:
DeepMind의 DiscoRL(2025)이 보여주듯, RL 알고리즘을 인간이 수동으로 설계하는 시대에서 AI가 자동으로 발견하는 시대로의 전환이 시작되었다. 이는 RL 연구의 메타 레벨에서의 혁신이다.
Multi-Agent RL (MARL):
단일 에이전트에서 다수 에이전트 간의 협력과 경쟁을 다루는 MARL 연구가 급격히 확대되고 있다. 자율주행 차량 군집, 드론 편대, 복잡한 경제 시뮬레이션 등에 필수적이다.
로보틱스의 실용화:
Google DeepMind의 Gemini Robotics(2025), Genie 3(2025) 등이 보여주듯, RL 기반 로보틱스가 연구실을 넘어 실제 응용으로 빠르게 이행하고 있다. 시뮬레이션에서 학습한 정책을 실제 로봇에 전이하는 기술이 급속히 발전하고 있다.
Offline RL / Batch RL:
과거 수집된 데이터셋만으로 RL 정책을 학습하는 Offline RL이 성장하고 있다. 환경과의 실시간 상호작용이 불가능하거나 위험한 경우(헬스케어, 자율주행 등)에 핵심적이다.
Hybrid AI:
2025년 9월 Google DeepMind가 발표한 Deep RL과 Symbolic Reasoning의 결합은 AI 문제 해결의 새로운 가능성을 열었다. RL의 학습 능력과 심볼릭 추론의 논리적 추론 능력을 결합한 하이브리드 시스템은 복잡한 다단계 문제를 해결하는 데 큰 잠재력을 보이고 있다.
마무리
강화학습은 1989년 Q-Learning에서 시작하여, 2015년 DQN의 Atari 정복, 2016년 AlphaGo의 바둑 정복, 그리고 2022년 이후 RLHF를 통한 LLM 혁명에 이르기까지, AI 역사에서 가장 극적인 발전을 보여온 분야다.
특히 2025~2026년에는 GRPO와 RLVR을 통한 효율적인 LLM 정렬, DiscoRL을 통한 자율 알고리즘 발견, 그리고 로보틱스와 시각적 생성 분야로의 확장이 이루어지며, 강화학습은 단순한 게임 AI를 넘어 범용 AI의 핵심 학습 패러다임으로 자리잡고 있다.
이 글에서 다룬 수학적 기초(MDP, Bellman Equation)와 핵심 알고리즘(Q-Learning, DQN, PPO, SAC)을 탄탄히 이해하고, PyTorch 구현을 통해 직접 실험해 본다면, 급변하는 RL 연구의 최전선을 따라갈 수 있는 견고한 토대를 갖출 수 있을 것이다.