メインコンテンツまでスキップ

4-9 カリキュラム学習

「カリキュラム学習」はタスクの難易度を徐々に上げていくことで、より難しいタスクの攻略を可能にする学習方法です。



カリキュラム学習とは

小学生の頃の授業を思い出してください。算数では「足し算・引き算」を教えた後、「掛け算・割り算」を教え、その後に「面積の計算」を教えます。レッスンで学んだ知識を、後のレッスンのための足場とすることで、より難しい問題を解くことを可能にしています。
これと同じ原理を「強化学習」に適用します。



カリキュラム学習の実装手順

「カリキュラム学習」の実装手順は、次の2つです。

①カリキュラムに応じて変化するパラメーターを「環境パラメータ」で実装

②学習設定ファイルへのカリキュラム学習の設定の追加



カリキュラム学習の学習環境の準備

「4-6 Curiosity」で作成した学習環境をカスタマイズして「カリキュラム学習」を行います。
「Behaviour Paramaters」を以下のように変更してください。



「環境パラメータ」の準備

今回は、以下の3つの変数を「環境パラメータ」として定義します。

・checkpointReward:チェックポイント通過時の報酬
・episodeReward:1周した時の報酬
・stepReward:ステップ毎のペナルティ

レッスンは全部で3つです。

レッスン0

コースを反時計回りに回ることを覚えさせます。チェックポイント通過時の報酬のみを与えます

・checkpointReward:0.2
・episodeReward:0.0
・stepReward:0.0

レッスン1

コースを1周することを覚えさせます。 1周した時の報酬のみを与えます。

・checkpointReward:0.0
・episodeReward:1.0
・stepReward:0.0

レッスン2

コースをできるだけ早く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;//ステップ毎のペナルティ

② OnEpisodeBegin()で環境パラメータの値を設定

環境パラメータは、「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」でカリキュラム学習専用のグラフも提供されます。

Lesson Numberグラフ

環境パラメータ毎のレッスンの進捗状況を示すグラフです。



カリキュラム学習の「あり」と「なし」の比較

「カリキュラム学習」の「あり」と「なし」を比較してみます。
「カリキュラム学習」なしは、最初から「レッスン2」のパラメータのみで学習しました。
学習結果のグラフは、次のとおりです。難易度の高い「レッスン2」から始めてしまうと、まったく報酬が見つけられないことがわかります。