From eca367b92489593d96752ec2c515ae0e8a2ded83 Mon Sep 17 00:00:00 2001 From: Rui Vieira Date: Wed, 13 Mar 2024 23:01:41 +0000 Subject: [PATCH] Add documentation for data drift integration tutorial --- .../modules/ROOT/images/python-service-01.png | Bin 0 -> 20606 bytes .../modules/ROOT/images/python-service-02.png | Bin 0 -> 33579 bytes docs/modules/ROOT/nav.adoc | 3 +- .../pages/accessing-service-from-python.adoc | 267 ++++++++++++++++++ .../ROOT/pages/data-drift-monitoring.adoc | 11 +- docs/modules/ROOT/pages/python-trustyai.adoc | 16 +- 6 files changed, 287 insertions(+), 10 deletions(-) create mode 100644 docs/modules/ROOT/images/python-service-01.png create mode 100644 docs/modules/ROOT/images/python-service-02.png create mode 100644 docs/modules/ROOT/pages/accessing-service-from-python.adoc diff --git a/docs/modules/ROOT/images/python-service-01.png b/docs/modules/ROOT/images/python-service-01.png new file mode 100644 index 0000000000000000000000000000000000000000..f69b0c4dbff2221bd7c261cc49fc4edae07881b8 GIT binary patch literal 20606 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 VX|LWq8NNV!ASNT4b?@ox{|5|B7Cis} literal 0 HcmV?d00001 diff --git a/docs/modules/ROOT/images/python-service-02.png b/docs/modules/ROOT/images/python-service-02.png new file mode 100644 index 0000000000000000000000000000000000000000..7f917a9e4220ed8b7d3875c8534e7f2344231286 GIT binary patch literal 33579 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 z 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

iA8vtNJ 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 literal 0 HcmV?d00001 diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 019f86b..10f3ba1 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -7,8 +7,9 @@ ** xref:installing-opendatahub.adoc[] ** xref:bias-monitoring.adoc[] ** xref:data-drift-monitoring.adoc[] +** xref:accessing-service-from-python.adoc[] * Components ** xref:trustyai-service.adoc[] ** xref:trustyai-operator.adoc[] ** xref:python-trustyai.adoc[] -** xref:trustyai-core.adoc[] \ No newline at end of file +** xref:trustyai-core.adoc[] diff --git a/docs/modules/ROOT/pages/accessing-service-from-python.adoc b/docs/modules/ROOT/pages/accessing-service-from-python.adoc new file mode 100644 index 0000000..0962a8e --- /dev/null +++ b/docs/modules/ROOT/pages/accessing-service-from-python.adoc @@ -0,0 +1,267 @@ += Accessing Service from Python + +Data drift occurs when a machine model's performance declines or is different on unseen data compared to its training data due distribution changes in the data over time. In this notebook, we explore and visualize data drift on a simple XGBoost model, that predicts credit card acceptance based on an applicant's age, credit score, years of education, and years in employment. This tutorial is a counterpart to the xref:data-drift-monitoring.adoc[data drift monitoring tutorial]. + +== Prerequisites + +Follow the instructions within the xref:installing-opendatahub.adoc[Installing Open Data Hub] section. Additionally, follow the instructions in the xref:data-drift-monitoring.adoc#deploy-model[Deploy Model] section in the Data Drift tutorial. Before proceeding, check that you have the following: + +. ODH installation +. A TrustyAI Operator +. A model-namespace project containing an instance of the TrustyAI Service +. A model storage container +. A Seldon MLServer serving runtime +. The delpoyed credit model + +== Imports + +[source,python] +---- +import os +import subprocess +import warnings +warnings.filterwarnings("ignore") + +import matplotlib.pyplot as plt + +from trustyai.utils.api.api import TrustyAIApi +from trustyai.utils.extras.metrics_service import TrustyAIMetricsService +---- + +== Clone the Data Drift Repository + +For the purposes of recreating the data drift demo, we will be reusing the data in that repository. + +[source,shell] +---- +git clone https://github.com/trustyai-explainability/odh-trustyai-demos.git +cd odh-trustyai-demos/3-DataDrift +---- + +== Initialize Metrics Service + +In order to use the metrics service, we first have to initialize it using our OpenShift login token and model namespace. + +[source,python] +---- +TOKEN = os.environ.get("TOKEN", "None") +trustyService = TrustyAIMetricsService( + token = TOKEN, + namespace="model-namespace", + verify=False +) +---- + +== Upload Model Training Data To TrustyAI + +[source,python] +---- +trustyService.upload_payload_data( + json_file="data/training_data.json" +) +---- + +== Label Data Fields + +[source,python] +---- +name_mapping = { + "modelId": "gaussian-credit-model", + "inputMapping": + { + "credit_inputs-0": "Age", + "credit_inputs-1": "Credit Score", + "credit_inputs-2": "Years of Education", + "credit_inputs-3": "Years of Employment" + }, + "outputMapping": { + "predict-0": "Acceptance Probability" + } +} + +trustyService.label_data_fields(payload=name_mapping) +---- + +== Examining TrustyAI's Model Metadata + +[source,python] +---- +trustyService.get_model_metadata() +---- + +[source,text] +---- + + +[{'metrics': {'scheduledMetadata': {'metricCounts': {}}}, + 'data': {'inputSchema': {'items': {'credit_inputs-2': {'type': 'DOUBLE', + 'name': 'credit_inputs-2', + 'values': None, + 'index': 2}, + 'credit_inputs-3': {'type': 'DOUBLE', + 'name': 'credit_inputs-3', + 'values': None, + 'index': 3}, + 'credit_inputs-0': {'type': 'DOUBLE', + 'name': 'credit_inputs-0', + 'values': None, + 'index': 0}, + 'credit_inputs-1': {'type': 'DOUBLE', + 'name': 'credit_inputs-1', + 'values': None, + 'index': 1}}, + 'remapCount': 2, + 'nameMapping': {'credit_inputs-0': 'Age', + 'credit_inputs-1': 'Credit Score', + 'credit_inputs-2': 'Years of Education', + 'credit_inputs-3': 'Years of Employment'}, + 'nameMappedItems': {'Years of Education': {'type': 'DOUBLE', + 'name': 'credit_inputs-2', + 'values': None, + 'index': 2}, + 'Age': {'type': 'DOUBLE', + 'name': 'credit_inputs-0', + 'values': None, + 'index': 0}, + 'Years of Employment': {'type': 'DOUBLE', + 'name': 'credit_inputs-3', + 'values': None, + 'index': 3}, + 'Credit Score': {'type': 'DOUBLE', + 'name': 'credit_inputs-1', + 'values': None, + 'index': 1}}}, + 'outputSchema': {'items': {'predict-0': {'type': 'FLOAT', + 'name': 'predict-0', + 'values': None, + 'index': 4}}, + 'remapCount': 2, + 'nameMapping': {'predict-0': 'Acceptance Probability'}, + 'nameMappedItems': {'Acceptance Probability': {'type': 'FLOAT', + 'name': 'predict-0', + 'values': None, + 'index': 4}}}, + 'observations': 1000, + 'modelId': 'gaussian-credit-model'}} +---- + +== Register Drift Monitoring + +[source,python] +---- +drift_monitoring = { + "modelId": "gaussian-credit-model", + "referenceTag": "TRAINING" +} +trustyService.get_metric_request( + payload=drift_monitoring, + metric="drift/meanshift", reoccuring=True +) +---- + +[source,text] +---- +'{"requestId":"709174f5-a3f4-4ae9-8f7e-a56b708836ff","timestamp":"2024-03-06T14:23:17.740+00:00"}' +---- + +== Check the Metrics + +Let's get the meanshift values for the training data we just uploaded to the TrustyAI service for the past 5 minutes. + +[source,python] +---- +train_df = trustyService.get_metric_data( + metric="trustyai_meanshift", + time_interval="[5m]" +) +display(train_df.head()) +---- + +[options="header"] +|=== +| timestamp | Age | Credit Score | Years of Education | Years of Employment + +| 2024-03-06 09:23:18 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:22 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:26 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:30 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:34 | 1.0 | 1.0 | 1.0 | 1.0 +|=== + +Let's also visualize the meanshift in a plot similar to the one displayed in ODH Observe -> Metrics tab. We will define a helper function so that we can use it again for the unseen data. + +[source,python] +---- +def plot_meanshift(df): + """ + :param df: A pandas DataFrame returned by the TrustyAIMetricsService().get_metric_request + function with columns corresponding to the timestamp and name of the metric + returns a scatterplot with the timestamp on the x-axis and the specific metric on the y-axis + """ + plt.figure(figsize=(12,5)) + for col in df.columns[1:]: + plt.plot( + df["timestamp"], + df[col] + ) + plt.xlabel("timestamp") + plt.ylabel("meanshift") + plt.xticks(rotation=45) + plt.legend(df.columns[1:]) + plt.tight_layout() + plt.show() + +plot_meanshift(train_df) +---- + +image::python-service-01.png[Mean Shift plot] + +== Collect "Real-World" Inferences + +[source,python] +---- +model_name = "gaussian-credit-model" +model_route = TrustyAIApi().get_service_route( + name=model_name, + namespace=trustyService.namespace +) + +for batch in list(range(0, 596, 5)): + trustyService.upload_data_to_model( + model_route=f"{model_route}/v2/models/gaussian-credit-model", + json_file=f"data/data_batches/{batch}.json" + ) +---- + +== Observe Drift + +Let's check if our model is behaving differently on the unseen data. + +[source,python] +---- +test_df = trustyService.get_metric_data( + metric="trustyai_meanshift", + time_interval="[5m]" + ) +display(test_df.head()) +---- + +[options="header"] +|=== +| timestamp | Age | Credit Score | Years of Education | Years of Employment + +| 2024-03-06 09:23:18 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:22 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:26 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:30 | 1.0 | 1.0 | 1.0 | 1.0 +| 2024-03-06 09:23:34 | 1.0 | 1.0 | 1.0 | 1.0 +|=== + +[source,python] +---- +plot_meanshift(test_df) +---- + +image::python-service-02.png[Mean Shift plot] + +As observed, the meanshift values for each of the features have changed drastically from the training to test data, dropping below 1.0. In particular, Age and Credit Score are significantly different according to a p-value of 0.05. Thus, it is clear that our model suffers from data drift. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/data-drift-monitoring.adoc b/docs/modules/ROOT/pages/data-drift-monitoring.adoc index 146a05a..2b08252 100644 --- a/docs/modules/ROOT/pages/data-drift-monitoring.adoc +++ b/docs/modules/ROOT/pages/data-drift-monitoring.adoc @@ -17,6 +17,7 @@ Follow the instructions within the xref:installing-opendatahub.adoc[Installing o you should have an ODH installation, a TrustyAI Operator, and a `model-namespace` project containing an instance of the TrustyAI Service. +[#deploy-model] == Deploy Model . Navigate to the `model-namespace` created in the setup section: @@ -97,7 +98,7 @@ include::example$model_gaussian_credit.yaml[] + . `data_tag`: A string tag to reference this particular set of data. Here, we choose `"TRAINING"` . `request`: A https://kserve.github.io/website/0.8/modelserving/inference_api/#inference-request-json-object[KServe Inference Request], as if you were sending this data directly to the model server's `/infer` endpoint. -. `response`: (Optionally) the https://kserve.github.io/website/0.8/modelserving/inference_api/#inference-response-json-objectt[KServe Inference Response] that is returned from sending the above request to the model. +. `response`: (Optionally) the https://kserve.github.io/website/0.8/modelserving/inference_api/#inference-response-json-objectt[KServe Inference Response] that is returned from sending the above request to the model. == Examining TrustyAI's Model Metadata @@ -144,7 +145,7 @@ curl -sk -H 'Authorization: Bearer ${TOKEN}' \ You should see the message `Feature and output name mapping successfully applied.` The payload of the request is a simple set of `original-name : new-name` pairs, assigning new meaningful names to the input and output -features of our model. +features of our model. == Register the Drift Monitoring @@ -174,7 +175,7 @@ the reference distribution. + image::data_drift_meanshift_initial.png[Initial Meanshift Chart] + -. You'll notice that a metric is emitted for each of the four features and the single output, making for five measurements in total. All metric values should equal 1 (no drift), which makes sense: we _only_ have the training data, which can't drift from itself. +. You'll notice that a metric is emitted for each of the four features and the single output, making for five measurements in total. All metric values should equal 1 (no drift), which makes sense: we _only_ have the training data, which can't drift from itself. == Collect "Real-World" Inferences @@ -200,7 +201,7 @@ done image::data_drift_meanshift_post.png[Post-deployment metrics] Navigating back to the Observe -> Metrics page in the OpenShift console, we can see the MeanShift metric -values for the various features changes. Notably, the values for `Credit Score`, `Age`, and `Acceptance Probability` have all dropped to 0, indicating there is a statistically very high likelihood that the values of these fields in the inference data come from a different distribution than that of the training data. Meanwhile, the `Years of Employment` and `Years of Education` scores have dropped to 0.34 and 0.82 respectively, indicating that there is a little drift, but not enough to be particularly concerning. Remember, the Mean-Shift metric scores are p-values, so only values < 0.05 indicate statistical significance. +values for the various features changes. Notably, the values for `Credit Score`, `Age`, and `Acceptance Probability` have all dropped to 0, indicating there is a statistically very high likelihood that the values of these fields in the inference data come from a different distribution than that of the training data. Meanwhile, the `Years of Employment` and `Years of Education` scores have dropped to 0.34 and 0.82 respectively, indicating that there is a little drift, but not enough to be particularly concerning. Remember, the Mean-Shift metric scores are p-values, so only values < 0.05 indicate statistical significance. == A Peek Behind The Curtain To better understand the what these metrics tell us, let's take a look behind the curtain at the actual data I generated for this example, and look at the real distributions of the training and inference @@ -211,7 +212,7 @@ image::data_drift_gaussian_credit_model_distributions.png[Real Data Distribution In red are each features' distributions in the training set, while the blue shows the distribution seen in the "real-world" inference data. We can clearly see that the `Age` and `Credit Score` data are drawn from two different distributions, while `Years of Education` and `Years of Employment` look -to be the same distribution, and this exactly aligns with the metric values we observed in the previous section. Naturally, the differing input distributions also cause the output `Acceptance Probability` distribution to shift as well. +to be the same distribution, and this exactly aligns with the metric values we observed in the previous section. Naturally, the differing input distributions also cause the output `Acceptance Probability` distribution to shift as well. == Conclusion diff --git a/docs/modules/ROOT/pages/python-trustyai.adoc b/docs/modules/ROOT/pages/python-trustyai.adoc index 021cb7c..5d168a1 100644 --- a/docs/modules/ROOT/pages/python-trustyai.adoc +++ b/docs/modules/ROOT/pages/python-trustyai.adoc @@ -6,12 +6,20 @@ Python TrustyAI is a Python library for explainable AI. It is a wrapper around t The library is available on PyPi and can be installed with pip. -```bash +[source,shell] +---- pip install trustyai -``` +---- To install additional experimental features, the following command can be used: -```bash +[source,shell] +---- pip install trustyai[extras] -``` \ No newline at end of file +---- + +== Service integration + +The Python TrustyAI library allows for interaction with a running xref:trustyai-service.adoc[TrustyAI service]. + +For an example, please consult the xref:accessing-service-from-python.adoc[] tutorial. \ No newline at end of file