미로 구현
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
fig = plt.figure(figsize=(5,5))
ax = plt.gca()
plt.plot([1,1], [0,1], color = 'red', linewidth=2)
plt.plot([1,2], [2,2], color = 'red', linewidth=2)
plt.plot([2,2], [2,1], color = 'red', linewidth=2)
plt.plot([2,3], [1,1], color = 'red', linewidth=2)
plt.text(0.5, 2.5, "S0", size = 14, ha ='center')
plt.text(1.5, 2.5, "S1", size = 14, ha ='center')
plt.text(2.5, 2.5, "S2", size = 14, ha ='center')
plt.text(0.5, 1.5, "S3", size = 14, ha ='center')
plt.text(1.5, 1.5, "S4", size = 14, ha ='center')
plt.text(2.5, 1.5, "S5", size = 14, ha ='center')
plt.text(0.5, 0.5, "S0", size = 14, ha ='center')
plt.text(1.5, 0.5, "S0", size = 14, ha ='center')
plt.text(2.5, 0.5, "S0", size = 14, ha ='center')
plt.text(0.5, 2.3, "START", size = 14, ha ='center')
plt.text(2.5, 0.3, "GOAL", size = 14, ha ='center')
ax.set_xlim(0, 3)
ax.set_ylim(0, 3)
plt.tick_params(axis = "both", which ='both', bottom = False, top = False, labelbottom = False, right = False, left = False, labelleft = False)
line, =ax.plot([0.5], [2.5], marker = "o", color = 'g', markersize = 60)

에이전트 구현
- 강화학습에서 에이전트가 어떻게 행동할지를 결정하는 규칙을
정책(Policy)이라고 한다
- πθ(s,a) : 상태가 s일 때 행동 a를 취할 확률을 파라미터 θ가 결정하는 정책 π를 따른다
- 미로탐색의 경우 상태 s는 에이전트의 미로 내 위치에 해당한다(S0 ~ S9 까지 9개의 상태)
- 행동 a는 어떤 상태에 있을 때 에이전트가 취할 수 있는 행동을 나타낸다(상, 하, 좌, 우)
- 정책 π는 함수나 신경망 등을 이용해 표현할 수 있다
- 여기서는 표형식 표현(tabular representation)을 사용할 것이다
- 행이 상태 s, 열이 행동 a를 나타낸다
- 가장 먼저 파라미터 θ의 초기값 θ0을 구현한다
- 이동 가능한 방향에는 1
- 벽이 있어 이동할 수 없는 방향에는 np.nan을 대입
theta_0 = np.array([[np.nan, 1, 1, np.nan],
[np.nan, 1, np.nan, 1],
[np.nan, np.nan, 1, 1],
[1, 1, 1, np.nan],
[np.nan, np.nan, 1, 1],
[1, np.nan, np.nan, np.nan],
[1, np.nan, np.nan, np.nan],
[1, 1, np.nan, np.nan],
])
- 이어서 파라미터 θ0을 변환해서 정책 πθ(s,a)를 구한다
- 단순한 변환 방법을 택해서 이동 방향에 대한 θ 값의 비율을 계산해서 확률로 삼는다
def simple_convert_into_pi_from_theta(theta):
'''단순히 값의 비율을 계산'''
[m, n] = theta.shape
pi = np.zeros((m, n))
for i in range(0, m):
pi[i, :] = theta[i, :] / np.nansum(theta[i, :])
pi = np.nan_to_num(pi)
return pi
- 다음으로 정의한 변환 함수를 실행해 πθ(s,a)를 구한다
pi_0 = simple_convert_into_pi_from_theta(theta_0)
pi_0

- 이번에는 에이전트가 정책 πθ0(s,a)를 따라 행동하게끔 한다
- 이동 후 에이전트의 상태를 구하는 함수를 정의한다
- 미로의 위치는 0부터 8까지의 숫자로 정의, 에이전트 위로 이동시 상태의 값이 3감소하여 3을 뺀다
def get_next_s(pi, s):
direction = ["up", "right", "down", "left"]
next_direction = np.random.choice(direction, p=pi[s,:])
if next_direction == "up":
s_next = s - 3
elif next_direction == "right":
s_next = s + 1
elif next_direction == "down" :
s_next = s + 3
elif next_direction == 'left' :
s_next = s - 1
return s_next
- 마지막으로 에이전트가 목표에 도달할 때까지 πθ0(s,a)에 따라 에이전트를 이동시키며 진행
- 상태 이력을
state_history 리스트에 저장한다
- 마지막으로 리스트를 반환한다
def goal_maze(pi):
s = 0
state_history = [0]
while (1):
next_s = get_next_s(pi, s)
state_history.append(next_s)
if next_s == 8:
break
else:
s = next_s
return state_history
- 그리고 정책 πθ0(s,a)를 따라 에이전트를 이동시키고 그 과정에서 취한 행동이력을 저장한다
state_history = goal_maze(pi_0)
print(state_history)
print("걸린 단계 수 " + str(len(state_history) - 1) + "단계")

- 마지막으로 에이전트 이동 애니메이션을 구현한다
from matplotlib import animation
from IPython.display import HTML
def init():
'''배경 이미지 초기화'''
line.set_data([], [])
return (line,)
def animate(i):
'''프레임 단위로 이미지 생성'''
state = state_history[i]
x = (state % 3) + 0.5
y = 2.5 - int(state / 3)
line.set_data(x,y)
return (line,)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=len(state_history), interval = 200, repeat = False)
