

 Amazon Redshift dejará de admitir la creación de nuevas UDF de Python a partir del parche 198. Las UDF de Python existentes seguirán funcionando hasta el 30 de junio de 2026. Para obtener más información, consulte la [publicación del blog](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

# Tutorial: Creación de modelos de regresión
<a name="tutorial_regression"></a>

En este tutorial, utilizará Amazon Redshift ML para crear un modelo de regresión de machine learning y ejecutar consultas de predicción en el modelo. Los modelos de regresión le permiten predecir resultados numéricos, como el precio de una casa o cuántas personas utilizarán el servicio de alquiler de bicicletas de una ciudad. El comando CREATE MODEL se usa en Amazon Redshift con los datos de entrenamiento. A continuación, Amazon Redshift ML compila el modelo, importa el modelo entrenado a Redshift y prepara una función de predicción de SQL. Puede usar la función de predicción en consultas SQL en Amazon Redshift.

En este tutorial, utilizará Amazon Redshift ML para crear un modelo de regresión que prediga el número de personas que utilizan el servicio de bicicletas compartidas de la ciudad de Toronto a cualquier hora del día. Las entradas para el modelo incluyen días festivos y condiciones meteorológicas. Utilizará un modelo de regresión, porque quiere un resultado numérico para este problema.

Puede utilizar el comando CREATE MODEL para exportar datos de entrenamiento, entrenar un modelo y hacer que el modelo esté disponible en Amazon Redshift como una función SQL. Utilice la operación CREATE MODEL para especificar los datos de entrenamiento en forma de tabla o con la instrucción SELECT.

## Ejemplos de casos de uso
<a name="tutorial_regression_tasks"></a>

Puede resolver otros problemas de regresión con Amazon Redshift ML, como predecir el valor de por vida de un cliente. También puede usar Redshift ML para predecir el precio más rentable y los ingresos resultantes de un producto.

**Tareas**
+ Requisitos previos
+ Paso 1: Cargar los datos desde Amazon S3 en Amazon Redshift
+ Paso 2: Crear el modelo de machine learning
+ Paso 3: Validar el modelo

## Requisitos previos
<a name="tutorial_regression_prereqs"></a>

Para completar este tutorial, debe realizar el procedimiento de [configuración administrativa](https://docs.aws.amazon.com/redshift/latest/dg/admin-setup.html) de Amazon Redshift ML.

## Paso 1: Cargar los datos desde Amazon S3 en Amazon Redshift
<a name="tutorial_regression_step_load"></a>

Use el [editor de consultas de Amazon Redshift v2](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-using.html) para ejecutar las siguientes consultas.

1. Debe crear tres tablas para cargar los tres conjuntos de datos públicos en Amazon Redshift. Los conjuntos de datos son los [datos del número de usuarios de bicicletas de Toronto](https://open.toronto.ca/dataset/bike-share-toronto-ridership-data/), los[datos meteorológicos históricos](https://climate.weather.gc.ca/historical_data/search_historic_data_e.html) y los [datos históricos de días festivos](https://github.com/uWaterloo/Datasets/blob/master/Holidays/holidays.csv). Ejecute la siguiente consulta en el editor de consultas de Amazon Redshift para crear las tablas denominadas `ridership`, `weather` y `holiday`.

   ```
   CREATE TABLE IF NOT EXISTS ridership (
       trip_id INT,
       trip_duration_seconds INT,
       trip_start_time timestamp,
       trip_stop_time timestamp,
       from_station_name VARCHAR(50),
       to_station_name VARCHAR(50),
       from_station_id SMALLINT,
       to_station_id SMALLINT,
       user_type VARCHAR(20)
   );
   
   CREATE TABLE IF NOT EXISTS weather (
       longitude_x DECIMAL(5, 2),
       latitude_y DECIMAL(5, 2),
       station_name VARCHAR(20),
       climate_id BIGINT,
       datetime_utc TIMESTAMP,
       weather_year SMALLINT,
       weather_month SMALLINT,
       weather_day SMALLINT,
       time_utc VARCHAR(5),
       temp_c DECIMAL(5, 2),
       temp_flag VARCHAR(1),
       dew_point_temp_c DECIMAL(5, 2),
       dew_point_temp_flag VARCHAR(1),
       rel_hum SMALLINT,
       rel_hum_flag VARCHAR(1),
       precip_amount_mm DECIMAL(5, 2),
       precip_amount_flag VARCHAR(1),
       wind_dir_10s_deg VARCHAR(10),
       wind_dir_flag VARCHAR(1),
       wind_spd_kmh VARCHAR(10),
       wind_spd_flag VARCHAR(1),
       visibility_km VARCHAR(10),
       visibility_flag VARCHAR(1),
       stn_press_kpa DECIMAL(5, 2),
       stn_press_flag VARCHAR(1),
       hmdx SMALLINT,
       hmdx_flag VARCHAR(1),
       wind_chill VARCHAR(10),
       wind_chill_flag VARCHAR(1),
       weather VARCHAR(10)
   );
   
   CREATE TABLE IF NOT EXISTS holiday (holiday_date DATE, description VARCHAR(100));
   ```

1. La siguiente consulta carga los datos de muestra en las tablas que ha creado en el paso anterior.

   ```
   COPY ridership
   FROM
       's3://redshift-ml-bikesharing-data/bike-sharing-data/ridership/' 
       IAM_ROLE default 
       FORMAT CSV 
       IGNOREHEADER 1 
       DATEFORMAT 'auto' 
       TIMEFORMAT 'auto' 
       REGION 'us-west-2' 
       gzip;
   
   COPY weather
   FROM
       's3://redshift-ml-bikesharing-data/bike-sharing-data/weather/' 
       IAM_ROLE default 
       FORMAT csv 
       IGNOREHEADER 1 
       DATEFORMAT 'auto' 
       TIMEFORMAT 'auto' 
       REGION 'us-west-2' 
       gzip;
   
   COPY holiday
   FROM
       's3://redshift-ml-bikesharing-data/bike-sharing-data/holiday/' 
       IAM_ROLE default 
       FORMAT csv 
       IGNOREHEADER 1 
       DATEFORMAT 'auto' 
       TIMEFORMAT 'auto' 
       REGION 'us-west-2' 
       gzip;
   ```

1. La siguiente consulta realiza transformaciones en los conjuntos da datos `ridership` y `weather` para eliminar sesgos o anomalías. La eliminación de sesgos y anomalías mejora la precisión del modelo. La consulta simplifica las tablas mediante la creación de dos nuevas vistas denominadas `ridership_view` y `weather_view`.

   ```
   CREATE
   OR REPLACE VIEW ridership_view AS
   SELECT
       trip_time,
       trip_count,
       TO_CHAR(trip_time, 'hh24') :: INT trip_hour,
       TO_CHAR(trip_time, 'dd') :: INT trip_day,
       TO_CHAR(trip_time, 'mm') :: INT trip_month,
       TO_CHAR(trip_time, 'yy') :: INT trip_year,
       TO_CHAR(trip_time, 'q') :: INT trip_quarter,
       TO_CHAR(trip_time, 'w') :: INT trip_month_week,
       TO_CHAR(trip_time, 'd') :: INT trip_week_day
   FROM
       (
           SELECT
               CASE
                   WHEN TRUNC(r.trip_start_time) < '2017-07-01' :: DATE THEN CONVERT_TIMEZONE(
                       'US/Eastern',
                       DATE_TRUNC('hour', r.trip_start_time)
                   )
                   ELSE DATE_TRUNC('hour', r.trip_start_time)
               END trip_time,
               COUNT(1) trip_count
           FROM
               ridership r
           WHERE
               r.trip_duration_seconds BETWEEN 60
               AND 60 * 60 * 24
           GROUP BY
               1
       );
   
   CREATE
   OR REPLACE VIEW weather_view AS
   SELECT
       CONVERT_TIMEZONE(
           'US/Eastern',
           DATE_TRUNC('hour', datetime_utc)
       ) daytime,
       ROUND(AVG(temp_c)) temp_c,
       ROUND(AVG(precip_amount_mm)) precip_amount_mm
   FROM
       weather
   GROUP BY
       1;
   ```

1. La siguiente consulta crea una tabla que combina todos los atributos de entrada relevantes de `ridership_view` y `weather_view` en la tabla `trip_data`.

   ```
   CREATE TABLE trip_data AS
   SELECT
       r.trip_time,
       r.trip_count,
       r.trip_hour,
       r.trip_day,
       r.trip_month,
       r.trip_year,
       r.trip_quarter,
       r.trip_month_week,
       r.trip_week_day,
       w.temp_c,
       w.precip_amount_mm,CASE
           WHEN h.holiday_date IS NOT NULL THEN 1
           WHEN TO_CHAR(r.trip_time, 'D') :: INT IN (1, 7) THEN 1
           ELSE 0
       END is_holiday,
       ROW_NUMBER() OVER (
           ORDER BY
               RANDOM()
       ) serial_number
   FROM
       ridership_view r
       JOIN weather_view w ON (r.trip_time = w.daytime)
       LEFT OUTER JOIN holiday h ON (TRUNC(r.trip_time) = h.holiday_date);
   ```

### Ver los datos de muestra (opcional)
<a name="tutorial_regression_view_data"></a>

La siguiente consulta muestra las entradas de la tabla. Puede ejecutar esta operación para asegurarse de que la tabla se creó correctamente.

```
SELECT * 
FROM trip_data 
LIMIT 5;
```

A continuación se muestra un ejemplo de la salida de la operación anterior.

```
+---------------------+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+
|      trip_time      | trip_count | trip_hour | trip_day | trip_month | trip_year | trip_quarter | trip_month_week | trip_week_day | temp_c | precip_amount_mm | is_holiday | serial_number |
+---------------------+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+
| 2017-03-21 22:00:00 |         47 |        22 |       21 |          3 |        17 |            1 |               3 |             3 |      1 |                0 |          0 |             1 |
| 2018-05-04 01:00:00 |         19 |         1 |        4 |          5 |        18 |            2 |               1 |             6 |     12 |                0 |          0 |             3 |
| 2018-01-11 10:00:00 |         93 |        10 |       11 |          1 |        18 |            1 |               2 |             5 |      9 |                0 |          0 |             5 |
| 2017-10-28 04:00:00 |         20 |         4 |       28 |         10 |        17 |            4 |               4 |             7 |     11 |                0 |          1 |             7 |
| 2017-12-31 21:00:00 |         11 |        21 |       31 |         12 |        17 |            4 |               5 |             1 |    -15 |                0 |          1 |             9 |
+---------------------+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+
```

### Mostrar la correlación entre los atributos (opcional)
<a name="tutorial_regression_show_correlation"></a>

Determinar la correlación le ayuda a medir la fuerza de la asociación entre los atributos. El nivel de asociación puede ayudarle a determinar qué afecta a la salida objetivo. En este tutorial, la salida objetivo es `trip_count`.

La siguiente consulta crea o reemplaza el procedimiento `sp_correlation`. Se utiliza el procedimiento almacenado denominado `sp_correlation` para mostrar la correlación entre un atributo y otros atributos en una tabla de Amazon Redshift.

```
CREATE OR REPLACE PROCEDURE sp_correlation(source_schema_name in varchar(255), source_table_name in varchar(255), target_column_name in varchar(255), output_temp_table_name inout varchar(255)) AS $$
DECLARE
  v_sql varchar(max);
  v_generated_sql varchar(max);
  v_source_schema_name varchar(255)=lower(source_schema_name);
  v_source_table_name varchar(255)=lower(source_table_name);
  v_target_column_name varchar(255)=lower(target_column_name);
BEGIN
  EXECUTE 'DROP TABLE IF EXISTS ' || output_temp_table_name;
  v_sql = '
SELECT
  ''CREATE temp table '|| output_temp_table_name||' AS SELECT ''|| outer_calculation||
  '' FROM (SELECT COUNT(1) number_of_items, SUM('||v_target_column_name||') sum_target, SUM(POW('||v_target_column_name||',2)) sum_square_target, POW(SUM('||v_target_column_name||'),2) square_sum_target,''||
  inner_calculation||
  '' FROM (SELECT ''||
  column_name||
  '' FROM '||v_source_table_name||'))''
FROM
  (
  SELECT
    DISTINCT
    LISTAGG(outer_calculation,'','') OVER () outer_calculation
    ,LISTAGG(inner_calculation,'','') OVER () inner_calculation
    ,LISTAGG(column_name,'','') OVER () column_name
  FROM
    (
    SELECT
      CASE WHEN atttypid=16 THEN ''DECODE(''||column_name||'',true,1,0)'' ELSE column_name END column_name
      ,atttypid
      ,''CAST(DECODE(number_of_items * sum_square_''||rn||'' - square_sum_''||rn||'',0,null,(number_of_items*sum_target_''||rn||'' - sum_target * sum_''||rn||
        '')/SQRT((number_of_items * sum_square_target - square_sum_target) * (number_of_items * sum_square_''||rn||
        '' - square_sum_''||rn||''))) AS numeric(5,2)) ''||column_name outer_calculation
      ,''sum(''||column_name||'') sum_''||rn||'',''||
            ''SUM(trip_count*''||column_name||'') sum_target_''||rn||'',''||
            ''SUM(POW(''||column_name||'',2)) sum_square_''||rn||'',''||
            ''POW(SUM(''||column_name||''),2) square_sum_''||rn inner_calculation
    FROM
      (
      SELECT
        row_number() OVER (order by a.attnum) rn
        ,a.attname::VARCHAR column_name
        ,a.atttypid
      FROM pg_namespace AS n
        INNER JOIN pg_class AS c ON n.oid = c.relnamespace
        INNER JOIN pg_attribute AS a ON c.oid = a.attrelid
      WHERE a.attnum > 0
        AND n.nspname = '''||v_source_schema_name||'''
        AND c.relname = '''||v_source_table_name||'''
        AND a.atttypid IN (16,20,21,23,700,701,1700)
      )
    )
)';
  EXECUTE v_sql INTO v_generated_sql;
  EXECUTE  v_generated_sql;
END;
$$ LANGUAGE plpgsql;
```

La siguiente consulta muestra la correlación entre la columna objetivo, `trip_count`, y otros atributos numéricos de nuestro conjunto de datos.

```
call sp_correlation(
    'public',
    'trip_data',
    'trip_count',
    'tmp_corr_table'
);

SELECT
    *
FROM
    tmp_corr_table;
```

A continuación se muestra la salida de la operación `sp_correlation` anterior.

```
+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+
| trip_count | trip_hour | trip_day | trip_month | trip_year | trip_quarter | trip_month_week | trip_week_day | temp_c | precip_amount_mm | is_holiday | serial_number |
+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+
|          1 |      0.32 |     0.01 |       0.18 |      0.12 |         0.18 |               0 |          0.02 |   0.53 |            -0.07 |      -0.13 |             0 |
+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+
```

## Paso 2: Crear el modelo de machine learning
<a name="tutorial_regression_create_model"></a>

1. La siguiente consulta divide los datos en un conjunto de entrenamiento y un conjunto de validación al designar el 80 % del conjunto de datos para el entrenamiento y el 20 % para la validación. El conjunto de entrenamiento es la entrada del modelo de ML para identificar el mejor algoritmo posible para el modelo. Una vez creado el modelo, se utiliza el conjunto de validación para validar la precisión del modelo.

   ```
   CREATE TABLE training_data AS
   SELECT
       trip_count,
       trip_hour,
       trip_day,
       trip_month,
       trip_year,
       trip_quarter,
       trip_month_week,
       trip_week_day,
       temp_c,
       precip_amount_mm,
       is_holiday
   FROM
       trip_data
   WHERE
       serial_number > (
           SELECT
               COUNT(1) * 0.2
           FROM
               trip_data
       );
   
   CREATE TABLE validation_data AS
   SELECT
       trip_count,
       trip_hour,
       trip_day,
       trip_month,
       trip_year,
       trip_quarter,
       trip_month_week,
       trip_week_day,
       temp_c,
       precip_amount_mm,
       is_holiday,
       trip_time
   FROM
       trip_data
   WHERE
       serial_number <= (
           SELECT
               COUNT(1) * 0.2
           FROM
               trip_data
       );
   ```

1. La siguiente consulta crea un modelo de regresión para predecir el valor de `trip_count` para cualquier fecha y hora de entrada. En el siguiente ejemplo, reemplace amzn-s3-demo-bucket por el bucket de S3 propio.

   ```
   CREATE MODEL predict_rental_count
   FROM
       training_data TARGET trip_count FUNCTION predict_rental_count 
       IAM_ROLE default 
       PROBLEM_TYPE regression 
       OBJECTIVE 'mse' 
       SETTINGS (
           s3_bucket 'amzn-s3-demo-bucket',
           s3_garbage_collect off,
           max_runtime 5000
       );
   ```

## Paso 3: Validar el modelo
<a name="tutorial_regression_step_validate"></a>

1. Utilice la siguiente consulta para generar aspectos del modelo y buscar la métrica del error cuadrado medio raíz en la salida. El error cuadrado medio es una métrica de precisión típica para los problemas de regresión.

   ```
   show model predict_rental_count;
   ```

1. Ejecute las siguientes consultas de predicción con los datos de validación para comparar el recuento de viajes previsto con el recuento de viajes real.

   ```
   SELECT
       trip_time,
       actual_count,
       predicted_count,
       (actual_count - predicted_count) difference
   FROM
       (
           SELECT
               trip_time,
               trip_count AS actual_count,
               PREDICT_RENTAL_COUNT (
                   trip_hour,
                   trip_day,
                   trip_month,
                   trip_year,
                   trip_quarter,
                   trip_month_week,
                   trip_week_day,
                   temp_c,
                   precip_amount_mm,
                   is_holiday
               ) predicted_count
           FROM
               validation_data
       )
   LIMIT
       5;
   ```

1. La siguiente consulta calcula el error cuadrado medio y el error cuadrado medio raíz basándose en los datos de validación. El error cuadrado medio y el error cuadrado medio raíz se utilizan para medir la distancia entre el destino numérico predicho y la respuesta numérica real. Un buen modelo tiene una puntuación baja en ambas métricas. La siguiente consulta devuelve el valor de ambas métricas.

   ```
   SELECT
       ROUND(
           AVG(POWER((actual_count - predicted_count), 2)),
           2
       ) mse,
       ROUND(
           SQRT(AVG(POWER((actual_count - predicted_count), 2))),
           2
       ) rmse
   FROM
       (
           SELECT
               trip_time,
               trip_count AS actual_count,
               PREDICT_RENTAL_COUNT (
                   trip_hour,
                   trip_day,
                   trip_month,
                   trip_year,
                   trip_quarter,
                   trip_month_week,
                   trip_week_day,
                   temp_c,
                   precip_amount_mm,
                   is_holiday
               ) predicted_count
           FROM
               validation_data
       );
   ```

1. La siguiente consulta calcula el porcentaje de error en el recuento de viajes para cada tiempo de viaje el 01/01/2017. La consulta ordena los tiempos de viaje desde el tiene el error porcentual más bajo hasta el tiempo con el error porcentual más alto.

   ```
   SELECT
       trip_time,
       CAST(ABS(((actual_count - predicted_count) / actual_count)) * 100 AS DECIMAL (7,2)) AS pct_error
   FROM
       (
           SELECT
               trip_time,
               trip_count AS actual_count,
               PREDICT_RENTAL_COUNT (
                   trip_hour,
                   trip_day,
                   trip_month,
                   trip_year,
                   trip_quarter,
                   trip_month_week,
                   trip_week_day,
                   temp_c,
                   precip_amount_mm,
                   is_holiday
               ) predicted_count
           FROM
               validation_data
       )
   WHERE
      trip_time LIKE '2017-01-01 %%:%%:%%'
   ORDER BY
      2 ASC;
   ```

## Temas relacionados
<a name="tutorial_regression_related_topics"></a>

Para obtener más información sobre Amazon Redshift ML, consulte la siguiente documentación:
+ [Costes de utilizar Amazon Redshift ML](https://docs.aws.amazon.com/redshift/latest/dg/cost.html)
+ [Operación CREATE MODEL](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_MODEL.html)
+ [Función EXPLAIN\$1MODEL](https://docs.aws.amazon.com/redshift/latest/dg/r_explain_model_function.html)

Para obtener más información sobre machine learning, consulte la siguiente documentación:
+ [Información general sobre machine learning](https://docs.aws.amazon.com/redshift/latest/dg/machine_learning_overview.html)
+ [Machine learning para principiantes y expertos](https://docs.aws.amazon.com/redshift/latest/dg/novice_expert.html)
+ [Qué es la equidad y la explicabilidad del modelo para las predicciones de machine learning?](https://docs.aws.amazon.com/sagemaker/latest/dg/clarify-fairness-and-explainability.html)