Tutorial: Como criar modelos de regressão - Amazon Redshift

Tutorial: Como criar modelos de regressão

Neste tutorial, você usa o Amazon Redshift ML para criar um modelo de regressão de machine learning e executar consultas de previsão no modelo. Os modelos de regressão permitem prever resultados numéricos, como o preço de uma casa ou quantas pessoas usarão o serviço de aluguel de bicicletas em uma cidade. Você usa o comando CREATE MODEL no Amazon Redshift com os dados de treinamento. Em seguida, o Amazon Redshift ML compila o modelo, importa o modelo treinado para o Redshift e prepara uma função de previsão SQL. Você pode usar a função de previsão em consultas SQL no Amazon Redshift.

Neste tutorial, você usará o Amazon Redshift ML para criar um modelo de regressão que prevê o número de pessoas que usam o serviço de compartilhamento de bicicletas da cidade de Toronto a qualquer hora do dia. As entradas para o modelo incluem feriados e condições climáticas. Você usará um modelo de regressão porque deseja um resultado numérico para esse problema.

Você pode usar o comando CREATE MODEL para exportar dados de treinamento, treinar e importar o modelo e disponibilizá-lo no Amazon Redshift como uma função SQL. Use a operação CREATE MODEL para especificar dados de treinamento como uma tabela ou instrução SELECT.

Exemplos de casos de uso

Você pode resolver outros problemas de regressão com o Amazon Redshift ML, como prever o valor da vida útil de um cliente. Você também pode usar o Redshift ML para prever o preço mais lucrativo e a receita resultante de um produto.

Tarefas

  • Pré-requisitos

  • Etapa 1: Carregar dados do Amazon S3 para o Amazon Redshift

  • Etapa 2: Criar o modelo de machine learning

  • Etapa 3: Validar o modelo

Pré-requisitos

Para finalizar este tutorial, você deve concluir a configuração administrativa do Amazon Redshift ML.

Etapa 1: Carregar dados do Amazon S3 para o Amazon Redshift

Use o editor de consultas v2 do Amazon Redshift para executar as consultas a seguir.

  1. Você deve criar três tabelas para carregar os três conjuntos de dados públicos no Amazon Redshift. Os conjuntos de dados são Toronto Bike Ridership Data (Dados sobre usuários de bicicleta em Toronto), historical weather data (dados climáticos históricos) e historical holidays data (dados históricos de feriados). Execute a consulta a seguir no editor de consultas do Amazon Redshift para criar tabelas com os nomes ridership, weather e 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));
  2. A consulta a seguir carrega os dados de exemplo nas tabelas que você criou na etapa 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;
  3. A consulta a seguir executa transformações nos conjuntos de dados ridership e weather para remover vieses ou anomalias. A remoção de vieses e anomalias resulta em melhor precisão do modelo. A consulta simplifica as tabelas criando duas novas visualizações chamadas ridership_view e 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;
  4. A consulta a seguir cria uma tabela que combina todos os atributos de entrada relevantes de ridership_view e de weather_view na tabela 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);

Visualizar os dados de exemplo (opcional)

A consulta a seguir mostra as entradas da tabela. Você pode executar essa operação para garantir se a tabela foi feita corretamente.

SELECT * FROM trip_data LIMIT 5;

Veja a seguir um exemplo de saída da operação 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 a correlação entre atributos (opcional)

Determinar a correlação ajuda a medir a consistência da associação entre os atributos. O nível de associação pode ajudar você a determinar o que afeta o resultado pretendido. Neste tutorial, o resultado pretendido é trip_count.

A consulta a seguir cria ou substitui o procedimento sp_correlation. Use o procedimento armazenado, denominado sp_correlation, para mostrar a correlação entre um atributo e outros atributos em uma tabela no 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;

A consulta a seguir mostra a correlação entre a coluna de destino, trip_count, e outros atributos numéricos em nosso conjunto de dados.

call sp_correlation( 'public', 'trip_data', 'trip_count', 'tmp_corr_table' ); SELECT * FROM tmp_corr_table;

Veja a seguir um exemplo de saída da operação anterior sp_correlation.

+------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+ | 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 | +------------+-----------+----------+------------+-----------+--------------+-----------------+---------------+--------+------------------+------------+---------------+

Etapa 2: Criar o modelo de machine learning

  1. A consulta a seguir divide os dados em um conjunto de treinamento e um conjunto de validação, designando 80% do conjunto de dados para treinamento e 20% para validação. O conjunto de treinamento é a entrada para o modelo de ML que visa identificar o melhor algoritmo possível para o modelo. Depois que o modelo é criado, o conjunto de validação é usado para validar a precisão do 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 );
  2. A consulta a seguir cria um modelo de regressão para prever o valor trip_count referente a qualquer data e hora de entrada. No exemplo a seguir, substitua amzn-s3-demo-bucket por seu próprio bucket do S3.

    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 );

Etapa 3: Validar o modelo

  1. Use a consulta a seguir para gerar aspectos do modelo e encontrar a métrica de erro quadrático médio na saída. O erro quadrático médio é uma métrica de precisão típica para problemas de regressão.

    show model predict_rental_count;
  2. Execute as consultas de previsão a seguir em relação aos dados de validação para comparar a contagem prevista com a contagem real de viagens.

    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;
  3. A consulta a seguir calcula o erro quadrático médio e o erro quadrático médio da raiz com base nos dados de validação. O erro quadrático médio e o erro quadrático médio da raiz são usados para medir a distância entre o destino numérico previsto e a resposta numérica real. Um bom modelo tem uma pontuação baixa em ambas as métricas. A consulta a seguir retorna o valor de ambas as 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 );
  4. A consulta a seguir calcula o erro percentual na contagem de viagens para cada tempo de viagem em 1.º/1/2017. A consulta ordena os tempos de viagem desde o momento com o menor erro percentual até o tempo com o erro percentual mais 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;

Para obter mais informações sobre o Amazon Redshift ML, consulte a seguinte documentação:

Para obter mais informações sobre machine learning, consulte a seguinte documentação: