本記事の概要
10月で2019年のDeepRacerのVirtual Raceが終了したため、前回は10月のVitrual Raceでの試行錯誤した結果を報告させていただきましたが、今回もその続きを報告させていただきたいと思います。
DeepRacerのモデル作成
車体がトラックから出ないようにするモデルの作成
まずは、トラック内に車体があることを重視した報酬関数1を用いて2時間学習し、その後報酬関数2を用いて8時間学習を行いました。
報酬関数2については、GitHubで公開されており、評判が良い報酬関数です。
def reward_function(params): #トラックの幅 float track_width = params['track_width'] #トラック幅の半分 float half_track_width = track_width * 0.5 #車体がトラックの真ん中からどれだけ離れているか float distance_from_center = params['distance_from_center'] #コースの完走率(0~100) float progress = params["progress"] #ステップ数 int steps = params["steps"] #スピード float speed = params["speed"] #最高速度 今回は10.0 max_speed = 10.0 #車体のホイールが全てトラック上にある時,(かつ,stepsとhalf_track_widthが0より大きい時) if params["all_wheels_on_track"] and steps > 0 and half_track_width > 0: #車体がトラックの真ん中に近ければ近いほど良い 最大値1.0 reward = (half_track_width - distance_from_center) / half_track_width #早いステップでコースを走るほど良い 最大値1.0 reward += progress * 0.01 / steps #スピードが早いほど良い 最大値1.0 reward += speed / max_speed reward /= 3.0 else: reward = 1e-3 return float(reward)
def reward_function(params): if params["all_wheels_on_track"] and params["steps"] > 0: reward = ((params["progress"] / params["steps"]) * 100) + (params["speed"]**2) else: reward = 0.01 return float(reward)
また、アクションスペースとハイパーパラメータは以下のように設定して学習しました。
その結果、右肩上がりのグラフになり、順調に学習ができていることがわかります。そしてVirtual Raceに提出した結果、15.617秒(312位)でした。
分析した結果、練習コースと本番コースでコースが違う部分でコースアウトしており、過学習の可能性がありました。
過学習の抑制
そこで、以下のLondon Loopで2時間、報酬関数2を用いて過学習の抑制をしました。
そしてその結果、右肩上がりのグラフになりこちらも順調に学習できていることがわかります。
そして分析した結果、過学習によるコースアウトは減少したため、完走率は右肩上がりのグラフになったのではないかと考えられます。
そのため、練習用のレースコースと本番用のレースコースでのログの分析を行い、過学習が生じているときは別のコースで学習をすることが効果的であるということもわかりました。
新たなモデルの作成
上記の結果を踏まえて、新たなモデルを作成しました。
まず、以下の報酬関数3を用いて計16時間(8時間→6時間→2時間)学習しました。
def reward_function(params): #トラックの幅 float track_width = params['track_width'] #トラック幅の半分 float half_track_width = track_width * 0.5 #車体がトラックの真ん中からどれだけ離れているか float distance_from_center = params['distance_from_center'] #コースの完走率(0~100) float progress = params["progress"] #ステップ数 int steps = params["steps"] #スピード float speed = params["speed"] #最高速度 max_speed = 10.0 #車体のホイールが全てトラック上にある時,(かつ,stepsとhalf_track_widthが0より大きい時) if params["all_wheels_on_track"] and steps > 0 and half_track_width > 0: #車体がトラックの真ん中に近ければ近いほど良い reward = (half_track_width - distance_from_center) / half_track_width #早いステップでコースを走るほど良い reward += progress / steps #スピードが早いほど良い reward += speed / max_speed reward = reward / 3.0 if speed > 6.0: reward = reward * 5.0 else: reward = 1e-3 return float(reward)
アクションスペースとハイパーパラメータは以下のように設定しました。 その結果、学習は右肩上がりに学習は進んでおり、Virtual Raceに提出した結果、10秒台後半で80位台を記録しました。
分析した結果、基本的なコース取りはよさそうな一方で、関数の狙い通り、6m/sで走っていることがわかりました。
そこで、さらに報酬関数3で4時間学習し、以下の報酬関数4で4時間学習しました。この報酬関数4では、スタート付近とステアリングを切っていない時は10m/sで走れるように設定しました。
def reward_function(params): #トラックの幅 float track_width = params['track_width'] #トラック幅の半分 float half_track_width = track_width * 0.5 #車体がトラックの真ん中からどれだけ離れているか float distance_from_center = params['distance_from_center'] #コースの完走率(0~100) float progress = params["progress"] #ステップ数 int steps = params["steps"] #スピード float speed = params["speed"] #ステアリング角度 steering = abs(params['steering_angle']) #最高速度 max_speed = 10.0 #車体のホイールが全てトラック上にある時,(かつ,stepsとhalf_track_widthが0より大きい時) if params["all_wheels_on_track"] and steps > 0 and half_track_width > 0: #車体がトラックの真ん中に近ければ近いほど良い reward = (half_track_width - distance_from_center) / half_track_width #早いステップでコースを走るほど良い reward += progress / steps #スピードが早いほど良い reward += speed / max_speed reward = reward / 3.0 if speed > 6.0: reward = reward * 5.0 if steering <= 10.0 and speed > 7.0: reward = reward * 5.0 if progress < 10.0 and speed > 7.0: reward = reward * 5.0 else: reward = 1e-3 return float(reward)
その結果、報酬関数の値は右肩上がりに上がっており、Virtual Raceに参加した結果、10.573秒(77位/1362チーム)でした。
52位を獲得したモデル
ここまでの結果を踏まえて、報酬関数4のmax_speed
を10.5にした報酬関数5を作成し、20時間(4時間+8時間+4時間+4時間)学習しました。
そのときのアクションスペースとハイパーパラメータは以下のように設定しました。
そしてVirtual Raceに参加させた結果、10秒前半で60位後半の結果になりました。
そして、さらに最大速度を10.5m/sにして、以下のような報酬関数6で4時間学習しました。
def reward_function(params): #トラックの幅 float track_width = params['track_width'] #トラック幅の半分 float half_track_width = track_width * 0.5 #車体がトラックの真ん中からどれだけ離れているか float distance_from_center = params['distance_from_center'] #コースの完走率(0~100) float progress = params["progress"] #ステップ数 int steps = params["steps"] #スピード float speed = params["speed"] #最高速度 max_speed = 10.5 #車体のホイールが全てトラック上にある時,(かつ,stepsとhalf_track_widthが0より大きい時) if params["all_wheels_on_track"] and steps > 0 and half_track_width > 0: #車体がトラックの真ん中に近ければ近いほど良い reward = (half_track_width - distance_from_center) / half_track_width #早いステップでコースを走るほど良い reward += progress / steps #スピードが早いほど良い reward += speed / max_speed reward = reward / 3.0 if speed > 8.0: reward = reward * 5.0 else: reward = 1e-3 return float(reward)
その結果、グラフは以下のようになり、報酬関数はこれ以上伸びそうにもなかったため、Virtual Raceに再度参加させたところ、9.602秒を記録し、49位(提出時の順位、最終的には52位)を記録しました。
そこで、分析をしたところ、最大速度10.5m/sを出せているところは多くなかったです。
そのため、以下2つの方針を考えました。
- 方針1:最大速度をより高く設定して、平均速度を上げる
最大速度をより高く設定することで、平均速度自体を上げることでタイムを短くする方針。一方でカーブを曲がり切れない可能性もある。 - 方針2:最大速度を少し低く設定して、カーブを早く曲がりきる
最大速度をこのモデルでの平均速度(約7m/s程度)まで下げて、アクションスペースでの速度を3.5, 7.0, 10.5の3段階から2.33, 4.66, 7.00の3段階にして、4.66m/sの速度でカーブを曲がるようにする方針。
しかし、方針1、方針2ともに試したところ、方針1では、スピンやコースアウトが多発、すなわち危惧どおりカーブがうまく曲がれないということが生じ、方針2では、4.66m/sで曲がることはできず、むしろ平均速度を落としてしまい、うまくいきませんでした。
また、この52位のコース取りを分析すると、以下のようなコース取りをしており、中心線に沿って走るというよりもコースから出ないように走るような結果になっていました。(報酬関数でもそのように報酬を与えるようにはなっていますが)
一方で、ほかのより良いタイムを出しているモデルのログ分析などを見ると、中心線に沿って走るようにコース取りをしていました。
そのため、より中心線に近く、かつスピードが出るような報酬関数を組んだ方がもしかするとより速いタイムを出せるのかもしれません。
まとめ
目標とする月間1位には届きませんでしたが、今回の2019年10月のVirtual Raceの我々のチームのベストタイムは9.602秒で、最終順位は全体52位(全1983チーム)でした。しかし、月間1位は7.172秒で約2.5秒ほど差があり、もう少しうまいモデルを作る必要があると感じました。