Comet.mlを使ってJupyter NotebookなどのPythonの学習を記録・レポートする方法についてまとめます。
[7/18 追記]
本投稿では、稼働環境としてGoogle Colaboratoryを使ってます。環境によってデフォルトで送られるデータに差がありますので、注意が必要です。
Comet.ml
Jupyter Notebookの実験結果を良い感じに・楽に記録したいケースがよくあります。
- ハイパパラメータやシステム設定などの実験条件をトラックしたい
- トレーニングの経過をビジュアライズしたい
Comet.mlはこうしたことを実現するサービスです。
- workspace配下に、複数のprojectを作成し、各プロジェクトでexperimentをトラックする、という構造になってます
- パブリックなプロジェクトであれば無料で利用できます
実装
Keras: スパムメッセージをLSTMで分類する - け日記 の実験をComet.mlでレポートできるようにしてみましょう。
comet_mlのインストールとインポート
comet_mlのパッケージをインストールします。このパッケージをノートブック上でインポートすることで
$ pip install comet_ml
インストールしたcomet_mlパッケージをインポートするのですが、注意すべき点としてtensorflowやKerasより前にインポートする必要があります (後でインポートするとエラーになります) 。
from comet_ml import Experiment # tensorflowやKerasの前にインポートする import pandas as pd from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Input, LSTM, Dense, Embedding
実験の開始
Experimentクラス (APIはこちら) をインスタンス化すると、実験開始となります。
このExperimentクラスがキモとなります。以降はこのインスタンスを介して実験を記録していきます。APIリファレンスを見るとcomet.mlでできることが概ね把握できます。
# Experimentを作る experiment = Experiment( api_key='xxxxxx', # ワークスペースに紐づくAPIキー project_name='lstm_spam' # プロジェクト名 )
これでComet.mlのワークスペースに、指定したプロジェクト名で新規作成されます。
プロジェクト (ここではlstm-spam) を見ると、experimentsに追加されていきます。
なおAPIキーはこちらで確認できます。
モデリングと学習・推論
あとは以前の投稿と同様にデータロード、前処理、モデル生成を実装していきます。
# ハイパパラメータ hp = { 'epochs': 10, # 学習エポック数 'batch_size': 32, # 学習バッチサイズ数 'optimizer': 'adam', # 最適化アルゴリズム 'max_len': 100, # 1メッセージの最大単語数 (不足分はパディング) 'embedding_output_dim': 32, # Embedding層の出力次元数 'lstm_hidden_units': 16, # LTSM層の隠れユニット数 'lstm_activation': 'tanh', # LSTM層の活性化関数 } # データロード dataset_df = pd.read_csv('./SMSSpamCollection', sep='\t', header=None) dataset_df.rename({0: 'label', 1: 'text'}, axis=1, inplace=True) dataset_df['category'] = dataset_df.apply(lambda r: 1 if r['label'] == 'spam' else 0, axis=1) X_train, X_test, Y_train, Y_test = train_test_split( dataset_df[['text']], dataset_df[['category']], test_size=0.2, random_state=0 ) # 入力の前処理 tokenizer = Tokenizer() tokenizer.fit_on_texts(X_train['text']) x_train = tokenizer.texts_to_sequences(X_train['text']) x_test = tokenizer.texts_to_sequences(X_test['text']) x_train = pad_sequences(x_train, maxlen=hp['max_len']) x_test = pad_sequences(x_test, maxlen=hp['max_len']) # 出力の前処理 y_train = Y_train['category'].values y_test = Y_test['category'].values # モデル生成 vocabulary_size = len(tokenizer.word_index) + 1 # 学習データの語彙数+1 model = Sequential() model.add( Embedding(input_dim=vocabulary_size, output_dim=hp['embedding_output_dim']) ) model.add( LSTM(hp['lstm_hidden_units'], activation=hp['lstm_activation'], return_sequences=False) ) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer=hp['optimizer'], metrics=['accuracy'])
学習・推論では、以下のようにそれぞれtrain・testメソッドを呼び出してwith句でくくることで、結果がComet.mlにアップロードされます。
# 学習 with experiment.train(): history = model.fit( x_train, y_train, batch_size=hp['batch_size'], epochs=hp['epochs'], validation_data=(x_test, y_test) ) # 推論 with experiment.test(): y_pred = model.predict_classes(x_test)
するとこんな感じでChartsから学習過程などをグラフで見ることができるようになります。
また最終的なaccuracyなどの数字はMetricsで確認できます。
実験条件のロギング
最後に実験条件を送ります。詳しくはAPIドキュメントを見ていただければと思いますが、log_*メソッドで送ることができます。
# 各種条件を履歴に残す experiment.log_dataset_hash(x_train) # 学習データ (ハッシュ値) experiment.log_parameters(hp) # ハイパパラメータ
Hyper parametersで送った値が確認できます。特に指定が無い場合でも、最適化アルゴリズムのパラメータなどはデフォルトで残します。
リソース状況などは自動的に記録されており、System Metricsで確認できます。ボトルネックの洗い出しなどはさすがにできませんが、逼迫してないか・有効活用できているかなどのチェックには十分です。
実験の終了
実験完了後はendでクローズします。
# 実験終了
experiment.end()
使う上でのTips
上述した方法で一通りのことはできるようになりましたが、その他実際に使う上で便利なTipsを紹介します。
任意の情報を残したい (log_other)
メトリックスやハイパパラメータ以外に、実験に付随した情報を残したい場合、log_otherメソッドを使うと良いです。
例えば、False negativeとFalse positiveの件数を残したい場合、以下のように記述できます。
- 第1引数がキー、第2引数が値となります
# FN/FPを送る cm = confusion_matrix(y_test, y_pred) experiment.log_other('false_negative', cm[1, 0]) experiment.log_other('false_positive', cm[0, 1])
comet.mlでOtherの項目をそれぞれ残っていることがわかります (train_trainable_paramsが送られているのはデフォルトでしょうか) 。
Jupyter Notebookで結果を見たい (display)
Jupyter Notebookでも学習経過を出力したい場合、matplotlibなどで可視化もできますが、displayメソッドでcomet.mlをiframeで表示することもできます。
コードを残したい (set_code)
set_codeメソッドで、実験に使ったコードを残すこともできます。Jupyter NotebookではIn
に実行したコードをリストで持ってますので、つなげて出力してます。
# コードを出力 code = '' for cell_in in In: code += cell_in + '\n' experiment.set_code(code)
comet.mlのCodeを開くとビジュアライズされたコードが表示されます。 api_keyの値が消されてて、地味な気遣いを感じます。
まとめ
Jupyter Notebookの学習をComet.mlを使って記録・レポートできるようになりました。