OpenAI Gym으로 이미 구현되어있는 환경을 이용할 수 있다.
가장 단순해 보이는 CartPole 환경을 가져와서 강화 학습을 시켜보자.
cart위에 막대기가 있고 한 끝이 cart에 고정되어 있다. 중력에 의해 막대기는 바닥으로 떨어지려 할 테니 cart를 좌우로 움직여 최대한 오래 지탱하는 것이 목표이다.
OpenAI Gym에서는 environment로 cart의 위치, 속도와 막대기의 각도, 속도가 주어지고 이를 판단해서 cart의 움직임을 구해야 한다.
environment로 주어지는 모든 상태에 대해 Q-Value를 구한다면 좋겠지만 경우의 수가 무한하기 때문에 구할 수 없다. 따라서 deep learning으로 학습시켜 모델을 만들어 입력으로 주어지는 environment에 대해 cart의 움직임을 예측하도록 구현한다.
순서는 다음과 같다.
- 맨 처음에는 아무 지식이 없으니 랜덤으로 좌우로 움직여서 가장 오래 지탱한 방법을 몇 개 골라 학습시킨다.
- 어느 정도 괜찮아지면 self-play로 더 좋은 방법을 찾아 학습시킨다.
구현
환경 설정
CartPole-v1
환경을 가져온다. v0도 있는데 max_episode_steps
, reward_threshold
와 같은 기본 설정값이 다르다. 더 오래 버틸 수 있음에도 불구하고 환경이 끝내버리지 않도록 v1로 구성한다.
import gym
env = gym.make("CartPole-v1")
모델 설정
적당한 모델인지는 모르겠지만 구현이 완성되면 후에 보완하면 되기 때문에 일단 fully connected로만 구성했다.
def create_model():
model = Sequential()
model.add(Dense(128, input_shape=(4,), activation="relu"))
model.add(Dropout(0.4))
model.add(Dense(256, activation="relu"))
model.add(Dropout(0.4))
model.add(Dense(256, activation="relu"))
model.add(Dropout(0.4))
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.4))
model.add(Dense(2, activation="softmax"))
model.compile(
loss="categorical_crossentropy",
optimizer="adam",
metrics=["accuracy"])
return model
학습 데이터 만들기
모델을 학습시킬 데이터를 만드는 함수이다.
def generate_training_data(env, action_function, trial, top_k):
training_x, training_y = [], []
data = []
for _ in range(trial):
obs = env.reset()
score = 0
training_sample_x, training_sample_y = [], []
for _ in range(SIMULATION_MAX_STEP):
action = action_function(obs)
training_sample_x.append(obs)
training_sample_y.append(keras.utils.to_categorical(action, 2))
observation, reward, done, _ = env.step(action)
score += reward
if done:
break
data.append((score, (training_sample_x, training_sample_y)))
data.sort(key=lambda x: -x[0])
for i in range(top_k):
training_x += data[i][1][0]
training_y += data[i][1][1]
return np.array(training_x), np.array(training_y)
처음에는 action_function
을 모르기 때문에 랜덤으로 넘길거고, self play에서는 모델에서 구한 함수를 넘길 것이다. 이렇게 받은 action_function
으로 총 trial
횟수만큼 시뮬레이션해서 상위 top_k
개의 데이터만 리턴한다.
학습하기
위에서 구현한 generate_traning_data
로 양질의 데이터를 받아 모델에 학습시키는 함수까지 만들었다.
def train(env, action_function, model, trial, top_k):
training_x, training_y = generate_training_data(env, action_function, trial, top_k)
model.fit(training_x, training_y, epochs=15)
처음에는 cart를 랜덤으로 움직여 10000번 해보고 가장 오래 버틴 100개의 데이터만 학습시켜본다.
train(env, lambda x: np.random.randint(2), model, 10000, 100)
이렇게만 하고 실제 render
로 출력해봐도 그럴싸하게 움직인다.
그럼 이제 self-play로 양질의 데이터를 얻을 수 있고 이를 또 학습시킨다.
for _ in range(SELF_PLAY_COUNT):
train(env, lambda x: np.random.choice([0, 1], p=model.predict(x.reshape(-1, 4))[0]), model, 100, 10)
action_function
의 np.random.choice
는 [0, 1] 을 model에서 예측한 p의 확률로 선택한다는 뜻이다.
각종 파라미터는 임의로 넣었기 때문에 튜닝하는 과정이 남았지만, 이렇게 OpenAI Gym의 환경을 손쉽게 구성할 수 있다.
'딥러닝' 카테고리의 다른 글
딥러닝에 사용하는 확률분포 함수 (0) | 2020.03.30 |
---|---|
Keras로 모델 저장, 불러오기 (0) | 2019.11.16 |
Keras로 간단한 CNN 구현하기 (0) | 2019.11.13 |
알파고의 몬테카를로 방법 (0) | 2019.11.10 |
알파고의 강화학습 (0) | 2019.11.03 |
댓글