<TD(Temporal Difference) 예제 연습_3>

코드 설명
1. 환경 (environment.py)
이 코드는 강화학습에서 사용되는 4x4 그리드 환경을 구현:
- 상태 공간: 4x4 그리드로 다음과 같은 값을 가짐
- 에이전트 위치: 1
- 직장 위치: 2 (오른쪽 상단 모서리, [0,3])
- 집 위치: 3 (오른쪽 하단 모서리, [3,3])
- 공원 구역: -1 (중앙 2x2 영역, [1:3, 1:3])
- 행동 공간: {0, 1, 2, 3}
- 0: 위로 이동
- 1: 오른쪽으로 이동
- 2: 아래로 이동
- 3: 왼쪽으로 이동
- 전이 역학:
- 사용자가 선택한 행동이 70% 확률로 실행됨
- 30% 확률로 다른 임의의 행동이 대신 실행됨
- 에이전트가 그리드 경계에 도달하면 그 자리에 머무름
- 보상 구조:
- 기본 이동 보상: -0.5
- 공원 구역에 있을 때: -1.0
- 직장에 도착했을 때: +5
- 직장에 머무를 때: 0
- 집에 도착했을 때: +10
- 집에 머무를 때: 0
- 종료 조건:
- 에이전트가 직장이나 집에 도착하면 에피소드 종료
- 전이 확률 함수:
- 환경의 확률적 특성을 명시적으로 계산하는 함수 포함

2. TD 예측 알고리즘 (td_prediction.py)
이 코드는 시간차(TD) 학습 알고리즘으로 주어진 정책에 따른 상태 가치와 행동 가치를 예측:
- 하이퍼파라미터:
- 감마(gamma): 0.9 (할인 인자)
- 알파(alpha): 1e-3 (학습률)
- TD 상태 가치 예측:
- td_value_prediction 함수
- 주어진 정책을 평가하여 각 상태의 가치를 계산
- TD(0) 업데이트 규칙 사용: V(s) ← V(s) + α[r + γV(s') - V(s)]
- TD 행동 가치 예측:
- td_action_value_prediction 함수
- 주어진 정책에 대해 각 상태-행동 쌍의 가치를 계산
- Sarsa 업데이트 규칙 사용: Q(s,a) ← Q(s,a) + α[r + γQ(s',a') - Q(s,a)]
- 메인 실행부:
- 균일한 무작위 정책(모든 행동에 대해 확률 0.25)을 사용
- 상태 가치와 행동 가치를 계산하고 출력
- 계산된 행동 가치에서 정책을 사용해 상태 가치를 역산하여 일관성 확인

코드 실행 흐름
- 환경 초기화: 4x4 그리드 생성, 에이전트는 [0,0]에서 시작
- 정책 설정: 모든 상태에서 4가지 행동에 대해 균등한 확률(0.25) 부여
- TD 상태 가치 예측:
- 10,000번의 반복으로 상태 가치 추정
- 각 반복마다 에피소드 생성 (에이전트가 목표 지점에 도달할 때까지)
- TD 업데이트로 상태 가치 조정
- TD 행동 가치 예측:
- 유사하게 10,000번 반복으로 행동 가치 추정
- Sarsa 알고리즘으로 상태-행동 가치 조정
- 결과 출력:
- 계산된 상태 가치와 행동 가치 출력
- 일관성 검증을 위한 비교값 계산
주요 알고리즘 및 초기화 코드 상세 분석
1. 환경 초기화 코드 (__init__)
def __init__(self):
'''
state_space: 4x4 grid info using numpy
value ot the agent location: 1
value of the workplace location: 2
value of the home location: 3
value of the park: -1
action_space: {0, 1, 2, 3}
0: up
1: right
2: down
3: left
'''
self.agent_pos = {'y': 0, 'x': 0}
self.workplace_pos = {'y': 0, 'x': 3}
self.home_pos = {'y': 3, 'x': 3}
self.park_area = {'y':[1, 2], 'x':[1, 2]}
self.y_min, self.x_min, self.y_max, self.x_max = 0, 0, 3, 3
# set up state
self.state = self.set_state(self.agent_pos['y'], self.agent_pos['x'])
self.state_space = list()
for y in range(4):
for x in range(4):
state = self.set_state(y, x)
self.state_space.append(state)
self.action_space = [0, 1, 2, 3]
상세 설명:
- 위치 초기화: 환경에서 주요 요소들의 위치를 딕셔너리로 설정.
- 에이전트: 왼쪽 상단 모서리 (0,0)
- 직장: 오른쪽 상단 모서리 (0,3)
- 집: 오른쪽 하단 모서리 (3,3)
- 공원: 중앙 2x2 영역 ([1,2], [1,2])
- 그리드 경계: 4x4 그리드의 경계를 지정 (y_min=0, x_min=0, y_max=3, x_max=3)
- 상태 공간 생성: 가능한 모든 상태(16개 위치)를 생성하고 리스트에 저장
- 각 상태는 4x4 NumPy 배열로 표현
- 배열 내 값은 에이전트, 직장, 집, 공원의 위치 정보를 담음
2. 상태 설정 함수 (set_state)
def set_state(self, y_agent, x_agent):
state = np.zeros([4,4])
state[self.workplace_pos['y'], self.workplace_pos['x']] = 2
state[self.home_pos['y'], self.home_pos['x']] = 3
state[self.park_area['y'], self.park_area['x']] = -1
state[y_agent, x_agent] = 1
return state
상세 설명:
- 4x4 크기의 0으로 초기화된 배열 생성
- 환경의 주요 요소들을 배열에 표시:
- 직장 위치(값: 2)
- 집 위치(값: 3)
- 공원 영역(값: -1)
- 에이전트 위치(값: 1)
- 주의할 점: 에이전트가 직장이나 집에 있을 때는 값 1이 덮어씌워짐
3. 환경 진행 함수 (step)
def step(self, action):
# Update environmental variables
is_random_action = np.random.choice([0, 1], p=[0.7, 0.3])
if is_random_action:
random_action_set = list(self.action_space)
random_action_set.remove(action)
action = np.random.choice(random_action_set)
if action == 0:
# 'y' should be decreased by 1 or stay the same when it is at the top row
self.agent_pos['y'] = max(
self.agent_pos['y'] - 1,
self.y_min
)
elif action == 1:
# 'x' should be increased by 1 or stay the same when it is at the most right column
self.agent_pos['x'] = min(
self.agent_pos['x'] + 1,
self.x_max
)
elif action == 2:
# 'y' should be increased by 1 or stay the same when it is at the bottom row
self.agent_pos['y'] = min(
self.agent_pos['y'] + 1,
self.y_max
)
elif action == 3:
# 'x' should be decreased by 1 or stay the same when it is at the most left column
self.agent_pos['x'] = max(
self.agent_pos['x'] - 1,
self.x_min
)
else:
assert False, "Invalid action value was fed to step."
# Make a next state after transition
prev_state = self.state
self.state = self.set_state(self.agent_pos['y'], self.agent_pos['x'])
done = False
if (
self.agent_pos == self.workplace_pos or
self.agent_pos == self.home_pos
):
done = True
reward = self.reward(prev_state, action, self.state)
return reward, self.state, done
상세 설명:
- 확률적 행동 처리:
- 70% 확률로 선택된 행동 실행
- 30% 확률로 다른 임의의 행동으로 대체
- 행동 실행:
- 상/하/좌/우 이동을 처리하며 그리드 경계 체크
- 경계에 도달하면 그 자리에 머무름 (max/min 함수 사용)
- 상태 업데이트:
- 이전 상태 저장 후 새 상태 설정
- set_state 함수로 에이전트 새 위치 반영
- 종료 조건 확인:
- 에이전트가 직장이나 집에 도착했는지 확인
- 도착했다면 done = True로 설정
- 보상 계산:
- reward 함수 호출하여 보상 계산
- 이전 상태, 행동, 새 상태를 기반으로 함
- 반환값:
- 보상, 새 상태, 종료 여부를 튜플로 반환
4. 보상 함수 (reward)
def reward(self, s, a, s_next):
reward = -0.5
y, x = np.where(s == 1)
y_next, x_next = np.where(s_next == 1)
was_at_workplace = (
y == self.workplace_pos['y'] and
x == self.workplace_pos['x']
)
is_at_workplace = (
y_next == self.workplace_pos['y'] and
x_next == self.workplace_pos['x']
)
was_at_home = (
y == self.home_pos['y'] and
x == self.home_pos['x']
)
is_at_home = (
y_next == self.home_pos['y'] and
x_next == self.home_pos['x']
)
is_in_park = (
y_next in self.park_area['y'] and
x_next in self.park_area['x']
)
if was_at_workplace and is_at_workplace:
reward = 0
elif (
not was_at_workplace and
is_at_workplace
): # Reached the workplace
reward = 5
if was_at_home and is_at_home:
reward = 0
if (
not was_at_home and
is_at_home
): # Reached the home
reward = 10
if is_in_park:
reward = -1.0
return reward
상세 설명:
- 기본 보상: 모든 이동에 대해 -0.5 기본 보상 설정
- 위치 파악: 이전 상태와 새 상태에서 에이전트 위치 추출 (numpy의 where 사용)
- 직장 관련 보상:
- 직장에 이미 있었고 계속 있음: 0
- 다른 곳에서 직장으로 도착: +5
- 집 관련 보상:
- 집에 이미 있었고 계속 있음: 0
- 다른 곳에서 집으로 도착: +10
- 공원 관련 보상:
- 공원 구역 내에 있음: -1.0
5. TD 가치 예측 알고리즘 (td_value_prediction)
def td_value_prediction(env, policy):
value_vector = np.zeros([len(env.state_space)])
# Repeat policy evaluation
for loop_count in range(10000):
done = False
step_count = 0
s = env.reset()
# Generate an episode
while not done:
i_s = get_state_index(env.state_space, s)
pi_s = policy[i_s]
a = np.random.choice(env.action_space, p=pi_s)
r, s_next, done = env.step(a)
i_s_next = get_state_index(env.state_space, s_next)
td = r + gamma * value_vector[i_s_next] - value_vector[i_s]
value_vector[i_s] = value_vector[i_s] + alpha * td
if done:
value_vector[i_s_next] = 0
step_count += 1
s = s_next
if (loop_count + 1) % 100 == 0:
print(f"[{loop_count}] value_vector: \n{value_vector}")
return value_vector
상세 설명:
- 초기화: 모든 상태의 가치를 0으로 초기화
- 정책 평가 반복: 10,000회 반복하여 가치 함수 학습
- 에피소드 생성: 각 반복마다 에피소드 생성
- 에이전트가 목표(직장/집)에 도달할 때까지 진행
- 행동 선택: 현재 상태에서 정책에 따라 확률적으로 행동 선택
- TD 업데이트: TD(0) 알고리즘으로 상태 가치 업데이트
- TD 오차 = 보상 + (감마 * 다음 상태 가치) - 현재 상태 가치
- 현재 상태 가치 += 학습률 * TD 오차
- 목표 상태 처리: 에피소드 종료 시 목표 상태 가치를 0으로 설정
- 로깅: 100회 반복마다 현재 가치 벡터 출력
6. TD 행동 가치 예측 알고리즘 (td_action_value_prediction)
def td_action_value_prediction(env, policy):
action_value_matrix = np.zeros([len(env.state_space), len(env.action_space)])
# Repeat policy evaluation
for loop_count in range(10000):
done = False
step_count = 0
s = env.reset()
i_s = get_state_index(env.state_space, s)
pi_s = policy[i_s]
a = np.random.choice(env.action_space, p=pi_s)
# Generate an episode
while not done:
r, s_next, done = env.step(a)
i_s_next = get_state_index(env.state_space, s_next)
pi_s_next = policy[i_s_next]
a_next = np.random.choice(env.action_space, p=pi_s_next)
td = r + gamma * action_value_matrix[i_s_next][a_next] - action_value_matrix[i_s][a]
action_value_matrix[i_s][a] = action_value_matrix[i_s][a] + 5 * alpha * td
if done:
action_value_matrix[i_s_next] = 0
step_count += 1
s = s_next
i_s = i_s_next
a = a_next
if (loop_count + 1) % 100 == 0:
print(f"[{loop_count}] action_value_matrix: \n{action_value_matrix}")
return action_value_matrix
상세 설명:
- 초기화: 모든 상태-행동 쌍의 가치를 0으로 초기화
- 에피소드 사전 준비:
- 초기 상태와 행동을 에피소드 시작 전에 선택
- 이는 Sarsa 알고리즘의 특징 (on-policy TD 제어)
- Sarsa 업데이트:
- 현재 (s,a), 다음 (s',a')의 행동-상태 쌍을 사용
- TD 오차 = 보상 + (감마 * 다음 상태-행동 가치) - 현재 상태-행동 가치
- 현재 상태-행동 가치 += 5 * 학습률 * TD 오차
- (주의: 학습률이 상태 가치 예측보다 5배 높음)
- 목표 상태 처리: 에피소드 종료 시 목표 상태의 모든 행동 가치를 0으로 설정
- 상태-행동 갱신: 다음 단계로 이동하여 현재 상태와 행동 업데이트
7. 메인 실행 코드
if __name__ == "__main__":
np.set_printoptions(formatter={'float': '{: 0.3f}'.format})
env = Env()
policy1 = list()
for i_s, s in enumerate(env.state_space):
pi = np.array([0.25, 0.25, 0.25, 0.25])
policy1.append(pi)
policy1 = np.array(policy1) # (|S|, |A|)
value_vector1 = td_value_prediction(env, policy1)
value_table1 = value_vector1.reshape(4, 4)
action_value_matrix1 = td_action_value_prediction(env, policy1) # (|S|, |A|)
value_vector_temp1 = np.sum(policy1 * action_value_matrix1, axis=-1)
print(f"value_table1: \n{value_table1}")
print(f"action_value_matrix1: \n{action_value_matrix1}")
print(f"value_vector1: \n{value_vector1}")
print(f"value_vector_temp1: \n{value_vector_temp1}")
상세 설명:
- 출력 형식 설정: NumPy 출력 형식을 소수점 3자리로 지정
- 환경 초기화: 4x4 그리드 환경 생성
- 정책 생성: 모든 상태에서 균등한 확률(0.25)의 무작위 정책 생성
- 상태 가치 예측: TD 알고리즘으로 상태 가치 계산
- 가치 테이블 변환: 벡터를 4x4 그리드 형태로 재구성하여 시각화
- 행동 가치 예측: TD-Sarsa 알고리즘으로 행동 가치 계산
- 일관성 검증:
- 정책과 행동 가치를 곱하여 각 상태의 가치 재계산
- 이는 직접 계산한 상태 가치와 비교를 위한 것
TD 학습 알고리즘 학습 과정 및 결과 분석
제공된 이미지는 TD(Temporal Difference) 학습 알고리즘의 실행 결과를 보여주고 있다. 이는 강화학습 과정에서 가치 함수가 어떻게 학습되는지 보여주는 중요한 정보이다.

1. 가치 벡터 (value_vector) 수렴 과정
이미지 1의 상단부는 TD 상태 가치 예측 알고리즘이 반복됨에 따라 각 상태의 가치가 어떻게 변화하는지 보여준다:
- 반복 횟수: [9399], [9499], [9599], ... 등의 숫자는 알고리즘 반복 횟수를 나타낸다.
- 가치 수렴: 반복이 진행됨에 따라 가치 벡터의 값들이 점차 안정화되고 있다. 예를 들어:
- 첫 번째 위치의 가치는 약 -3.67에서 -3.69 사이로 수렴
- 세 번째 위치의 가치는 약 -0.1에서 -0.2 사이로 수렴
이는 TD 학습의 핵심 특성을 보여준다 - 매 반복마다 예측된 가치가 실제 얻은 보상과 다음 상태의 가치를 기반으로 점차 조정된다.
2. 행동 가치 행렬 (action_value_matrix) 학습
이미지 1의 하단부와 이미지 2는 행동 가치 행렬의 학습 과정과 최종 결과를 보여준다:
- 초기 행렬([99]): 초기에는 상대적으로 작은 값(-0.3~0.6 범위)을 가짐
- 중간 행렬([199]): 학습이 진행됨에 따라 값의 범위가 넓어짐(-0.6~1.3)
- 최종 행렬([9999]): 충분한 학습 후 행동 가치가 크게 분화됨(-3.9~7.1)
행동 가치 행렬의 특징적인 패턴:
- 집과 직장 위치([3,3]과 [0,3])의 행은 모두 0으로 설정됨 (종료 상태)
- 집 근처 위치([2,3])에서는 아래(2) 행동이 높은 가치(7.152)를 가짐
- 직장 근처 위치([0,2])에서는 오른쪽(1) 행동이 높은 가치(3.060)를 가짐
- 공원 구역에 있는 상태는 대체로 낮은 행동 가치를 가짐

3. 가치 테이블 (value_table1) 분석
바로 위 이미지의 중간부에 나타난 가치 테이블은 4x4 그리드에서 각 위치의 가치를 보여준다:
[[-3.673 -2.834 -0.098 0.000]
[-3.896 -3.253 -1.444 1.231]
[-3.734 -2.960 -0.723 2.739]
[-3.246 -2.140 1.787 0.000]]
이 테이블에서 중요한 패턴:
- 목표 위치: 직장(0,3)과 집(3,3)은 0 값을 가짐 (종료 상태)
- 높은 가치 위치: 집 근처([3,2]는 1.787, [2,3]은 2.739)와 직장 근처([1,3]은 1.231)는 양수 값
- 낮은 가치 위치: 공원 구역(중앙 2x2)과 시작점 근처(왼쪽 상단)는 큰 음수 값
- 가치 경사: 목표 위치에서 멀어질수록 가치가 감소하는 경향
4. 일관성 검증 결과
이미지 2의 하단부는 두 가지 방법으로 계산된 가치 벡터를 비교한다:
- value_vector1: TD 상태 가치 예측으로 직접 계산된 가치
- value_vector_temp1: 행동 가치와 정책을 곱해 계산된 가치
두 벡터의 값이 매우 유사하지만 약간의 차이가 있다. 이는 두 알고리즘(TD 상태 가치 예측과 TD 행동 가치 예측)이 서로 다른 방식으로 학습되었지만, 결과적으로 일관된 가치 체계를 학습했음을 의미한다.
디버깅 결과의 의미
이 디버깅 출력은 다음과 같은 중요한 의미를 가진다:
- 학습 성공: TD 학습 알고리즘이 성공적으로 가치 함수를 학습했음을 보여준다.
- 정책 평가 검증: 균등한 무작위 정책(모든 행동에 0.25의 확률)에 대한 가치 함수 예측이 정확함을 검증한다.
- 보상 구조 반영: 가치 함수가 환경의 보상 구조(집 도착 +10, 직장 도착 +5, 공원 -1, 이동 -0.5)를 잘 반영하고 있다.
- 에이전트 동작 예측: 에이전트가 어떤 위치에서 어떤 행동을 취하는 것이 유리한지 행동 가치를 통해 알 수 있다.
특히, 행동 가치 행렬에서 각 상태별로 가장 높은 가치를 가진 행동을 선택하면 최적 정책을 구성할 수 있으며, 이는 에이전트가 가장 효율적으로 목표(직장 또는 집)에 도달하는 경로를 나타낸다.
|인증|




-------
패스트캠퍼스 링크