강화 학습에서 Q-Learning과 Policy Gradient를 선택하는 기준

MDP를 바탕으로 Q-Learning과 Policy Gradient의 학습 방식, 탐색, 안정화 기법, 운영 적용 기준을 정리한다.

2026-08-14 · 최초 발행 2024-04-29

보상을 기준으로 의사결정을 학습하는 방식

강화 학습(Reinforcement Learning, RL)은 환경에서 행동하고 받은 보상 신호를 바탕으로 정책을 학습하는 의사결정 자동화 기법이다. 목표는 누적 보상이 커지도록 행동 선택을 바꾸는 데 있다.

실무에서는 알고리즘 이름보다 먼저 문제를 어떻게 상태·행동·보상·제약으로 표현할지 정해야 한다. 이 표현이 흔들리면 Q-Learning이든 Policy Gradient든 안정적인 정책을 얻기 어렵다.

MDP로 문제를 정식화한다

MDP(Markov Decision Process)는 강화 학습 문제를 기술하는 수학적 틀이다. 상태 집합 S, 행동 집합 A, 전이확률 P(s'|s,a), 보상 함수 R(s,a,s'), 감가율 γ ∈ [0,1)로 구성한다. 마르코프성 가정에서는 현재 상태만으로 다음 상태의 분포가 결정된다.

학습의 목적은 누적 할인 보상 G = Σ γ^t r_t의 기댓값을 최대화하는 것이다. 최적 가치 함수 V*, Q는 벨만 최적 방정식으로 정의되며, 최적 정책 π는 Q*에서 유도할 수 있다.

Q 값을 갱신해 행동을 고르는 Q-Learning

Q-Learning은 환경에서 얻은 전이 샘플로 상태-행동 가치 Q(s,a)를 갱신하는 오프폴리시 TD 제어 방식이다. 정책은 탐욕적 선택 또는 ε-탐욕 형태로 구성한다.

핵심 갱신식은 다음과 같다.

Q(s,a) ← Q(s,a) + α [r + γ max_a' Q(s',a') − Q(s,a)]

탐색과 학습률 조건을 만족하는 표 기반의 유한 MDP에서는 수렴 보장이 있다. 디스크리트 행동 공간에서 특히 직접적으로 적용할 수 있다.

정책 자체를 최적화하는 Policy Gradient

Policy Gradient는 파라미터화한 정책 π*θ(a|s)를 직접 최적화한다. 목적함수 J(θ)=E[G]에 대해 ∇*θ J(θ) 방향으로 상승시키며, REINFORCE, Actor-Critic(A2C/A3C), PPO, TRPO가 대표적인 방식이다.

연속 행동 공간과 확률적 정책을 다루기 좋고 탐색이 정책 안에 내재돼 있다. 반면 추정 분산이 커질 수 있어 baseline, advantage, GAE, entropy 보너스 같은 기법으로 이를 완화한다.

알고리즘 선택은 행동 공간과 데이터 흐름에서 시작된다

가치 기반 접근은 Q 값을 추정한 뒤 정책을 끌어낸다. Q-Learning은 디스크리트 행동과 표 기반 문제, DQN 계열에 잘 맞지만 연속 제어를 직접 처리하는 데는 한계가 있다.

정책 기반 접근은 정책을 바로 최적화한다. 연속·고차원 제어에는 강점이 있지만, 분산을 낮추고 배치 학습을 안정화하는 장치가 필요하다.

탐색도 접근마다 다르다. ε-탐욕, 소프트맥스, 볼츠만 탐색은 외재적으로 탐색을 부여하는 방식이고, 확률적 정책은 정책 자체에서 탐색을 수행한다. 초기에는 탐색을 강화하고 이후 활용 비중을 높이는 흐름을 취할 수 있다. 보상이 희소한 환경에서는 shaping, curriculum, intrinsic reward, HER를 적용한다.

심층 신경망으로 Q 함수·정책·가치 함수를 근사할 때는 발산을 제어해야 한다. 가치 기반에서는 리플레이 버퍼, 타깃 네트워크, 배치 정규화, 학습률 스케줄을 활용한다. 정책 기반에서는 PPO의 클리핑, TRPO의 신뢰영역, gradient clipping, KL 제어로 업데이트를 안정화한다.

오프폴리시인 Q-Learning과 DQN은 과거 데이터를 다시 쓸 수 있어 샘플 효율이 높다. 대신 분포 시프트와 드리프트에 대응해야 한다. REINFORCE, A2C, PPO 같은 온폴리시 방법은 최신 정책 데이터와의 일관성이 있지만 샘플 비용이 증가할 수 있으며, 대규모 병렬 수집으로 이를 보완한다.

학습과 평가가 반복되는 운영 흐름

ε-탐욕/정책오프폴리시온폴리시Q-LearningPolicy Gradient발산 감지?정상아니오아니오시작: 정책/가치 초기화에피소드 시작: 상태 s 관측행동 선택행동 a 실행환경 전이: r, s' 수집저장/배치리플레이 버퍼 저장롤아웃 버퍼에 trajectory 적재배치 샘플링업데이트 유형Q 갱신: r + γ max Q(s',a')∇θ J 계산: advantage,클리핑안정화gradient clipping/학습률감소타깃 네트워크/EMA 업데이트종료 상태?에피소드 종료, 메트릭 로깅평가: 리턴/성공률/KL/제약위반수용 기준 충족?정책 고정/배포

학습 중 비정상 보상이나 NaN이 발생하면 배치를 제거하고, 학습률을 낮추며, 관측 정규화를 다시 점검한다. 행동 제약을 위반하면 조건부 정책이나 action clipping 같은 안전 필터를 두고 비용 보상을 도입할 수 있다. 오프폴리시 학습에서 분포 시프트가 문제라면 importance sampling과 데이터 리밸런싱을 검토한다.

Q-Learning과 Policy Gradient의 차이

항목 Q-Learning Policy Gradient
행동 공간 디스크리트 적합, 연속은 DDPG/SAC 등 변형 필요 연속·다차원 직접 처리
샘플 효율 높음(오프폴리시·리플레이) 낮음~중간(온폴리시가 일반적)
안정성/수렴 표 기반 수렴 이론 존재, 함수 근사 시 불안정 가능 목적 직접 최적화, 클리핑/배리언스 완화로 안정화
탐색 ε-탐욕 등 외재적 확률적 정책으로 내재적
구현 복잡도 단순(표 기반), DQN 계열 중간 REINFORCE 단순, PPO/Actor-Critic 중간~복잡
확장성 대규모 오프폴리시 학습 유리 병렬 수집·분산 학습로 보완
오프/온 정책 오프폴리시 주로 온폴리시(예: PPO), 오프폴리시 변형 존재

추천·제어·스케줄링 환경에서의 적용

추천과 광고 입찰에서는 사용자 상태, 컨텍스트, 품목 또는 입찰 행동을 환경으로 삼고 클릭·전환·ROI의 가중 합을 보상으로 둔다. 시뮬레이터와 오프라인 로그로 사전학습한 뒤 IPS/DR 기반 오프폴리시 평가를 거쳐 제한적 온라인 A/B와 안전 제약 하 배포로 이어갈 수 있다. 디스크리트 문제에는 DQN/SlateQ를, 안정성과 탐색의 균형에는 정책 기반과 가치 기반을 혼합한 AC를 적용한다.

로보틱스와 제조 공정 제어는 연속 제어, 높은 주파수 제약, 안전 문제가 함께 있다. 시뮬레이터와 실제 환경의 차이를 줄이는 일이 중요하며, PPO/SAC/TD3, 도메인 랜덤화, RL with costs, 실험 설계로 다운타임을 최소화하는 접근을 쓴다.

운영·네트워크·자원 스케줄링에서는 지연, 처리량, SLA를 목표로 삼고 큐 길이·부하·지표를 상태로 사용한다. 오프폴리시 학습 후 온라인 파인튜닝을 수행하면서 보상 설계와 페널티 기반 제약 관리를 함께 둔다.

금융과 트레이딩은 비정상성과 노이즈가 크고 리스크 제약이 중요하다. 오프라인·시뮬레이션 기반 개발을 전제로 하며, 오프폴리시·오프라인 RL, CVaR 기반 리스크 조정 보상, 안정화와 규제 준수에 초점을 둔다.

게임과 시뮬레이션에서는 셀프플레이, 커리큘럼, 대규모 분산 롤아웃으로 학습을 가속하며 정책 기반과 가치 기반 방식을 함께 적용한다.

최소 실행 예제

전제조건은 Python 3.10+, pip install gymnasium numpy torch다. 재현성을 높이려면 시드를 고정하는 편이 좋다.

FrozenLake-v1에서의 표 기반 Q-Learning

import gymnasium as gym
import numpy as np
env = gym.make("FrozenLake-v1", is_slippery=True)
nS, nA = env.observation_space.n, env.action_space.n
Q = np.zeros((nS, nA))
alpha, gamma, eps = 0.8, 0.99, 1.0
eps_min, eps_decay = 0.05, 0.995

def choose_action(s):
    if np.random.rand() < eps:
        return env.action_space.sample()
    return np.argmax(Q[s])

for ep in range(5000):
    s, _ = env.reset()
    done = False
    while not done:
        a = choose_action(s)
        s2, r, terminated, truncated, _ = env.step(a)
        done = terminated or truncated
        Q[s,a] += alpha * (r + gamma * (0 if done else np.max(Q[s2])) - Q[s,a])
        s = s2
    eps = max(eps_min, eps * eps_decay)

# 평가
wins = 0
for _ in range(100):
    s, _ = env.reset()
    done = False
    while not done:
        a = np.argmax(Q[s])
        s, r, term, trunc, _ = env.step(a)
        done = term or trunc
        if done and r > 0: wins += 1
print("Success rate:", wins, "%")

CartPole-v1에서의 REINFORCE Policy Gradient

import gymnasium as gym, torch, torch.nn as nn, torch.optim as optim
import numpy as np
env = gym.make("CartPole-v1")
torch.manual_seed(0); np.random.seed(0)

class Policy(nn.Module):
    def __init__(self, obs, act):
        super().__init__()
        self.net = nn.Sequential(nn.Linear(obs, 64), nn.ReLU(),
                                 nn.Linear(64, act), nn.Softmax(dim=-1))
    def forward(self, x): return self.net(x)

obs_dim, act_dim = env.observation_space.shape[0], env.action_space.n
pi = Policy(obs_dim, act_dim)
opt = optim.Adam(pi.parameters(), lr=1e-2)
gamma = 0.99

def discount(r):
    G, out = 0, []
    for x in reversed(r):
        G = x + gamma * G
        out.append(G)
    out.reverse()
    return torch.tensor(out, dtype=torch.float32)

for ep in range(300):
    s, _ = env.reset()
    logps, rewards = [], []
    done = False
    while not done:
        s_t = torch.tensor(s, dtype=torch.float32)
        probs = pi(s_t)
        m = torch.distributions.Categorical(probs)
        a = m.sample()
        s, r, term, trunc, _ = env.step(a.item())
        done = term or trunc
        logps.append(m.log_prob(a))
        rewards.append(r)
    G = discount(rewards)
    G = (G - G.mean()) / (G.std() + 1e-8)  # baseline 대용
    loss = -(torch.stack(logps) * G).sum()
    opt.zero_grad(); loss.backward()
    nn.utils.clip_grad_norm_(pi.parameters(), 1.0)
    opt.step()

# 간단 평가
s, _ = env.reset()
total = 0
done = False
while not done:
    with torch.no_grad():
        a = torch.argmax(pi(torch.tensor(s, dtype=torch.float32))).item()
    s, r, term, trunc, _ = env.step(a)
    done = term or trunc
    total += r
print("Eval return:", total)

FrozenLake는 확률적 전이를 사용하므로 성공률이 달라질 수 있다. CartPole 예제에는 간단한 베이스라인 정규화만 적용돼 있으며, 실제 서비스에서는 advantage 추정, 엔트로피 보너스, 조기 종료 기준, 검증 루프가 필요하다.

성능과 안전성을 함께 측정한다

강화 학습은 누적 보상과 정책 가치를 지속적으로 개선하는 데 사용될 수 있다. 예시로 CTR 15%p, 운영 비용 520% 절감 가능성이 있으며 도메인과 제약에 따라 달라진다. 규칙 기반 방식과 비교하면 환경 변화에 자동으로 적응할 수 있고, 온라인 학습·배포 파이프라인과 연결해 응답성을 높일 수 있다.

제약 기반 정책과 리스크 보상은 위반율을 낮추는 데 활용할 수 있으며, 오프라인 평가는 안전한 전환을 돕는다. 운영 지표로는 리턴, 성공률, regret, 샘플 효율(에피소드/스텝당 개선량), 제약 위반율, 배포 전후 KPI 변화를 확인한다.

MDP에서 보상·제약·관찰을 명확히 정의한 뒤, 디스크리트·저차원 문제에는 Q-Learning 또는 DQN을 우선 검토하고 연속·고차원 제어에는 Policy Gradient 계열의 Actor-Critic, PPO/SAC를 검토할 수 있다. 초기 학습과 오프폴리시 평가는 시뮬레이터 또는 오프라인 로그에서 수행하고, 제한적 온라인 실험을 거쳐 안전 제약과 모니터링을 포함한 점진적 롤아웃으로 이어간다. 시드와 버전 관리로 재현성을 확보하고, 메트릭·로그 추적, 롤백 전략, drift 감지 체계를 운영에 포함한다.

강화 학습Q-LearningPolicy GradientMDPActor-Critic