Crie um modelo de detecção de fraudes na AI Platform do Cloud com o TensorFlow Enterprise e o BigQuery

1. Visão geral

Neste laboratório, você vai ingerir diretamente um conjunto de dados do BigQuery e treinar um modelo de detecção de fraudes com o TensorFlow Enterprise na AI Platform do Google Cloud.

Conteúdo do laboratório

Você vai aprender a:

  • Analisar dados no BigQuery
  • Ingerir dados usando o conector do BigQuery no TensorFlow Enterprise
  • Criar um modelo de aprendizado profundo para detectar fraudes com um conjunto de dados desequilibrado

2. Analise os dados no BigQuery

Para executar este codelab, você vai precisar de um projeto do Google Cloud Platform com o faturamento ativado. Para criar um projeto, siga estas instruções.

Etapa 1: acessar o conjunto de dados público do BigQuery

Siga este link para acessar os conjuntos de dados públicos do BigQuery no console do Google Cloud.

Na árvore de recursos, no canto inferior esquerdo, você verá uma lista de conjuntos de dados. Navegue pelos conjuntos de dados disponíveis até encontrar ml-datasets e selecione a tabela ulb-fraud-detection dentro dele:

d5e78261514a90ef.png

Clique em cada guia para saber mais sobre o conjunto de dados:

  • A guia Esquema descreve os tipos de dados.
  • A guia Detalhes explica que esse é um conjunto de dados desequilibrado com 284.407 transações, das quais 492 são fraudulentas.
  • A guia Visualização mostra registros do conjunto de dados.

Etapa 2: consultar a tabela

A guia "Detalhes" informa o seguinte sobre os dados:

  • Tempo é o número de segundos entre a primeira transação no conjunto de dados e o horário da transação selecionada.
  • V1-V28 são colunas transformadas por uma técnica de redução de dimensionalidade chamada PCA, que anonimiza os dados.
  • Valor é o valor da transação.

Para conferir mais detalhes, clique em Tabela de consulta para executar a consulta:

581e596426a98383.png

Atualize a instrução adicionando um * para visualizar todas as colunas e clique em Executar.

SELECT * FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection` LIMIT 1000

Etapa 3: analisar os dados

O BigQuery oferece várias funções estatísticas. Vamos dar uma olhada em como os dados se correlacionam com a variável de destino Class.

SELECT CORR(Time,Class) as TimeCorr, CORR(V1,Class) as V1Corr, CORR(V2,Class) as V2Corr, CORR(Amount,Class) as AmountCorr FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`

e1e98a8315b62e9e.png

A correlação fornecerá um intervalo de -1 (correlacionada negativamente) a 1 (correlacionada positivamente), sendo 0 independente.

V1 e V2 têm uma pequena correlação com a variável de destino (em torno de -0,1 e 0,1, respectivamente).

Não vemos muita correlação com o Tempo. Uma correlação ligeiramente negativa pode nos dizer que há menos transações fraudulentas ao longo do tempo no conjunto de dados.

Valor tem até uma correlação menor, indicando que transações fraudulentas são um pouco mais propensas a transações fraudulentas em valores mais altos.

Etapa 4: calcular os valores médios para o escalonamento de atributos

A normalização de valores de atributos pode ajudar uma rede neural a convergir mais rapidamente. Um esquema comum é centralizar os valores em torno de 0 com um desvio padrão de 1. A consulta a seguir recuperará os valores médios. Não é preciso salvar o resultado, porque teremos um snippet de código para ele depois.

Observe também que a consulta inclui uma cláusula WHERE interessante. Vamos descrever isso na próxima seção, quando abordarmos como dividir os dados entre conjuntos de treinamento e teste.

SELECT
   AVG(Time), AVG(V1), AVG(V2), AVG(V3), AVG(V4), AVG(V5), AVG(V6), AVG(V7), AVG(V8),
   AVG(V9), AVG(V10),AVG(V11), AVG(V12), AVG(V13), AVG(V14), AVG(V15), AVG(V16),
   AVG(V17), AVG(V18), AVG(V19), AVG(V20), AVG(V21), AVG(V22), AVG(V23), AVG(V24),
   AVG(V25), AVG(V26), AVG(V27),AVG(V28), AVG(Amount)
FROM
   `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE
   MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),
   SAFE_CAST(Amount AS STRING)))),10) < 8

Etapa 5: dividir os dados

É uma prática comum usar três conjuntos de dados ao criar um modelo de machine learning:

  • Treinamento: usado para criar o modelo ajustando iterativamente os parâmetros
  • Validação: usada para avaliar se o modelo está com overfitting por meio da verificação de dados independentes durante o processo de treinamento
  • Teste: usado após a criação do modelo para avaliar a acurácia.

Neste codelab, usaremos uma divisão de treinamento/validação/teste 80/10/10.

Colocaremos cada conjunto de dados em uma tabela própria no BigQuery. A primeira etapa é criar um "conjunto de dados" do BigQuery - que é um contêiner para tabelas relacionadas. Com o projeto selecionado, selecione Criar conjunto de dados.

1084d9f5edbf760b.png

Em seguida, crie um conjunto de dados chamado tfe_codelab para conter as tabelas de treinamento, validação e teste.

e5b8646ebdf5f272.png

Agora, vamos executar três consultas para treinamento, teste e validação e salvar os dados no novo conjunto de dados tfe_codelab.

No Editor de consultas, execute uma consulta para gerar os dados de treinamento:

SELECT *
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),SAFE_CAST(Amount AS STRING)))),10) < 8

Quando a consulta for concluída, salve os resultados em uma tabela do BigQuery.

49d20c9b4b62f6a7.png

No conjunto de dados tfe_codelab que você acabou de criar, nomeie a tabela como ulb_fraud_detection_train e salve os dados.

6d83cf113a0682e1.png

A cláusula WHERE primeiro divide os dados calculando um hash em algumas colunas. Em seguida, ele seleciona as linhas em que o restante do hash, quando dividido por 10, é menor que 80, resultando em 80%.

Vamos repetir o mesmo processo para conjuntos de validação e teste com consultas semelhantes que selecionam 10% dos dados cada.

Validação

SELECT *
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),SAFE_CAST(Amount AS STRING)))),10) = 8

Salve os resultados dessa consulta em uma tabela chamada ulb_fraud_detection_val.

Teste

SELECT *
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
WHERE MOD(ABS(FARM_FINGERPRINT(CONCAT(SAFE_CAST(Time AS STRING),SAFE_CAST(Amount AS STRING)))),10) = 9

Salve os resultados dessa consulta em uma tabela chamada ulb_fraud_detection_test.

3. Configurar o ambiente do notebook

Agora que fizemos uma breve introdução aos dados, vamos configurar nosso ambiente de desenvolvimento de modelos.

Etapa 1: ativar as APIs

O conector do BigQuery usa a API BigQuery Storage. Procure a API BigQuery Storage no console e ative-a se ela estiver desativada.

9895a2fd3cdf8f8c.png

Etapa 2: criar uma instância de Notebooks no AI Platform

Acesse a seção de Notebooks do AI Platform do console do Cloud e clique em Nova instância. Em seguida, selecione o tipo de instância mais recente do TensorFlow Enterprise 1.x sem GPUs:

35301141e9fd3f44.png

Use as opções padrão e clique em Criar. Depois que a instância for criada, selecione Abrir JupyterLab:

3b801f8ff3db0f2f.png

Depois crie um notebook Python 3 no JupyterLab:

58523671a252b95a.png

4. Ingerir registros do BigQuery

Etapa 1: importar pacotes do Python

Na primeira célula do notebook, adicione as importações abaixo e execute a célula. Para executá-lo, pressione o botão de seta para a direita no menu superior ou pressione Command + Enter:

import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers as layers

from tensorflow_io.bigquery import BigQueryClient

import functools

tf.enable_eager_execution()

Etapa 2: definir as constantes

Agora vamos definir algumas constantes para uso no projeto. Altere GCP_PROJECT_ID para o ID do projeto real que você está usando. Continue e execute novas células ao criá-las.

GCP_PROJECT_ID = '<YOUR_PROJECT_ID>'
DATASET_GCP_PROJECT_ID = GCP_PROJECT_ID # A copy of the data is saved in the user project
DATASET_ID = 'tfe_codelab'
TRAIN_TABLE_ID = 'ulb_fraud_detection_train'
VAL_TABLE_ID = 'ulb_fraud_detection_val'
TEST_TABLE_ID = 'ulb_fraud_detection_test'

FEATURES = ['Time','V1','V2','V3','V4','V5','V6','V7','V8','V9','V10','V11','V12','V13','V14','V15','V16','V17','V18','V19','V20','V21','V22','V23','V24','V25','V26','V27','V28','Amount']
LABEL='Class'
DTYPES=[tf.float64] * len(FEATURES) + [tf.int64]

Etapa 3: definir funções auxiliares

Agora, vamos definir algumas funções. read_session() lê dados de uma tabela do BigQuery. extract_labels() é uma função auxiliar que separa a coluna de rótulos das restantes. Assim, o conjunto de dados fica no formato esperado por keras.model_fit() posteriormente.

client = BigQueryClient()

def read_session(TABLE_ID):
    return client.read_session(
        "projects/" + GCP_PROJECT_ID, DATASET_GCP_PROJECT_ID, TABLE_ID, DATASET_ID,
        FEATURES + [LABEL], DTYPES, requested_streams=2
)

def extract_labels(input_dict):
  features = dict(input_dict)
  label = tf.cast(features.pop(LABEL), tf.float64)
  return (features, label)

Etapa 4: ingerir dados

Por fim, vamos criar cada conjunto de dados e imprimir o primeiro lote do conjunto de dados de treinamento. Definimos um BATCH_SIZE de 32. Esse é um parâmetro importante que afeta a velocidade e a precisão do treinamento.

BATCH_SIZE = 32

raw_train_data = read_session(TRAIN_TABLE_ID).parallel_read_rows().map(extract_labels).batch(BATCH_SIZE)
raw_val_data = read_session(VAL_TABLE_ID).parallel_read_rows().map(extract_labels).batch(BATCH_SIZE)
raw_test_data = read_session(TEST_TABLE_ID).parallel_read_rows().map(extract_labels).batch(BATCH_SIZE)

next(iter(raw_train_data)) # Print first batch

5. Criar um modelo

Etapa 1: pré-processar dados

Vamos criar colunas para cada atributo no conjunto de dados. Neste conjunto de dados específico, todas as colunas são do tipo numeric_column, mas há vários outros tipos (por exemplo, categorical_column).

Como discutimos anteriormente, também vamos normalizar os dados para serem centralizados em torno de zero, para que a rede converja mais rapidamente. Pré-calculamos as médias de cada recurso a serem usadas nesse cálculo.

MEANS = [94816.7387536405, 0.0011219465482001268, -0.0021445914636999603, -0.002317402958335562,
         -0.002525792169927835, -0.002136576923287782, -3.7586818983702984, 8.135919975738768E-4,
         -0.0015535579268265718, 0.001436137140461279, -0.0012193712736681508, -4.5364970422902533E-4,
         -4.6175444671576083E-4, 9.92177789685366E-4, 0.002366229151475428, 6.710217226762278E-4,
         0.0010325807119864225, 2.557260815835395E-4, -2.0804190062322664E-4, -5.057391100818653E-4,
         -3.452114767842334E-6, 1.0145936326270006E-4, 3.839214074518535E-4, 2.2061197469126577E-4,
         -1.5601580596677608E-4, -8.235017846415852E-4, -7.298316615408554E-4, -6.898459943652376E-5,
         4.724125688297753E-5, 88.73235686453587]

def norm_data(mean, data):
  data = tf.cast(data, tf.float32) * 1/(2*mean)
  return tf.reshape(data, [-1, 1])

numeric_columns = []

for i, feature in enumerate(FEATURES):
  num_col = tf.feature_column.numeric_column(feature, normalizer_fn=functools.partial(norm_data, MEANS[i]))
  numeric_columns.append(num_col)

numeric_columns

Etapa 2: criar o modelo

Agora estamos prontos para criar um modelo. Vamos alimentar as colunas que acabamos de criar na rede. Em seguida, vamos compilar o modelo. Também incluímos a métrica AUC de precisão/recall, que é útil para conjuntos de dados desequilibrados.

model = keras.Sequential([
    tf.keras.layers.DenseFeatures(numeric_columns),
    layers.Dense(64, activation='relu'),
    layers.Dense(64, activation='relu'),
    layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy', tf.keras.metrics.AUC(curve='PR')])

Etapa 3: treinar o modelo

Há diversas técnicas para lidar com dados desequilibrados, incluindo sobreamostragem (gerando novos dados na classe minoritária) e subamostragem (redução dos dados na classe majoritária).

Para os fins deste codelab, vamos usar uma técnica que pondere em excesso a perda ao classificar incorretamente a classe minoritária. Vamos especificar um parâmetro class_weight ao treinar e peso "1" (fraude), já que é muito menos prevalente.

Vamos usar três períodos (passa pelos dados) neste laboratório para agilizar o treinamento. Em um cenário real, queremos executá-la por tempo suficiente até que a precisão do conjunto de validação seja eliminada.

CLASS_WEIGHT = {
    0: 1,
    1: 100
}
EPOCHS = 3

train_data = raw_train_data.shuffle(10000)
val_data = raw_val_data
test_data = raw_test_data

model.fit(train_data, validation_data=val_data, class_weight=CLASS_WEIGHT, epochs=EPOCHS)

Etapa 4: avaliar o modelo

A função evaluate() pode ser aplicada para testar dados que o modelo nunca viu para fornecer uma avaliação objetiva. Felizmente, reservamos dados de teste só para isso.

model.evaluate(test_data)

Etapa 5: análise

Neste laboratório, demonstramos como ingerir um grande conjunto de dados do BigQuery diretamente em um modelo Keras do TensorFlow. Também vimos todas as etapas da criação de um modelo. Por fim, aprendemos um pouco sobre como lidar com problemas de classificação desequilibrados.

Fique à vontade para testar diferentes arquiteturas e abordagens no conjunto de dados desequilibrado para melhorar a acurácia.

6. Limpeza

Se você quiser continuar usando este notebook, é recomendado que você o desative quando não estiver em uso. A partir da IU de Notebooks no Console do Cloud, selecione o notebook e depois clique em Parar:

57213ef2edad9257.png

Se quiser excluir todos os recursos criados neste laboratório, basta Excluir a instância do notebook em vez de interrompê-la.

Usando o menu de navegação do console do Cloud, acesse "Storage" e exclua os dois buckets que você criou para armazenar os recursos do modelo.