forked from rlcode/reinforcement-learning-kr-v2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrain.py
139 lines (112 loc) · 5.18 KB
/
train.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import sys
import gym
import pylab
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.initializers import RandomUniform
# 정책 신경망과 가치 신경망 생성
class A2C(tf.keras.Model):
def __init__(self, action_size):
super(A2C, self).__init__()
self.actor_fc = Dense(24, activation='tanh')
self.actor_out = Dense(action_size, activation='softmax',
kernel_initializer=RandomUniform(-1e-3, 1e-3))
self.critic_fc1 = Dense(24, activation='tanh')
self.critic_fc2 = Dense(24, activation='tanh')
self.critic_out = Dense(1,
kernel_initializer=RandomUniform(-1e-3, 1e-3))
def call(self, x):
actor_x = self.actor_fc(x)
policy = self.actor_out(actor_x)
critic_x = self.critic_fc1(x)
critic_x = self.critic_fc2(critic_x)
value = self.critic_out(critic_x)
return policy, value
# 카트폴 예제에서의 액터-크리틱(A2C) 에이전트
class A2CAgent:
def __init__(self, action_size):
self.render = False
# 행동의 크기 정의
self.action_size = action_size
# 액터-크리틱 하이퍼파라미터
self.discount_factor = 0.99
self.learning_rate = 0.001
# 정책신경망과 가치신경망 생성
self.model = A2C(self.action_size)
# 최적화 알고리즘 설정, 미분값이 너무 커지는 현상을 막기 위해 clipnorm 설정
self.optimizer = Adam(lr=self.learning_rate, clipnorm=5.0)
# 정책신경망의 출력을 받아 확률적으로 행동을 선택
def get_action(self, state):
policy, _ = self.model(state)
policy = np.array(policy[0])
return np.random.choice(self.action_size, 1, p=policy)[0]
# 각 타임스텝마다 정책신경망과 가치신경망을 업데이트
def train_model(self, state, action, reward, next_state, done):
model_params = self.model.trainable_variables
with tf.GradientTape() as tape:
policy, value = self.model(state)
_, next_value = self.model(next_state)
target = reward + (1 - done) * self.discount_factor * next_value[0]
# 정책 신경망 오류 함수 구하기
one_hot_action = tf.one_hot([action], self.action_size)
action_prob = tf.reduce_sum(one_hot_action * policy, axis=1)
cross_entropy = - tf.math.log(action_prob + 1e-5)
advantage = tf.stop_gradient(target - value[0])
actor_loss = tf.reduce_mean(cross_entropy * advantage)
# 가치 신경망 오류 함수 구하기
critic_loss = 0.5 * tf.square(tf.stop_gradient(target) - value[0])
critic_loss = tf.reduce_mean(critic_loss)
# 하나의 오류 함수로 만들기
loss = 0.2 * actor_loss + critic_loss
# 오류함수를 줄이는 방향으로 모델 업데이트
grads = tape.gradient(loss, model_params)
self.optimizer.apply_gradients(zip(grads, model_params))
return np.array(loss)
if __name__ == "__main__":
# CartPole-v1 환경, 최대 타임스텝 수가 500
env = gym.make('CartPole-v1')
# 환경으로부터 상태와 행동의 크기를 받아옴
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
# 액터-크리틱(A2C) 에이전트 생성
agent = A2CAgent(action_size)
scores, episodes = [], []
score_avg = 0
num_episode = 1000
for e in range(num_episode):
done = False
score = 0
loss_list = []
state = env.reset()
state = np.reshape(state, [1, state_size])
while not done:
if agent.render:
env.render()
action = agent.get_action(state)
next_state, reward, done, info = env.step(action)
next_state = np.reshape(next_state, [1, state_size])
# 타임스텝마다 보상 0.1, 에피소드가 중간에 끝나면 -1 보상
score += reward
reward = 0.1 if not done or score == 500 else -1
# 매 타임스텝마다 학습
loss = agent.train_model(state, action, reward, next_state, done)
loss_list.append(loss)
state = next_state
if done:
# 에피소드마다 학습 결과 출력
score_avg = 0.9 * score_avg + 0.1 * score if score_avg != 0 else score
print("episode: {:3d} | score avg: {:3.2f} | loss: {:.3f}".format(
e, score_avg, np.mean(loss_list)))
# 에피소드마다 학습 결과 그래프로 저장
scores.append(score_avg)
episodes.append(e)
pylab.plot(episodes, scores, 'b')
pylab.xlabel("episode")
pylab.ylabel("average score")
pylab.savefig("./save_graph/graph.png")
# 이동 평균이 400 이상일 때 종료
if score_avg > 400:
agent.model.save_weights("./save_model/model", save_format="tf")
sys.exit()