BLOG

R3 Cloud Journey

Hack & Tips

DeepRacer敗戦記

2019-08-29

ちょっと、ダメージがデカすぎて遅れましたが、DeepRacerに挑戦してみたので、今更ながら顛末記などを。。

そもそもどんなの?

詳しくはこちらをみていただくとして、簡単にいうと機械学習をお手軽に試せるサービスです。

AWS DeepRacer(機械学習で運転する 1/18 スケールのクルマ型デバイス)| AWS
_AWS DeepRacer は、文字どおり機械学習を自由自在に操る最速の手段です。強化学習により駆動する 1/18 スケールの完全自走型レーシングカー、3D レーシングシミュレーター、そしてレースの世界大会をご用意しています。…_aws.amazon.com

一昨年だと、DeepLensなんてのがありましたが、あれを試してみても画像識別が出来るくらいなので、いまいち盛り上がりませんでした。

これは、re:Invent2017でのDeepLensのワークショップで触っている様子。この時は盛り上がってたんですが、使い道が限定されるという問題が。。

ホットドッグが判別出来ても使い道ない(笑

で、去年の re:Invent2018ではDeepRacerのワークショップがあって、これも盛り上がりましたー。

まぁ、MGMのレース会場もかなり熱かったですね。早くなりそうなモデルを選んで30秒で6位に入ったとか、今考えるとなんと甘い状況だったのかと(苦笑

簡単な仕組み

ユーザー側では、「報酬関数」というものの中身を作成して、車が早くゴールできるようにします。

サンプルも最初から用意されてて、以下のソースはコースの真ん中を走るようにするというものです。ざっくり言うと、道路の真ん中に近ければ報酬が高く、端に行くと低くなります。

def reward_function(params):
‘’’
Example of rewarding the agent to follow center line
‘’’

Read input parameters

track_width = params[‘track_width’]
distance_from_center = params[‘distance_from_center’]

Calculate 3 markers that are at varying distances away from the center line

marker_1 = 0.1 * track_width
marker_2 = 0.25 * track_width
marker_3 = 0.5 * track_width

Give higher reward if the car is closer to center line and vice versa

if distance_from_center <= marker_1:
reward = 1.0
elif distance_from_center <= marker_2:
reward = 0.5
elif distance_from_center <= marker_3:
reward = 0.1
else:
reward = 1e-3 # likely crashed/ close to off track

return float(reward)

ここで使われている params の中に各種パラメータが入っているので、これをどう使うか(どう計算するか)と言うのがポイントになります。

なお、どのような内容なのかはこちらを参照してください。

AWS DeepRacer 報酬関数の入力パラメータ
_AWS DeepRacer 報酬関数は辞書オブジェクトを入力として取ります。 params 辞書オブジェクトには、次のキーと値のペアが含まれています。 { "all_wheels_on_track": Boolean, # flag to…_docs.aws.amazon.com

あと重要なのは、ステアリングの角度と何段階にするか、そして最大スピードと何段階にするかという4つの設定です。

全てを最大にしたくはなりますが、やってみたところスピード以外は中央値を選んだ方が結果が出やすい感じです。

色々と試してみた

まずは分かっていることを整理してみました。

・MGMで実際のコースを試した感じでは、スピードは4.7程度までにしないと処理が追いつかずコースアウトしがちだった

・報酬関数内にログ出力を追加するとparamsの中身を確認できる(waypointsを出力してexcelでプロットするとこんな感じ)

なので、先読みというか早めにハンドル操作をしてみるという方向で検討してみました。
車が今いる場所から一番近いwaypoint間の角度を計算して、今の車の向きとズレてたらペナルティという方法です。

# トラック上のwaypointと直近のwaypoint、およびコース上の基準軸に対する車体の向きをparamsから取得

waypoints = params['waypoints']
closest_waypoints = params['closest_waypoints']
heading = params['heading']

# 現在の位置から最も近い次のwaypointと前のwaypointを取得する
next_point = waypoints[closest_waypoints[1]]
prev_point = waypoints[closest_waypoints[0]]

# 前のwaypointから次のwaypointに向かう角度(radian)を計算する
track_direction = math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0])

# degreeに変換
track_direction = math.degrees(track_direction)

# コース上の基準軸に対する車体の向きと直近のwaypointを繋ぐ向きの差分を取るdirection_diff = abs(track_direction - heading)

# 算出した方向の差分から車体の向きが大きくズレている場合にペナルティを与える
# 閾値の設定はコースの種類によって調整が必要
DIRECTION_THRESHOLD1 = 10.0
DIRECTION_THRESHOLD2 = 20.0

if direction_diff > DIRECTION_THRESHOLD2:
reward = 1e-3 # likely crashed
elif direction_diff > DIRECTION_THRESHOLD1:
reward *= 0.5

ただ、waypointsがスカスカなせいか、ロジックのせいかは不明ですが、タイムは24秒程度でした。

なかなかに厳しい。。。

DeepRacer Virtual Circuit

ここからがある意味本題ですが、なんと毎月コースが変わるバーチャルサーキットが開催されているのです。(今だと、Shanghai Sudu

毎月新コースになるので、最初の方はランキングに載ることも可能ですが、あっという間に圏外になります(笑

なお、kumoというコースだと、waypointはこんなに増えていました。

なので、青い線のようになるべくまっすぐ走ると良いかなと思って、各waypointでの向きを定義するというのも試してみました。なお、角度はexcelでゴニョゴニョして計算しています。

# トラック上のwaypointと直近のwaypoint、およびコース上の基準軸に対する車体の向きをparamsから取得

heading = params['heading']

track_base_direrction = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,48.2286,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,90.9686,127.2628,127.2628,146.1017,146.1017,146.1017,146.1017,-173.599,-173.599,-173.599,-134.2943,-134.2943,-134.2943,-134.2943,-134.2943,-134.2943,-134.2943,-86.7936,-86.7936,-86.7936,-86.7936,-86.7936,-86.7936,-86.7936,-86.7936,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-164.9729,-133.4798,-133.4798,-133.4798,-133.4798,-91.4633,-91.4633,-91.4633,-91.4633,-91.4633,-57.6956,-57.6956,-57.6956,-57.6956,-57.6956,-57.6956,-57.6956,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

# 次のwaypointの角度を配列から取得して、値があれば評価する
track_direction = track_base_direrction[closest_waypoints[1]]

# コース上の基準軸に対する車体の向きと直近のwaypointの向きの差分を取る
if track_direction < 0 and heading >= 0:
direction_diff = 180 + track_direction + heading
elif track_direction >= 0 and heading < 0:
direction_diff = track_direction + 180 + heading
else:
direction_diff = abs(track_direction - heading)

# 算出した方向の差分から車体の向きが大きくズレている場合にペナルティを与えるDIRECTION_THRESHOLD1 = 10.0
DIRECTION_THRESHOLD2 = 20.0

if direction_diff > DIRECTION_THRESHOLD2:
reward = 1e-3
elif direction_diff > DIRECTION_THRESHOLD1:
reward *= 0.1

ただ、上のカーブを超えたところからうまくいかずコースアウトしてたのでダメでした。なお、このwaypointsで諸々指定は、その後、全くダメというのが判明します(後述)

ここで、料金が半端なくかかってた事に気づいたので、一旦終了です。

お金かかった割には、全然ダメですな。。

Empire City Circuit

翌月、新しいコースが始まったので、方針を変えてみました。

・前の方法は「山ほどのif文」だったのでは?
・「こんな風に走る」を覚えさせよう
・同じ報酬関数じゃなく、段階に応じて内容を変えよう

という事で、まずは、道の真ん中を走るサンプルを使って、確実にゴールするようにしてみます。

ステアリング30度で7段階、最大速度が8m/sで3段階で、8時間を2回学習
empirer-center1–30d-7g-8m-3s-A-8H-8H
00:00:22.679

さらに、コースの半分以内を高速に走っているほど報酬が高いようにしたものに差し替えて追加で学習させます。

ステアリング30度で7段階、最大速度が8m/sで3段階で、8時間を2回学習の後に、コースの半分以内にいればスピードを返すのに差し替え
empirer-center1–30d-7g-8m-3s-A-8H-8H-B-8H
00:00:20.046

マジか。。。前回のコースであんなに時間とお金をかけたよりも、こんなにシンプルな方が良かったのか。。

でも、この段階で$300超えてたので、ここでも断念です。。高い、、、高いよ機械学習って。。

でも、コースの締め切り間際に新たな技が判明します。なんと、1秒台です。

どうやら、コースを逆走してからゴールラインを通過するとクリアになるようです(爆笑

自作レースゲームとかで、よくあるバグですね。私も、ゲーム攻略記事を書くときによく試しましたが、まさか、この時代にそんなのがあるとは。。(流石に、レギュレーション違反として今は消されてます)

そういえば、waypointsの話ですが、なんと、学習用と本番用のコースが違うというオチがあるそうで。。使えない。。。そんなのありかー。絶対わざとだ(苦笑

DeepRacerの走行ログをTableauで分析してみた #AWSDeepRacer #AWSDeepRacerJP | DevelopersIO
_せーのでございます。 クラメソでは今一部の社員でDeepRacerがブームです。 DeepRacerって何?という方はこちらをご覧ください。 【DeepRacer】ワークショップに参加してきたので初心者なりに色々いじってみる…_dev.classmethod.jp

なお、費用の話として、余計なのも入ってますが、合計コストは見ての通りです。なお、DeepRacerの分だけでも$1000超えてます・・・
途中、NATインスタンスで余計な費用かかったり(あとで値引きは発生しましたが)、ワークショップの$100クーポンが利用出来たりとか、料金に関してはなかなかにドラマティックなものがありました。

商品とか賞金とかに釣られてうっかり始めて、更にはランキング競争にハマってましたが、高い勉強代でした。(苦笑

まさに、“このたびは強者(つわもの)どもが賞品(ゆめ)のあと始末…”

R3の
ご提供サービス
自社のシステム開発・移行などをご依頼したい方
お客様とともに
作りながら考える
新しいシステム開発
kintone導入・アプリ開発・カスタマイズにお困りの方
kintoneをもっと
使いやすくする
gusukuシリーズ

サイボウズ公認kintoneエバンジェリスト Customineでも色々とやってます

R3のご提供サービス
自社のシステム開発・移行などをご依頼したい方
お客様とともに作りながら考える
新しいシステム開発
kintone導入・アプリ開発・カスタマイズにお困りの方
kintoneをもっと使いやすくする
gusukuシリーズ