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. Analisar 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ê vai encontrar uma lista de conjuntos de dados. Navegue pelos conjuntos de dados disponíveis até encontrar ml-datasets e selecione a tabela ulb-fraud-detection:

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 momento da transação selecionada.
  • V1-V28 são colunas transformadas por uma técnica de redução de dimensionalidade chamada PCA, que anonimizou os dados.
  • Valor é o valor da transação.

Clique em Consultar tabela para fazer uma consulta e analisar melhor:

581e596426a98383.png

Atualize a instrução para adicionar um * e ver todas as colunas. Depois, 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 Classe.

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 fornece um intervalo de -1 (correlação negativa) a 1 (correlação positiva), sendo 0 independente.

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

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

Valor tem uma correlação ainda menor, indicando que transações fraudulentas são muito ligeiramente mais prováveis em valores mais altos.

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

Normalizar os valores de atributos pode ajudar uma rede neural a convergir mais rápido. Um esquema comum é centralizar os valores em torno de 0 com um desvio padrão de 1. A consulta a seguir vai extrair os valores médios. Não é necessário salvar o resultado, porque vamos ter um snippet de código para isso mais tarde.

Você também vai notar 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 de 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

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

  • Treinamento: usado para criar o modelo ajustando os parâmetros de maneira iterativa.
  • Validação: usada para avaliar se o modelo está sofrendo overfitting. Isso é feito verificando dados independentes durante o processo de treinamento.
  • Teste: usado depois que o modelo é criado para avaliar a acurácia.

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

Vamos colocar cada conjunto de dados em uma tabela separada no BigQuery. A primeira etapa é criar um "conjunto de dados" do BigQuery, que é um contêiner para tabelas relacionadas. Com o projeto selecionado, clique em 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 treino, 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 é inferior a 80, resultando em 80%.

Agora, repita 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 já fizemos uma breve introdução aos dados, vamos configurar o ambiente de desenvolvimento do modelo.

Etapa 1: ativar as APIs

O conector do BigQuery usa a API BigQuery Storage. Pesquise a API BigQuery Storage no console do Google Cloud e ative a API se estiver desativada.

9895a2fd3cdf8f8c.png

Etapa 2: criar uma instância do AI Platform Notebooks

Acesse a seção AI Platform Notebooks 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. Quando a instância tiver sido criada, selecione Abrir o JupyterLab:

3b801f8ff3db0f2f.png

Em seguida, crie um notebook Python 3 no JupyterLab:

58523671a252b95a.png

4. Ingerir registros do BigQuery

Etapa 1: importar pacotes Python

Na primeira célula do notebook, adicione as importações a seguir e execute a célula. Para executar, 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 constantes

Em seguida, vamos definir algumas constantes para uso no projeto. Mude GCP_PROJECT_ID para o ID do projeto que você está usando. Execute novas células à medida que as cria.

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 para separar a coluna de rótulos do restante, de modo que o conjunto de dados esteja no formato esperado por keras.model_fit() mais tarde.

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 acurácia 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 de atributos 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 de colunas, como categorical_column.

Como discutimos antes, também vamos normalizar os dados para centralizar em torno de zero para que a rede convirja mais rápido. Pré-calculamos as médias de cada recurso para usar 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 a rede com as colunas que acabamos de criar. Em seguida, vamos compilar o modelo. Estamos incluindo 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á várias técnicas para lidar com dados desequilibrados, incluindo superamostragem (gerar novos dados na classe minoritária) e subamostragem (reduzir os dados na classe majoritária).

Para este codelab, vamos usar uma técnica que aumenta a perda ao classificar incorretamente a classe minoritária. Vamos especificar um parâmetro "class_weight" ao treinar e ponderar "1" (fraude) mais alto, já que é muito menos comum.

Vamos usar três épocas (passagens pelos dados) neste laboratório para que o treinamento seja mais rápido. Em um cenário real, seria necessário executar o treinamento por tempo suficiente até que o aumento na acurácia do conjunto de validação parasse.

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 a dados de teste 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 detalhada

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

Continue testando diferentes arquiteturas e abordagens para o conjunto de dados desequilibrado e veja se consegue melhorar a acurácia.

6. Limpeza

Se você quiser continuar usando esse notebook, recomendamos que o desative quando não estiver em uso. Na interface de Notebooks no console do Cloud, selecione o notebook e 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.

No menu de navegação do console do Cloud, acesse "Storage" e exclua os dois buckets criados para armazenar os recursos do modelo.