モデル・モニタリングの例
モデル・モニタリングは、ユーザーが実稼働環境の機械学習モデルのパフォーマンスをモニターできるようにすることで、MLOpsで重要な役割を果たします。モニタリングを使用すると、ビジネスの目的を満たすのにモデルのパフォーマンスが十分でなくなり、更新されたモデルに置き換える必要がある時期を識別できます。
- データ・ドリフト: これは、予測作成の基盤となったデータのプロファイルが変化した場合に発生します。
- コンセプト・ドリフト: これは、正しい予測の想定が時間の経過とともに変化した場合に発生します。たとえば、消費者の好みが変化したために、保持する在庫などのターゲット変数の統計プロパティが時間の経過とともに変化する場合があります。
データ・ドリフトとコンセプト・ドリフトに影響する要因は多岐にわたるため、モデル・モニタリング・タスクが重要になります。これにより、これらの変化によって実稼働環境モデルの予測品質が損なわれた時点で、ユーザーが認識できるようになります。
- 精度:正数と負数の両方のケースを正しく分類する割合を計算します。たとえば、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乗差の平均です。
- 平均絶対誤差: これは、予測ターゲットと実際のターゲットの絶対差の平均です。
- 中央絶対誤差: これは、予測ターゲットと実際のターゲットの間の絶対差の中央値です。
モデル・モニタリング・ワークフロー
- AutoML UIを使用したモデルのデプロイ
- アクセス・トークンの取得
- モニタリングに使用するモデルのモデルIDの取得
- モデル・モニタリング・ジョブの作成
- モデル・モニタリング・ジョブの詳細の表示
- モデル・モニタリング・ジョブの更新(オプション)
- モデル・モニタリング・ジョブの有効化
- モデル・モニタリング・ジョブの出力の表示および理解
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リクエストの例
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
が指定されていない場合、startDate
はfrequency
が指定されているかどうかによって異なります。frequency
が指定されていないと、timeColumn
の最も早い日付がstartDate
として使用されます。startDate
とfrequency
の両方が指定されていないと、timeColumn
の最も早い日付か、最新のサイクルの10番目の開始日のどちらか早いほうがstartDate
とみなされます。endDate:
newData
のモニタリングの終了日またはタイムスタンプ。endDate
には、列timeColumn
か必須です。endDate
を指定しないと、timeColumn
の最新の日付が使用されます。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です。
$ 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回に実行されている場合は、最後のジョブ実行に関する情報が返されます。
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
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_BASELINE
、MODEL_ID
、ROUND (METRIC, 4)
、HAS_DRIFT
、ROUND (DRIFT, 4)
、MODEL_TYPE
、THRESHOLD
およびMODEL_METRICS
を含む表を返します。結果の最初の行は、ベースライン期間であることに注意してください。ベースライン期間のデータではドリフトが計算されないため、この行の列HAS_DRIFT
、ROUND (DRIFT, 4)
およびTHRESHOLD
は空になります。
6: モデル・モニタリング・ジョブに関するアクションの実行(オプション)
デフォルトでは、ジョブが正常に発行されると、その状態がENABLED
に設定されます。つまり、DISABLED
など、別の状態に更新されないかぎり、ジョブの発行時に指定したスケジュールに従って実行されます。これは、/omlmod/v1/jobs/{jobid}/action
エンドポイントにリクエストを送信すれば実行できます。
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データを使用して作成されています。ここで説明する例を再作成するには、次のステップに従います:
-
OMLノートブックのR段落で次のコマンドを実行し、表が存在する場合はを削除して、警告を抑制します:
%r options(warn=-1) try(ore.drop(table="HOUSEHOLD_POWER_BASE")) try(ore.drop(table="HOUSEHOLD_POWER_NEW"))
-
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")
-
ここで、ベースライン・データ
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")
-
ベースライン・データ
HOUSEHOLD_POWER_BASE
を表示するには、ノートブックのSQL段落で次のSQLコマンドを実行します:%sql SELECT * FROM HOUSEHOLD_POWER_BASE FETCH FIRST 5 ROWS ONLY;
-
次のSQLコマンドを実行して、新しいデータ
HOUSEHOLD_POWER_NEW
を表示します:%sql SELECT * FROM HOUSEHOLD_POWER_NEW FETCH FIRST 5 ROWS ONLY;