Categories Machine Learning

Funciones de Machine Learning en Snowflake: Clasificación

Press enter or click to view image in full size

Tomada de google.com

En mi artículo anterior, revisé cómo podemos usar las funciones de Machine Learning directamente en Snowflake, usando SQL. Sin necesidad de ser científico de datos o saber python ni nada tan sofisticado y lo mejor de todo, de forma simple y rápida, sin mover datos ni utilizar ninguna herramienta adicional.

Antes de mostrarte cómo se hace, retomaré las ventajas de hacerlo en Snowflake, que enuncie en mi artículo anterior:

Ventajas de hacerlo en Snowflake

  • Está integrado dentro de Snowflake
  • No es un producto o característica adicional
  • Está justo al lado de tus datos, no se requiere integración ni movimiento de datos
  • Es un proceso auto-administrado, no necesitamos infraestructura que manejar
  • Alto desempeño, con paralelización incluida
  • Flujo de datos basado en SQL, lo que lo simplifica
  • Listo para colaborar dentro de Snowflake

¿Cómo lo hago?

tomado de giphy.com

Para esta guía me voy a basar en uno de los quickstarts de Snowflake: https://quickstarts.snowflake.com/guide/getting-started-with-snowflake-cortex-ml-forecasting-and-classification/index.html?index=..%2F..index#0

Creamos una cuenta de prueba de Snowflake, si no sabes cómo hacerlo, en mi artículo anterior viene una sección donde explico cómo crearla.

Snowsight

Recordemos que Snowsight es la interfaz web de Snowflake sobre la que usualmente trabajaremos.

Tomada de https://changelog.keboola.com/snowsight-ui-for-snowflake-workspaces/

Creamos una nueva Worksheet.

Configurar los datos en Snowflake

Para empezar, crearemos los objetos necesarios para trabajar, warehouse (poder de cómputo), base de datos y el schema de la misma.

Usaremos datos que se encuentran en un bucket de S3 y los cargaremos en Snowflake.

Para hacerlo, usaremos el siguiente código, lo puedes cortar y pegar en tu worksheet.

- Usualmente se sugiere usar accountadmin para los quickstarts, pero cualquier rol con privilegios suficientes puede funcionar.
USE ROLE ACCOUNTADMIN;
- Crear base de datos de desarrollo y el schema para nuestro trabajo:
CREATE OR REPLACE DATABASE quickstart;
CREATE OR REPLACE SCHEMA ml_functions;
- Utilice recursos adecuados:
USE DATABASE quickstart;
USE SCHEMA ml_functions;
- Crear un warehouse para trabajar:
CREATE OR REPLACE WAREHOUSE quickstart_wh;
USE WAREHOUSE quickstart_wh;
- Cree un formato de archivo csv que se utilizará para ingerir desde el stage:
CREATE OR REPLACE FILE FORMAT quickstart.ml_functions.csv_ff
TYPE = 'csv'
SKIP_HEADER = 1,
COMPRESSION = AUTO;
- Cree un external stage que apunte a AWS S3 para cargar nuestros datos:
CREATE OR REPLACE STAGE s3load
COMMENT = 'Quickstart S3 Stage Connection'
URL = 's3://sfquickstarts/hol_snowflake_cortex_ml_for_sql/'
FILE_FORMAT = quickstart.ml_functions.csv_ff;
- Definir nuestro schema de tabla
CREATE OR REPLACE TABLE quickstart.ml_functions.bank_marketing(
CUSTOMER_ID TEXT,
AGE NUMBER,
JOB TEXT,
MARITAL TEXT,
EDUCATION TEXT,
DEFAULT TEXT,
HOUSING TEXT,
LOAN TEXT,
CONTACT TEXT,
MONTH TEXT,
DAY_OF_WEEK TEXT,
DURATION NUMBER(4, 0),
CAMPAIGN NUMBER(2, 0),
PDAYS NUMBER(3, 0),
PREVIOUS NUMBER(1, 0),
POUTCOME TEXT,
EMPLOYEE_VARIATION_RATE NUMBER(2, 1),
CONSUMER_PRICE_INDEX NUMBER(5, 3),
CONSUMER_CONFIDENCE_INDEX NUMBER(3,1),
EURIBOR_3_MONTH_RATE NUMBER(4, 3),
NUMBER_EMPLOYEES NUMBER(5, 1),
CLIENT_SUBSCRIBED BOOLEAN,
TIMESTAMP TIMESTAMP_NTZ(9)
);
- Ingerir datos de S3 en nuestra tabla:
COPY INTO quickstart.ml_functions.bank_marketing
FROM @s3load/customers.csv;
- Ver una muestra de los datos ingeridos:
SELECT * FROM quickstart.ml_functions.bank_marketing LIMIT 100;

Para ejecutar los enunciados de SQL, seleccionamos el botón azul “Run” de la esquina superior derecha de la pantalla Notemos que si hacemos clic en la pestaña que tiene, podemos seleccionar que ejecute todos los enunciados de forma secuencial.

Exploramos los Datos

Lo podemos hacer directamente desde la misma interfaz de Snowflake, de forma simple. Nos da, sin mayor esfuerzo, las principales métricas e incluso gráficas de acuerdo al tipo de datos para ver las distribuciones de los datos.

Veamos qué datos tenemos.

Copia y pega el siguiente código:

- Consultar una muestra de los datos ingeridos
SELECT *
FROM bank_marketing
LIMIT 100;Vemos el resultado:

Podemos ver los datos de las columnas y en la parte derecha nos genera un gráfico automáticamente si son números o fechas y un conteo de frecuencias para los datos categóricos (texto) o binarios.

En caso de que quieran revisar el diccionario de datos del dataset, pueden hacerlo aquí: https://archive.ics.uci.edu/dataset/222/bank+marketing?_fsi=TNKw8Mx5&_fsi=TNKw8Mx5

Clasificación

Una vez que exploramos nuestros datos y tenemos una idea de las columnas y su distribución, prepararemos las vistas de entrenamiento e inferencia.

Corremos el siguiente código:

- Total count of rows in the dataset
SELECT COUNT(1) as num_rows
FROM bank_marketing;
- Count of subscribed vs not subscribed:
SELECT client_subscribed, COUNT(1) as num_rows
FROM bank_marketing
GROUP BY 1;

Al ejecutarlo vemos que 41, 188 clientes, de los cuales 36, 548 (89%) no se registraron a nuestro depósito a plazos y el resto, 4, 640 (11) % si lo hicieron.

Para dejar datos disponibles para predecir, voy a usar sólo el 95% y los dividiré en muestra de entrenamiento y validación.

Para asegurar que el modelo no esté memorizando los datos ni generalizando en exceso. Es decir que se adapte a la realidad, sea capaz de predecir correctamente cuando sean datos que nunca ha visto antes.

 - Create a view with a column that will be filtered for either training/inference purposes
CREATE OR REPLACE TABLE partitioned_data as (
SELECT *,
CASE WHEN UNIFORM(0::float, 1::float, RANDOM()) < .95 THEN 'training' ELSE 'inference' END AS split_group
FROM bank_marketing
);
- Training data view:
CREATE OR REPLACE VIEW training_view AS (
SELECT * EXCLUDE split_group
FROM partitioned_data
WHERE split_group LIKE 'training');
- Inference data view
CREATE OR REPLACE VIEW inference_view AS (
SELECT * EXCLUDE split_group
FROM partitioned_data
WHERE split_group LIKE 'inference');

Snowflake AI & ML Studio

Para continuar, usaremos el Snowflake AI & ML Studio, que nos llevará paso a paso en el proceso de crear el modelo de clasificación.

En Snowsight, vamos a AI & ML, hacemos clic y ahí seleccionamos Studio.

Dentro del AI & ML Studio, seleccionamos Classification y hacemos clic en Create para abrir el asistente que nos guiará paso a paso en la creación de nuestro modelo.

Press enter or click to view image in full size

Le ponemos un nombre al modelo, seleccionamos el rol con el que estaremos trabajando y un warehouse para ejecutarlo (poder de cómputo). Al terminar seleccionamos Let’s go.

Seleccionamos la base de datos y el schema donde está la información con la que trabajaremos, aquí será training_view que recién creamos. A la derecha se visualiza un previo de los datos de la tabla que usaremos.

Seleccionamos la variable objetivo, lo que queremos predecir. Es client_subscribed, al hacerlo, se ilumina la columna en el previo de los datos a la derecha.

Clic en Next.

Press enter or click to view image in full size

Dejamos seleccionada la opción “Log all errors if training fails” abajo de la lista de campos de la izquierda. Así dejaremos que el proceso de entrenamiento del modelo se complete y grabe todos los errores relevantes en lugar de que se detenga cuando encuentre el primer error. Esto nos ayudará a hacer la depuración de los errores.

Hacemos clic en Next.

Ahora, sólo queda seleccionar los datos que vamos a clasificar. Después de entrenar el modelo, que reconozca el patrón de los clientes que se suscribieron al depósito y los que no, se hará la inferencia, la predicción de cuáles de los que no se han suscrito tienen posibilidad de hacerlo o no. Dejaremos la opción de saltar las filas que no puedan ser incluidas en la predicción para que, en caso de fallas no se detenga el proceso por completo y sólo tengamos que revisar al final las filas que dieron algún error.

Seleccionamos la tabla donde almacenaremos las predicciones del modelo, para poder tenerlas de referencia más adelante.

Hacemos clic en Done.

Press enter or click to view image in full size

¿El resultado?, un nuevo worksheet con el código listo para que lo ejecutemos, todo perfectamente documentado.

Este código entrenará el modelo, generará las predicciones así como las métricas para evaluarlo. Todo en código de SQL dentro de Snowflake.

Generar predicciones

Usando el código SQL que se generó en el paso anterior, entrenaremos un modelo, generaremos predicciones y evaluaremos las métricas de desempeño del modelo.

Primero entrenaremos el modelo

- Train our classifier:
CREATE OR REPLACE snowflake.ml.classification bank_classifier(
INPUT_DATA => SYSTEM$REFERENCE('VIEW', 'training_view'),
TARGET_COLNAME => 'CLIENT_SUBSCRIBED',
CONFIG_OBJECT => {'on_error': 'skip'}
);

Del código primero llamamos a la función snowflake.ml.classification y el nombre del modelo.

Luego, con INPUT_DATA especificamos los datos que usaremos para entrenar al modelo. Podemos pasar como referencia una vista o una tabla si los datos están listos como en nuestro caso o un query para los datos sobre los que queremos entrenar nuestro modelo.

TARGET_COLNAME, se refiere al nombre de la variable/columna objetivo que usamos para nuestro modelo. En nuestro caso es una variable CLIENT_SUBSCRIBED que tiene sólo 2 valores.

CONFIG_OBJECT es un par de valores que especifican opciones para crear métricas de evaluación como parte del proceso de entrenamiento, manejar errores que puedan aparecer, y configurar cuánto de los datos de entrada que especificamos en INPUT_DATA se reservarán para el holdout de evaluación.

Ahora clasificaremos a los clientes en nuestro nuevo dataset inference_view.

- Classify your data.
CREATE TABLE My_classification_2024_04_15 AS SELECT
*,
bank_classifier!PREDICT(
OBJECT_CONSTRUCT(*),
- This option alows the prediction process to complete even if individual rows must be skipped.
{'ON_ERROR': 'SKIP'}
) as predictions
from INFERENCE_VIEW;
- View your predictions.
SELECT * FROM My_classification_2024_04_15;
Press enter or click to view image in full size

En los resultados del modelo podemos ver que se produjeron ambos resultados, verdadero y falso ya que nuestra variable objetivo es binaria. Usualmente lo que queremos es ver la probabilidad de cada categoría directamente, en su propia columna, para eso ejecutamos el siguiente código:

SELECT * EXCLUDE predictions,
predictions:class AS class,
round(predictions['probability'][class], 3) as probability
FROM My_classification_2024_04_15;

Con él, creamos una nueva tabla con las predicciones redondeadas a 3 dígitos para mayor claridad.

Press enter or click to view image in full size

Con esto, cada fila tiene un id de cliente. Ahora podemos entender cuáles clientes tomaran la oferta individualmente, además de entender cuántos lo harán en total.

Evaluación de resultados e importancia de las variables

Ya que obtuvimos los resultados del clasificador, podemos comenzar a evaluarlo para entender mejor su desempeño, así como las variables dentro del conjunto de datos que impulsan primariamente las predicciones, es decir cuáles variables tienen más peso a la hora de influir en que un cliente tome el depósito o no.

Matriz de confusión y precisión del modelo

Uno de los métodos más comunes para evaluar un clasificador es mediante el uso de una matriz de confusión, lo que nos permite visualizar los tipos de error que el modelo está cometiendo. Típicamente se usan para calcular el precision y recall de un modelo, los cuales describen la precisión al predecir una cierta clase que nos interesa (clientes que tomaran el depósito), así como cuántos de esa clase se clasificaron correctamente (recall). En este caso:

  1. La precisión responderá “cuántas de las veces que el modelo predijo que un cliente se iba a suscribir, fue correcto” contra
  2. El recall establecerá “del total de clientes que se suscribieron, qué porcentaje pudimos identificar correctamente.

Vamos a crear nuestra matriz de confusión para revisar los datos ya que, no por nada se llama matriz de confusión.

CALL bank_classifier!SHOW_CONFUSION_MATRIX();

Esto crea la matriz de confusión.

Press enter or click to view image in full size

Para simplificarlo, podemos crear la tabla de arriba en una visualización que nos aporte más claridad para interpretarla.

Primero hacemos clic en Chart, después seleccionamos Heatgrid en Chart type, En Data seleccionamos Count en cell value, Actual Class en Rows y Predicted Class en Columns para que nos cree la siguiente gráfica.

Press enter or click to view image in full size

Para interpretarla podemos ver el siguiente meme que me ha sido muy útil para entender la matriz de confusión.

Tomada de https://sid-sharma1990.medium.com/confusion-matrix-in-machine-learning-797769539bd7

Igual que se ilustra en el meme:

  1. Sí el valor está en la columna falso (valor real) y la fila falso (valor del modelo), el modelo acertó, validamos su resultado. El cliente no se suscribió y el modelo dijo que no se suscribiría. Es un rechazo correcto.
Press enter or click to view image in full size

1. Verdadero Negativo

2. Sí está en la columna falso y la fila verdadero, es un falso negativo o un error tipo 2 como en el meme. El modelo dice que el cliente no se va a suscribir y en realidad lo hace.

Press enter or click to view image in full size

2. Falso Negativo

3. Estando en la columna verdadero y la fila falso, es un falso positivo. El modelo dijo que el cliente se va a suscribir y en realidad no lo hizo.

Press enter or click to view image in full size

3. Falso positivo

4. El cliente se suscribe y el modelo predice que lo hará. Es un verdadero positivo. Es la tierra prometida, lo que buscamos que haga el modelo correctamente ya que en este caso es el objetivo, predecir correctamente el número de clientes que se suscribirán al préstamo a plazos.

Press enter or click to view image in full size

4. Verdadero positivo

Precision & Recall

Con base en la matriz de confusión podemos ahora calcular tanto el precision como el recall (y otras métricas) del modelo de clasificación al ejecutar los siguientes queries.

El primero mostrará las métricas del modelo contra cada una de las clases (verdadero-falso para client_subscribed), mientras que las métricas globales de evaluación proporcionan el promedio de las métricas para todas las clases.

 - Calculate the evaluation metrics
CALL bank_classifier!SHOW_EVALUATION_METRICS();
CALL bank_classifier!SHOW_GLOBAL_EVALUATION_METRICS();

Aquí vemos el precision & recall además del F1 y el support que nos ayudan a entender con mayor detalle los resultados del modelo.

Press enter or click to view image in full size

Recordemos que hay varias métricas que podemos revisar y dependen en buena medida de los datos y el tipo de problema al que nos enfrentamos. Si tenemos una muestra de datos desbalanceada como es normalmente en el caso de fraude, precision y recall no son la mejor opción.

Importancia de las características

Una parte importante de crear un modelo predictivo es poder explicar sus resultados o saber en qué variables enfocarnos de todo el conjunto de datos para tomar mejores decisiones de negocio.

Este conocimiento también nos puede llevar a descartar variables que no son tan importantes para el resultado que buscamos y mejorar el proceso de negocio, así como el desempeño del modelo al trabajar con menos datos.

La función de clasificación que estamos usando nos provee con un método para hacerlo. Nos da una clasificación de las variables, ordenadas de mayor a menor importancia con valores entre 1 y 0. La importancia de todas las variables debería sumar 1. Entre más cerca esté el valor de 1, mayor importancia tendrá para predecir la variable objetivo, sí el cliente se suscribirá al préstamo.

CALL bank_classifier!SHOW_FEATURE_IMPORTANCE();

Llamamos a nuestro modelo y le indicamos que nos muestre la importancia de las variables.

Vemos la lista con las variables más relevantes para este modelo en particular. Las 3 primeras, con mayor peso son la duración, que es el tiempo que el cliente pasó durante la última interacción que tuvo con el banco; el segundo es la edad que indica que es una variable a considerar cuando se oferte el producto y, el timestamp_epochtime que es una variable que el modelo creó automáticamente para mejorar los resultados. Al ser una variable que creamos con base en los datos existentes, no estará disponible en los datos por lo que podríamos considerar la siguiente que es el euribor, la tasa de interés que de acuerdo a su valor, influirá para que el usuario tome el producto o no.

Conclusión

Con esto, vimos cómo dentro de Snowflake podemos usar una función de clasificación para crear un modelo que podemos combinar con el pronóstico del número de clientes que se suscribirán, aquí podemos también predecir qué clientes especificamente serán los que se suscriban al producto y, más importante, nos dará las variables más importantes que impulsan a que los clientes a tomar el producto que les ofrecemos, mejorando el desempeño y los ingresos hacia el negocio.

Otro beneficio adicional es ejecutar todo el ciclo de vida del modelo desde la exploración de datos, la creación de las tablas necesarias, entrenamiento, predicción y revisión de las métricas de desempeño. Todo usando SQL y dentro de Snowflake, sin necesidad de herramientas adicionales.

También se puede automatizar el proceso completo usando tareas y un cron para calendarizar el proceso de actualización de datos, entrenamiento e inferencia del modelo.

Tomado de giphy.com

You May Also Like