第3回 強化学習を簡単に調整できるDeepRacerのコンソールとシミュレーター:AWS DeepRacer入門(2/2 ページ)
DeepRacerのコンソールとシミュレーション環境の内容について解説。また、コンソール上で設定できる強化学習の各ハイパーパラメーターについても説明する。ディープラーニングや強化学習の初学者にもってこいの学習コンテンツだ。
行動空間の設定
行動空間(Action space)とは、
- 車がどれくらいのスピードで進み
- どれくらいのステアリング(=車の進行方向を変えるためのハンドル機構)角度で曲がるか(もしくは0度で曲がらないか)
の組み合わせにより定義される行動リスト(Action list)を自動作成するための、コンソール上の設定セクションである。具体的には図6および表1に示す設定項目がある。
設定項目 | 英語表記 | デフォルト値 | 設定できる値 |
---|---|---|---|
最大ステアリング角度 | Maximum steering angle | 30度(degrees) | 1〜30 |
ステアリング角度の分割数 | Steering angle granularity | 5個 | 3/5/7 |
最大スピード | Maximum speed | 1 m/s(メートル毎秒) | 0.8〜8 |
スピードの分割数 | Speed granularity | 2個 | 1/2/3 |
表1 行動空間に関する設定項目の一覧 |
例えば、
- 最大ステアリング角度=10度(もしくは逆方向に-10度)
- ステアリング角度の分割数=3段階
- 最大スピード=1 m/s
- スピードの分割数=2段階
のように設定すると、ステアリング角度と走行スピードの組み合わせは3段階×2段階=6段階となり、図7のように6つの運転行動リストが自動生成される。
より理解が深まるようにもう少し例を挙げておくと、ステアリング角度の分割数を例えば3段階から5段階に増やすと、-10度/0度/10度という3分割から、-10度/-5度/0度/5度/10度という5分割に変化する。
また、スピードの分割数を例えば2段階から3段階に増やすと、0.5 m/s/1 m/sという2分割から、0.33 m/s/0.67 m/s/1 m/sという3分割に変化する、という仕組みになっている。
設定指針
では、それぞれどのような数値を設定すればよいのだろうか。
当然ながら、最大ステアリング角度が1度と少なければ、ほとんど曲がらない。30度と大きければ、進むたびにジグザグと方向変化が激しくなって進みにくくなる可能性がある。ほどよい曲がり方を試行錯誤しながら設定する必要がある。
また、ステアリング角度の分割数が3段階と少なければ、真っすぐ進むか左右どちらかに曲がるかの三択と極端な行動をするようになる。7段階と多ければ、真っすぐ進む/ちょっとだけ曲がる/少し大きく曲がる/とても大きく曲がるのように多彩な行動ができるようになる。当然7段階の方がベターだと思われるが、それだけ学習時間が長くなるというデメリットもある。
さらに、最大スピードは、0.8 m/sと小さければ進み方が極端に遅くなり、シミュレーションに時間がかかる。8 m/sと大きければ進み方は速くなる。車のスピードが速い方が、シミュレーションも速くなって良さそうだが、コースアウトする可能性が高まるだろう。
スピードの分割数については、1段階と少なければスピードが一定になるので学習は速く進むだろう。3段階と多ければ、スピードに強弱が出せるようになり、よりコースアウトしにくくなる可能性が高まるだろうが、学習にはより時間がかかるはずだ。
行動空間の設定における注意点として、一度学習すると行動空間は設定変更できないという点がある。よって、十分に戦略を練ってから設定する必要がある。
報酬関数の実装
報酬関数の意味と役割については前回説明した。今回は、報酬関数のPythonコードを書く際に、どのようなパラメーターが利用できるのかを紹介しよう。
念のため、前回と同じ報酬関数のコード例をリスト1に示しておく。コード内容の説明は割愛する。コメントを多めに書き込んだので、コメントを参考にしてほしい。
def reward_function(params):
'''
エージェントがセンターラインに沿って進むように報酬を定義した例。
'''
# 入力パラメーター(車の各種情報)を読み込む
track_width = params['track_width'] # コースの幅
distance_from_center = params['distance_from_center'] # センターラインからの距離
# センターラインからの距離を表す、3段階のコース幅のマーカーを計算する
marker_1 = 0.1 * track_width # コース幅の10%の距離
marker_2 = 0.25 * track_width # コース幅の25%の距離
marker_3 = 0.5 * track_width # コース幅の50%の距離
# 車がセンターラインに近ければ近いほど、高い報酬を与える
if distance_from_center <= marker_1:
reward = 1.0 # 10%幅内を走行中の場合は1.0ポイントの報酬
elif distance_from_center <= marker_2:
reward = 0.5 # 25%幅内なら0.5ポイント
elif distance_from_center <= marker_3:
reward = 0.1 # 50%幅内なら0.1ポイント
else:
reward = 1e-3 # それらよりも外なら1e-3(=0.001)ポイント
# クラッシュしたか、コースアウトに近い状態と見なすということ
# 計算された報酬は、関数の呼び出し元にfloat値として返却する
return float(reward)
図8はコンソール上にある報酬関数のコード入力欄である。
入力欄の上部に3つのボタンがある。そのうちの1つ、赤枠で囲んだ[Reward function examples]ボタンをクリックすると、図9のようなダイアログが表示される。
このダイアログでは、報酬関数のコード例(=サンプルコード)を、(2019年8月6日時点では)下記の3つから選択できる。
- [Follow the center line (Default)]: センターラインに沿って走る(デフォルト)
- [Stay inside the two borders]: 2つの境界線内にとどまるように走る
- [Prevent zig-zag]: ジグザグにならないように走る
先ほどのリスト1のコードは、このうち[Follow the center line (Default)]のコード内容そのものである。
ここから使いたいコード例を選択して[Use code]ボタンをクリックすると、先ほどの報酬関数のコード入力欄にそのコード例が反映される。
あとは、初期のコード例から、独自のロジックに書き換えていけばよい。まずは書き換えずに学習してみて、少しずつ書き換えながら繰り返し学習していき、どのような走りに変化するかを見るとよいだろう。
ロジックを作る際には、コースに対する車の位置などさまざまな情報が必要となる。この情報は、リスト1で示したように入力パラメーター(params)としてreward_function関数に渡される。実際にどのような情報があるのかを紹介しよう。
前提知識(1) コースの構成要素
前提知識として、まずはコースの構成要素を押さえておこう。図10はシミュレーターのカメラ映像の一場面である。
図10に示すとおり、サーキット上のコースには下記の要素がある。
- サーキットの壁: 青色の部分。壁に衝突すると車は前に進めない
- フィールド: 緑色の部分。いわゆるコース外(off-track)
- コース面: 濃い灰色の部分。いわゆるコース上(on-track)
- コースの境界線: 白色の線。「コース上」を明示する。境界線をはみ出すと「コース外」となる
- センターライン: 黄色の点線。コース幅の中央に引かれた線
これらの要素は、行動が良いか悪いかを決定する基準となるため、重要だ。
コードでは、「車がコース上にあるかどうか」や「センターラインからの距離」などの情報を、主に下記のようなパラメーターのキー名で取得できる(※paramsは前述の入力パラメーターのこと)。
- params['all_wheels_on_track']: 4輪全てがコース上にあるかどうか
- params['distance_from_center']: センターラインからの距離
- params['is_left_of_center']: 車がセンターラインの左側にいるか、いないか(=右側にいるか)
前提知識(2) 座標系
次に、座標系も前提知識として押さえておこう。
シミュレーターは3D(3次元)の空間となっており、X軸・Y軸・Z軸が設定されている。図11は、シミュレーション環境のコースを上から見た画像で、Z軸は見えず、横がX軸、縦がY軸で表現されている。シミュレーターでは、車が平面マップ上のどの位置にいるかは、X軸とY軸上の値で判定する仕様となっている(※Z軸上の値は取得できない)。コードでは、
- params['x']
- params['y']
により値を取得できる。
前提知識(3) 参照点
また、前掲の図11に示す下記の情報も取得可能で、行動の決定基準として役立つ。
- 自動運転カーの向き: 車の先頭が向いている角度
- コース幅: コースの外周〜内周の距離
- コース外側の参照点: コースの外周にある点々のことで、コースの境界線(外側)を形成する
- コース中央の参照点: コースの中央にある点々のことで、センターラインを形成する
- コース内側の参照点: コースの内周にある点々のことで、コースの境界線(内側)を形成する
サーキット上のコースの中央と周囲(内側と外側)には参照点(waypoints、コース上の地点)がある。参照点は、[X軸の値、Y軸の値]のリスト値(=params['waypoints']で取得可能)となっている。参照点は、コースの完走率や、前述のセンターラインからの距離の計算に使われており、独自のロジックを作り込む際にも役立つ。
コードでは、下記のようなパラメーターからそれぞれの情報が取得できる。
- params['heading']: 自動運転カーの向き
- params['track_width']: コース幅
- params['waypoints'][i]: i番目の、コース中央の参照点
- params['closest_waypoints']: 最も近い参照点のインデックスを2点分。インデックスは、上記のiの部分に指定する値。この情報に基づき、次に進むべき方向を自分で計算したりする
コースの完走率に関するパラメーターは、下記のように入力パラメーターに初めから用意されている。
- params['progress']: コースの完走率(パーセンテージ)
- params['steps']: コース上での完了したステップ数
ちなみに当然ながら、スピードやステアリング角度も入力パラメーターとして下記のように取得できる。
- params['speed']: 現在の車のスピード(単位はm/s:メートル毎秒)
- params['steering_angle']: 現在の車のステアリング角度(単位は度)
入力パラメーターについて詳しくは、公式ドキュメントやGitHub上にある公式ワークショップ資料を参照してほしい。
ハイパーパラメーターの設定&調整
ハイパーパラメーターとは、強化学習の学習方法を調整するための各種数値のことである。DeepRacerのコンソールでは、図12に示す7項目が指定できる。
それぞれ表2に簡単にまとめた。
設定項目 | 英語表記 | デフォルト値 | 設定できる値 | 機能概要 | 効果 |
---|---|---|---|---|---|
バッチサイズ | Batch size | 64 | 32/64/128/256/512 | 勾配降下(Gradient descent)法と呼ばれるアルゴリズムでニューラルネットワークを最適化する際に、何個ごとのデータで学習していくかの数値 | バッチサイズを大きくすると、まとめて処理できるので学習が高速化するが、メモリの消費量が大きくなる |
エポック数 | Number of epochs | 10 | 3〜10 | 1つの訓練データを何回学習させるかの数値 | エポック数が増えると、時間がかかるようになるが、学習は収束(=納得のいく精度に収まること)しやすくなり安定する |
学習率 | Learning rate | 0.0003 | 0.00000001(=1e-8)〜0.001(=1e-3) | 1回の学習で変化する大きさの数値 | 学習率が大きいと、学習は速くなるが、収束が難しくなることがある |
エントロピー | Entropy | 0.01 | 0.0〜1.0 | 行動空間の確率分布における不確実性/ランダム性(要するに、車が探索する量)の数値 | エントロピーを大きくすると、車は行動空間をより広範かつ徹底的に探索するようになる。逆に小さくすると、探索も狭まる |
割引率 | Discount factor | 0.999 | 0.0〜1.0 | 前回説明したように、どこまでの将来を考慮するかの数値 | 割引率が大きいと、将来をより考慮するようになるが、学習は遅くなる |
損失タイプ | Loss type | Huber | Mean square error(平均二乗誤差)損失/Huber損失 | ネットワークを更新する際に使われる損失関数(=出力と教師ラベル/望ましい行動の誤差)の数値 | 収束しやすい場合は、平均二乗誤差を使うと、学習が速くなる。なかなか収束しない場合は、外れ値に敏感ではないHuberを使うとよい |
トレーニングごとの経験エピソードの数 | Number of experience episodes between each policy-updating iteration | 20 | 5〜100 | トレーニングにより方策(=どういう行動をするかのポリシー)を更新するイテレーション(=繰り返し処理)の1回で、いくつのエピソード(後述)を必要とするかの数値 | エピソード数が大きいと、トレーニングは遅くなるが、学習が収束しやすくなる。推奨値は、10、20、40あたり |
表2 DeepRacerコンソールで指定できるハイパーパラメーターの一覧 |
データに関する用語が若干ややこしいので、粒度ごとに用語と意味の違いも以下に整理しておこう。
- データポイント(Data point): 状態+行動+報酬の1セットを構成する、1つのステップ(Step)、経験(Experience)のこと
- エピソード(Episode): エージェントがスタート地点からゴール地点まで完走する、もしくはコースから外れて走行中止される、までの全ステップの経験のこと。よって、エピソードごとに長さは異なる
- 経験バッファー(Experience buffer): 複数のエピソードのセットで、トレーニング時はこのセットごとにニューラルネットワークを更新する。1セットのエピソード数は固定で、上記の[トレーニングごとの経験エピソードの数]で指定できる
- バッチ(Batch): 複数の経験バッファーのセットで、ニューラルネットワークの更新に利用される。上記の[バッチサイズ]で指定できる
- 訓練データ(Training data): 複数のバッチのセットで、ニューラルネットワークの更新に利用される
今回は、DeepRacerのコンソールとシミュレーターについて解説した。次回は実践編として、学習&評価してバーチャルで走らせるまでの手順を説明する。Please follow on Twitter @DeepInsiderJP.
Copyright© Digital Advantage Corp. All Rights Reserved.