概要
みなさんが機械学習を用いてデータ分析を行う時,一番面倒なことといえば何でしょうか?おそらく多くの人が上げることは__実験管理__じゃないでしょうか。
学習データを用意して,モデルのパラメータを決めて,学習を行って,バリデーションデータに適用して,テストデータで予測を行って,またパラメータを作成して...と言う流れの中で,それぞれ__パラメータやモデル毎の結果をまとめるのはすごく面倒__です。
実験管理に使えるツールといえば,Comet MLやTensorboardが有名ですが,クラウド環境で学習することの多い昨今の現状と,膨大な結果ファイルが絡むことを考えると,出来ればS3やBlobといったクラウドストレージと連携させたいところです。
今回紹介するのは,Azureの機械学習サービスの一つであるAzure Machine Learning Serviceです。DLを含む機械学習といえばGCPとAWSのイメージでしたが,__このサービスがあるだけでAzureを選択肢に入れる__のもアリだと個人的に思いました。筆者は実際にKaggleなどのコンペで活用してます。
注:筆者はクラウドサービスの専門家ではないので,AWSやGCPについて詳しくないです。実験管理ツールががあればぜひ教えてください!
Azure Machine Learning Serviceとは?
簡単にいうと,Azure上で機械学習を簡易に行うためのサービス,コンポーネントの総称です。公式の概要はこちら。
DBによるデータの保管や,GPUインスタンスやJupyter notebookインスタンスによるデータ分析, Azure Container InstancesやAzure Kubernetes Serviceへの機械学習モデルのデプロイを一続きに行うために様々なコンポーネントが用意されています。
デプロイや学習インスタンスも興味深いのですが,今回はその中のAzure Machine Learning Service Workspace(以下,ML Workspace)に絞って,さらにその中の__実験管理__を紹介させていただきます。
どんなことができるの?
実際の画面だとこんな感じになります。
- Experimentsの画面
- 学習の実行であるRunのサマリーが保存されます。
- 実行Statusやハイパーパラメータ,結果の情報を一覧できます。
- Runの画面
- Experiment画面のRun番号のリンクを踏むことでいけます。
- 実行した学習のLossの変化やハイパーパラメータの詳細が保存されます。
ML Workspaceの概念としては以下の二つです。
- 毎回の学習の実行結果を示す__Run__
- そのRunを管理する__Experiments__
Experimentを呼び出す度にRunが生成されるので,Experimentsの中にRunが沢山あるという階層構造となっています。具体的にはpythonコード上で__同じExperiments名からRunを呼び出してロギングする度にそのExperimentsのRunが増加__します。
Runでは__学習に利用したログやファイルを基本何でも記録することができます。__例えば学習ロスやバリデーションロスなどの変化,設定したハイパーパラメータ,学習済みモデルや推論結果のCSVなどを記録できます。
(2019/4/25)追記
上記に加えて,なんと実行ディレクトリ配下にあるファイルを全てsnapshotとして自動でAzure上にアップロードするようになりました。これにより実行時の設定やコードの状態も全て保存されるため,再現性という点では非常に優れたものとなりました。
具体的には後に示すrun
を生成するrun = exp.start_logging()
を実行すると,自動的にsnapshotがアップロードされます。
ML Workspaceの始め方
ML Workspaceの画面が伝わったところで,実際に初めてみましょう。
といっても,Azureのチュートリアルはかなり詳しく書かれているので,Azure PortalからML Workspaceを作成して,Azure notebookから使うまでところはこちらのチュートリアルとPythonのチュートリアルに譲ります。
もちろんチュートリアルではsklearnの例しかなく,味気ないので,今回はローカルPC上に立てたJupyter labでkerasでMNISTを回した時のコードを紹介します。このコードでは以下をML workspaceに記録/保存します。
- 学習ロスとバリデーションロスのグラフ
- 探索パラメータ
- 学習済みモデル
コード自体は全然難しくないです!基本的には結果をprint()
するくらいの気持ちで書けてしまいます。
下準備
Azureポータル上
上記のチュートリアルの通りにとりあえずML Workspaceを立ち上げておきましょう。それ以外は特にいりません。
ローカルPC上
とりあえずローカルPCのコンソールからazure-sdkを入れましょう。ついでにJupyter labも立ち上げ。
$ pip install azureml-sdk[notebooks]
$ jupyter lab
コード
以下のコードはJupyter lab上のセルの上で実行していきます。
クラウド環境との接続
import azureml
ポータル上のML workspaceとローカルPCの接続はjsonの設定ファイルからなります。具体的には./aml_config/config.json
に下記の場所に書いてある赤い部分の情報を書くことになります。
! mkdir ./aml_config # ディレクトリの作成
%%writefile ./aml_config/config.json
# 赤い部分の情報を書く
{
"subscription_id": "XXXXX-XXXXXX-XXXXX-XXXXX",
"resource_group": "<リソースグループ>",
"workspace_name": "<ワークスペースの名前>"
}
# ファイルへの書き込み
from azureml.core import Workspace
ws = Workspace.from_config() # Azureとの接続
ここでAzureの認証がブラウザで開きますので,自分のアカウントを入れて認証しましょう。それで接続は終わりです。
実行結果のロギング(お試し)
実際に何かの計算の実行結果をML workspace上に上げて見ましょう。今回はチュートリアルにもあるフィボナッチ数を投げて見ます。
from azureml.core import Experiment
# Experimentの作成
# この時点でworkspace上のExperimentsにmyexpの項目ができる
exp = Experiment(workspace=ws, name='myexp')
# Runを作成,実行
# この時点でworkspace上のExperiments->myexp内にrun:1の項目ができる
# 追記: さらに実行ディレクトリ配下の全てのファイルがAzure上にアップロードされます。
run = exp.start_logging()
# Runにログを上げてみる
# これによりmyexp->run:1内のTracked Metricsに'my magic number': 42が付与される
run.log('my magic number', 42)
# listをあげる (Fibonacci numbers)
# グラフとなって表示される
run.log_list('my list', [1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
# 同じkeyのログを複数回上げてもグラフとなって表示される
run.log('next magic number', 42)
run.log('next magic number', 43)
# finish the run
# statusがcompleteとなる
run.complete()
これの結果は以下のようになります。Azure PortalよりAzure ML workspaceからExperiment -> myexp -> 最新のRun番号とリンクを辿って見てください。
見ての通り,リストや同じkey名で複数回上げたものはそのままグラフ化され,一度だけ上げたものはTracked Metricに格納されました。
これを見るだけで,「お,ハイパーパラメータをTrack Metricとして上げてLossはグラフとしてあげれば良さそう」というのが浮かんできますよね。
ちなみにこのコードを走らせる度にRun番号が増えて,それぞれ結果が表示されます。
実行結果のロギングとついでにモデルのアップロード(MNIST)
kerasでMNISTを学習したLossの結果を上げつつ,ついでにモデルをアップロードしたいと思います。
from keras.datasets import mnist
import keras
from keras.callbacks import ModelCheckpoint
# データ準備
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
# ラベルをバイナリ化
num_classes = 10
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
# ハイパーパラメータ定義
batch_size = 128
epochs = 10
lr = 0.01
optname = 'adam'
# モデル定義
model = Sequential()
model.add(Dense(128, activation='relu', input_shape=(784,)))
model.add(Dense(64, activation='relu'))
model.add(Dense(10, activation='softmax'))
# Optimizerを取り出す関数
def choice_opt(opt, lr):
if opt == 'sgd':
return keras.optimizers.SGD(lr=lr)
if opt == 'adam':
return keras.optimizers.Adam(lr=lr)
else:
raise ValueError()
# コンパイル
opt = choice_opt(optname, lr)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['acc'])
# 学習の実行
# 最も良いモデルを`./best_model.h5`として保存
history = model.fit(
x_train, y_train, validation_data=(x_test, y_test), epochs=epochs, batch_size=batch_size,
callbacks=[ModelCheckpoint('./best_model.h5', monitor='val_loss', save_best_only=True)])
ここまでは普通の実行です。ここからML Workspace上に記録して行きます。
# Experimentsの定義
exp = Experiment(workspace=ws, name='my_mnistexp')
# Runの作成
run = exp.start_logging()
# historyの中身=Lossのリストを記録
for k, v in history.history.items():
run.log_list(k, v)
# ハイパーパラメータの記録
run.log('epochs', epochs)
run.log('batch_size', batch_size)
run.log('opt', optname)
run.log('lr', lr)
# モデルファイルのアップロード
# name: Azure上の保管場所, path_or_stream: ローカルのファイルパス
run.upload_file(name='outputs/bast_model.h5', path_or_stream = './best_model.h5')
# StatusをCompleteにする
run.complete()
この状態でML WorkspaceのRunに上がった内容を見てみましょう。(と言っても上の例でネタバレしてますが。)
Experiments -> my_mnistexp -> 最新のRunを進んでみます。
見ての通り,run.log
で記録したものが一通り上がってます。さらに,上部のOutputタブを見てみると...
ちゃんとモデルも保存されてますね!
ここを使えばモデルだけでなく,実験結果のcsvや極端に言えば実行したデータ,ipynbファイルなんかもまとめて上げられちゃいます。
ハイパーパラメータ探索を行うOptunaなどと組み合わせれば捗ること間違いなしです!
追記
さらに,snapshotを見てみると,実行ディレクトリ配下のファイルが全てアップロードされているのも確認できます。このアップロードは実行の度に行われるため,実行時の状況を完全に再現することが可能になります。また,まとめてダウンロードしたり,実行時のコードをブラウザ上からプレビューすることも可能です。(プレビューは.pyファイルのみ)
Tips
runのStatusを変化させたい
run.fail()
を呼び出せばStatus Failedとなって終了します。例えば,実行をtry内として,except内で左記fail()を呼ぶと良さげです。
リアルタイムにロスを記録したい
kerasならば専用のcallbackを書いてしまえば良いです。具体的にはepochが終わるたびにrun.log('val_loss', val_loss)
などを呼び出せば良いです。
例えばこんな感じですかね?(筆者はmxnetをよく使うのでkerasは詳しくないです。)
class AzureCallback(keras.callbacks.Callback):
def __init__(self, run):
super().__init__()
self.run = run
def on_epoch_end(self, epoch, logs=None):
# epoch終了時にrun.logで記録
logs = logs or {}
train_loss = logs.get('loss')
val_loss = logs.get('val_loss')
val_acc = logs.get('val_acc')
self.run.log('loss', train_loss)
self.run.log('val_loss', val_loss)
self.run.log('val_acc', val_acc)
Experiment表示画面で,全てのRunから一番良い値を見たい
Experiments -> Add chartから見たいメトリックを表示できます。
Runにメタデータを付与したい
そのRunでどんなネットワークを使ったかなどは何百とRunを行うと忘れがちなのでメタデータを付与したくなります。そんな場合はrun.tag
を利用すると良いです。
まとめ
今回はAzure Machine Learning Service Workspaceを紹介させていただきました。まとめると出来ることは以下になります。
- 学習のパラメータ,結果,ファイルに至るまでをGUIで管理できる
- 実行に対してファイルが紐づくのでのモデルファイルや実行結果の管理が簡単
- SDKの使い方が比較的簡単
今回実行したipynbファイルはこちらに置いてますので,使って見てください!