モデル・モニタリングの例

モデル・モニタリングは、ユーザーが実稼働環境の機械学習モデルのパフォーマンスをモニターできるようにすることで、MLOpsで重要な役割を果たします。モニタリングを使用すると、ビジネスの目的を満たすのにモデルのパフォーマンスが十分でなくなり、更新されたモデルに置き換える必要がある時期を識別できます。

実稼働環境モデルの劣化は通常の想定内のイベントですが、いくつかの理由で発生する可能性があります。その理由の一部を次に示します。
  • データ・ドリフト: これは、予測作成の基盤となったデータのプロファイルが変化した場合に発生します。
  • コンセプト・ドリフト: これは、正しい予測の想定が時間の経過とともに変化した場合に発生します。たとえば、消費者の好みが変化したために、保持する在庫などのターゲット変数の統計プロパティが時間の経過とともに変化する場合があります。

データ・ドリフトとコンセプト・ドリフトに影響する要因は多岐にわたるため、モデル・モニタリング・タスクが重要になります。これにより、これらの変化によって実稼働環境モデルの予測品質が損なわれた時点で、ユーザーが認識できるようになります。

OML Servicesのモデル・モニタリングでは、分類および回帰モデルがサポートされており、モデル精度メトリックを使用してパフォーマンスが追跡されます。分類の場合、モデル品質メトリックには次のものが含まれます:
  • 精度:正数と負数の両方のケースを正しく分類する割合を計算します。たとえば、TP + TN + FP + FN (True Positives+True Negatives+False Positives+False Negatives)ケースから正しく分類されたTP (True Positives) + TN (True Negatives)ケースの合計がある場合、式は次のようになります。Accuracy = (TP+TN)/(TP+TN+FP+FN)
  • バランスの取れた精度: 二項分類子がどの程度良好かを評価します。これは、クラスが不均衡な場合、つまり2つのクラスのいずれかが他方よりも頻繁に出現する場合に特に便利です。これは、異常検出などの多くの設定でよく発生します。
  • 再現率: 正しく分類された実際の陽性の比率を計算します。
  • 適合率: 予測された陽性のうち真陽性であるものの割合を計算します。
  • F1スコア: 適合率と再現率を組み合せて単一の数値にします。F1スコアは、次の式で計算される調和平均を使用して計算されます: F1-score = 2*(precision*recall)/(precision+recall)
  • AUC (ROC曲線の下の領域): 決定しきい値に関係なく、識別の集計メジャーを提供します。AUC - ROC曲線は、様々なしきい値設定での分類問題のパフォーマンス測定です。
回帰の場合、モデル精度メトリックには次のものが含まれます:
  • R2: 適合回帰線へのデータの近似度を計算する統計的測定。一般に、R2乗の値が大きいほど、モデルはデータに適合します。R2の値は常に0から1の間です。
    • 0は、平均に関するレスポンス・データの変動がモデルで説明されていないことを示します。
    • 1は、平均に関するレスポンス・データのすべての変動をモデルが説明していることを示します。
  • 平均二乗誤差: これは、予測ターゲットと実際のターゲットの2乗差の平均です。
  • 平均絶対誤差: これは、予測ターゲットと実際のターゲットの絶対差の平均です。
  • 中央絶対誤差: これは、予測ターゲットと実際のターゲットの間の絶対差の中央値です。

モデル・モニタリング・ワークフロー

OML RESTサービスを介して機械学習モデルをモニターするには、次のステップに従います:
  1. AutoML UIを使用したモデルのデプロイ
  2. アクセス・トークンの取得
  3. モニタリングに使用するモデルのモデルIDの取得
  4. モデル・モニタリング・ジョブの作成
  5. モデル・モニタリング・ジョブの詳細の表示
  6. モデル・モニタリング・ジョブの更新(オプション)
  7. モデル・モニタリング・ジョブの有効化
  8. モデル・モニタリング・ジョブの出力の表示および理解

1. モデルのデプロイ

機械学習モデルをモニタリングする前に、モデルをデプロイする必要があります。そのためには、AutoML UIに移動し、次のようにします:
  1. 機械学習モデルを自動構築する方法を選択する場合は、AutoML実験を作成してモデルをデプロイします

2: アクセス・トークンの取得

OML Servicesにリクエストを送信するには、Oracle Machine Learning (OML)アカウントの資格証明を使用して認証トークンを取得する必要があります。トークンを認証および取得するには、-dオプションを指定したcURLを使用して、Oracle Machine Learningユーザー管理クラウド・サービスRESTエンドポイント/oauth2/v1/tokenにOracle Machine Learningアカウントの資格証明を渡します。次のコマンドを実行して、アクセス・トークンを取得します:

$ curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{"grant_type":"password", "username":"'<yourusername>'", 
"password":"' <yourpassword>'"}'"<oml-cloud-service-location-url>/omlusers/api/oauth2/v1/token"
説明:
  • -X POSTで、HTTPサーバーとの通信時にPOSTリクエストを使用することを指定します
  • -headerで、リクエストに必要なヘッダー(application/json).を定義します
  • -dで、ユーザー名およびパスワードの認証資格証明をPOSTリクエストのデータとしてHTTPサーバーに送信します
  • Content-Typeで、レスポンス形式(JSON).を定義します
  • Acceptでは、レスポンス形式(JSON).を定義します
  • yourusernameは、デフォルトのOML_DEVELOPERロールを持つOracle Machine Learningユーザーのユーザー名です
  • yourpasswordは、ユーザー名のパスワードです
  • oml-cloud-service-location-urlは、テナンシIDおよびデータベース名を含むOracle Machine Learningユーザー管理クラウド・サービスのインスタンスURLのRESTサーバー部分を含むURLです。URLは、Oracle Autonomous Databaseインスタンスのサービス・コンソールの「開発」タブから取得できます。

3: モニタリングに使用するモデルのモデルIDの取得

modelIdを取得するには、デプロイメント・エンドポイントに、GETリクエストを送信してモデルURIを設定します。

modelIdを取得するGETリクエスト:
$ curl -X GET "<oml-cloud-service-location-url>/omlmod/v1/deployment/HousePowerNN" \
       --header "Authorization: Bearer ${token}" | jq '.modelId'
この例では、モデルURIはHousePowerNNです。

ノート:

モデルURIは、AutoML UIを使用してモデルをデプロイするとき、またはRESTクライアントを介してモデルをデプロイするときにユーザーが指定します。

GETリクエストは次のものを返します:

"modelId": "0bf13d1f-86a6-465d-93d1-8985afd1bbdb"

4: モデル・モニタリング・ジョブの作成

アクセス・トークンを取得したら、POSTリクエストをデプロイメント・エンドポイントに送信し、モデルURIを指定することによって、モデル・モニタリング・ジョブを作成できます。モデル・モニタリング・ジョブを作成するには、モニターするモデルのモデルIDが必要です。リクエスト本文には、単一のモデル、または最大20個のモデルのリストをモデルIDで指定できます。

モデル・モニタリング・ジョブ作成のPOSTリクエストの例

これは、モデル・モニタリング・ジョブを作成するPOSTリクエストの例です。ジョブは非同期で発行されます。そのため、スケジュールどおりに実行され、ジョブの完了時に結果を取得できます。
  • jobScheduleパラメータに、ジョブ開始日、ジョブ終了日、ジョブ頻度および最大実行数を指定します。
  • jobPropertyパラメータに、次のようなモデル・モニタリングの詳細を指定します:
    • モデル・モニタリング・ジョブの名前とジョブ・タイプ
    • Autonomous Databaseサービス・レベル
    • モデル・モニタリングの詳細が保存される表
    • ドリフト・アラート・トリガー
    • しきい値
    • 最大実行回数
    • 使用するベースラインおよび新しいデータ
    • パフォーマンス・メトリックのバランスのとれた精度の選択
    • newDataで示される表またはビューのDATEまたはTIMESTAMP列に対応した開始日(オプション)および終了日(オプション)。timeColumnフィールドに格納されています。開始日と終了日が指定されていない場合は、timeColumn内の最も早い日時と最も遅い日時が使用されます。
$ curl -X POST "<oml-cloud-service-location-url>/omlmod/v1/jobs" \
         --header "Authorization: Bearer ${token}" \
         --header 'Content-Type: application/json' \
         --data '{
            "jobSchedule": {
            "jobStartDate": "2023-03-25T00:30:07Z",                 # job start date and time 
            "repeatInterval": "FREQ=DAILY",                         # job frequency
            "jobEndDate": "2023-03-30T20:50:06Z",                   # job end date and time 
            "maxRuns": "5"                                          # max runs within the schedule
         },
         "jobProperties": {
            "jobName": "MY_MODEL_MONITOR1",                         # job name
            "jobType": "MODEL_MONITORING",                          # job type; MODEL_SCORING
            "disableJob": false,                                    # flag to disable the job at submission
            "jobServiceLevel": "LOW",                               # Autonomous Database service level; either LOW, MEDIUM, and HIGH
            "inputSchemaName": "OMLUSER",                           # database schema that owns the input table/view
            "outputSchemaName": "OMLUSER",                          # database schema that owns the output table
            "outputData": "Global_Active_Power_Monitor",            # table where the job results will be saved in the format {jobID}_{outputData}
            "jobDescription": "Global active power monitoring job", # job description
            "baselineData": "HOUSEHOLD_POWER_BASE",                 # table/view containing baseline data 
            "newData": "HOUSEHOLD_POWER_NEW",                       # table/view with new data to compare against baseline
            "frequency": "Year",                                    # time window unit that the monitoring is done on in the new data
            "threshold": 0.15,                                      # threshold to trigger drift alert
            "timeColumn": "DATES",                                  # date or timestamp column in newData
            "startDate": "2008-01-01T00:00:00Z",                    # the start date and time of monitoring in the new data
            "endDate": "2010-11-26T00:00:00Z",                      # the end date and time of monitoring in the new data
            "caseidColumn": null,                                   # case identifier column in the baseline and new data
            "performanceMetric": "MEAN_SQUARED_ERROR",              # metric used to measure model performance
            "modelList": [                                          # model ID or list of model IDs to be monitored
                "0bf13d1f-86a6-465d-93d1-8985afd1bbdb"
             ],
            "recompute": false                                      # flag to determine whether to overwrite the results table
         }
    }' | jq

このジョブを実行するためのパラメータは、次のように分類されます:

必須パラメータ:
  • jobTypeでは、実行するジョブのタイプを指定します。モデル・モニタリング・ジョブの場合はMODEL_MONITORINGに設定します。
  • outputData: 出力データ識別子。ジョブの結果は、{jobId}_{ouputData}という名前の表に書き込まれます
  • baselineData: モニターするベースライン・データを含む表またはビュー。モデル・モニタリングには期間当たり少なくとも50行が必要です。それ以外の場合は分析がスキップされます
  • newData: ベースラインと比較する新しいデータを含む表またはビュー。モデル・モニタリングには期間当たり少なくとも50行が必要です。それ以外の場合は分析がスキップされます
  • modelList: モニターするモデルのリスト。modelIdで識別されます。デフォルトでは、1つのジョブで最大20個のモデルをモニターできます。
オプションのパラメータ:
  • disableJob: 送信時にジョブを無効にするフラグ。設定しないと、デフォルトではfalseになり、発行時にジョブが有効になります。
  • timeColumn: 新しいデータの日付またはtimestamp列が格納された列の名前。指定しないと、newData全体が1つの期間として処理されます。
  • frequency: 新しいデータでモニタリングが実行される時間の単位を示します。frequencyには、"day""week""month"または"year"を指定できます。指定しないと、"new"のデータ全体が単一の期間として使用されます。
  • threshold: ドリフト・アラートをトリガーするためのしきい値。
  • recompute: すでに計算済の期間を更新するかどうかに関するフラグ。デフォルト値はFalseです。つまり、出力結果テーブルに存在しない期間だけが計算されます。
  • performanceMetric: モデル・パフォーマンスの測定に使用するメトリック。

    ノート:

    回帰モデルの場合、デフォルトはMEAN_SQUARED_ERRORです。分類モデルの場合、デフォルトはBALANCED_ACCURACYです。
  • caseidColumn: ベースラインおよび新しいデータのケース識別子列。これにより、結果の再現性が向上します。
  • startDate: newData列のモニタリングの開始日またはタイムスタンプ。startDateには、列timeColumnか必須です。startDateが指定されていない場合、startDatefrequencyが指定されているかどうかによって異なります。frequencyが指定されていないと、timeColumnの最も早い日付がstartDateとして使用されます。startDatefrequencyの両方が指定されていないと、timeColumnの最も早い日付か、最新のサイクルの10番目の開始日のどちらか早いほうがstartDateとみなされます。

    ノート:

    サポートされている日時書式は、ISO-8601日時書式です。たとえば、2022-05-12T02:33:16Zです
  • endDate: newDataのモニタリングの終了日またはタイムスタンプ。endDateには、列timeColumnか必須です。endDateを指定しないと、timeColumnの最新の日付が使用されます。

    ノート:

    サポートされている日時書式は、ISO-8601日時書式です。たとえば、2022-05-12T02:33:16Zです
  • jobDescription: ジョブの説明テキスト。
  • outputSchemaName: 出力表を所有するデータベース・スキーマ。指定しないと、出力スキーマは入力スキーマと同じになります。
  • inputSchemaName: 入力表またはビューを所有するデータベース・スキーマ。指定しないと、要求トークンのユーザー名と同じ入力スキーマになります。
  • jobServiceLevel: ジョブのサービス・レベル。LOW、MEDIUMまたはHIGHのいずれかを指定できます。

ジョブ作成のためのPOSTリクエストのレスポンス

モデル・モニタリング・ジョブ作成のレスポンス例を次に示します:

{
  "jobId": "OML$736F509B_FC1A_400A_AC75_553F1D6C5D97",
  "links": [
    {
      "rel": "self",
      "href": "<OML Service URL>/v1/jobs/OML%24736F509B_FC1A_400A_AC75_553F1D6C5D97"
    }
  ]
}

ジョブが正常に発行されると、レスポンスとしてジョブIDが届きます。ジョブ詳細を取得したり、ジョブに対してアクションを実行するためにリクエストを送信するために将来参照できるように、jobIdをメモしておきます。

5: 発行されたジョブの詳細の表示

発行済ジョブの詳細を表示するには、/omlmod/v1/jobs/{jobId}エンドポイントにGETリクエストを送信します。ここで、jobIdは、モデル・モニタリング・ジョブの正常発行に対するレスポンスに示されていたIDです。

発行済ジョブの詳細を表示するためのGETリクエストの例
$ export jobid='OML$736F509B_FC1A_400A_AC75_553F1D6C5D97'   # define the Job ID as a single-quoted variable 

$ curl -X GET "<oml-cloud-service-location-url>/omlmod/v1/jobs/${jobid}"  \
       --header 'Accept: application/json' \
       --header 'Content-Type: application/json' \
       --header "Authorization: Bearer ${token}" | jq

次に、ジョブ詳細リクエストの出力例を示します。CREATEDのjobStatusは、ジョブが作成されたことを示します。ジョブがすでに1回に実行されている場合は、最後のジョブ実行に関する情報が返されます。

GETリクエストのレスポンス
returns:

{
  "jobId": "OML$736F509B_FC1A_400A_AC75_553F1D6C5D97",
  "jobRequest": {
    "jobSchedule": {
      "jobStartDate": "2023-03-25T00:30:07Z",
      "repeatInterval": "FREQ=DAILY",
      "jobEndDate": "2023-03-30T00:30:07Z",
      "maxRuns": 5
    },
    "jobProperties": {
      "jobType": "MODEL_MONITORING",
      "inputSchemaName": "OMLUSER",
      "outputSchemaName": "OMLUSER",
      "outputData": "Global_Active_Power_Monitor",
      "jobDescription": "Global active power monitoring job",
      "jobName": "MY_MODEL_MONITOR1",
      "disableJob": false,
      "jobServiceLevel": "LOW",
      "baselineData": "HOUSEHOLD_POWER_BASE",
      "newData": "HOUSEHOLD_POWER_NEW",
      "timeColumn": "DATES",
      "startDate": "2008-01-01T00:00:00Z",
      "endDate": "2010-11-26T00:00:00Z",
      "frequency": "Year",
      "threshold": 0.15,
      "recompute": false,
      "caseidColumn": null,
      "modelList": [
        "0bf13d1f-86a6-465d-93d1-8985afd1bbdb"
      ],
      "performanceMetric": "MEAN_SQUARED_ERROR"
    }
  },
  "jobStatus": "CREATED",
  "dateSubmitted": "2023-03-25T00:26:16.127906Z",
  "links": [
    {
      "rel": "self",
      "href": "<OML Service URL>/omlmod/v1/jobs/OML%24736F509B_FC1A_400A_AC75_553F1D6C5D97"
    }
  ],
  "jobFlags": [],
  "state": "SCHEDULED",
  "enabled": true,
  "runCount": 0,
  "nextRunDate": "2023-03-25T00:30:07Z"
}

6: モデル・モニタリング・ジョブの更新(オプション)

非同期ジョブの発行後に、ジョブを更新することもできます。POSTリクエストを/omlmod/v1/jobs/{jobID}エンドポイントに送信して、ジョブを更新します。

このジョブでは、次のパラメータを更新する必要があります:
  • startDate
  • endDate
  • threshold
  • recompute
  • modelList
これは、モデル・モニタリング・ジョブを更新する例です。ここでは、同じジョブIDを使用して、updatePropertiesフィールドの元のパラメータの一部を更新しています。ドリフト・アラートのトリガーが0.20に更新され、すでに計算済の期間を更新するようにrecomputeフラグが設定されているため、ジョブを実行するたびに、指定されたtimeColumnのすべての期間のデータが再計算されます。
$ curl -i -X POST "<oml-cloud-service-location-url>/omlmod/v1/jobs/${jobid}" \    
         --header "Authorization: Bearer ${token}" \
         --header 'Content-Type: application/json' \
         --data '{
            "updateProperties": {
                "threshold": 0.20,
                "recompute": "true"
            }
         }'

ノート:

正しく更新されると、コンテンツなしのHTTP 204レスポンスが返されます。

7: モデル・モニタリング・ジョブの出力の表示

スケジュールまたはRUNアクションでジョブが実行されたら、ジョブ・リクエストにoutputDataパラメータで指定した表にジョブの出力を表示できます。表のフルネームは{jobId}_{outputData}です。詳細を表示するリクエストを送信することで、ジョブが完了しているかどうかを確認できます。ジョブが少なくとも1回実行されている場合は、lastRunDetailパラメータにその実行に関する情報が表示されます。

%sql


SELECT IS_BASELINE, MODEL_ID, round(METRIC, 4), HAS_DRIFT, round(DRIFT, 4), MODEL_TYPE, 
       THRESHOLD, MODEL_METRICS 
FROM OML$736F509B_FC1A_400A_AC75_553F1D6C5D97_Global_Active_Power_Monitor

このコマンドは、列IS_BASELINEMODEL_IDROUND (METRIC, 4)HAS_DRIFTROUND (DRIFT, 4)MODEL_TYPETHRESHOLDおよびMODEL_METRICSを含む表を返します。結果の最初の行は、ベースライン期間であることに注意してください。ベースライン期間のデータではドリフトが計算されないため、この行の列HAS_DRIFTROUND (DRIFT, 4)およびTHRESHOLDは空になります。

6: モデル・モニタリング・ジョブに関するアクションの実行(オプション)

デフォルトでは、ジョブが正常に発行されると、その状態がENABLEDに設定されます。つまり、DISABLEDなど、別の状態に更新されないかぎり、ジョブの発行時に指定したスケジュールに従って実行されます。これは、/omlmod/v1/jobs/{jobid}/actionエンドポイントにリクエストを送信すれば実行できます。

OML Servicesは、DBMS_SCHEDULERと対話してジョブに関するアクションを実行します。このエンドポイントに送信できるアクションには4つのオプションがあります:
  • DISABLE: 発行時にジョブを無効にします。このアクションでforceプロパティを使用すると、実行中のジョブを強制的に中断できます。

    ノート:

    disableJobフラグをtrueに設定することで、ジョブの発行時にDISABLEDに設定できます。
  • ENABLE: ジョブを有効にします。無効なジョブを有効にすると、スケジューラによってスケジュールどおりにジョブが自動的に実行され始めます。
  • RUN: ジョブをテストするか、スケジュール外で実行する場合は、このオプションで即時にジョブを実行できます。
  • STOP: 現在実行中のジョブを停止します。
次に、ジョブ・ステータスをDISABLEDに更新するPOSTリクエストの例を示します。
$ curl -i -X POST "<oml-cloud-service-location-url>/omlmod/v1/jobs/${jobid}/action" \
       --header "Authorization: Bearer ${token}" \
       --header 'Content-Type: application/json' \
       --data '{
            "action": "DISABLE",
            "force": "false"
         }'

ノート:

デフォルトでは、forceパラメータはfalseに設定されます。これをDISABLEアクションで使用すると、実行中のジョブを中断できます。

ジョブが正常に送信されると、本文なしの204レスポンスが届きます。

7: モデル・モニタリング・ジョブの削除

以前に発行したジョブを削除するには、jobidを指定したDELETEリクエストを/omlmod/v1/jobsエンドポイントに送信します。

次に、/omlmod/v1/jobsエンドポイントへのDELETEリクエストの例を示します:
$ curl -X DELETE "<oml-cloud-service-location-url>/omlmod/v1/jobs/${jobid}"  \
       --header 'Accept: application/json' \
       --header 'Content-Type: application/json' \
       --header "Authorization: Bearer ${token}" | jq

例の再作成(オプション)

この例では、表HOUSEHOLD_POWER_BASEおよびHOUSEHOLD_POWER_NEWを使用します。これらの表は、UCI Machine Learning RepositoryのIndividual Household Electric Power Consumptionデータを使用して作成されています。ここで説明する例を再作成するには、次のステップに従います:

  1. OMLノートブックのR段落で次のコマンドを実行し、表が存在する場合はを削除して、警告を抑制します:
    %r
    
    options(warn=-1)
    
    try(ore.drop(table="HOUSEHOLD_POWER_BASE"))
    try(ore.drop(table="HOUSEHOLD_POWER_NEW"))
  2. R段落で次のコマンドを実行し、データを読み取って変換します:
    %r
    
    test <- read.csv("https://objectstorage.us-sanjose-1.oraclecloud.com/n/adwc4pm/b/OML_Data/o/household_power_consumption.txt", sep=";")
    
    test <- transform(test, Date = as.Date(Date, format = "%d/%m/%Y"))
    test <- transform(test, Global_active_power = as.numeric(Global_active_power))
    test <- transform(test, Global_reactive_power = as.numeric(Global_reactive_power))
    test <- transform(test, Voltage = as.numeric(Voltage))
    test <- transform(test, Global_intensity = as.numeric(Global_intensity))
    test <- transform(test, Sub_metering_1 = as.numeric(Sub_metering_1))
    test <- transform(test, Sub_metering_2 = as.numeric(Sub_metering_2))
    test <- transform(test, Sub_metering_3 = as.numeric(Sub_metering_3))
    
    colnames(test) <- c("DATES", "TIMES", "GLOBAL_ACTIVE_POWER", "GLOBAL_REACTIVE_POWER", "VOLTAGE", "GLOBAL_INTENSITY", "SUB_METERING_1", "SUB_METERING_2", "SUB_METERING_3") 
    
  3. ここで、ベースライン・データHOUSEHOLD_POWER_BASEおよび新しいデータHOUSEHOLD_POWER_NEWを作成します。そのために、次のRスクリプトを実行します:
    %r
    
    test_base <- test[test$DATES < "2008-01-01",]
    test_new <- test[test$DATES > "2007-12-31",]
    
    # Create OML proxy objects
    
    ore.create(test_base, table="HOUSEHOLD_POWER_BASE")
    ore.create(test_new, table="HOUSEHOLD_POWER_NEW")
    
  4. ベースライン・データHOUSEHOLD_POWER_BASEを表示するには、ノートブックのSQL段落で次のSQLコマンドを実行します:
    %sql
    
    SELECT * FROM HOUSEHOLD_POWER_BASE
    FETCH FIRST 5 ROWS ONLY;
  5. 次のSQLコマンドを実行して、新しいデータHOUSEHOLD_POWER_NEWを表示します:
    %sql
    
    SELECT * FROM HOUSEHOLD_POWER_NEW
    FETCH FIRST 5 ROWS ONLY;