Amazon SageMakerでのパラメータチューニング

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、小澤です。

Amazon SageMaker(以下SageMaker)を使うと手軽に機械学習ができます。 ただ、実際に利用可能なモデルを作成しようと思うと、いろいろやらなければならないことも増えてきます。

今回は、その中の1つであるパラメータチューニングについて書かせていただこうかと思います。

そもそもパラメータチューニングって何?

機械学習の文脈でパラメータというと、大きく分けて以下の2つが考えられます。

  • 学習によって得られるモデルのパラメータ
  • 学習時に人間が指定するハイパーパラメータ

まずは、それぞれどういったものなのかをみていきましょう

学習によって得られるモデルのパラメータ

モデルのパラメータとはどういったものなのかを理解するために線形回帰を例としみてみましょう。 線形回帰は以下の式に当てはめます。

\[ y = w_1 x_1 + w_2 x_2 + ... + w_m x_m + w_0 \]

ここで\(x_1,x_2, ..., x_m\)はデータから得られる特徴量となっています。 \(y\)は予測対象の数値となります。

例えば、ビールの売り上げが気温に影響するとした時に、以下のようなデータがあったとします。

横軸が気温、縦軸がビールの売り上げ本数とします。

これに対して線形回帰が行うことは以下のような近似線を引くことです。

この青い線は

\[ y = ax + b \]

の形で表すことが可能です。 線形回帰の式は、\(w_1\)が\(a\)、\(w_0\)が\(b\)対応しています(今回は気温しか使ってませんが、ビールの売り上げに関連しそうな気温以外の要素を入れていくと\(w_2\)以降の項目として追加していきます)。

機械学習ではこの\(x_1,x_2, ..., x_m\)と正解となる\(y\)の値の組み合わせを大量に与えることで、 新たな観測値として別な\(x_1,x_2, ..., x_m\)の値に対応する\(y\)を答えれるようにすることが目的です。

この仕組みを実現するために右辺の計算結果が正解となる\(y\)になるように\(w_1,x_2, ..., w_m\)の値を調整するが 機械学習における"学習"のプロセスであり、その結果得られた\(w_1,x_2, ..., w_m\)がモデルとなります。

個々の\(w_i\)の値のことをさしてパラメータといっているパータンがこの1つ目のとなります。

学習時に人間が指定するハイパーパラメータ

さて、続いてハイパーパラメータについてみていきましょう。 ここでは決定木を例に考えます。

決定木は先ほどの線形回帰のと同様、 \(x_1,x_2, ..., x_m\)と正解となる\(y\)の値の組み合わせを大量に与えることで、新たな観測値として別な\(x_1,x_2, ..., x_m\)の値に対応する\(y\)を答えれるようにすることが目的です。

特徴としては、線形回帰のような数式というよりは、if文の組み合わせような形式で特徴から結果を導き出すための判定を繰り返し行なっていきます。

さて、この決定木ではif文のような仕組みを繰り返す構造を自動的に作るため、完璧に分類できるようにしようとすると、この画像での階層が無限に深くなっていく恐れがあります。

それを防ぐために、「どこまで深くしていいか」を事前に決めてやることが可能です。 この「どこまで深くしていいか」はあらかじめ人間が決めるものとなります。 このようなものがハイパーパラメータとなります。

ハイパーパラメータは利用する手法によって設定する値が異なりますが、 どのような値にするかによって学習結果や予測性能のが変わるためうまいこと調整してやる必要があります。

ハイパーパラメータをどのように決定するか

では、このハイパーパラメータはどのように決めればいいのでしょうか? 手法によっては元となっている論文にオススメの値が書いてあったり、経験豊かなデータサイエンティストによってなぜかいい感じの結果になる値を設定してたりといったこともあります。 しかし、もちろんデータによって適切な値は違いますし、謎の値をそのまま使ったりするのは怖いですね。。 そこで、いろんな値で試してみて、一番いい結果になるものを選択するという方法が存在します。 このやり方として

  • グリッドサーチ
  • ランダムサーチ
  • ベイズ最適化

などの方法が挙げられます。 今回は、これらが具体的に何をしているかの解説は割愛しますが、興味ある方は上記ワードで調べてみてください。

SageMakerでやってみる

それでは、SageMakerでハイパーパラメータのチューニングをやってみましょう。 今回はサンプルとして用意されているhpo_xgboost_direct_marketing_sagemaker_python_sdk.ipynbを例に見ていきます。

途中まではデータの取得とXGBoostを利用するためのデータの整形なので、「Setup_Hyperparameter_Tuning」以降を見ていきましょう。

設定項目

まずは従来の学習方法と同様にEstimatorのインスタンスを作成したのち、固定値とするハイパーパラメータの値を設定しています。

sess = sagemaker.Session()

containers = {'us-west-2': '433757028032.dkr.ecr.us-west-2.amazonaws.com/xgboost:latest',
              'us-east-1': '811284229777.dkr.ecr.us-east-1.amazonaws.com/xgboost:latest',
              'us-east-2': '825641698319.dkr.ecr.us-east-2.amazonaws.com/xgboost:latest',
              'eu-west-1': '685385470294.dkr.ecr.eu-west-1.amazonaws.com/xgboost:latest',
              'ap-northeast-1': '501404015308.dkr.ecr.ap-northeast-1.amazonaws.com/xgboost:latest'}

xgb = sagemaker.estimator.Estimator(containers[region],
                                    role, 
                                    train_instance_count=1, 
                                    train_instance_type='ml.m4.xlarge',
                                    output_path='s3://{}/{}/output'.format(bucket, prefix),
                                    sagemaker_session=sess)

xgb.set_hyperparameters(eval_metric='auc',
                        objective='binary:logistic',
                        num_round=100,
                        rate_drop=0.3,
                        tweedie_variance_power=1.4)

ここから、チューニングを行うための設定をしていきます。 パラメータチューニングを行うには、

  • どのパラメータ値をどのような範囲で探索するか
  • パラメータごとのモデルの良し悪しを判断するための指標

が必要となります。 まず、前者は以下のように行なっています。

hyperparameter_ranges = {'eta': ContinuousParameter(0, 1),
                        'min_child_weight': ContinuousParameter(1, 10),
                        'alpha': ContinuousParameter(0, 2),
                        'max_depth': IntegerParameter(1, 10)}

パラメータ名と各パラメータの探索範囲をdictで指定しています。 パラメータがどのような値を取りうるかはsagemaker.tunerで定義されたクラスを利用します。 ここでは以下のクラスを利用しています。

  • 連続値として任意の実数をとるもの : ContinuousParameter
  • 整数値としかならないもの : IntegerParameter

他にも決まった値のうちのいずれかとなるCategoricalParameterもあります。 手法ごとにチューニング可能なパラメータ名とクラスの指定についてはドキュメントに記載があります。 今回利用しているXGBoostの場合以下のページの「Tunable Hyperparameters」という項目にあります。

XGBoost以外のBuild-Inアルゴリズムも同様の階層構造で見つけることが可能です。

続いて、後者の設定を見ていきます。 こちらは以下のようになっています。

objective_metric_name = 'validation:auc'

シンプルに1行です。 どのような指標が利用可能かはパラメータ項目と同様のページに記載があります。

チューニングの実行

さて、必要な項目が揃ったのでチューニングを行いましょう。 これにはHyperparameterTunerクラスを利用します。

tuner = HyperparameterTuner(xgb,
                            objective_metric_name,
                            hyperparameter_ranges,
                            max_jobs=10,
                            max_parallel_jobs=3)

コンストラクタのパラメータとして、

  • 利用する手法のEstimator
  • パラメータの範囲
  • 評価指標

の3つをまず渡しています。 その下の2つは

  • max_jobs : 最大で何種類のパラメータで試すか
  • max_parallel : 1度に並列で実行する最大数

を指定します。 HyperprameterTunerは他にも多くの設定が可能です。 詳細はSageMaker Python SDKのドキュメントを参照してください。

設定が完了したらあとは実行するのみです。 パラメータチューニング時の学習に利用するデータと性能を検証するために利用するデータを指定して処理を実行します。

s3_input_train = sagemaker.s3_input(s3_data='s3://{}/{}/train'.format(bucket, prefix), content_type='csv')
s3_input_validation = sagemaker.s3_input(s3_data='s3://{}/{}/validation/'.format(bucket, prefix), content_type='csv')

tuner.fit({'train': s3_input_train, 'validation': s3_input_validation})

処理の状況確認

さて、パラメータチューニングの処理が実行できたので、状況を確認して見ましょう。 状況はSageMakerの管理コンソールから確認できます。

まずはメニューから「ハイパーパラメータの調整ジョブ」を選択して、先ほど処理で実行が始まったチューニングジョブを選びます。

続いての画面で、ジョブの実行状況が確認できます。

全てのジョブの実行を終えたのち、「最善のトレーニングジョブ」を選択することで、もっとも性能の良かったパラメータ値が確認できます。

あとは、このモデルをデプロイすることで従来通りAPIのエンドポイントから利用可能な状態になります。

おわりに

今回はSageMakerのハイパーパラメータチューニングについて解説しました。 パラメータチューニングは学習と評価のプロセスを繰り返すことになるので、従来のようにコーディング環境と学習環境が同じ端末だったりすると、なかなか複数の処理を同時に動かすことは難しいため非常に多くの時間がかかったりします。 SageMakerはNotebook用のインスタンスとは別コンテナで学習処理が実行されるので、パラメータチューニングも簡単に並列化できて便利ですね。