LoginSignup
0
0

More than 1 year has passed since last update.

ランド研究所の「機械学習による航空支配」を実装する(その18): 2D問題 mission_4 Reward shaping による改良

Last updated at Posted at 2021-07-24

本記事は、ランド研究所の「機械学習による航空支配」を実装する(その18)です。

Air Dominance Through Machine Learning: A Preliminary Exploration of Artificial Intelligence–Assisted Mission Planning, 2020

使用したコードは、下記 GitHub の mission_4 フォルダにあります。

https://github.com/DreamMaker-Ai/AirDominance_2D_RL

強化学習アルゴリズムは、これまでと同様に、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の大きさで与えることができます。

図1.png

以上をふまえ、ステップ毎に与えるステップ報酬は、次のコードで与えました。

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 報酬シェーピングの効果

報酬シェーピングにより、学習が誘導されるので、学習が加速されているのが分かります。

episode length mean_trail.jpg

episode reward mean_trial.jpg

下図は、報酬シェーピング無しの場合のエピソード報酬(1 or -1)の分布です。

episode_reward_id_2.png

下図は、報酬シェーピングによって、エピソード報酬の分布が狭い範囲内で安定したものになることを示しています。

episode rewrad_id_12.png

下図も、報酬シェーピング無しの場合には、エピソード報酬(1 or -1)が、安定しないことを示しています。

ID_2_reward.png

報酬シェーピングにより、安定したエピソード報酬が得られるようになります。

ID_12_reward.png

下図は、100エピソードでテストした場合の成功率の分布です。報酬シューピングにより、以下の効果が得られることが分かります。
- 学習が早くなる
- 学習が安定する(成功率が安定する)
- 高い性能が得られる(高い成功率が得られる)

test_history.png

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つのパッケージとしてプランニングしたほうが良いと思います。

episode reward mean_trial (1).jpg

episode length mean_trail (1).jpg

episode reward.png

episode_length.png

3. 学習結果

トレーニング中に 100 エピソードでテストを行い成功率を計算た結果を示します。上に示した平均エピソード長や平均エピソード報酬の履歴からは読み取れませんが、N=40 (97.23sec)の場合に比べると、cooldown time が短い N=20 (48.6 sec), 10 (24.3 sec) のケースは少し学習が難しいのが判ります。

learning_history.png

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

Robustness to Initial heading error & Initial range (1).png

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

Robustness to Range difference (Decoy).png

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

Robustness to Range difference (Fighter).png

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
  }
}

sac_success_21.gif

{
  "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
  }
}

sac_success_7.gif

{
  "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
  }
}

sac_success_2.gif

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
  }
}

sac_fail_25.gif

{
  "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
  }
}

sac_fail_29.gif

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
  }
}

sac_success_1.gif

{
  "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
  }
}

sac_success_26.gif

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
  }
}

sac_fail_0.gif

{
  "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
  }
}

sac_fail_21.gif

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
  }
}

sac_success_22.gif

{
  "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
  }
}

sac_success_27.gif

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
  }
}

sac_fail_2.gif

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
  }
}

sac_success_0.gif

{
  "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
  }
}

sac_success_12.gif

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
  }
}

sac_fail_19.gif

(その19)へ続く

ランド研究所のレポートの実装は今回で終了です。
(その19)では、全体の総括、今回やり残した事、やりながらこうすればよかったと思った事、今後の研究課題などを纏めておきたいと思います。

過去記事へのリンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0