本記事は、ランド研究所の「機械学習による航空支配」を実装する(その18)です。
使用したコードは、下記 GitHub の mission_4 フォルダにあります。
強化学習アルゴリズムは、これまでと同様に、SAC を用いました。
#1. 報酬シェーピング
報酬シェーピングでは、学習時にプランナーのサーチ空間を制限して、望ましい方向に学習を意図的に誘導するために、(毎ステップで密に)報酬を与えます。
ここで「望ましい方向」とは、あくまで設計者たる「私が望ましい」と思っている方向なだけであって、それがベストな方向であるとは限りません。たぶん、ほとんどの場合は、もっと良い解が解空間のどこかに存在するのではないかと思います。
このように、報酬シェーピングは、ニューラルネットの持つ可能性を限定してしまうような気がして、私はあまり好きではないので、今回まで敢えて使わずに来ました。とはいえ、現状の強化学習では、報酬シェーピングは正しく使えば威力を発揮します。逆に言えば、報酬シェーピング無しでは、上手くいかないことが多いのが現状の強化学習レベルですので、これは今後に期待するしかありません。
報酬シェーピングを有効に使うためには、ドメイン知識が重要なのですが、今回の例題では常識で考えれば十分だと思いますので、以下の方針で報酬を与えました。(かなり試行錯誤しました)。
(1) 不要な遠回りを避けるために、ステップ毎に負のペナルティ-0.1を与える。
(2) Decoy が未だ生きていて、
2−1)Decoy が SAM に接近している、
且つ
2−2)Decoy と Fighters の内の少なくとも一機との間で「同期(説明は後出)」が取れていて、且つ、その Fighter が SAM に接近しつつある、
且つ、
2-3)Decoy のほうが、その Fighter よりも先に SAM の射程内に入る位置関係になっている、
時、Decoy の SAM への指向度合いに応じた報酬を与える。
Decoyが生きているかどうかは、Decoy.alive > 0.5 で判定できます。
2−1)の Decoy が SAM に接近しているかどうかは、下図のように、Decoy の速度ベクトルと、Decoy に対する SAM の相対位置ベクトルの間の角度θdで判定できます。
2−2)の「同期」ですが、これは、
Fighter_speed x cooldown time + fighter の内の1機の搭載ウェポンの射程 > SAM の射程
と定義しました。これは、cooldown 期間中に、少なくとも1機の Fighter の搭載ウェポンが、SAM を射程内に収めることが出来る位置関係にあることを意味しています。また、「その fighter が SAM に近づいている」は、その fighter の θf が小さい
て表すことができます。
2-3)は、SAM と Decoy, Fighter 間の各距離を比べれば判定できます。
Decoy の SAM への指向度合いに応じた報酬は、θdの大きさで与えることができます。
以上をふまえ、ステップ毎に与えるステップ報酬は、次のコードで与えました。
def get_reward_mission_4(self, done, fighter_1, fighter_2, fighter_3, decoy, sam):
reward = -0.1
# cond_1
cond_1 = (decoy.alive > .5)
# cond_2
v_d = self.make_v(decoy)
r_ds = self.make_r(sam, decoy)
_, cos_d = self.compute_heading_error(v_d, r_ds)
cond_2 = (cos_d > np.cos(10 * np.pi / 180))
# cond_3
fighters = ['fighter_1', 'fighter_2', 'fighter_3']
cos_f_list = []
r_f_list = []
for f in fighters:
fighter = eval(f)
v_f = self.make_v(fighter)
r_fs = self.make_r(sam, fighter)
_, cos_f = self.compute_heading_error(v_f, r_fs)
cos_f_list.append(cos_f)
r_f_list.append(np.linalg.norm(r_fs, ord=2) - np.linalg.norm(r_ds, ord=2))
cond_3_list = []
for i in range(len(fighters)):
con1 = (0 < r_f_list[i] <= sam.cooldown_max_count * self.resolution)
con2 = (cos_f_list[i] > np.cos(10 * np.pi / 180))
cond_3_list.append(con1 and con2)
cond_3 = (True in cond_3_list)
cond_4_list = []
for i in range(len(fighters)):
con1 = (0 < r_f_list[i])
cond_4_list.append(con1)
cond_4 = not (False in cond_4_list)
cond = (cond_1 and cond_2 and cond_3 and cond_4)
if cond:
alpha = 0.1
reward += alpha * cos_d
if done:
if (fighter_1.alive > .5) and (fighter_2.alive > .5) and (fighter_3.alive > .5) and \
(sam.alive < .5):
reward = 1
else:
reward = -1
return reward
#2. 学習履歴
以下では、報酬シェーピング無しで、何とか学習を進めることが出来た cooldown time step N=40 (97.297 secに対応) の場合の例を以下に示します。
各下図で、茶色のラインが報酬シェーピング無し、水色のラインが報酬シェーピング有りの場合の学習履歴です。報酬シェーピングは、非常に有効なことが判ります。
##2.1 報酬シェーピングの効果
報酬シェーピングにより、学習が誘導されるので、学習が加速されているのが分かります。
下図は、報酬シェーピング無しの場合のエピソード報酬(1 or -1)の分布です。
下図は、報酬シェーピングによって、エピソード報酬の分布が狭い範囲内で安定したものになることを示しています。
下図も、報酬シェーピング無しの場合には、エピソード報酬(1 or -1)が、安定しないことを示しています。
報酬シェーピングにより、安定したエピソード報酬が得られるようになります。
下図は、100エピソードでテストした場合の成功率の分布です。報酬シューピングにより、以下の効果が得られることが分かります。
- 学習が早くなる
- 学習が安定する(成功率が安定する)
- 高い性能が得られる(高い成功率が得られる)
##2.2 Small cooldown time
報酬シェーピング有の条件で、SAM のcooldown timeを変えてトレーニングした際の学習履歴を下図に示します。Cool down timeは、40 time steps (97.3 sec)、20 time steps (48.6 sec)、10 time steps (24.3 sec)で実施しました。いずれの場合も、トレーニングに成功しています。
※ さらに、5 time steps(12.2 sec)でも試みましたが、これは学習が進みませんでした。もし、cooldown time が十数秒よりも短いのであれば、今回のように、Decoy と Fighter を別々のエンティティとするのではなく、1つのパッケージとしてプランニングしたほうが良いと思います。
#3. 学習結果
トレーニング中に 100 エピソードでテストを行い成功率を計算た結果を示します。上に示した平均エピソード長や平均エピソード報酬の履歴からは読み取れませんが、N=40 (97.23sec)の場合に比べると、cooldown time が短い N=20 (48.6 sec), 10 (24.3 sec) のケースは少し学習が難しいのが判ります。
#4. 汎化能力
学習時のミッション条件(ノミナル条件)を外挿するミッション条件で、プランナーの汎化能力(ロバストネス)を調べました。
学習時の条件は、下記のとおりです。
Nominal mission conditions:
- Fighters Initial range to SAM: [30,50] km
- Fighters Initial heading error to SAM: 0 deg
- Decoy Initial range to SAM: [30,50] km
- Decoy Initial heading error to SAM: 0 deg
汎化能力確認条件
Fighetr と Decoy の距離変動と Initial heading error に対するロバストネス:
- Fighters Initial range to SAM: [50, 70] km, [70, 90] km
- Fighters Initial heading error to SAM: [-180, 180] deg
- Decoy Initial range to SAM: [50, 70] km, [70, 90] km
- Decoy Initial heading error to SAM: [-180, 180] deg
##4.1 Decoy の初期距離が遠方のミッションに対するロバストネス
SAM に対する Decoy の初期位置が、トレーニング時よりも遠方にある場合、Fighters は Decoy が近づいてくるのを待って、正確なタイミングで SAM の射程内に進入しなければなりません。
- Fighters Initial range to SAM: [30, 50] km
- Fighters Initial heading error to SAM: [-180, 180] deg
- Decoy Initial range to SAM: [50,70] km, [70, 90] km, [90, 110] km
- Decoy Initial heading error to SAM: [-180, 180] deg
##4.2 Fighter の初期距離が遠方のミッションに対するロバストネス
SAM に対する Fighters の初期位置が、トレーニング時よりも遠方にある場合、Decoy は Fighters が近づいてくるのを待って、正確なタイミングでSAMの射程内に進入しなければなりません。
- Fighters Initial range to SAM: [50,70] km, [70, 90] km, [90, 110] km
- Fighters Initial heading error to SAM: [-180, 180] deg
- Decoy Initial range to SAM: [30, 50] km
- Decoy Initial heading error to SAM: [-180, 180] deg
#5. プランニング例
以下にプランニング例を示します。
3つの青い丸がFighters、その外側の大きな円が搭載ウェポンの射程、水色の丸がDecoy、赤い丸がSAM、その外側の円がSAMの射程を表しています。
個々の解説は省略しますが、報酬シェーピングから予想されるような動きとなっています。(意表を突いた動きにはならないので、個人的には、物足りなさを感じます)。
##5.1 Nominal mission conditions
Fighters Initial range to SAM: [30,50] km
Fighters Initial heading error to SAM: 0 deg
Decoy Initial range to SAM: [30,50] km
Decoy Initial heading error to SAM: 0 deg
###5.1.1 成功プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 11.5
},
"fighter_2": {
"alive": 1,
"firing_range": 10.5
},
"fighter_3": {
"alive": 1,
"firing_range": 11.5
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 7
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 7.0
},
"fighter_2": {
"alive": 1,
"firing_range": 10.0
},
"fighter_3": {
"alive": 1,
"firing_range": 8.0
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 9
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 13.5
},
"fighter_2": {
"alive": 1,
"firing_range": 13.0
},
"fighter_3": {
"alive": 1,
"firing_range": 11.0
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 8
}
}
###5.1.2 失敗プラン
僅かなタイミングの違いなのですが、上手くいかないケースもあります。
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "fail",
"fighter_1": {
"alive": 0,
"firing_range": 10.0
},
"fighter_2": {
"alive": 1,
"firing_range": 12.0
},
"fighter_3": {
"alive": 1,
"firing_range": 13.5
},
"sam_1": {
"alive": 0,
"firing_range": 14.0,
"cooldown_on": 0,
"cooldown_max_count": 10,
"cooldown_counter": 0
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "fail",
"fighter_1": {
"alive": 1,
"firing_range": 11.0
},
"fighter_2": {
"alive": 1,
"firing_range": 10.0
},
"fighter_3": {
"alive": 0,
"firing_range": 9.0
},
"sam_1": {
"alive": 1,
"firing_range": 13.0,
"cooldown_on": 0,
"cooldown_max_count": 10,
"cooldown_counter": 0
}
}
##5.2 距離変動と Initial heading error に対するロバストネス
Fighters Initial range to SAM: [70, 90] km
Fighters Initial heading error to SAM: [-180, 180] deg
Decoy Initial range to SAM: [70, 90] km
Decoy Initial heading error to SAM: [-180, 180] deg
###5.2.1 成功プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 15.0
},
"fighter_2": {
"alive": 1,
"firing_range": 16.0
},
"fighter_3": {
"alive": 1,
"firing_range": 14.0
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 9
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 10.0
},
"fighter_2": {
"alive": 1,
"firing_range": 12.0
},
"fighter_3": {
"alive": 1,
"firing_range": 14.0
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 9
}
}
###5.2.2 失敗プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "fail",
"fighter_1": {
"alive": 0,
"firing_range": 17.5
},
"fighter_2": {
"alive": 1,
"firing_range": 15.0
},
"fighter_3": {
"alive": 1,
"firing_range": 13.5
},
"sam_1": {
"alive": 0,
"firing_range": 18.0,
"cooldown_on": 0,
"cooldown_max_count": 10,
"cooldown_counter": 0
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "fail",
"fighter_1": {
"alive": 1,
"firing_range": 14.0
},
"fighter_2": {
"alive": 0,
"firing_range": 14.0
},
"fighter_3": {
"alive": 1,
"firing_range": 13.0
},
"sam_1": {
"alive": 1,
"firing_range": 17.0,
"cooldown_on": 0,
"cooldown_max_count": 10,
"cooldown_counter": 0
}
}
##5.3 Decoy の初期距離が遠方のミッションに対するロバストネス
SAM に対する Decoy の初期位置が、トレーニング時よりも遠方にある場合、Fighters は Decoy が近づいてくるのを待って、正確なタイミングで SAM の射程内に進入しなければなりません。このようなプランニングが出来るかどうか確認します。
Fighters Initial range to SAM: [30, 50] km
Fighters Initial heading error to SAM: [-180, 180] deg
Decoy Initial range to SAM: [90, 110] km
Decoy Initial heading error to SAM: [-180, 180] deg
###5.3.1 成功プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 12.0
},
"fighter_2": {
"alive": 1,
"firing_range": 13.0
},
"fighter_3": {
"alive": 1,
"firing_range": 13.5
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 7
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 10.5
},
"fighter_2": {
"alive": 1,
"firing_range": 11.5
},
"fighter_3": {
"alive": 1,
"firing_range": 9.5
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 10
}
}
###5.3.2 失敗プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "fail",
"fighter_1": {
"alive": 0,
"firing_range": 12.5
},
"fighter_2": {
"alive": 0,
"firing_range": 11.5
},
"fighter_3": {
"alive": 1,
"firing_range": 14.5
},
"sam_1": {
"alive": 0,
"firing_range": 15.5,
"cooldown_on": 0,
"cooldown_max_count": 10,
"cooldown_counter": 0
}
}
##5.4 Fighter の初期距離が遠方のミッションに対するロバストネス
SAM に対する Fighters の初期位置が、トレーニング時よりも遠方にある場合、Decoy は Fighters が近づいてくるのを待って、正確なタイミングでSAMの射程内に進入しなければなりません。このような正確性が要求されるタイミングをプランニング出来るかどうか確認します。
Fighters Initial range to SAM: [90, 110] km
Fighters Initial heading error to SAM: [-180, 180] deg
Decoy Initial range to SAM: [30, 50] km
Decoy Initial heading error to SAM: [-180, 180] deg
###5.4.1 成功プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 13.0
},
"fighter_2": {
"alive": 1,
"firing_range": 14.0
},
"fighter_3": {
"alive": 1,
"firing_range": 13.0
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 8
}
}
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "success",
"fighter_1": {
"alive": 1,
"firing_range": 20.5
},
"fighter_2": {
"alive": 1,
"firing_range": 16.5
},
"fighter_3": {
"alive": 1,
"firing_range": 18.5
},
"sam_1": {
"alive": 0,
"firing_range": 0,
"cooldown_on": 1,
"cooldown_max_count": 10,
"cooldown_counter": 8
}
}
###5.4.2 失敗プラン
{
"mission_id": "mission_4",
"mission_condition": "d1",
"result": "fail",
"fighter_1": {
"alive": 1,
"firing_range": 8.5
},
"fighter_2": {
"alive": 0,
"firing_range": 7.5
},
"fighter_3": {
"alive": 1,
"firing_range": 9.5
},
"sam_1": {
"alive": 1,
"firing_range": 11.5,
"cooldown_on": 0,
"cooldown_max_count": 10,
"cooldown_counter": 0
}
}
#(その19)へ続く
ランド研究所のレポートの実装は今回で終了です。
(その19)では、全体の総括、今回やり残した事、やりながらこうすればよかったと思った事、今後の研究課題などを纏めておきたいと思います。
過去記事へのリンク
- ランド研究所の「機械学習による航空支配」を実装する(その1):レポートのまとめ
- ランド研究所の「機械学習による航空支配」を実装する(その2):1次元問題について
- ランド研究所の「機械学習による航空支配」を実装する(その3): 1D simulator for GAN と Random mission planner の実装)
- ランド研究所の「機械学習による航空支配」を実装する(その4): conditional GAN の実装とトレーニング
- ランド研究所の「機械学習による航空支配」を実装する(その5):トレーニング結果の分析
- ランド研究所の「機械学習による航空支配」を実装する(その6):トレーニング・データの重要性と GAN の性能向上
- ランド研究所の「機械学習による航空支配」を実装する(その7):1D simulator for RL の実装
- ランド研究所の「機械学習による航空支配」を実装する(その8): Stable Baselines による強化学習
- ランド研究所の「機械学習による航空支配」を実装する(その9): 少し複雑な環境
- ランド研究所の「機械学習による航空支配」を実装する(その10):GAN / 強化学習プランナーの連携を考える
- ランド研究所の「機械学習による航空支配」を実装する(その11): 2次元問題の概要
- ランド研究所の「機械学習による航空支配」を実装する(その12): 2D simulator for mission_1 の実装
- ランド研究所の「機械学習による航空支配」を実装する(その13): 2D 問題 mission_1 を強化学習する
- ランド研究所の「機械学習による航空支配」を実装する(その14): Relative Observation による mission planner の能力アップ
- ランド研究所の「機械学習による航空支配」を実装する(その15): 2D問題 mission_2
- ランド研究所の「機械学習による航空支配」を実装する(その16): 2D問題 mission_3
- ランド研究所の「機械学習による航空支配」を実装する(その17): 2D問題 mission_4