この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
Amazon SageMaker(以下、SageMaker)の組み込みアルゴリズムでは、トレーニング、評価、および検証メトリクスを自動で計算して発行しています。
そして、トレーニングの結果は、コンソールからグラフとして確認することもできます。
しかし、この機能は、トレーニングジョブ単位のため、増分学習などで、複数回に分けたジョブを俯瞰することは出来ません。また、グラフは時系列であり、epoch回数との関連を見ることは難しいと思います。
今回は、CloudWatch Logsから学習の進行の目安となる行を抜き出し、複数に分けたジョブも俯瞰できるようにしてみました。
2 CloudWatch Logs
SageMakerによるトレーニングのログでは、Epochごとに、cross_entropy (loass)、smooth_l1(loss) 及び、mAPの(score)の値がメトリックスとして出力されています。
ここで、cross_entropyの減少などは、モデルが十分に学習されているかどうかの目安になります。
以下は、CloudWatch Logsから"epoch="という文字列でフィルタした出力例です。
epoch=0, batch=113 train cross_entropy <loss>=(1.4180332298993061)
epoch=0, batch=113 train smooth_l1 <loss>=(0.6312907669714584)
epoch=0, validation mAP <score>=(0.06950676633142766)
epoch=1, batch=113 train cross_entropy <loss>=(1.1537240667553887)
epoch=1, batch=113 train smooth_l1 <loss>=(0.5577520465688716)
epoch=1, validation mAP <score>=(0.5435744797706069)
epoch=2, batch=113 train cross_entropy <loss>=(0.882764700426082)
epoch=2, batch=113 train smooth_l1 <loss>=(0.4858317924157635)
epoch=2, validation mAP <score>=(0.7965334703107155)
epoch=3, batch=113 train cross_entropy <loss>=(0.7305765847092396)
epoch=3, batch=113 train smooth_l1 <loss>=(0.3920442789711215)
epoch=3, validation mAP <score>=(0.9287345323256168)
epoch=4, batch=113 train cross_entropy <loss>=(0.6735127696786309)
epoch=4, batch=113 train smooth_l1 <loss>=(0.32503517851902314)
epoch=4, validation mAP <score>=(0.983961968966895)
epoch=5, batch=113 train cross_entropy <loss>=(0.6005626925608006)
epoch=5, batch=113 train smooth_l1 <loss>=(0.2669418989158258)
epoch=5, validation mAP <score>=(0.9913976509103337)
3 集計
上記のログを対象に、cross_entropy、smooth_l1及び、mAPの数値を抜き出して、一覧にするコードです。 ジョブ名は、配列で指定するようになっており、複数回に分けてトレーニングしたログも纏めて処理できます。
from boto3.session import Session
import re
# Job名(複数指定可能)
jobs = ['object-detection-2020-04-24-23-53-37-140/algo-1-1587772559']
session = Session(profile_name='developer')
client = session.client('logs')
group_name = '/aws/sagemaker/TrainingJobs'
# "epoch="が含まれるログ抽出する
filter_pattern = 'epoch='
response = client.filter_log_events(
logGroupName=group_name,
logStreamNames=jobs,
limit=300,
filterPattern=filter_pattern,
)
# cross_entropy, smooth_l1, mAPにそれぞれ振り分ける
cross_entropy = []
smooth_l1 = []
mAP = []
for event in response["events"]:
message = event["message"]
print(message) # debug
# ()の中を抜き出す
m = re.search(r'\(.*\)', message)
num = m.group().replace('(','').replace(')','')
# 視認しやすいように、少数第三位で丸める
num = round(float(num), 3)
if('cross_entropy' in message):
cross_entropy.append(num)
elif('smooth_l1' in message):
smooth_l1.append(num)
elif('mAP' in message):
mAP.append(num)
# 表示
print("epoch\tmAP\tsmooth_l1\tcross_entropy")
print("-----------------------------------------")
for i in range(len(mAP)):
print("{}\t{}\t{}\t{}".format(i, mAP[i], smooth_l1[i], cross_entropy[i]))
出力結果です。なお、ここで表示されているEpochは、ログが抽出したものではなく、単純に0からの連番になっているため、ストリームを複数指定したは、増分学習のログという前提です。
epoch mAP smooth_l1 cross_entropy
-----------------------------------------
0 0.07 0.631 1.418
1 0.544 0.558 1.154
2 0.797 0.486 0.883
3 0.929 0.392 0.731
4 0.984 0.325 0.674
5 0.991 0.267 0.601
6 0.991 0.239 0.547
7 0.991 0.214 0.502
8 0.992 0.198 0.465
9 0.992 0.177 0.449
10 0.994 0.159 0.419
4 最後に
今回は、複数に分けて行ったトレーニングの状況をEpochと共に俯瞰してみました。次回は、HPO(ハイパーパラメータ最適化)アルゴリズムで学習が進行する状況を、この一覧で確認してみたいと考えています。