DeepRacerの走行ログを Matplotlibで可視化する #AWSDeepRacer #AWSDeepRacerJP
はじめに
コンサルティング部の川原です。
DeepRacer 楽しいですよね。 知らず知らずのうちに機械学習の各種用語にふれることができるので、 入門としてもってこいだなと思ってます。
そして今月から私も DeepRacer リーグ の 仮想サーキットに参戦しています。 ※DeepRacerリーグの 仮想サーキットの概要・参加方法は以下を参照ください。
こちらの仮想サーキット、
モデルの評価 (submit) は 30分に1回可能です。
1 submitで、サーキット上での走行が 5回試行され、
1回も完走できなかった場合は Unable to finish 1 lap.
と結果が返され、
1回以上完走できた場合は、その中の最速タイムが リーダーボードに提出されます。
↓2019/07/21 14:00 時点リーダーボード (私は11位!)
5回の走行ログは CloudWatchのロググループ /aws/deepracer/leaderboard/SimulationJobs
に格納されます。
この走行ログを分析・可視化していきます。 今回はお勉強も兼ねて、データ分析・可視化でよく使用される Pythonの Pandasライブラリ、 Matplotlibライブラリ を使っていきます。
※Tableau を使ったより詳細な分析記事はこちら。
実行環境
- OS version: macOS Mojave, version 10.14.5
- Python version: 3.7.3
- pandas version: 0.24.2
- matplotlib version: 3.1.1
準備: 走行ログを取得
準備としてCloudWatch Logs Insights で走行ログのCSVをダウンロードします。
▼ 仮想サーキットのページの Latest model submitted
から Evaluation Logs を選択
▼ sim-
から始まる番号をメモ
▼ インサイト を選択
インサイトのページでロググループを /aws/deepracer/leaderboard/SimulationJobs
を選択します。
下記クエリを記載し クエリを実行 します。※ sim-xxx
には先程メモしていた番号を入れます。
filter @logStream like /^sim-xxx/ | fields @message | filter @message like /^SIM_TRACE_LOG/ | parse @message "SIM_TRACE_LOG:*,*,*,*,*,*,*,*,*,*,*,*,*,*,*" as episodes,steps,x,y,heading,steering,speed,action_taken,reward,done,all_wheels_on_track,current_progress,closest_waypoint_index,track_length,time | sort by time
下に表示されているクエリ結果を確認して アクション → クエリ結果をダウンロード (CSV)
を選択します。
logs-insights-results.csv という名前でCSVがダウンロードされます。 次章でこの走行ログCSVを分析・可視化していきます。
分析・可視化
以下、Pythonです。 19秒台で完走したときのログを分析してみます。
ライブラリインポート、CSVの読み込み
matplotlib, pandas ライブラリをインポートして、 次にダウンロードしたCSVを pandas.Dataframe オブジェクトとして読み込みます。
import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('./logs-insights-results.csv')
CloudWatch Logs Insights で取得したCSVの列構成を表示してみます。
>>> for c in list(df.columns): print(c) ... @message episodes steps x y heading steering speed action_taken reward done all_wheels_on_track current_progress closest_waypoint_index track_length time
以降では、 episodes, x, y, steering, speed
あたりを使っていきます。
軌跡の可視化
x
, y
列を使って 走行の軌跡を表示してみます。
plt.scatter(df.x, df.y, marker='o', alpha=0.3) plt.show()
▼(参考) 仮想サーキット: Empire City Circuit
中盤・後半にかけてジグザグ走行や、 曲がりすぎ・曲がりきれずのコースアウトが確認できますね。
速度も可視化
次は speed
列の情報も含めます。
速度ごとにプロットする点の色を変化させます。
from matplotlib import cm plt.scatter(df.x, df.y, marker='o', alpha=0.3, c=df.speed, cmap=cm.rainbow) plt.colorbar() plt.show()
直線を低速で走っていることが多い一方で、終盤のコーナーは高速で曲がることができています。 全体的に低速が多く、更に改善の余地があることが分かりました。
ステアリング角度も可視化
軌跡可視化の時点で、ある程度ステアリングの傾向はつかめますが 念の為
steering
列の情報も含めてみます。
ステアリング角度の大きさ毎にプロットする点の種類を変化させます。
今回のログの場合、ステアリング角度大きさは 0度(0 rad), 12.5度(0.22 rad), 25度(0.44 rad) の三種類です。
( df.steering.abs().unique()
などで確認できます)
from matplotlib import cm speed_min=df.speed.min() speed_max=df.speed.max() # ステアリング角度の大きさによってマーカー種類を変える # - 0.0度(0.00 rad)のときは "○" # - 12.5度(0.22 rad)のときは "△" # - 25.0度(0.44 rad)のときは "× df_st0 = df[df['steering'] == 0.0] df_st1 = df[df['steering'].abs() == 0.22] df_st2 = df[df['steering'].abs() == 0.44] plt.scatter(df_st0.x, df_st0.y, marker='$○$', alpha=0.3, c=df_st0.speed, cmap=cm.rainbow, vmin=speed_min, vmax=speed_max) plt.scatter(df_st1.x, df_st1.y, marker='$△$', alpha=0.3, c=df_st1.speed, cmap=cm.rainbow, vmin=speed_min, vmax=speed_max) plt.scatter(df_st2.x, df_st2.y, marker='$×$', alpha=0.3, c=df_st2.speed, cmap=cm.rainbow, vmin=speed_min, vmax=speed_max) plt.colorbar() plt.show()
直線で高速かつステアリング0度 ( 赤色 "○" プロット) のパターンを多くする必要があることが分かりますね。
おわりに
Pandas, Matplotlib を使ったDeepRacer走行ログの可視化でした。 Pandas はデータのフィルタリング機能や関数の豊富さなど、 使っていてとても便利だなと感じました。
以下に ライブラリインポート〜可視化までのサンプルスクリプトを載せます。 今までの可視化に加え、 5回の走行それぞれの Time, Progress, Estimated goal time もついでに記載します。
import matplotlib.pyplot as plt import pandas as pd from matplotlib import cm df = pd.read_csv('./logs-insights-results.csv') speed_min=df.speed.min() speed_max=df.speed.max() plt.figure(figsize=(9.0, 5.0)) # ステアリング角度の大きさによってマーカー種類を変える # - 0.0度(0.00 rad)のときは "○" # - 12.5度(0.22 rad)のときは "△" # - 25.0度(0.44 rad)のときは "× df_st0 = df[df['steering'] == 0.0] df_st1 = df[df['steering'].abs() == 0.22] df_st2 = df[df['steering'].abs() == 0.44] plt.scatter(df_st0.x, df_st0.y, marker='$○$', alpha=0.3, c=df_st0.speed, cmap=cm.rainbow, vmin=speed_min, vmax=speed_max) plt.scatter(df_st1.x, df_st1.y, marker='$△$', alpha=0.3, c=df_st1.speed, cmap=cm.rainbow, vmin=speed_min, vmax=speed_max) plt.scatter(df_st2.x, df_st2.y, marker='$×$', alpha=0.3, c=df_st2.speed, cmap=cm.rainbow, vmin=speed_min, vmax=speed_max) plt.colorbar() # 5回の走行それぞれの Time, Progress, Estimated goal time を記載する for i in range(0,5): time_start = df[df['episodes'] == i].time.min() time_end = df[df['episodes'] == i].time.max() time = time_end - time_start progress = df[df['episodes'] == i].current_progress.max() estimated_time = time * 100.0 / progress text = '#%d. Time:%1.2f Progress:%1.2f, Estimated time:%1.2f' %(i, time, progress, estimated_time) plt.text(0.5, 3.0 - 0.3*i, text, fontsize=9) plt.show()
※最初の試行 (#0...
)の走行時間はログから正しく取得できませんでした・・・
参考
- pandas-docs: pandas.readcsv
- pandas-docs: pandas.unique
- pandas-docs: pandas.DataFrame
- pandas-docs: pandas.DataFrame.abs
- pandas-docs: pandas.DataFrame.iterrows
- matplotlib: matplotlib.pyplot.scatter
- matplotlib: #module-matplotlib.markers
- matplotlib: matplotlib.pyplot.text
- matplotlib: matplotlib.pyplot.figure
- matplotlib: matplotlib.pyplot.colorbar
- matplotlib: colormaps