Dataikuでは、高パフォーマンスで信頼性の高い資産を構築し、データサイエンスとAIを民主化することを常に考えています。
Snowflakeが提供する以下のサービスは、この目的によく合致しています:
- Snowpark Python:データの移動を減らし、(DataFrameなど特定のSnowpark APIに関する)計算処理を並列化するなどの手段により、パフォーマンスを向上できます。
- Snowpark ML:Snowflakeの新しい機械学習(ML)ツールセットで、MLモデルの学習をより簡単に、利用しやすくします。
特に、新しいsnowflake-ml-pythonパッケージは、データサイエンティストに馴染みのあるscikit-learn、XGBoost、LightGBMの構文を利用しながら、SnowparkでPythonコードを実行できる利点があります。
この記事では、DataikuとSnowpark MLを組み合わせたモデル学習について、Pythonコードを利用する場合の手順について説明します。(訳注:DataikuのAuto MLを利用し、Dataikuのビジュアル環境上でモデル学習・実行した結果をSnowflakeに連携することも可能です。
この記事では、Snowpark MLを利用して、Snowpark側でモデル学習・実行を行う場合の手順として、コードの利用例を示しています。)
今回扱うユースケースは、ローンの貸倒れ予測です。既知の過去データを使い、MLモデルをトレーニングして、契約が貸倒れになったか、完済したかを2️値分類で予測します。
このモデルはデータ内の基本的なパターン(つまり、入力特徴量が目的変数にどのように関連しているか)を見つけ出します。そして、このモデルを使うことで、新規ローン申請者の特徴量に基づいて、(できる限り)正確な予測を行うことができます。
最終的なプロジェクトフローは以下のようになります。
プロジェクトの大まかなステップを以下に示します。
データクリーニング+特徴量エンジニアリング(Snowflake SQL + Snowpark Python)
- S3上の過去ローン申請データと顧客データに接続
- fast-path を利用して、Snowflakeにデータを同期(Syncレシピ)
- ビジュアル PrepareレシピとカスタムSQLコードで、乱雑な値をクレンジング
- 共通の「CUSTOMER_ID」フィールドでテーブルを結合
- Snowpark UDFをを利用して、新しい特徴量を生成
モデルのトレーニング(Snowpark ML)
- 特徴量の処理 - リスケール、エンコード、欠損値の補完
- RandomizedSearchで複数アルゴリズムのハイパーパラメータを調整
- 学習済みモデルをDataikuのSaved Model(緑色の菱形)としてデプロイ
- 学習済みモデル、学習データ、テストデータの情報を出力して、透明性を確保
今回はデータクリーニングと特徴量エンジニアリングの部分は省略します。(SnowflakeとSnowparkに特化したDataikuのデータクリーニングと特徴量エンジニアリングの機能についてもっと知りたい方は、こちらのビデオをご覧ください)
Snowpark MLとDataikuを使って、MLモデルをトレーニングするステップバイステップのウォークスルー(コードも付いています!)を確認したい方は、このまま読み進めてください。
0. Python 3.8の環境とPython Codeレシピを準備する
まず、Python 3.8の code environment をDataiku上で作成します。ここでは 「py_38_snowpark」と名付けました。コアパッケージのバージョンをPandas 1.3に変更し、以下リストのパッケージをテキストエリアに貼り付けて、「Update」をクリックします。
パッケージのリストはこちら:
0 - Python Package List
プロジェクトフローに戻り、クリーンアップ済みの入力データ(貸倒れか否かの目的変数をラベル付けした、すべてのローン申請データ)を選択します。そして、以下の3つの出力を持つPythonレシピを作成します。
- 学習データセット(Snowflake)
- テストデータセット(Snowflake)
- 学習済みモデル格納用フォルダ(S3)
1. Pythonパッケージをインポートする
まずは、パッケージをインポートします。一番下に、新しいSnowpark MLのインポート文が確認できます。scikit-learn、XGBoost、LightGBMの対応クラス/関数と同様な構文を利用できます。
▶️ Python Code 1 - Pythonパッケージをインポートする
2. レシピのインプット・アウトプット、その他の学習用パラメータを設定する
このコードブロックでは、入力データセット、2つの学習/テスト用出力データセット、学習済みモデル保存フォルダを指定します。最終的なモデルに名前をつけ、ターゲット列(今回の例では「DEFAULT」)を選択し、学習/テスト比率、スコアリング指標、クラス重みを使うかどうか、その他のオプションを選択します。
そして、モデルに入力する特徴量を選択します。このDictionary リストの構造に注目してください。各Dictionaryには、特徴量名、スケーリング/エンコーディング、欠損値の補完方法が含まれます。
▶️ Python Code 2 - レシピのインプット・アウトプット、その他の学習用パラメータを設定する
3. MLflowの実験管理(Experiment Tracking)を設定する
MLflowはMLの実験をトラッキングするための優れたオープンソースライブラリです。DataikuはMLflowの実験管理と連携した使いやすいUIを提供しています。詳しくはこちらをご覧ください。
DataikuとMLflowのAPIを使って新しい実験を作成し、モデルの学習プロセスを追跡してみます。
▶️ Python Code 3 - MLflowの実験管理(Experiment Tracking)を設定する
4. Snowparkセッションを設定する
モデル学習コードはSnowpark上で実行されます。SnowparkはSnowflake上で非SQLコードをデプロイ・実行するためのランタイム&ライブラリです。DataikuのSnowpark連携では、Snowflakeテーブルへの接続と同じ認証情報を利用して、Snowparkセッションを作成できます。
▶️ Python Code 4 - Snowparkセッションを設定する
5. ターゲットクラスの重み列を追加し、学習/テストデータを分割する
ターゲット列(目的変数)のデータ型を、様々なMLアルゴリズムがサポートしているより一般的な型に変換します。
また、ターゲット列のクラスの重みを保持する 「SAMPLE_WEIGHTS 」列を追加します。これは、対象クラスの不均衡問題を軽減するのに役立ちます。このトピックに関しては、Analytics Vidhyaの説明がわかりやすいです。
標準の scikit-learn、XGBoost、LightGBM アルゴリズムクラスでは、この問題を解決するために「class_weights = balanced」引数を渡します。Snowpark ML はこの引数を持っていないため、すべての行に対して明示的に「SAMPLE_WEIGHTS」列が必要です。以下のコードブロックは、その方法を示しています。
最後に、学習/テスト用のデータフレームをSnowflakeの永続テーブルとして保存します。
▶️ Python Code 5 - ターゲットクラスの重み列を追加し、学習/テストデータを分割する
6. 特徴量変換パイプラインを作成する
これまでに設定した特徴量と前処理オプションに基づき、適切なScaler、Encoder、Imputerクラスへの変換を行います。その結果をPipelineにまとめます。
Snowpark MLクラスの構文は、対応するscikit-learnのクラスと同様なことがわかるかと思います。
▶️ Python Code 6 - 特徴量変換パイプラインを作成する
7. アルゴリズムとRandomized Search用のハイパーパラメータ空間を初期化する
ロジスティック回帰、ランダムフォレスト、XGBoost、LightGBMの4つの異なるアルゴリズムを試してみます。
チューニングしたいパラメータと検証する値の分布を渡して、ハイパーパラメータの探索空間を定義します。例えば、n_estimatorsパラメータには clf__接頭辞を付け、XからYまでのランダムな整数分布を渡します。これにより、RandomizedSearchアルゴリズムは、XとYの間の整数をランダムに試行します。連続分布を試したい場合、scipy の uniform や loguniform を利用できます(コード内の clf__learning_rate を参照)。
n_iter パラメータは、各アルゴリズムが試すハイパーパラメータの組合せ数を制御します。
▶️ Python Code 7 - アルゴリズムとRandomized Search用のハイパーパラメータ空間を初期化する
8. モデルの学習、Randomized Searchを実行する
このコードはモデル学習とハイパーパラメータのチューニングを実行します。
RandomizedSearchCV オブジェクトに渡す引数に注目してください(input_cols、label_cols、 output_cols、 sample_weight_col)。これらはscikit-learnの同等クラスとは少し異なり、Snowpark MLのすべてのMLアルゴリズムクラスで必須です。これらの違いについては、こちらのドキュメントで説明しています。
▶️ Python Code 8 - モデルの学習、Randomized Searchを実行する
9. ハイパーパラメータ、性能メトリクス、学習済みモデルをMLFlowに登録する
異なるアルゴリズムとハイパーパラメータの組合せを利用して、多くのモデルをトレーニングしました。MLflowを使ってこれらの情報をすべて追跡してみましょう。
以下のコードでは、アルゴリズムの種類、ハイパーパラメータ、クロスバリデーションの性能メトリクス、学習済みモデルオブジェクト(先ほど選択したS3フォルダに格納したもの)をログに記録します。
このコードが実行されると、DataikuのExperiment Trackingタブですべてのモデルパフォーマンス情報を確認できるようになります。このタブを使用して、モデルを診断・反復学習・改善します。
▶️ Python Code 9 - ハイパーパラメータ、性能メトリクス、学習済みモデルをMLFlowに登録する
10. 学習済みモデルをDataikuのSaved Modelとして保存する
このコードでは、選択した性能指標(ここではROC AUC)に従って、最良の学習済みモデルを取得し、DataikuのSaved Model(フロー内の緑色の菱形)としてデプロイします。
最後の行:
mlflow_version.evaluate(output_test_dataset_name, container_exec_config_name='NONE')
では、ホールドアウトした検証データセットを利用して、最終的なモデルパフォーマンスを計算します。この行は、以下に示すShapley特徴量効果のように、Dataiku標準のモデル性能・説明可能性チャートも生成します。
▶️ Python Code 10 - 学習済みモデルをDataikuのSaved Modelとして保存する
11. DataikuのSaved ModelをPythonレシピのアウトプットに追加する
注意: このコードブロックは、Pythonレシピの中だけで実行してください(Jupyter notebookでは実行できません)。
このコードは、新しく作成したDataikuのSaved Model (緑色の菱形)をPythonレシピの出力に紐付けます(入力なしのモデルでは宙に浮いてしまうため、モデルをフローに紐づけるために、この手順を実施しました)。
▶️ Python Code 11 - DataikuのSaved ModelをPythonレシピのOutputに追加する
次のステップ
おめでとうございます!この重くてコードの多い記事を読み通していただきまして、ありがとうございました。
次のステップとしては、
- 別のPythonレシピを作成し、Snowpark MLを使用して、新規ローン申請をバッチ推論する。
- 学習済みモデルをRESTful APIエンドポイントとしてデプロイし、Snowpark Container Services上でリアルタイム推論する。(現時点では、プライベートプレビューとして公開。ビデオはこちら)
- Dataikuのガバナンスノードを使って、デプロイされたモデルを制御・監視する。(Governの詳細はこちら)
もちろん、今回のフレームワークとサンプルコードをご自身のユースケースに当てはめて、自由にご利用ください。
さらなる高みへ:Webinarのご紹介
こちらのウェビナーでは、SnowparkとDataikuの組合せがデータクリーニング、特徴量エンジニアリング、ML学習プロセスにどのような革命をもたらすかをPatrick Masi-Phelpsが解説します。
原文:Training ML Models With Dataiku and Snowpark ML: A Code Approach