「カリキュラム学習」はタスクの難易度を徐々に上げていくことで、より難しいタスクの攻略を可能にする学習方法です。
小学生の頃の授業を思い出してください。算数では「足し算・引き算」を教えた後、「掛け算・割り算」を教え、その後に「面積の計算」を教えます。レッスンで学んだ知識を、後のレッスンのための足場とすることで、より難しい問題を解くことを可能にしています。
これと同じ原理を「強化学習」に適用します。
「カリキュラム学習」の実装手順は、次の2つです。
「4-6 Curiosity」で作成した学習環境をカスタマイズして「カリキュラム学習」を行います。
「Behaviour Paramaters」を以下のように変更してください。
今回は、以下の3つの変数を「環境パラメータ」として定義します。
・checkpointReward:チェックポイント通過時の報酬
・episodeReward:1周した時の報酬
・stepReward:ステップ毎のペナルティ
レッスンは全部で3つです。
コースを反時計回りに回ることを覚えさせます。チェックポイント通過時の報酬のみを与えます
・checkpointReward:0.2
・episodeReward:0.0
・stepReward:0.0
コースを1周することを覚えさせます。 1周した時の報酬のみを与えます。
・checkpointReward:0.0
・episodeReward:1.0
・stepReward:0.0
コースをできるだけ早く1周することを覚えさせます。1周した時の報酬とは別に、1ステップ毎のマイナス報酬も与えます
・checkpointReward:0.0
・episodeReward:2.0
・stepReward:-0.001
「RaycastAgent.cs」全体
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Policies;
// RaycastAgent
public class RaycastAgent : Agent
{
Rigidbody rBody;
int lastCheckPoint; // 最終チェックポイント
int checkPointCount; // チェックポイント通過数
// ゲームオブジェクト生成時に呼ばれる
public override void Initialize()
{
this.rBody = GetComponent<Rigidbody>();
}
// 環境パラメータ
float checkPointReward;
float episodeReward;
float stepReward;
// エピソード開始時に呼ばれる
public override void OnEpisodeBegin()
{
// 周回数の環境
this.lastCheckPoint = 0;
this.checkPointCount = 0;
// 環境パラメータの設定
EnvironmentParameters envParams = Academy.Instance.EnvironmentParameters;
this.checkPointReward = envParams.GetWithDefault("checkpoint_reward", 0.0f);
this.episodeReward = envParams.GetWithDefault("episode_reward", 2.0f);
this.stepReward = envParams.GetWithDefault("step_reward", -0.001f);
}
// 状態取得時に呼ばれる
public override void CollectObservations(VectorSensor sensor)
{
sensor.AddObservation(rBody.velocity.x); // RaycastAgentのX速度
sensor.AddObservation(rBody.velocity.z); // RaycastAgentのZ速度
}
// 行動実行時に呼ばれる
public override void OnActionReceived(ActionBuffers actionBuffers)
{
// RaycastAgentに力を加える
Vector3 dirToGo = Vector3.zero;
Vector3 rotateDir = Vector3.zero;
int action = actionBuffers.DiscreteActions[0];
if (action == 1) dirToGo = transform.forward;
if (action == 2) dirToGo = transform.forward * -1.0f;
if (action == 3) rotateDir = transform.up * -1.0f;
if (action == 4) rotateDir = transform.up;
this.transform.Rotate(rotateDir, Time.deltaTime * 200f);
this.rBody.AddForce(dirToGo * 0.4f, ForceMode.VelocityChange);
// ステップ毎の報酬
AddReward(this.stepReward);
}
// チェックポイントに衝突時に呼ばれる
public void EnterCheckPoint(int checkPoint)
{
// 次のチェックポイントに衝突
if (checkPoint == (this.lastCheckPoint+1)%4)
{
// チェックポイント毎のプラス報酬
AddReward(this.checkPointReward);
this.checkPointCount++;
// ゴール
if (this.checkPointCount >= 4)
{
// エピソード毎の報酬
AddReward(this.episodeReward);
EndEpisode();
}
}
// 前のチェックポイントに衝突
else if (checkPoint == (this.lastCheckPoint-1+4)%4)
{
// チェックポイント毎の・マイナス報酬
AddReward(-this.checkPointReward);
this.checkPointCount--;
}
// 最終チェックポイントの更新
this.lastCheckPoint = checkPoint;
}
// ヒューリスティックモードの行動決定時に呼ばれる
public override void Heuristic(in ActionBuffers actionBuffers)
{
var actionsOut = actionBuffers.DiscreteActions;
actionsOut[0] = 0;
if (Input.GetKey(KeyCode.UpArrow)) actionsOut[0] = 1;
if (Input.GetKey(KeyCode.DownArrow)) actionsOut[0] = 2;
if (Input.GetKey(KeyCode.LeftArrow)) actionsOut[0] = 3;
if (Input.GetKey(KeyCode.RightArrow)) actionsOut[0] = 4;
}
}
「環境パラメータ」は環境開始時に設定するパラメータです。カリキュラムに応じて、このパラメータが変化するように実装します。
// 環境パラメータ
float checkPointReward;//チェックポイント通過時の報酬
float episodeReward;//1周した時の報酬
float stepReward;//ステップ毎のペナルティ
環境パラメータは、「Academy.Instance.EnviromentParameters」のGetWithDefault()で取得します。
float GetWithDefault(string key , float defaultValue)
説明:環境パラメータの値の取得
引数:key キー defaultValue 初期値
戻り値:環境パラメータの値
// 環境パラメータの設定
EnvironmentParameters envParams = Academy.Instance.EnvironmentParameters;
this.checkPointReward = envParams.GetWithDefault("checkpoint_reward", 0.0f);
this.episodeReward = envParams.GetWithDefault("episode_reward", 2.0f);
this.stepReward = envParams.GetWithDefault("step_reward", -0.001f);
どんな値で学習するかは、カリキュラム学習の学習設定ファイルで設定します。
チェックポイント通過時の報酬に「checkPointReward」を利用します
// チェックポイント毎のプラス報酬
AddReward(this.checkPointReward);
this.checkPointCount++;
// チェックポイント毎のマイナス報酬
AddReward(this.checkPointReward);
this.checkPointCount--;
1周した時の報酬に「episodeReward」を使います
// エピソード毎の報酬
AddReward(this.episodeReward);
EndEpisode();
ステップ毎のペナルティに「stepReward」を使います
// ステップ毎の報酬
AddReward(this.stepReward);
今回は「PPO」で学習します。以下のようにハイパーパラメータを設定してください。
behaviors:
CurriculumEx:
#トレーナー種別
trainer_type: ppo
#基本
max_steps: 10000000
time_horizon: 128
summary_freq: 10000
keep_checkpoints: 5
#学習アルゴリズム
hyperparameters:
#PPOとSAC共通
batch_size: 128
buffer_size: 2048
learning_rate: 0.0003
learning_rate_schedule: linear
#PPO用
beta: 0.01
epsilon: 0.2
lambd: 0.95
num_epoch: 3
#ニューラルネットワーク
network_settings:
normalize: false
hidden_units: 512
num_layers: 2
#報酬
reward_signals:
#環境報酬
extrinsic:
gamma: 0.99
strength: 1.0
#環境パラメータ
environment_parameters:
#チェックポイント報酬
checkpoint_reward:
curriculum:
- name: Lesson0
completion_criteria:
measure: reward
behavior: CurriculumEx
signal_smoothing: true
min_lesson_length: 10
threshold: 0.7
value: 0.3
- name: Lesson1
completion_criteria:
measure: reward
behavior: CurriculumEx
signal_smoothing: true
min_lesson_length: 10
threshold: 0.9
value: 0.0
- name: Lesson2
value: 0.0
#エピソード報酬
episode_reward:
curriculum:
- name: Lesson0
completion_criteria:
measure: reward
behavior: CurriculumEx
signal_smoothing: true
min_lesson_length: 10
threshold: 0.7
value: 0.0
- name: Lesson1
completion_criteria:
measure: reward
behavior: CurriculumEx
signal_smoothing: true
min_lesson_length: 10
threshold: 0.9
value: 1.0
- name: Lesson2
value: 2.0
#ステップ報酬
step_reward:
curriculum:
- name: Lesson0
completion_criteria:
measure: reward
behavior: CurriculumEx
signal_smoothing: true
min_lesson_length: 10
threshold: 0.7
value: 0.0
- name: Lesson1
completion_criteria:
measure: reward
behavior: CurriculumEx
signal_smoothing: true
min_lesson_length: 10
threshold: 0.9
value: 0.0
- name: Lesson2
value: -0.001
「environment_parameters:」の直下に「環境パラメータ」を並べ、「currilulum:」の下にレッスン情報を並べます。
environment_parameters:
checkpoint_reward:
curriculum:
- name: Lesson0
completion_criteria:
<次のレッスンに進む条件>
value:<値>
次のレッスンに進む条件は、以下の情報を持ちます。
・measure:レッスンの進捗条件の測定方法
・reward:エピソード報酬
・progress:ステップ数÷最大ステップ数
・behavior:対象となるBehavior
・signal_smoothing:シグナルのスムージング(true/false)
・min_lesson_length:閾値を何エピソード越えた時、次のレッスンに進むか
・threshold:閾値
mlagents-learn .\config\sample\CurriculumEx.yaml --run-id=CurriculumEx-1
学習結果のグラフは、次のとおりです。
カリキュラム学習の使用時には、「TensorBoard」でカリキュラム学習専用のグラフも提供されます。
環境パラメータ毎のレッスンの進捗状況を示すグラフです。
「カリキュラム学習」の「あり」と「なし」を比較してみます。
「カリキュラム学習」なしは、最初から「レッスン2」のパラメータのみで学習しました。
学習結果のグラフは、次のとおりです。難易度の高い「レッスン2」から始めてしまうと、まったく報酬が見つけられないことがわかります。