1. 벨만 기대 방정식 (Bellman Expectation Equation)
벨만 기대 방정식은 어떤 상태의 가치(Value)가 “현재 받을 보상”과 “다음 상태의 가치의 기대값”으로 표현된다는 관계식입니다.
즉, 지금 이 상태가 얼마나 좋은지는 단순히 현재 보상만으로 결정되는 것이 아니라, 현재 보상 + (정책에 따라 도달할 다음 상태들의 가치의 평균)으로 재귀적으로 정의된다는 의미입니다. 여기서 ‘기대(expectation)’라는 말은, 다음 상태가 확률적으로 결정되기 때문에 그 확률을 고려한 평균값을 사용한다는 뜻입니다.
쉽게 말해, 벨만 기대 방정식은 “현재 가치 = 지금 얻는 것 + 미래 가치의 평균”이라는 강화학습의 기본 원리를 수학적으로 표현한 식입니다.
1-1 현재만 보기
지금 받는 보상만 고려한 상태입니다.
1-2 한 번, 두 번 확장
다음 보상, 다다음 보상까지 할인율($\gamma$)을 적용해서 더해나갑니다.
1-3 무한 확장
이걸 무한히 확장하여 한 줄로 줄인 것이 바로 벨만 기대 방정식입니다.
2. 현실 MDP(Markov Decision Process)에 적용
현실의 강화학습 문제에서는 다음 요소들이 복합적으로 작용합니다.
- 행동이 여러 개 존재함
- 다음 상태가 확률적으로 여러 개 나옴
- 정책에 따라 행동 확률이 달라짐
- 보상도 확률적임
현재 가치 = (행동 확률 평균) $\times$ (전이 확률 평균) $\times$ (보상 + 감마 $\times$ 다음 가치)
이 식은 사실 아래 4가지를 차례대로 평균 내는 구조입니다.
- $\sum_a \pi(a|s)$ : 상태에서 정책이 고르는 행동들의 평균(기대값)
- $\sum_{s'} P(s'|s,a)$ : 그 행동을 했을 때 나올 수 있는 다음 상태들의 평균(기대값)
- $R(s,a,s')$ : 그 전이에서 받는 즉시 보상
- $\gamma V_\pi(s')$ : 다음 상태 가치의 할인된 미래 부분
이를 수식으로 완벽하게 조립하면 다음과 같습니다.
💡 핵심 요약:
상태 $s$에서 정책대로 움직일 때, (지금 보상 + 할인된 다음 상태 가치)의 평균이 바로 상태 가치 함수 $V_\pi(s)$가 됩니다.
3. 술취한 사람 문제 (1D Random Walk)
술취한 사람 문제는 강화학습이나 마르코프 과정에서 아주 자주 나오는 대표적인 예제입니다. 길 위에 서 있는 사람이 술에 취해 원하는 방향으로 정확히 가지 못하고 확률적으로 비틀거리며 이동한다고 가정합니다.
이 문제를 통해 “지금 이 위치가 안전한가?”, “이 위치에서 앞으로 좋은 결과를 얻을 가능성이 얼마나 되는가?”를 계산해 볼 수 있습니다. 현재 위치를 상태(State)로 보고, 다음 위치로 이동하는 확률을 상태 전이 확률로 표현하면 벨만 기대 방정식을 적용할 수 있습니다.
3-1 1차원 길 환경
[집(Home)] --- A --- B --- C --- [술집(Bar)]
- 맨 왼쪽 집(Home): 도착하면 좋은 상태
- 맨 오른쪽 술집(Bar): 도착하면 좋지 않은 상태
- 중간 상태: A, B, C
- 술취한 사람은 현재 위치에서 왼쪽 또는 오른쪽으로 움직이지만, 확률적으로 움직입니다.
3-2 상태(State) 정의
상태 공간(State Space)에는 5가지 상태가 들어있습니다.
- Home, Bar는 도달하면 끝나는 **종료 상태(Terminal State)**입니다.
3-3 전이 확률 (Transition Probability)
중간 상태에서는 다음과 같이 좌우 50% 확률로 한 칸씩 이동합니다.
- A에서: 50% 확률로 Home, 50% 확률로 B
- B에서: 50% 확률로 A, 50% 확률로 C
- C에서: 50% 확률로 B, 50% 확률로 Bar
3-4 보상(Reward) 설정
- Home에 도착하면 +1 (좋은 결과)
- Bar에 도착하면 -1 (나쁜 결과)
- 그 외 중간 이동은 0 (특별한 즉시 보상 없음)
3-5 각 상태의 의미 (가치 함수)
- A의 가치가 높다면 $\rightarrow$ 집에 갈 가능성이 높고 좋은 상태
- C의 가치가 낮다면 $\rightarrow$ 술집으로 갈 가능성이 높고 나쁜 상태
- B는 $\rightarrow$ 중간 정도
💡 가치(Value)란? “그 상태에서 시작했을 때 앞으로 얼마나 좋은 결과를 기대할 수 있는가?” 를 나타내는 점수입니다.
3-6 벨만 기대 방정식 적용
- 할인율 $\gamma = 1$로 설정 (미래 보상을 감가 없이 그대로 다 반영하겠다는 뜻)
- $$V(s) = \text{즉시 보상} + 1 \times \text{다음 상태 가치의 기대값}$$
3-7 종료 상태의 가치
3-8 수식으로 푸는 상태 가치 업데이트
각 상태의 가치는 이웃한 상태들의 가치 평균으로 수렴합니다.
- $V(A) = 0.5 \times V(Home) + 0.5 \times V(B)$
- $V(B) = 0.5 \times V(A) + 0.5 \times V(C)$
- $V(C) = 0.5 \times V(B) + 0.5 \times V(Bar)$
계산 결과, 각 상태의 점수는 위치의 좋고 나쁨을 직관적으로 보여줍니다.
- A = 0.5 (집에 가까워 비교적 좋은 상태)
- B = 0 (집과 술집의 딱 가운데 위치하는 중립적인 상태)
- C = -0.5 (술집에 가까워 좋지 않은 상태)
Home(+1) --- A(+0.5) --- B(0) --- C(-0.5) --- Bar(-1)
실습 코드
[코드 1] 가치 반복(Value Iteration)으로 풀기
초기 가치를 0으로 놓고, 방정식을 여러 번 반복(Iteration)하여 값을 업데이트하는 방식입니다.
V = {
"Home": 1.0,
"A": 0.0,
"B": 0.0,
"C": 0.0,
"Bar": -1.0
}
iterations = 10
for i in range(1, iterations + 1):
u_V = V.copy()
u_V["A"] = 0.5 * V["Home"] + 0.5 * V["B"]
u_V["B"] = 0.5 * V["A"] + 0.5 * V["C"]
u_V["C"] = 0.5 * V["B"] + 0.5 * V["Bar"]
V = u_V
print(f"{i:d}회 반복 -> A={V['A']:.4f}, B={V['B']:.4f}, C={V['C']:.4f}")
for state, value in V.items():
print(f'{state}: {value:.4f}')
[코드 2] 몬테카를로 시뮬레이션으로 풀기 (재귀 구조)
무작위로 좌우로 이동하는 시뮬레이션을 수만 번 반복하여 평균 보상을 계산합니다.
import random
def run(start_state):
while True:
if start_state == "Home":
return 1
elif start_state == "Bar":
return -1
move = random.choice(['left', 'right'])
if start_state == "A":
start_state = "Home" if move == "left" else "B"
elif start_state == "B":
start_state = "A" if move == "left" else "C"
elif start_state == "C":
start_state = "B" if move == "left" else "Bar"
def estimate_value(start_state, n=10000):
total = 0
for i in range(n):
total += run(start_state)
return total / n
print(f"A ≈ {estimate_value('A'):.4f}")
print(f"B ≈ {estimate_value('B'):.4f}")
print(f"C ≈ {estimate_value('C'):.4f}")
[코드 3] 몬테카를로 시뮬레이션 (반복문 구조)
import random
episodes = 100000
total_reward = 0
for _ in range(episodes):
state = "A"
while state not in ["Home", "Bar"]:
if state == "A":
state = random.choice(["Home", "B"])
elif state == "B":
state = random.choice(["A", "C"])
elif state == "C":
state = random.choice(["B", "Bar"])
if state == "Home":
total_reward += 1
elif state == "Bar":
total_reward -= 1
average_reward = total_reward / episodes
print(f"A에서 시작 시 평균 보상: {average_reward:.4f}")
5x5 격자 술취한 사람 문제 (2D Grid World)
이번에는 1차원 선상이 아니라 5x5 2차원 격자 위에서 술취한 사람이 비틀거리는 환경입니다.
+-----+-----+-----+-----+-----+
| H | A | B | C | BAR |
+-----+-----+-----+-----+-----+
| D | E | F | G | I |
+-----+-----+-----+-----+-----+
| J | K | L | M | N |
+-----+-----+-----+-----+-----+
| O | P | Q | R | S |
+-----+-----+-----+-----+-----+
| T | U | V | W | X |
+-----+-----+-----+-----+-----+
상태 및 보상 정의
- H (Home): (0, 0) 위치. 도착 시 보상 +1 (종료 상태)
- BAR (술집): (0, 4) 위치. 도착 시 보상 -1 (종료 상태)
- 나머지 (일반 상태): 이동 시 보상 0
4-2 이동 규칙
- 술취한 사람은 위, 아래, 왼쪽, 오른쪽 4방향으로 각각 25% 확률로 이동하려 합니다.
- 격자 밖으로 벗어나려고 하면 이동하지 않고 제자리를 유지합니다.
- 할인율 $\gamma = 1.0$을 사용하여 각 상태의 가치 $V(s)$를 구합니다.
[코드 4] 5x5 환경의 상태 가치 반복 (Value Iteration)
SIZE = 5
GAMMA = 1.0
ITERATIONS = 30
HOME = (0, 0)
BAR = (0, 4)
DIRECTIONS = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 상, 하, 좌, 우
def is_terminal(state):
return state == HOME or state == BAR
def move(state, direction):
r, c = state
dr, dc = direction
nr, nc = r + dr, c + dc
# 격자 밖으로 나가면 제자리 유지
if nr < 0 or nr >= SIZE or nc < 0 or nc >= SIZE:
return state
return (nr, nc)
def get_reward(next_state):
if next_state == HOME:
return 1.0
elif next_state == BAR:
return -1.0
else:
return 0.0
def print_grid(values, title=""):
if title:
print(f'\n{title}')
for r in range(SIZE):
row = []
for c in range(SIZE):
state = (r, c)
if state == HOME:
row.append(" HOME ")
elif state == BAR:
row.append(" BAR ")
else:
row.append(f"{values[r][c]:6.2f}")
print(" | ".join(row))
print()
def value_iteration():
V = [[0.0 for _ in range(SIZE)] for _ in range(SIZE)]
# 종료 상태 가치 고정
V[HOME[0]][HOME[1]] = 1.0
V[BAR[0]][BAR[1]] = -1.0
print_grid(V, title="초기 상태 가치")
for iteration in range(1, ITERATIONS + 1):
new_V = [[V[r][c] for c in range(SIZE)] for r in range(SIZE)]
for r in range(SIZE):
for c in range(SIZE):
state = (r, c)
# 종료 상태는 업데이트 안 함
if is_terminal(state):
continue
value = 0.0
# 4방향(각 25% 확률)에 대한 기대값 계산
for direction in DIRECTIONS:
next_state = move(state, direction)
reward = get_reward(next_state)
nr, nc = next_state
value += 0.25 * (reward + GAMMA * V[nr][nc])
new_V[r][c] = value
V = new_V
if iteration in [1, 2, 5, 10, 20, 30]:
print_grid(V, title=f"{iteration}회 반복 후 상태 가치")
return V
if __name__ == "__main__":
final_V = value_iteration()
print_grid(final_V, title='최종 상태 가치')
[코드 5] 5x5 환경의 몬테카를로 시뮬레이션
import random
# 상, 하, 좌, 우
dy = [-1, 1, 0, 0]
dx = [0, 0, -1, 1]
episodes = 100000
total_reward = 0
for _ in range(episodes):
# 시작 지점 (0, 1) 즉 'A' 위치
y, x = 0, 1
# 도착지에 도달할 때까지 반복
while (y, x) not in [(0, 0), (0, 4)]:
d = random.randint(0, 3)
ny = y + dy[d]
nx = x + dx[d]
# 격자 내부에 있을 때만 이동 (벗어나면 무시하고 다음 루프에서 제자리 취급 효과)
if 0 <= ny <= 4 and 0 <= nx <= 4:
y, x = ny, nx
if (y, x) == (0, 0):
total_reward += 1
elif (y, x) == (0, 4):
total_reward -= 1
average_reward = total_reward / episodes
print(f"(0, 1)에서 시작 시 평균 보상: {average_reward:.4f}")
'개념 정리 step2 > 강화 학습' 카테고리의 다른 글
| [강화학습] Deep Reinforcement Learning 개념 (0) | 2026.03.03 |
|---|---|
| [강화학습] TD Learning (시간차 학습) 개념, 랜덤 벽 GridWorld 실습 (0) | 2026.03.01 |
| [강화학습] Monte Carlo Learning 정리 (0) | 2026.02.28 |
| [강화학습] 마르코프 결정 과정 MDP 정리 (MP, MRP, MDP) (0) | 2026.02.26 |
| [강화학습] 강화학습 기본 개념 정리 (0) | 2026.02.21 |
