カスタムGym環境作成(6) - ちょっと複雑なマップをACKTRで学習・攻略

前回記事にてカスタムGym環境として、ちょっと複雑なマップをPPO(PPO2)アルゴリズムを使って、強化学習してみましたがうまく攻略できませんでした。

今回は学習アルゴリズムをACKTRに変えて、攻略できるかどうかを見ていきたいと思います。

(ACKTRは、以前学習アルゴリズムをいろいろ試していたときにかなり優秀だと感じていたアルゴリズムです。)

ACKTRで強化学習

カスタム環境を読み込み、ACKTRアルゴリズムで学習を行います。

変更箇所は下記の3点です。

  • 12,13行目
    読み込むアルゴリズムをPPO2からACKTRに変更
  • 26,27行目
    使用するアルゴリズムをPPO2からACKTRに変更
  • 39行目
    ステップ実行回数を5倍に増やす。

[ソース]

train4.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
# 警告を非表示
import os
import warnings
warnings.simplefilter('ignore')
import tensorflow as tf
tf.get_logger().setLevel("ERROR")

import gym
from env4 import MyEnv

from stable_baselines.common.vec_env import DummyVecEnv
#from stable_baselines import PPO2
from stable_baselines import ACKTR
from stable_baselines.bench import Monitor

# ログフォルダの作成
log_dir = './logs/'
os.makedirs(log_dir, exist_ok=True)

# 環境の生成
env = MyEnv()
env = Monitor(env, log_dir, allow_early_resets=True)
env = DummyVecEnv([lambda: env])

# モデルの生成
#model = PPO2('MlpPolicy', env, verbose=1)
model = ACKTR('MlpPolicy', env, verbose=1)

# モデルの学習
model.learn(total_timesteps=128000*5)

# モデルの保存
model.save('model4')

[実行結果(途中略)]

---------------------------------
| explained_variance | -0.0363  |(誤差の分散)
| fps                | 12       |(1秒あたりのフレーム数)
| nupdates           | 1        |(更新回数)
| policy_entropy     | 1.39     |(方策のエントロピー)
| policy_loss        | -13.5    |(方策の損失)
| total_timesteps    | 20       |(全環境でのタイムステップ数)
| value_loss         | 122      |(価値関数更新時の平均損失)
---------------------------------
---------------------------------
| ep_len_mean        | 969      |
| ep_reward_mean     | -868     |
| explained_variance | 9.41e-05 |
| fps                | 379      |
| nupdates           | 100      |
| policy_entropy     | 1.28     |
| policy_loss        | -9.35    |
| total_timesteps    | 2000     |
| value_loss         | 51.2     |
---------------------------------
---------------------------------
| ep_len_mean        | 969      |
| ep_reward_mean     | -868     |
| explained_variance | 1.19e-07 |
| fps                | 445      |
| nupdates           | 200      |
| policy_entropy     | 0.499    |
| policy_loss        | -5.09    |
| total_timesteps    | 4000     |
| value_loss         | 44.8     |
---------------------------------
         :
        (略)
         :
----------------------------------
| ep_len_mean        | 17        |
| ep_reward_mean     | 84        |
| explained_variance | 0         |
| fps                | 534       |
| nupdates           | 31800     |
| policy_entropy     | 0.000239  |
| policy_loss        | -0.000114 |
| total_timesteps    | 636000    |
| value_loss         | 42.5      |
----------------------------------
----------------------------------
| ep_len_mean        | 17        |
| ep_reward_mean     | 84        |
| explained_variance | 0         |
| fps                | 534       |
| nupdates           | 31900     |
| policy_entropy     | 0.000267  |
| policy_loss        | -0.000112 |
| total_timesteps    | 638000    |
| value_loss         | 32.2      |
----------------------------------
----------------------------------
| ep_len_mean        | 17        |←平均エピソード長
| ep_reward_mean     | 84        |←平均報酬
| explained_variance | 0         |
| fps                | 534       |
| nupdates           | 32000     |
| policy_entropy     | 0.000279  |
| policy_loss        | -0.000116 |
| total_timesteps    | 640000    |
| value_loss         | 31.2      |
----------------------------------

今回は最終的な平均報酬がプラスになっていて、平均エピソード長も最初に比べて少なく(短く)なっているので、きちんと学習(攻略)できているように思えます。

平均報酬をグラフ化して確認

学習したモデルを実行する前にmonitor.csvを読み込み、グラフ化して平均報酬の遷移を確認します。
(前回ソースlog_graph.pyと全く同じものです。)

[ソース]

log_graph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import matplotlib.pyplot as plt

# ログファイルの読み込み(報酬,エピソード,経過時間)
df = pd.read_csv('./logs/monitor.csv', names=['r', 'l', 't'])
df = df.drop(range(2)) # 先頭2行を排除

# 報酬グラフの表示
x = range(len(df['r']))
y = df['r'].astype(float)
plt.plot(x, y)
plt.xlabel('episode')
plt.ylabel('reward')
plt.show()

[結果]

マイナス報酬が大きいため判断しにくいのですが、エピソード数が多く、最終的にはマイナスに大きく振れることがないのでうまく学習できているような気がします。

log/monitor.csvを確認すると次のようになっていました。

[monitor.csv(途中略)]

#{"t_start": 1622147186.477496, "env_id": null}
r,l,t
-4,105,6.601282
-1732,1833,10.039687
-7852,7953,24.873165
-5720,5821,35.86051
-4527,4628,44.683237
-27310,27411,96.671992
-2342,2443,101.065658
-305,406,101.811046
         :
        (略)
         :
84,17,1181.376593
84,17,1181.400596
84,17,1181.441152
84,17,1181.466216
84,17,1181.499782
84,17,1181.531546
84,17,1181.566779
84,17,1181.595796

最初はマイナス報酬ばかりでしたが、最終的にはプラス報酬(84)となり、まっすぐゴールに向かっているようです。

次回は、この学習したモデルを使ってきちんと攻略できているかどうかを確認します。