{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "6vf1kppLlV7e" }, "source": [ "Análisis de modelos con TensorFlow Model Analysis\n", "=================================================" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
PRECAUCIÓN 😱: El tema presentado en esta sección está clasificado como avanzado. El entendimiento de este contenido es totalmente opcional.
" ] }, { "cell_type": "markdown", "metadata": { "id": "ucvcfvjFlV7k" }, "source": [ "¿Que es TensorFlow Model Analysis?\n", "-----------------------------------------------------\n", "\n", "TensorFlow Model Analysis (TFMA) es una biblioteca de `Python` para realizar la evaluación del modelo en diferentes segmentos de datos. TFMA es una herramienta muy potente en ambientes productivos ya que realiza sus cálculos de manera distribuida sobre grandes cantidades de datos utilizando [Apache Beam](https://beam.apache.org/), lo cual lo hace altamente escalable. TFMA se puede utilizar para investigar y visualizar el rendimiento de un modelo con respecto a las características del conjunto de datos.\n", "\n", "Para demostrar esta técnica utilizaremos el conjunto de datos del censo UCI." ] }, { "cell_type": "markdown", "metadata": { "id": "RVxebNdYlV7m" }, "source": [ "Instalar TFMA\n", "-------------" ] }, { "cell_type": "markdown", "metadata": { "id": "u7cVwX_olV7n" }, "source": [ "Instalaremos TFMA como cualquier librería utilizando `pip`:\n", "\n", "```bash\n", "pip install tensorflow-model-analysis\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instalaremos aqui esta librería junto con otras necesarias:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!wget https://raw.githubusercontent.com/santiagxf/E72102/master/docs/develop/modeling/selection/code/model_analysis.txt \\\n", " --quiet --no-clobber\n", "!pip install -r model_analysis.txt --quiet" ] }, { "cell_type": "markdown", "metadata": { "id": "xqfZZ5AplV7n" }, "source": [ "### Instalación en Jupyter corriendo en su equipo\n", "\n", "Para poder utilizar esta librería, deberá instalar las siguientes extensiones. Estas extensiones no son necesarias en Google Colab, pero si para ejecutar este notebook en su instalación local. Los `widgets` le permitiran explorar las propiedades de su modelo." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "osdZGA_0lV7o" }, "outputs": [], "source": [ "!jupyter nbextension install --py --symlink tensorflow_model_analysis --sys-prefix " ] }, { "cell_type": "markdown", "metadata": { "id": "KE5U1RnXlV7p" }, "source": [ "Habilitamos las extensiones en este notebook:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "6sG6F-3qlV7q", "outputId": "85d3ca9a-a0ef-417f-ea4b-e259236b472e" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enabling notebook extension jupyter-js-widgets/extension...\n", " - Validating: \u001b[32mOK\u001b[0m\n", "2021-10-26 09:22:53.328925: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory\n", "2021-10-26 09:22:53.328983: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", "Enabling notebook extension tensorflow_model_analysis/extension...\n", " - Validating: \u001b[32mOK\u001b[0m\n" ] } ], "source": [ "!jupyter nbextension enable --py widgetsnbextension --sys-prefix \n", "!jupyter nbextension enable --py tensorflow_model_analysis --sys-prefix " ] }, { "cell_type": "markdown", "metadata": { "id": "95aYT2MllV7r" }, "source": [ "Explorando un modelo\n", "------------------" ] }, { "cell_type": "markdown", "metadata": { "id": "EqDGh_A0lV7s" }, "source": [ "### Sobre el conjunto de datos del censo UCI\n", "\n", "El conjunto de datos del censo de la UCI es un conjunto de datos en el que cada registro representa a una persona. Cada registro contiene 14 columnas que describen a una una sola persona, de la base de datos del censo de Estados Unidos de 1994. Esto incluye información como la edad, el estado civil y el nivel educativo. La tarea es determinar si una persona tiene un ingreso alto (definido como ganar más de $50 mil al año). Esta tarea, dado el tipo de datos que utiliza, se usa a menudo en el estudio de equidad, en parte debido a los atributos comprensibles del conjunto de datos, incluidos algunos que contienen tipos sensibles como la edad y el género, y en parte también porque comprende una tarea claramente del mundo real.\n", "\n", "El mismo tiene las siguientes características:" ] }, { "cell_type": "markdown", "metadata": { "id": "lIa1d_AVlV7s" }, "source": [ "- Education-Num\n", "- Occupation\n", "- Marital-Status\n", "- Never-married\n", "- Capital-Loss\n", "- Race\n", "- Country\n", "- Workclass\n", "- Age\n", "- Education\n", "- Hours-per-week\n", "- Sex\n", "- Relationship\n", "- Capital-Gain\n", "- Target" ] }, { "cell_type": "markdown", "metadata": { "id": "DHRFZo5flV7t" }, "source": [ "### Sobre el modelo\n", "\n", "Utilizaremos un modelo entrenado en este conjunto de datos. El mismo lo puede acceder desde `datasets/uci_census/model/1`. Lo descargaremos para que esté disponible:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "hc9MhoajlV7t" }, "outputs": [], "source": [ "!wget https://santiagxf.blob.core.windows.net/public/datasets/uci_census.zip \\\n", " --quiet --no-clobber\n", "!mkdir -p datasets/uci_census\n", "!unzip -qq uci_census.zip -d datasets/uci_census" ] }, { "cell_type": "markdown", "metadata": { "id": "Y-pGBju8lV7t" }, "source": [ "### Utilizando TFMA" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "ptGNh46NlV7u" }, "outputs": [], "source": [ "import tensorflow as tf\n", "import tensorflow_model_analysis as tfma" ] }, { "cell_type": "markdown", "metadata": { "id": "ZJ8QYl-FlV7u" }, "source": [ "Como primer paso, deberemos cargar nuestro modelo en un formato que TFMA pueda interpretar. En este caso, utilizaremos un modelo que ya fué entrenado sobre el conjunto de datos utilizando `TensorFlow` `Keras`. TFMA soporta modelos de `keras`, modelos genéricos basados en `TF2 signature APIs`, y modelos basados en estimadores (`estimator`) de `TensorFlow`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "NxEfJwJvlV7u" }, "outputs": [], "source": [ "eval_shared_model = tfma.default_eval_shared_model(eval_saved_model_path='./datasets/uci_census/model/1',\n", " tags=[tf.saved_model.SERVING])" ] }, { "cell_type": "markdown", "metadata": { "id": "-S52vO_VlV7v" }, "source": [ "Para poder utilizar TFMA en nuestro modelo, deberemos generar un objeto de tipo `EvalConfig` donde insertaremos toda la configuración de cómo evaluar nuestro modelo y bajo que aspectos. Deberemos indicar:\n", "\n", "- `ModelSpec`, el cual representa la configuración del modelo que intentamos ejecutar. Aquí deberemos indicar la columna en donde se encuentran los valores verdaderos del conjunto de datos, el nombre de la columna donde nuestro modelo deposita las predicciones y la firma del mismo (en caso de que ubiera más de una.\n", "- `SlicingSpec`, las cuales representan todas las formas en las que queremos particionar los datos y obtener métricas al respecto. Siempre habrá un `SlicingSpec` que representa el `overall` del modelo, y está indicado en la primera posición (vea el siguiente código). Puede indicar especificaciones que cubren más de una columna.\n", "- `MetricsSpec`, las cuales representan las métricas que TFMA debe calcular sobre nuestro modelo. Para conocer el listado completo de métricas disponibles puede revisar [TensorFlow Metric Analysis Metrics](https://www.tensorflow.org/tfx/model_analysis/metrics). Algunos puntos a notar:\n", "\n", " - `binarize=BinarizationOptions` está indicado ya que nuestro modelo predice las probabilidades para cada una de las clases (en lugar de predecir alguna clase en particular junto con su nivel de confidencia). Para que TFMA pueda comparar las métricas correctamente es necesario que se compuden contra alguna clase en particular.\n", " - `MetricConfig` representa la configuración de cada una de las métricas. Note que es posible comparar la métrica con un modelo anteriormente disponible utilizando `MetricThreshold`. Esto es útil para comparar nuestro modelo con su versión anterior." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "oW1tkbdPlV7v" }, "outputs": [], "source": [ "eval_config = tfma.EvalConfig(\n", " model_specs=[tfma.ModelSpec(label_key='Target',\n", " signature_name='classification',\n", " prediction_key='scores')],\n", " slicing_specs=[\n", " tfma.SlicingSpec(), # Overall\n", " tfma.SlicingSpec(feature_keys=[\"Race\"]),\n", " tfma.SlicingSpec(feature_keys=[\"Occupation\"]),\n", " tfma.SlicingSpec(feature_keys=[\"Race\", \"Occupation\"]),\n", " ],\n", " metrics_specs=[\n", " tfma.MetricsSpec(\n", " binarize=tfma.BinarizationOptions(class_ids={ 'values': [0]}),\n", " metrics=[\n", " tfma.MetricConfig(class_name='BinaryAccuracy'),\n", " tfma.MetricConfig(class_name='ExampleCount'),\n", " tfma.MetricConfig(class_name='FalsePositives'),\n", " tfma.MetricConfig(class_name='TruePositives'),\n", " tfma.MetricConfig(class_name='FalseNegatives'),\n", " tfma.MetricConfig(class_name='TrueNegatives'),\n", " ])\n", " ])" ] }, { "cell_type": "markdown", "metadata": { "id": "WVAGpJqelV7w" }, "source": [ "> **Nota:** `BinarizationOptions` fué indicado en esta configuración ya que nuestro modelo [predice las probabilidades para cada una de las clases disponibles en lugar de la clase más probable](https://www.tensorflow.org/tfx/model_analysis/metrics#multi-classmulti-label_binarized_metrics). Para más información sobre esta configuración puede revisar https://github.com/tensorflow/model-analysis/blob/master/g3doc/faq.md" ] }, { "cell_type": "markdown", "metadata": { "id": "nalCp-CmlV7w" }, "source": [ "#### Evaluando el modelo" ] }, { "cell_type": "markdown", "metadata": { "id": "TPo4n1uYlV7w" }, "source": [ "Una vez que tenemos la configuración lista, evaluamos el modelo contra un conjunto de datos de validación. Note que esté conjunto de datos fué especificado utilizando el formato `TFRecord`, el cual es un formato altamente eficiente en el ecosistema de `TensorFlow`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "icReC08SlV7w", "outputId": "67f728d1-5334-41f8-b7e2-4a976bde01eb" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:absl:Tensorflow version (2.6.0) found. Note that TFMA support for TF 2.0 is currently in beta\n", "WARNING:root:Make sure that locally built Python SDK docker image has Python 3.8 interpreter.\n" ] } ], "source": [ "eval_result = tfma.run_model_analysis(\n", " eval_shared_model=eval_shared_model,\n", " eval_config=eval_config,\n", " data_location='datasets/uci_census/adult.tfrecord',\n", " output_path='datasets/uci_census/evaluation')" ] }, { "cell_type": "markdown", "metadata": { "id": "m_ly3lLwlV7x" }, "source": [ "Visualizamos los resultados en Jupyter utilizando la extensión que instalamos al comienzo de este notebook. Aquí indicamos los resultados de la evaluación y la vista en particular que queremos explorar:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "MbuNuxlplV7x" }, "outputs": [], "source": [ "tfma.view.render_slicing_metrics(eval_result, slicing_column=\"Race\")" ] }, { "cell_type": "markdown", "metadata": { "id": "I8PWAelilV7x" }, "source": [ "El resultado será algo similar a lo siguiente:\n", "\n", "![Model evaluation](../../../_images/tfma_model_eval.png)" ] }, { "cell_type": "markdown", "metadata": { "id": "ZTFGp6jwlV7x" }, "source": [ "> Tip: Si tiene problemas para visualizar este widget, pruebe:\n", "\n", "```\n", "jupyter nbextension disable --py widgetsnbextension\n", "jupyter nbextension enable --py widgetsnbextension\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "pceoegN8lV7x" }, "source": [ "#### Combinaciones de columnas" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "HMnOMIyBlV7x" }, "outputs": [], "source": [ "tfma.view.render_slicing_metrics(\n", " eval_result,\n", " slicing_spec=tfma.SlicingSpec(\n", " feature_keys=[\"Race\", \"Occupation\"]))" ] }, { "cell_type": "markdown", "metadata": { "id": "lhnwvXRmlV7y" }, "source": [ "![Cross model](../../../_images/tfma_model_cross.png)" ] }, { "cell_type": "markdown", "metadata": { "id": "-3Muag6ulV7y" }, "source": [ "Note que la cantidad de combinaciones puede ser bastante elevada. En general, estaremos interesados en acotarlas especificando algunos valores que estamos queriendo investigar:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "mNfLys-vlV7y" }, "outputs": [], "source": [ "tfma.view.render_slicing_metrics(\n", " eval_result,\n", " slicing_spec=tfma.SlicingSpec(\n", " feature_keys=['Occupation'], feature_values={'Race': 'White'}))" ] }, { "cell_type": "markdown", "metadata": { "id": "vivvNk_blV7y" }, "source": [ "![Cross metrics](../../../_images/tfma_model_cross_filtered.png)" ] }, { "cell_type": "markdown", "metadata": { "id": "sLMV_zZPlV7y" }, "source": [ "#### Métricas agregadas" ] }, { "cell_type": "markdown", "metadata": { "id": "kS7_05aalV7y" }, "source": [ "Una forma similar de trabajar con modelos de multiclase o con modelos de clasificación binaria pero que devuelve la probabilidad de cada una de las clases, es utilizar métricas agregredas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "wBm5gV2FlV7y" }, "outputs": [], "source": [ "eval_config = tfma.EvalConfig(\n", " model_specs=[tfma.ModelSpec(label_key='Target',\n", " signature_name='classification',\n", " prediction_key='scores')],\n", " slicing_specs=[\n", " tfma.SlicingSpec(), # Overall\n", " tfma.SlicingSpec(feature_keys=[\"Race\"]),\n", " tfma.SlicingSpec(feature_keys=[\"Occupation\"])\n", " ],\n", " metrics_specs=[\n", " tfma.MetricsSpec(\n", " metrics=[\n", " tfma.MetricConfig(class_name='BinaryAccuracy'), \n", " tfma.MetricConfig(class_name='BalancedAccuracy'),\n", " tfma.MetricConfig(class_name='ExampleCount'),\n", " tfma.MetricConfig(class_name='FalsePositives'),\n", " tfma.MetricConfig(class_name='TruePositives'),\n", " tfma.MetricConfig(class_name='FalseNegatives'),\n", " tfma.MetricConfig(class_name='TrueNegatives'),\n", " ],\n", " aggregate=tfma.AggregationOptions(macro_average=True, \n", " weighted_macro_average=True,\n", " class_weights={\n", " 0: 1.0, \n", " 1: 10.0,\n", " })\n", " ),\n", " ])" ] }, { "cell_type": "markdown", "metadata": { "id": "9u0wDRb7lV7z" }, "source": [ "`macro_average` computara las métricas de forma `macro`, es decir, computara la métrica para cada clase y luego tomará el promedio. Utilizando la opción de `weighted_macro` tendremos la posibilidad de cambiar el peso que representa en el promedio cada clase." ] }, { "cell_type": "markdown", "metadata": { "id": "gOwTe1ZClV7z" }, "source": [ "#### Generando graficos de calibración" ] }, { "cell_type": "markdown", "metadata": { "id": "gmOmtptolV7z" }, "source": [ "Generalmente, para cualquier problema de clasificación, solemos predecir el valor de clase mas probable de ser la verdadera. Sin embargo, a veces, queremos predecir las probabilidades propiamente dichas de cada clase.\n", "\n", "Esto es muy útil para la evaluación de un modelo de clasificación. Puede ayudarnos a comprender qué tan \"seguro\" es un modelo mientras predice una clase y puede ayudarnos a interpretar qué tan decisivo es un modelo de clasificación. Generalmente, los clasificadores que tienen una probabilidad lineal de predecir las etiquetas de cada clase se denominan **calibrados**. El problema es que no todos los modelos de clasificación están calibrados.\n", "\n", "Algunos modelos pueden dar estimaciones deficientes de las probabilidades de clase y algunos ni siquiera admiten la predicción de probabilidad.\n", "\n", "**Curvas de calibración:**\n", "\n", "Las curvas de calibración se utilizan para evaluar qué tan calibrado está un clasificador, es decir, cómo difieren las probabilidades de predecir cada clase. El eje x representa la probabilidad promedio predicha en cada contenedor. El eje y es la proporción de positivos (la proporción de predicciones positivas). La curva del modelo calibrado ideal es una línea recta lineal desde (0, 0) que se mueve linealmente." ] }, { "cell_type": "markdown", "metadata": { "id": "DIF2OsPnlV7z" }, "source": [ "**Curvas de calibración en TFMA**\n", "\n", "Al igual que con las métricas, los gráficos de calibración se pueden ver por cada predictor. Sin embargo, a diferencia de las métricas, solo se pueden mostrar los gráficos de un valor en particular, por lo que se debe usar `tfma.SlicingSpec` y debe especificar tanto el nombre como el valor del predictor. Tambiés es posible mostrar las gráficas generales del modelo." ] }, { "cell_type": "markdown", "metadata": { "id": "F0d8nr5xlV7z" }, "source": [ "Indicamos en la configuración que necesitamos tener métricas para la característica \"Race\" con el valor \"White\":" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "id": "pyEdvRJylV7z" }, "outputs": [], "source": [ "eval_config = tfma.EvalConfig(\n", " model_specs=[tfma.ModelSpec(label_key='Target',\n", " signature_name='classification',\n", " prediction_key='scores')],\n", " slicing_specs=[\n", " tfma.SlicingSpec(), # Overall\n", " tfma.SlicingSpec(feature_keys=[\"Occupation\"]),\n", " tfma.SlicingSpec(feature_values={ \"Race\": \"White\" }),\n", " ],\n", " metrics_specs=[\n", " tfma.MetricsSpec(\n", " binarize=tfma.BinarizationOptions(class_ids={ 'values': [0]}),\n", " metrics=[\n", " tfma.MetricConfig(class_name='BinaryAccuracy'),\n", " tfma.MetricConfig(class_name='ExampleCount'),\n", " tfma.MetricConfig(class_name='FalsePositives'),\n", " tfma.MetricConfig(class_name='TruePositives'),\n", " tfma.MetricConfig(class_name='FalseNegatives'),\n", " tfma.MetricConfig(class_name='TrueNegatives'),\n", " tfma.MetricConfig(class_name='Calibration'),\n", " tfma.MetricConfig(class_name='CalibrationPlot'),\n", " tfma.MetricConfig(class_name='ConfusionMatrixPlot'),\n", " ])\n", " ])" ] }, { "cell_type": "markdown", "metadata": { "id": "3fvRQpYUlV70" }, "source": [ "Volvemos a correr el análisis:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "id": "y3MeAccOlV70", "outputId": "3e4c2317-54f2-4b37-de2a-ba4da0487830" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:absl:Tensorflow version (2.6.0) found. Note that TFMA support for TF 2.0 is currently in beta\n", "WARNING:root:Make sure that locally built Python SDK docker image has Python 3.8 interpreter.\n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n" ] } ], "source": [ "eval_result = tfma.run_model_analysis(\n", " eval_shared_model=eval_shared_model,\n", " eval_config=eval_config,\n", " data_location='datasets/uci_census/adult.tfrecord',\n", " output_path='datasets/uci_census/evaluation')" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "referenced_widgets": [ "597d43c29f024ef4840d82eee4f2acc1" ] }, "id": "E8jcQsgQlV70", "outputId": "599587b0-10f2-4e65-e7d4-ddce7e22c476" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "28583e2daa944e929ac490790ae4ccba", "version_major": 2, "version_minor": 0 }, "text/plain": [ "PlotViewer(config={'sliceName': 'Race:White', 'metricKeys': {'calibrationPlot': {'metricName': 'calibrationHis…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tfma.view.render_plot(eval_result, slicing_spec=tfma.SlicingSpec(feature_values={\"Race\": \"White\"}), class_id=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Obtendrá unos graficos similares a los siguientes:\n", "\n", "![Calibrartion](../../../_images/tfma_model_calibration.png)\n", "\n", "![Calibrartion](../../../_images/tfma_model_residuals.png)" ] }, { "cell_type": "markdown", "metadata": { "id": "SO_-QOL3lV70" }, "source": [ "### Comparando multiples modelos" ] }, { "cell_type": "markdown", "metadata": { "id": "VoBacNAJlV70" }, "source": [ "TFMA se puede configurar para evaluar varios modelos al mismo tiempo. Por lo general, esto se hace para comparar un nuevo modelo con una línea de base (el modelo que estamos utilizando actualmente por ejemplo) para determinar cuáles son las diferencias en las métricas (por ejemplo, AUC, etc.) en relación con la línea de base. Cuando se configuran los umbrales, TFMA producirá un registro `tfma.ValidationResult` que indica si el rendimiento coincide con las expectativas." ] }, { "cell_type": "markdown", "metadata": { "id": "GG_ORePHlV71" }, "source": [ "Exploremos un modelo candidato:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TUgWCC99lV71", "outputId": "afc6cba7-9d38-4ad4-dcc2-f2d244c39a0d" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2021-10-24 16:23:40.457824: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory\n", "2021-10-24 16:23:40.457893: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", "The given SavedModel SignatureDef contains the following input(s):\n", " inputs['dense_input'] tensor_info:\n", " dtype: DT_FLOAT\n", " shape: (-1, 11)\n", " name: dense_input:0\n", "The given SavedModel SignatureDef contains the following output(s):\n", " outputs['dense_4'] tensor_info:\n", " dtype: DT_FLOAT\n", " shape: (-1, 1)\n", " name: dense_4/Sigmoid:0\n", "Method name is: tensorflow/serving/predict\n" ] } ], "source": [ "!saved_model_cli show --dir datasets/uci_census/model/2 --tag serve --signature serving_default" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "12KZwswDlV71" }, "outputs": [], "source": [ "eval_config = tfma.EvalConfig(\n", " model_specs=[tfma.ModelSpec(name='candidate'\n", " label_key='Target',\n", " signature_name='classification',\n", " prediction_key='scores'),\n", " tfma.ModelSpec(name='baseline',\n", " label_key='Target',\n", " signature_name='classification',\n", " prediction_key='scores'\n", " is_baseline=True)],\n", " \n", " slicing_specs=[\n", " tfma.SlicingSpec(), # Overall\n", " tfma.SlicingSpec(feature_keys=[\"Race\"]),\n", " tfma.SlicingSpec(feature_keys=[\"Occupation\"])\n", " ],\n", " metrics_specs=[\n", " tfma.MetricsSpec(\n", " metrics=[\n", " tfma.MetricConfig(class_name='BinaryAccuracy', \n", " threshold=tfma.MetricThreshold(\n", " # Verifica que Accuracy no sea menor a 0.7\n", " value_threshold=tfma.GenericValueThreshold(\n", " lower_bound={'value': 0.7}),\n", " # Verifica que el nuevo modelo no haya degradado la perfomrance.\n", " # (candidate - baseline) > -1e-10 or candidate > baseline - 1e-10\n", " change_threshold=tfma.GenericChangeThreshold(\n", " direction=tfma.MetricDirection.HIGHER_IS_BETTER,\n", " absolute={'value': -1e-10}))),\n", " tfma.MetricConfig(class_name='BalancedAccuracy'),\n", " tfma.MetricConfig(class_name='ExampleCount'),\n", " tfma.MetricConfig(class_name='FalsePositives'),\n", " tfma.MetricConfig(class_name='TruePositives'),\n", " tfma.MetricConfig(class_name='FalseNegatives'),\n", " tfma.MetricConfig(class_name='TrueNegatives'),\n", " ],\n", " aggregate=tfma.AggregationOptions(macro_average=True, \n", " weighted_macro_average=True,\n", " class_weights={\n", " 0: 20.0, \n", " 1: 1.0,\n", " })\n", " ),\n", " ])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "tqD96gMulV71", "outputId": "1028b813-0d34-4531-cdd7-125f0b40f429" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:absl:Tensorflow version (2.6.0) found. Note that TFMA support for TF 2.0 is currently in beta\n", "ERROR:absl:There are change thresholds, but the baseline is missing. This is allowed only when rubber stamping (first run).\n", "WARNING:root:Make sure that locally built Python SDK docker image has Python 3.8 interpreter.\n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n", "WARNING:apache_beam.io.filebasedsink:Deleting 1 existing files in target path matching: \n" ] } ], "source": [ "eval_result = tfma.run_model_analysis(\n", " eval_shared_model=eval_shared_model,\n", " eval_config=eval_config,\n", " data_location='datasets/uci_census/adult.tfrecord',\n", " output_path='datasets/uci_census/eval.tfrecord')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Dca_Rl-qlV71", "scrolled": false }, "outputs": [], "source": [ "tfma.view.render_slicing_metrics(eval_result, slicing_column=\"Race\")" ] } ], "metadata": { "colab": { "name": "model_analysis.ipynb", "provenance": [] }, "kernelspec": { "display_name": "Python 3.8.12 ('sphinx')", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.12" }, "vscode": { "interpreter": { "hash": "c0c26a04c01997af4d3a54c44ba2029caf4208eaf3de13f3aa81bddca06af044" } } }, "nbformat": 4, "nbformat_minor": 1 }