Skip to content

Commit fe6cf87

Browse files
committed
DQN 소스 개선 및 정리
1 parent 83bfe12 commit fe6cf87

25 files changed

Lines changed: 128 additions & 394 deletions
File renamed without changes.

10 - DQN/agent.py

Lines changed: 128 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,153 @@
1-
import gym
2-
import time
3-
import threading
4-
import numpy as np
1+
# 게임 구현과 DQN 모델을 이용해 게임을 실행하고 학습을 진행합니다.
52
import tensorflow as tf
6-
from scipy.misc import imresize
3+
import numpy as np
4+
import random
5+
import time
76

8-
from brain import Brain
7+
from game import Game
8+
from model import DQN
99

1010

11-
# 이미지 사이즈를 줄이고, 흑백 사진으로 만듭니다.
12-
def preprocess(screen, width, height):
13-
# 완전한 그레이스케일이 아닌 적당한 수준의 흑백으로 만듭니다.
14-
gray = screen.astype('float32').mean(2)
15-
# 이미지를 리사이즈하고 수치를 보정합니다. 0~1.0 사이의 값으로 만듭니다.
16-
processed = imresize(gray, (width, height)).astype('float32') * (1. / 255)
11+
tf.app.flags.DEFINE_boolean("train", False, "학습모드. 게임을 화면에 보여주지 않습니다.")
12+
FLAGS = tf.app.flags.FLAGS
1713

18-
return processed
14+
# 최대 학습 횟수
15+
MAX_EPISODE = 10000
16+
# 1000번의 학습마다 한 번씩 타겟 네트웍을 업데이트합니다.
17+
TARGET_UPDATE_INTERVAL = 1000
18+
# 4 프레임마다 한 번씩 학습합니다.
19+
TRAIN_INTERVAL = 4
20+
# 학습 데이터를 어느정도 쌓은 후, 일정 시간 이후에 학습을 시작하도록 합니다.
21+
OBSERVE = 100
1922

23+
# action: 0: 좌, 1: 유지, 2: 우
24+
NUN_ACTION = 3
25+
SCREEN_WIDTH = 6
26+
SCREEN_HEIGHT = 10
2027

21-
def trainer(brain):
22-
# 컴퓨터의 성능에 따라 학습 빈도를 적절히 제어 할 필요가 있습니다.
23-
# 원래는 게임 몇 프레임마다 학습을 한 번씩 하게 해야 하지만,,
24-
# 일반 컴퓨터/CPU로 학습을 시키는 경우 학습 속도가 느려 학습과정을 보기 어려워
25-
# 적당한 미니배치 사이즈로 계속 학습을 시키도록 했습니다.
26-
# 컴퓨터가 빠르거나 여러개의 GPU를 사용할 수 있다면
27-
# 게임 안에 학습 과정을 넣거나, 게임을 여러개를 한 번에 돌리는 방법을 써봐도 좋겠습니다.
28-
steps = 1
29-
while True:
30-
if len(brain.memory) > 5000:
31-
if steps == 1:
32-
print('Trainer: 학습 시작!')
3328

34-
brain.train()
35-
steps += 1
36-
else:
37-
time.sleep(1)
29+
def train():
30+
print('뇌세포 깨우는 중..')
31+
sess = tf.Session()
3832

39-
if steps % 100 == 0:
40-
print('Trainer: 타겟 네트웍 업데이트. Step: {}'.format(steps))
41-
brain.update_target_network()
33+
game = Game(SCREEN_WIDTH, SCREEN_HEIGHT, show_game=False)
34+
brain = DQN(sess, SCREEN_WIDTH, SCREEN_HEIGHT, NUN_ACTION)
4235

36+
rewards = tf.placeholder(tf.float32, [None])
37+
tf.summary.scalar('avg.reward/ep.', tf.reduce_mean(rewards))
4338

44-
MAX_EPISODE = 9999999
45-
SCREEN_WIDTH = 84
46-
SCREEN_HEIGHT = 84
47-
ENV_NAME = 'Breakout-v0'
48-
# ENV_NAME = 'Freeway-v0'
49-
# ENV_NAME = 'Pong-v0'
39+
saver = tf.train.Saver()
40+
sess.run(tf.global_variables_initializer())
5041

51-
env = gym.make(ENV_NAME)
42+
writer = tf.summary.FileWriter('logs', sess.graph)
43+
summary_merged = tf.summary.merge_all()
5244

53-
sess = tf.Session()
45+
# 타겟 네트웍을 초기화합니다.
46+
brain.update_target_network()
5447

55-
print('뇌세포 깨우는 중..')
56-
brain = Brain(session=sess,
57-
width=SCREEN_WIDTH, height=SCREEN_HEIGHT,
58-
n_action=env.action_space.n)
48+
# 다음에 취할 액션을 DQN 을 이용해 결정할 시기를 결정합니다.
49+
epsilon = 1.0
50+
# 프레임 횟수
51+
time_step = 0
52+
total_reward_list = []
5953

60-
sess.run(tf.global_variables_initializer())
54+
# 게임을 시작합니다.
55+
for episode in range(MAX_EPISODE):
56+
terminal = False
57+
total_reward = 0
6158

62-
# 타겟 네트웍을 초기화합니다.
63-
brain.update_target_network()
59+
# 게임을 초기화하고 현재 상태를 가져옵니다.
60+
# 상태는 screen_width x screen_height 크기의 화면 구성입니다.
61+
state = game.reset()
62+
brain.init_state(state)
6463

65-
# 학습을 시키는 trainer 함수를 쓰레드로 돌립니다. 게임과 학습을 동시에 진행합니다.
66-
# 컴퓨터가 빠르거나 반대로 너무 느리면 쓰레드 대신 게임 반복문 안에서 순차적으로 학습시키는 것이 좋을 수 있습니다.
67-
train_thread = threading.Thread(target=trainer, args=[brain])
68-
train_thread.start()
64+
while not terminal:
65+
# 입실론이 랜덤값보다 작은 경우에는 랜덤한 액션을 선택하고
66+
# 그 이상일 경우에는 DQN을 이용해 액션을 선택합니다.
67+
# 초반엔 학습이 적게 되어 있기 때문입니다.
68+
# 초반에는 거의 대부분 랜덤값을 사용하다가 점점 줄어들어
69+
# 나중에는 거의 사용하지 않게됩니다.
70+
if np.random.rand() < epsilon:
71+
action = random.randrange(NUN_ACTION)
72+
else:
73+
action = brain.get_action()
6974

70-
# 게임을 시작합니다.
71-
for episode in range(MAX_EPISODE):
72-
terminal = False
73-
total_reward = 0.
74-
# 다음에 취할 액션을 DQN 을 이용해 결정할 시기를 결정합니다.
75-
# 초반에는 액션을 랜덤값을 이용합니다. 아직 학습이 되지 않았기 때문입니다.
76-
# refer: https://github.com/hunkim/ReinforcementZeroToAll/
77-
epsilon = 1. / ((episode / 100) + 1)
78-
79-
# 게임 상태를 초기화합니다.
80-
state = env.reset()
81-
state = preprocess(state, SCREEN_WIDTH, SCREEN_HEIGHT)
82-
brain.init_state(state)
83-
84-
while not terminal:
85-
# 학습을 한 번도 하지 않았을 때와 입실론이 랜덤값보다 작은 경우에는 랜덤한 액션을 선택합니다.
86-
# 위의 수식에 의하면 랜덤값을 사용하는 빈도가 점점 줄어들다가
87-
# 1000번 정도의 에피소드가 지나면 랜덤값을 거의 사용하지 않게됩니다.
88-
if episode < 10 or np.random.rand() < epsilon:
89-
action = env.action_space.sample()
90-
else:
75+
# 일정 시간이 지난 뒤 부터 입실론 값을 줄입니다.
76+
# 초반에는 학습이 전혀 안되어 있기 때문입니다.
77+
if episode > OBSERVE:
78+
epsilon -= 1 / 1000
79+
80+
# 결정한 액션을 이용해 게임을 진행하고, 보상과 게임의 종료 여부를 받아옵니다.
81+
state, reward, terminal = game.step(action)
82+
total_reward += reward
83+
84+
# 현재 상태를 Brain에 기억시킵니다.
85+
# 기억한 상태를 이용해 학습하고, 다음 상태에서 취할 행동을 결정합니다.
86+
brain.remember(state, action, reward, terminal)
87+
88+
if time_step > OBSERVE and time_step % TRAIN_INTERVAL == 0:
89+
# DQN 으로 학습을 진행합니다.
90+
brain.train()
91+
92+
if time_step % TARGET_UPDATE_INTERVAL == 0:
93+
# 타겟 네트웍을 업데이트 해 줍니다.
94+
brain.update_target_network()
95+
96+
time_step += 1
97+
98+
print('게임횟수: %d 점수: %d' % (episode + 1, total_reward))
99+
100+
total_reward_list.append(total_reward)
101+
102+
if episode % 10 == 0:
103+
summary = sess.run(summary_merged, feed_dict={rewards: total_reward_list})
104+
writer.add_summary(summary, time_step)
105+
total_reward_list = []
106+
107+
if episode % 100 == 0:
108+
saver.save(sess, 'model/dqn.ckpt', global_step=time_step)
109+
110+
111+
def replay():
112+
print('뇌세포 깨우는 중..')
113+
sess = tf.Session()
114+
115+
game = Game(SCREEN_WIDTH, SCREEN_HEIGHT, show_game=True)
116+
brain = DQN(sess, SCREEN_WIDTH, SCREEN_HEIGHT, NUN_ACTION)
117+
118+
saver = tf.train.Saver()
119+
ckpt = tf.train.get_checkpoint_state('model')
120+
saver.restore(sess, ckpt.model_checkpoint_path)
121+
122+
# 게임을 시작합니다.
123+
for episode in range(MAX_EPISODE):
124+
terminal = False
125+
total_reward = 0
126+
127+
state = game.reset()
128+
brain.init_state(state)
129+
130+
while not terminal:
91131
action = brain.get_action()
92132

93-
state, reward, terminal, info = env.step(action)
94-
total_reward += reward
133+
# 결정한 액션을 이용해 게임을 진행하고, 보상과 게임의 종료 여부를 받아옵니다.
134+
state, reward, terminal = game.step(action)
135+
total_reward += reward
136+
137+
brain.remember(state, action, reward, terminal)
138+
139+
# 게임 진행을 인간이 인지할 수 있는 속도로^^; 보여줍니다.
140+
time.sleep(0.3)
95141

96-
if terminal:
97-
reward = -1
142+
print('게임횟수: %d 점수: %d' % (episode + 1, total_reward))
98143

99-
# 현재 상태를 Brain에 기억시킵니다.
100-
# 기억한 상태를 이용해 학습하고, 다음 상태에서 취할 행동을 결정합니다.
101-
state = preprocess(state, SCREEN_WIDTH, SCREEN_HEIGHT)
102-
brain.remember(state, action, reward, terminal)
103144

104-
# 화면을 그립니다.
105-
env.render()
145+
def main(_):
146+
if FLAGS.train:
147+
train()
148+
else:
149+
replay()
106150

107-
print('게임횟수: {} 점수: {}'.format(episode + 1, total_reward))
108151

109-
# 에피소드 10회가 지나면 매 회 3번의 샘플링 학습을 시킵니다.
110-
# 학습을 쓰레드로 동시에 시키지 않고 에피소드가 끝난 후 시키려면 이 코드를 사용하세요.
111-
# if episode > 9:
112-
# for count in range(3):
113-
# brain.train()
114-
#
115-
# # 타겟 네트웍을 업데이트 해 줍니다.
116-
# brain.update_target_network()
152+
if __name__ == '__main__':
153+
tf.app.run()

10 - DQN/brain.py

Lines changed: 0 additions & 150 deletions
This file was deleted.

0 commit comments

Comments
 (0)