Esta seção explora o uso potencial de autoencoders no contexto de detecção de fraude em cartão de crédito.
Definição e uso¶
Um autoencoder é um tipo especial de arquitetura de aprendizado profundo usado para aprender representações de dados baseadas exclusivamente em características descritivas. A representação, que é uma transformação dos dados brutos, é aprendida com o objetivo de reconstruir os dados originais da forma mais precisa possível. Essa estratégia de aprendizado de representação pode ser usada para redução de dimensionalidade, remoção de ruído ou até mesmo aplicações generativas.
Um autoencoder pode ser dividido em duas partes:
A parte codificadora (encoder) que mapeia a entrada para a representação, também referida como “código” ou “gargalo” (bottleneck).
O decodificador (decoder) que mapeia o código para uma reconstrução da entrada.

O encoder e o decoder podem ter arquiteturas complexas como redes neurais recorrentes ao lidar com dados sequenciais ou redes neurais convolucionais ao lidar com imagens. Mas em sua forma mais simples, são redes neurais feed-forward de múltiplas camadas. A dimensão do código, que também é a entrada do decoder, pode ser fixada arbitrariamente. Essa dimensão geralmente é escolhida para ser menor do que a dimensão de entrada original para reduzir a dimensionalidade e aprender meta-variáveis subjacentes. A dimensão da saída do decoder é a mesma que a entrada do encoder porque seu objetivo é reconstruir a entrada.
A arquitetura geralmente é treinada de ponta a ponta otimizando a reconstrução da entrada, ou seja, minimizando uma perda que mede uma diferença entre a saída do modelo e a entrada. Ela pode ser treinada com quaisquer dados não rotulados. Note que quando o autoencoder é “profundo”, ou seja, há camadas intermediárias e respectivamente entre a entrada e o bottleneck e entre o bottleneck e a saída (como na figura acima), pode-se treinar as camadas sucessivamente em vez de simultaneamente. Mais precisamente, pode-se primeiro considerar um submodelo com apenas , e e treiná-lo para reconstruir a entrada a partir do código intermediário . Em seguida, considerar um segundo submodelo com apenas , e e treiná-lo para reconstruir o código intermediário a partir do código . Finalmente, ajustar o modelo inteiro com , , , e para reconstruir a entrada.
Autoencoders podem ser usados como técnicas para detecção de anomalias não supervisionada ou semi-supervisionada, o que levou ao seu uso múltiplas vezes para detecção de fraude em cartão de crédito An & Cho (2015)Zhou & Paffenroth (2017).
Detecção de anomalias¶
Embora não detalhado anteriormente, a detecção de fraude pode ser realizada com técnicas supervisionadas e não supervisionadas Carcillo et al. (2019)Veeramachaneni et al. (2016), pois é um caso especial de um problema mais amplo denominado detecção de anomalias ou detecção de outliers. O último geralmente inclui técnicas para identificar itens que são raros ou diferem significativamente do comportamento “normal”, observável na maioria dos dados.
E pode-se facilmente ver como uma fraude de cartão de crédito pode ser definida como uma anomalia nas transações. Essas anomalias podem ser eventos raros ou surtos inesperados na atividade de comportamento de um único titular de cartão, ou padrões específicos, não necessariamente raros, no comportamento global dos consumidores. Eventos raros ou outliers podem ser detectados com técnicas não supervisionadas que aprendem a normalidade e que são capazes de estimar a discrepância em relação a essa normalidade. Mas a detecção de outros tipos de anomalia pode exigir técnicas supervisionadas com treinamento adequado.
Portanto, pode-se pensar em três tipos de técnicas de detecção de anomalias:
Técnicas supervisionadas que foram amplamente exploradas nas seções e capítulos anteriores. Essas técnicas requerem anotações em dados que consistem em duas classes, “normal” (ou “genuíno”) e “anormal” (ou “fraude”), e aprendem a discriminar entre essas classes.
Técnicas não supervisionadas que visam detectar anomalias modelando o comportamento majoritário e considerando-o como “normal”. Em seguida, detectam o comportamento “anormal” ou fraudulento buscando exemplos que não se encaixam bem ao comportamento normal.
Técnicas semi-supervisionadas que estão entre os dois casos acima e que podem aprender tanto com dados não rotulados quanto com dados rotulados para detectar transações fraudulentas.
Um autoencoder pode ser usado para modelar o comportamento normal dos dados e detectar outliers usando o erro de reconstrução como indicador. Em particular, uma maneira de fazer isso é treiná-lo para reconstruir globalmente as transações em um conjunto de dados. A tendência normal observada na maioria das transações será melhor aproximada do que eventos raros. Portanto, o erro de reconstrução de dados “normais” será menor do que o erro de reconstrução de outliers.
Um autoencoder pode, portanto, ser considerado uma técnica não supervisionada para detecção de fraude. Nesta seção, implementaremos e testaremos para detecção de fraude semi-supervisionada e não supervisionada.
Aprendizado de representação¶
Além de sua capacidade de detecção de anomalias não supervisionada, um autoencoder tem outras vantagens, como foi mencionado na introdução. Em particular, após o treinamento, pode-se usar apenas a parte do encoder para obter representações das transações para fins de visualização ou agrupamento. Se a dimensão do código for escolhida como 2 ou 3, pode-se visualizar a transação no novo espaço 2D/3D. Caso contrário, o código também pode ser usado para outros fins, como:
Agrupamento (Clustering): O agrupamento pode ser realizado no código em vez das características originais. Os grupos aprendidos a partir do agrupamento podem ser úteis para caracterizar os tipos de comportamentos de consumidores ou fraudadores.
Variáveis adicionais ou substitutivas: O código pode ser usado como variáveis substitutas, ou variáveis adicionais, para treinar qualquer modelo de aprendizado supervisionado para detecção de fraude em cartão de crédito.
Conteúdo da seção¶
O seguinte coloca em prática o uso de autoencoders para detecção de fraude em cartão de crédito. Começa definindo as estruturas de dados para transações não rotuladas. Em seguida, implementa e avalia um autoencoder para detecção de fraude não supervisionada. O autoencoder é então usado para calcular a representação de transações para visualização e agrupamento. Por fim, exploramos uma estratégia semi-supervisionada para detecção de fraude.
Vamos começar fazendo todas as importações necessárias.
# Initialization: Load shared functions and simulated data
# Load shared functions
!curl -O https://raw.githubusercontent.com/Fraud-Detection-Handbook/fraud-detection-handbook/main/Chapter_References/shared_functions.py
%run shared_functions.py
# Get simulated data from Github repository
if not os.path.exists("simulated-data-transformed"):
!git clone https://github.com/Fraud-Detection-Handbook/simulated-data-transformedEsta seção reutiliza alguns materiais específicos de “aprendizado profundo” que foram implementados na seção anterior. Isso inclui a função de avaliação, a preparação de geradores, a estratégia de parada antecipada, o laço de treinamento e assim por diante. Este material foi adicionado às funções compartilhadas.
Carregamento de dados¶
A mesma configuração experimental da seção anterior é usada para nossa exploração, ou seja, um período fixo de treinamento e validação, e as mesmas características dos dados simulados transformados (simulated-data-transformed/data/).
DIR_INPUT='simulated-data-transformed/data/'
BEGIN_DATE = "2018-06-11"
END_DATE = "2018-09-14"
print("Load files")
%time transactions_df=read_from_files(DIR_INPUT, BEGIN_DATE, END_DATE)
print("{0} transactions loaded, containing {1} fraudulent transactions".format(len(transactions_df),transactions_df.TX_FRAUD.sum()))
output_feature="TX_FRAUD"
input_features=['TX_AMOUNT','TX_DURING_WEEKEND', 'TX_DURING_NIGHT', 'CUSTOMER_ID_NB_TX_1DAY_WINDOW',
'CUSTOMER_ID_AVG_AMOUNT_1DAY_WINDOW', 'CUSTOMER_ID_NB_TX_7DAY_WINDOW',
'CUSTOMER_ID_AVG_AMOUNT_7DAY_WINDOW', 'CUSTOMER_ID_NB_TX_30DAY_WINDOW',
'CUSTOMER_ID_AVG_AMOUNT_30DAY_WINDOW', 'TERMINAL_ID_NB_TX_1DAY_WINDOW',
'TERMINAL_ID_RISK_1DAY_WINDOW', 'TERMINAL_ID_NB_TX_7DAY_WINDOW',
'TERMINAL_ID_RISK_7DAY_WINDOW', 'TERMINAL_ID_NB_TX_30DAY_WINDOW',
'TERMINAL_ID_RISK_30DAY_WINDOW']Load files
CPU times: user 387 ms, sys: 282 ms, total: 669 ms
Wall time: 760 ms
919767 transactions loaded, containing 8195 fraudulent transactions
# Set the starting day for the training period, and the deltas
start_date_training = datetime.datetime.strptime("2018-07-25", "%Y-%m-%d")
delta_train=7
delta_delay=7
delta_test=7
delta_valid = delta_test
start_date_training_with_valid = start_date_training+datetime.timedelta(days=-(delta_delay+delta_valid))
(train_df, valid_df)=get_train_test_set(transactions_df,start_date_training_with_valid,
delta_train=delta_train,delta_delay=delta_delay,delta_test=delta_test)
# By default, scales input data
(train_df, valid_df)=scaleData(train_df, valid_df,input_features)Implementação do autoencoder¶
Por consistência, a implementação dos autoencoders será feita com a biblioteca PyTorch. Como de costume, uma semente será usada da seguinte forma para garantir a reprodutibilidade:
SEED = 42
if torch.cuda.is_available():
DEVICE = "cuda"
else:
DEVICE = "cpu"
print("Selected device is",DEVICE)
seed_everything(SEED)Selected device is cuda
Vamos também converter nossas características e rótulos em tensores torch.
x_train = torch.FloatTensor(train_df[input_features].values)
x_valid = torch.FloatTensor(valid_df[input_features].values)
y_train = torch.FloatTensor(train_df[output_feature].values)
y_valid = torch.FloatTensor(valid_df[output_feature].values)O autoencoder tem a mesma entrada que a rede neural feed-forward de linha de base, mas uma saída diferente. Em vez do rótulo fraude/genuíno, seu alvo será o mesmo que a entrada. Portanto, os experimentos aqui não dependerão do FraudDataset definido anteriormente, mas de um novo Dataset: FraudDatasetUnsupervised, que recebe apenas as características descritivas da transação x e as retorna como entrada e saída.
class FraudDatasetUnsupervised(torch.utils.data.Dataset):
def __init__(self, x,output=True):
'Initialization'
self.x = x
self.output = output
def __len__(self):
'Returns the total number of samples'
return len(self.x)
def __getitem__(self, index):
'Generates one sample of data'
# Select sample index
item = self.x[index].to(DEVICE)
if self.output:
return item, item
else:
return itemtraining_set = FraudDatasetUnsupervised(x_train)
valid_set = FraudDatasetUnsupervised(x_valid)Este Dataset também pode ser convertido em DataLoaders com a função prepare_generators das funções compartilhadas.
training_generator,valid_generator = prepare_generators(training_set, valid_set, batch_size = 64)O segundo e principal elemento em nosso pipeline de aprendizado profundo é o modelo/módulo. Como nossos dados são tabulares e cada amostra é um vetor, recorreremos a um autoencoder feed-forward regular. Sua definição é muito similar à nossa rede feed-forward supervisionada para detecção de fraude, exceto que a saída tem tantos neurônios quanto a entrada, com ativações lineares, em vez de um único neurônio com ativação sigmoid. Uma camada intermediária, antes da camada de representação, também será considerada de modo que a sucessão geral de camadas com suas dimensões (input_dim, output_dim) é a seguinte:
Uma primeira camada de entrada com ativação ReLU (
input_size,intermediate_size)Uma segunda camada com ativação ReLU (
intermediate_size,code_size)Uma terceira camada com ativação ReLU (
code_size,intermediate_size)Uma camada de saída com ativação linear (
intermediate_size,input_size)
class SimpleAutoencoder(torch.nn.Module):
def __init__(self, input_size, intermediate_size, code_size):
super(SimpleAutoencoder, self).__init__()
# parameters
self.input_size = input_size
self.intermediate_size = intermediate_size
self.code_size = code_size
self.relu = torch.nn.ReLU()
#encoder
self.fc1 = torch.nn.Linear(self.input_size, self.intermediate_size)
self.fc2 = torch.nn.Linear(self.intermediate_size, self.code_size)
#decoder
self.fc3 = torch.nn.Linear(self.code_size, self.intermediate_size)
self.fc4 = torch.nn.Linear(self.intermediate_size, self.input_size)
def forward(self, x):
hidden = self.fc1(x)
hidden = self.relu(hidden)
code = self.fc2(hidden)
code = self.relu(code)
hidden = self.fc3(code)
hidden = self.relu(hidden)
output = self.fc4(hidden)
#linear activation in final layer)
return outputO terceiro elemento de nosso pipeline é o problema de otimização. O problema de aprendizado de máquina subjacente é uma regressão aqui, onde as saídas previstas e esperadas são variáveis de valor real. Portanto, a função de perda mais adaptada é o erro quadrático médio torch.nn.MSELoss.
criterion = torch.nn.MSELoss().to(DEVICE)Usando o autoencoder para detecção de fraude não supervisionada¶
Como explicado na introdução, o objetivo do autoencoder é prever a entrada a partir da entrada. Portanto, não se pode usar sua previsão diretamente para detecção de fraude. Em vez disso, a ideia é usar seu erro de reconstrução, ou seja, o erro quadrático médio (MSE) entre a entrada e a saída, como um indicador de probabilidade de fraude. Quanto maior o erro, maior a pontuação de risco. Portanto, o erro de reconstrução pode ser considerado como uma pontuação de risco de fraude prevista, e sua relevância pode ser medida diretamente com qualquer métrica sem limiar.
Para esse fim, vamos definir uma função per_sample_mse que calculará o MSE de um model para cada amostra fornecida por um generator:
def per_sample_mse(model, generator):
model.eval()
criterion = torch.nn.MSELoss(reduction="none")
batch_losses = []
for x_batch, y_batch in generator:
# Forward pass
y_pred = model(x_batch)
# Compute Loss
loss = criterion(y_pred.squeeze(), y_batch)
loss_app = list(torch.mean(loss,axis=1).detach().cpu().numpy())
batch_losses.extend(loss_app)
return batch_lossesVeja o que acontece ao tentar nas amostras de validação com um autoencoder não treinado. Vamos usar 100 neurônios na camada intermediária e 20 neurônios na camada de representação:
seed_everything(SEED)
model = SimpleAutoencoder(x_train.shape[1], 100, 20).to(DEVICE)
losses = per_sample_mse(model, valid_generator)Antes de treiná-lo, aqui estão os valores de perda para as cinco primeiras amostras e a perda média geral.
print(losses[0:5])
print(np.mean(losses))[0.6754841, 0.7914626, 1.1697073, 0.807015, 1.258897]
0.9325166
Com pesos aleatórios em suas camadas, o autoencoder não treinado é bastante ruim na reconstrução. Ele tem um erro quadrático médio de 0,93 em média para as variáveis de transação padronizadas.
Vamos agora treiná-lo e ver como isso evolui. Como na seção anterior, o processo é o seguinte:
Preparar os geradores.
Definir o critério.
Instanciar o modelo.
Realizar vários laços de otimização (com uma técnica de otimização como o gradiente descendente com Adam) nos dados de treinamento.
Parar a otimização com parada antecipada usando dados de validação.
Todos esses passos são implementados na função compartilhada training_loop definida na seção anterior.
seed_everything(SEED)
training_generator,valid_generator = prepare_generators(training_set, valid_set, batch_size = 64)
criterion = torch.nn.MSELoss().to(DEVICE)
model = SimpleAutoencoder(len(input_features), 100,20).to(DEVICE)
optimizer = torch.optim.Adam(model.parameters(), lr = 0.0001)model,training_execution_time,train_losses,valid_losses = training_loop(model,
training_generator,
valid_generator,
optimizer,
criterion,
max_epochs=500,
verbose=True)
Epoch 0: train loss: 0.44459555436274745
valid loss: 0.11862650322295278
New best score: 0.11862650322295278
Epoch 1: train loss: 0.08513386782087799
valid loss: 0.043951269408148495
New best score: 0.043951269408148495
Epoch 2: train loss: 0.033392506879513964
valid loss: 0.023117523054119016
New best score: 0.023117523054119016
Epoch 3: train loss: 0.020011974392676046
valid loss: 0.014828811516690124
New best score: 0.014828811516690124
Epoch 4: train loss: 0.012006818789661101
valid loss: 0.007833917340253545
New best score: 0.007833917340253545
Epoch 5: train loss: 0.006807905782315075
valid loss: 0.0051493146614543074
New best score: 0.0051493146614543074
Epoch 6: train loss: 0.005084841840688574
valid loss: 0.003938508272181199
New best score: 0.003938508272181199
Epoch 7: train loss: 0.0038803787977678655
valid loss: 0.003023105256559704
New best score: 0.003023105256559704
Epoch 8: train loss: 0.002949208616150853
valid loss: 0.002528339391192574
New best score: 0.002528339391192574
Epoch 9: train loss: 0.0023992182049200465
valid loss: 0.002028128087057483
New best score: 0.002028128087057483
Epoch 10: train loss: 0.002048360905142583
valid loss: 0.0017903703262983654
New best score: 0.0017903703262983654
Epoch 11: train loss: 0.0017800394437421847
valid loss: 0.0015466983321306036
New best score: 0.0015466983321306036
Epoch 12: train loss: 0.0015514137394313148
valid loss: 0.0013498795192683614
New best score: 0.0013498795192683614
Epoch 13: train loss: 0.0013534181380584786
valid loss: 0.0012023842363628493
New best score: 0.0012023842363628493
Epoch 14: train loss: 0.0011936210340287815
valid loss: 0.0010217127795751038
New best score: 0.0010217127795751038
Epoch 15: train loss: 0.0010376906175015898
valid loss: 0.0009490489228145102
New best score: 0.0009490489228145102
Epoch 16: train loss: 0.0009196382938585036
valid loss: 0.0008569012993063696
New best score: 0.0008569012993063696
Epoch 17: train loss: 0.000808632700802201
valid loss: 0.0006878849415393556
New best score: 0.0006878849415393556
Epoch 18: train loss: 0.000717277750494199
valid loss: 0.0006156707037484548
New best score: 0.0006156707037484548
Epoch 19: train loss: 0.0006314616377501486
valid loss: 0.0005276680644569776
New best score: 0.0005276680644569776
Epoch 20: train loss: 0.0005619078842173135
valid loss: 0.0004729103698405371
New best score: 0.0004729103698405371
Epoch 21: train loss: 0.0005059312825463133
valid loss: 0.0004051279672771397
New best score: 0.0004051279672771397
Epoch 22: train loss: 0.00045364069106100914
valid loss: 0.0005014552684854513
1 iterations since best score.
Epoch 23: train loss: 0.00041752959810872697
valid loss: 0.00033180076396569885
New best score: 0.00033180076396569885
Epoch 24: train loss: 0.0003782341861741236
valid loss: 0.0002830096538852305
New best score: 0.0002830096538852305
Epoch 25: train loss: 0.0003408297134593822
valid loss: 0.00027195419235914546
New best score: 0.00027195419235914546
Epoch 26: train loss: 0.00031857445692523546
valid loss: 0.0002608046046877407
New best score: 0.0002608046046877407
Epoch 27: train loss: 0.0002881577817039132
valid loss: 0.00033317482079216405
1 iterations since best score.
Epoch 28: train loss: 0.00026948186539978955
valid loss: 0.000231769638331009
New best score: 0.000231769638331009
Epoch 29: train loss: 0.00024825533775938363
valid loss: 0.0002077069559342564
New best score: 0.0002077069559342564
Epoch 30: train loss: 0.0002292815091932147
valid loss: 0.00021443175747300387
1 iterations since best score.
Epoch 31: train loss: 0.00021850082260071492
valid loss: 0.00018189250032100675
New best score: 0.00018189250032100675
Epoch 32: train loss: 0.0002003885048218608
valid loss: 0.00023674504868648031
1 iterations since best score.
Epoch 33: train loss: 0.0001864828156532936
valid loss: 0.0001377424587060817
New best score: 0.0001377424587060817
Epoch 34: train loss: 0.0001759348686819397
valid loss: 0.00014076000892988513
1 iterations since best score.
Epoch 35: train loss: 0.00016855719783386223
valid loss: 0.00013386969116393633
New best score: 0.00013386969116393633
Epoch 36: train loss: 0.00015410608822975889
valid loss: 0.00015747381228402695
1 iterations since best score.
Epoch 37: train loss: 0.00014448216809085328
valid loss: 0.00013747311631313658
2 iterations since best score.
Epoch 38: train loss: 0.0001393559023808135
valid loss: 0.00011850201456089978
New best score: 0.00011850201456089978
Epoch 39: train loss: 0.00012889235032522076
valid loss: 0.00010649465980524161
New best score: 0.00010649465980524161
Epoch 40: train loss: 0.0001246698037786603
valid loss: 9.618921698735202e-05
New best score: 9.618921698735202e-05
Epoch 41: train loss: 0.00011618241758029194
valid loss: 0.00015093085798657566
1 iterations since best score.
Epoch 42: train loss: 0.00011435067549593118
valid loss: 0.00016568731693926273
2 iterations since best score.
Epoch 43: train loss: 0.00010542401560435254
valid loss: 8.921389312316699e-05
New best score: 8.921389312316699e-05
Epoch 44: train loss: 0.00010427492318011766
valid loss: 7.638492299589872e-05
New best score: 7.638492299589872e-05
Epoch 45: train loss: 9.43076783905485e-05
valid loss: 8.106221539293457e-05
1 iterations since best score.
Epoch 46: train loss: 9.408740700618431e-05
valid loss: 9.908837212114137e-05
2 iterations since best score.
Epoch 47: train loss: 8.668002232277154e-05
valid loss: 8.026456355074004e-05
3 iterations since best score.
Early stopping
losses = per_sample_mse(model, valid_generator)
print(losses[0:5])
print(np.mean(losses))[2.0756474e-05, 2.1485403e-05, 3.70714e-05, 3.204957e-05, 4.3641372e-05]
8.030665e-05
print(x_train[0])
print(model(x_train[0].to(DEVICE)))tensor([-0.1323, -0.6306, 2.1808, -0.3003, 0.1241, -1.6917, 0.5035, -1.6630,
-0.0482, -0.9810, -0.0816, -1.9895, -0.1231, -0.9719, -0.1436])
tensor([-0.1373, -0.6222, 2.1850, -0.3158, 0.1244, -1.6941, 0.5060, -1.6674,
-0.0407, -0.9684, -0.0796, -1.9885, -0.1316, -0.9716, -0.1380],
device='cuda:0', grad_fn=<AddBackward0>)
Quando treinado, o autoencoder é muito melhor em codificar/decodificar uma transação. Agora obtém um erro quadrático médio muito baixo (0,00008) em média para nossas variáveis de transação padronizadas. Além disso, o exemplo acima (com x_train[0]) ilustra quão bem a transação reconstruída é similar à transação de entrada.
Agora a questão restante é a seguinte: as fraudes são menos bem reconstruídas do que as transações genuínas, de modo que o erro de reconstrução possa ser usado como indicador de risco de fraude?
Para responder, pode-se calcular o erro quadrático médio para transações fraudulentas e genuínas separadamente.
genuine_losses = np.array(losses)[y_valid.cpu().numpy() == 0]
fraud_losses = np.array(losses)[y_valid.cpu().numpy() == 1]
print("Average fraud reconstruction error:", np.mean(fraud_losses))
print("Average genuine reconstruction error:", np.mean(genuine_losses))Average fraud reconstruction error: 0.0018339771
Average genuine reconstruction error: 6.9023976e-05
Parece que as fraudes são de fato menos bem reconstruídas do que as transações genuínas, o que é muito encorajador. Vamos agora calcular a AUC ROC, a precisão média e a precisão de cartão@100 no conjunto de validação considerando o erro de reconstrução como uma pontuação de fraude prevista.
predictions_df=valid_df
predictions_df['predictions']=losses
performance_assessment(predictions_df, top_k_list=[100])Embora menos preciso do que as técnicas supervisionadas cobertas anteriormente, este método não supervisionado leva a resultados encorajadores e é muito mais preciso do que o classificador aleatório.
Comparação com outra linha de base não supervisionada: Isolation Forest¶
O autoencoder tem uma AUC ROC muito alta sem fazer uso algum dos rótulos durante o treinamento. Para contrastar esse resultado e como verificação de sanidade, é interessante implementar e testar outra linha de base não supervisionada popular.
O Isolation Forest é uma técnica de detecção de anomalias de última geração que depende de modelos baseados em árvores. Ele calcula, para cada amostra de dados, uma pontuação de anomalia que reflete quão atípica é a amostra. Para calcular essa pontuação, o algoritmo tenta isolar a amostra do restante do conjunto de dados recursivamente: escolhe um corte aleatório (par característica-limiar) e avalia se ele permite que a amostra em questão seja isolada. Se sim, o algoritmo para. Caso contrário, adiciona outro corte e repete o processo até que a amostra seja isolada do restante. Essa partição recursiva de dados pode ser representada como uma árvore de decisão e o número de cortes necessários para isolar uma amostra pode ser considerado como a pontuação de anomalia. Quanto menor o número de cortes (ou seja, quanto mais fácil é isolar o ponto de dados), mais provável é que a amostra seja um outlier.
Este algoritmo é implementado no sklearn sob a classe sklearn.ensemble.IsolationForest. Vamos treiná-lo nos dados de treinamento e avaliar a pontuação de anomalia dos dados de validação. Neste último, a pontuação de anomalia de uma amostra é calculada a partir da profundidade média das folhas atingidas por ela.
from sklearn.ensemble import IsolationForest
anomalyclassifier = IsolationForest(random_state=SEED, n_estimators=10)
anomalyclassifier.fit(train_df[input_features])IsolationForest(n_estimators=10, random_state=42)predictions_df = valid_df
predictions_df['predictions'] = -anomalyclassifier.score_samples(valid_df[input_features])
performance_assessment(predictions_df, top_k_list=[100])Podemos ver que essa linha de base não supervisionada de última geração fornece desempenhos próximos (ligeiramente inferiores) aos do autoencoder.
Representação, visualização e agrupamento de transações¶
Além de sua capacidade de detectar anomalias, o autoencoder tem outras vantagens, como foi mencionado na introdução. Em particular, após o treinamento, pode-se usar apenas a parte do encoder para obter representações das transações para fins de visualização ou agrupamento. Para isso, vamos treinar um autoencoder com uma dimensão de código igual a 2.
seed_everything(SEED)
training_generator,valid_generator = prepare_generators(training_set, valid_set, batch_size = 64)
criterion = torch.nn.MSELoss().to(DEVICE)
small_model = SimpleAutoencoder(len(input_features), 100,2).to(DEVICE)
optimizer = torch.optim.Adam(small_model.parameters(), lr = 0.0001)
small_model,training_execution_time,train_losses,valid_losses = training_loop(small_model,
training_generator,
valid_generator,
optimizer,
criterion,
max_epochs=500,
verbose=True)
Epoch 0: train loss: 0.7684247642185674
valid loss: 0.5768663428194536
New best score: 0.5768663428194536
Epoch 1: train loss: 0.5679652139003145
valid loss: 0.493461870886589
New best score: 0.493461870886589
Epoch 2: train loss: 0.5022419279095776
valid loss: 0.473104252678449
New best score: 0.473104252678449
Epoch 3: train loss: 0.4897903477769509
valid loss: 0.4661512801393134
New best score: 0.4661512801393134
Epoch 4: train loss: 0.48440276228788937
valid loss: 0.4619032563733273
New best score: 0.4619032563733273
Epoch 5: train loss: 0.4809599176305658
valid loss: 0.45911747171579165
New best score: 0.45911747171579165
Epoch 6: train loss: 0.4785268415000653
valid loss: 0.45734123809090077
New best score: 0.45734123809090077
Epoch 7: train loss: 0.47650860255694527
valid loss: 0.45569751822883314
New best score: 0.45569751822883314
Epoch 8: train loss: 0.47459852245296164
valid loss: 0.4537866956223556
New best score: 0.4537866956223556
Epoch 9: train loss: 0.47209983668067484
valid loss: 0.45195874930079516
New best score: 0.45195874930079516
Epoch 10: train loss: 0.4688010113758977
valid loss: 0.4489863704625375
New best score: 0.4489863704625375
Epoch 11: train loss: 0.46363054532165965
valid loss: 0.4430646009621073
New best score: 0.4430646009621073
Epoch 12: train loss: 0.45564043236964064
valid loss: 0.436130166786616
New best score: 0.436130166786616
Epoch 13: train loss: 0.4461127134114789
valid loss: 0.4285837764134173
New best score: 0.4285837764134173
Epoch 14: train loss: 0.4380761761909233
valid loss: 0.42339507507496194
New best score: 0.42339507507496194
Epoch 15: train loss: 0.43373974593601994
valid loss: 0.4212275084413466
New best score: 0.4212275084413466
Epoch 16: train loss: 0.43143339252836616
valid loss: 0.41868471999963125
New best score: 0.41868471999963125
Epoch 17: train loss: 0.4295925242153226
valid loss: 0.4175699397025864
New best score: 0.4175699397025864
Epoch 18: train loss: 0.42802723729359715
valid loss: 0.41582820369897644
New best score: 0.41582820369897644
Epoch 19: train loss: 0.42654467802886525
valid loss: 0.4146303626194678
New best score: 0.4146303626194678
Epoch 20: train loss: 0.4251323835229783
valid loss: 0.41341693038171756
New best score: 0.41341693038171756
Epoch 21: train loss: 0.42361518552608746
valid loss: 0.4119065884032536
New best score: 0.4119065884032536
Epoch 22: train loss: 0.4221145006655279
valid loss: 0.41042865231388903
New best score: 0.41042865231388903
Epoch 23: train loss: 0.420692662379026
valid loss: 0.4093369360504255
New best score: 0.4093369360504255
Epoch 24: train loss: 0.41928241582833103
valid loss: 0.4075301027851678
New best score: 0.4075301027851678
Epoch 25: train loss: 0.41791854382814914
valid loss: 0.40682729972841963
New best score: 0.40682729972841963
Epoch 26: train loss: 0.4165563806179149
valid loss: 0.4052450547615687
New best score: 0.4052450547615687
Epoch 27: train loss: 0.4153376409986963
valid loss: 0.4041597635042472
New best score: 0.4041597635042472
Epoch 28: train loss: 0.4141319388983127
valid loss: 0.402859646179637
New best score: 0.402859646179637
Epoch 29: train loss: 0.41285213913561963
valid loss: 0.40170063721677646
New best score: 0.40170063721677646
Epoch 30: train loss: 0.4116742888440593
valid loss: 0.40088034272193906
New best score: 0.40088034272193906
Epoch 31: train loss: 0.41035284606266204
valid loss: 0.3995635224821789
New best score: 0.3995635224821789
Epoch 32: train loss: 0.4091937180686863
valid loss: 0.39790562842387317
New best score: 0.39790562842387317
Epoch 33: train loss: 0.40791810011886503
valid loss: 0.39734370631924093
New best score: 0.39734370631924093
Epoch 34: train loss: 0.4066621295922573
valid loss: 0.39603803266918725
New best score: 0.39603803266918725
Epoch 35: train loss: 0.4054151028394699
valid loss: 0.39471466424035245
New best score: 0.39471466424035245
Epoch 36: train loss: 0.4042683201583804
valid loss: 0.39363554948991764
New best score: 0.39363554948991764
Epoch 37: train loss: 0.40304669034070767
valid loss: 0.3928234031617316
New best score: 0.3928234031617316
Epoch 38: train loss: 0.4019878175301944
valid loss: 0.39189601801132246
New best score: 0.39189601801132246
Epoch 39: train loss: 0.4009062413047878
valid loss: 0.3904342273219687
New best score: 0.3904342273219687
Epoch 40: train loss: 0.39968154577976434
valid loss: 0.389421878518954
New best score: 0.389421878518954
Epoch 41: train loss: 0.3985906217111912
valid loss: 0.3884314530534171
New best score: 0.3884314530534171
Epoch 42: train loss: 0.3975262547884115
valid loss: 0.38768000658092605
New best score: 0.38768000658092605
Epoch 43: train loss: 0.3963781732845033
valid loss: 0.3869185962312208
New best score: 0.3869185962312208
Epoch 44: train loss: 0.3953533396837132
valid loss: 0.3854033345244621
New best score: 0.3854033345244621
Epoch 45: train loss: 0.39430287879238163
valid loss: 0.38500170057914296
New best score: 0.38500170057914296
Epoch 46: train loss: 0.393358859659153
valid loss: 0.3836113703381168
New best score: 0.3836113703381168
Epoch 47: train loss: 0.3923147459786891
valid loss: 0.3828077902233666
New best score: 0.3828077902233666
Epoch 48: train loss: 0.3912491195231505
valid loss: 0.3819570972456958
New best score: 0.3819570972456958
Epoch 49: train loss: 0.39028021909766625
valid loss: 0.3809337183100278
New best score: 0.3809337183100278
Epoch 50: train loss: 0.38943510518247265
valid loss: 0.38022821946222274
New best score: 0.38022821946222274
Epoch 51: train loss: 0.3884981773352076
valid loss: 0.3795201025373949
New best score: 0.3795201025373949
Epoch 52: train loss: 0.3876228652766284
valid loss: 0.37822110652923585
New best score: 0.37822110652923585
Epoch 53: train loss: 0.38679932696071684
valid loss: 0.37764905341010274
New best score: 0.37764905341010274
Epoch 54: train loss: 0.38596470047137477
valid loss: 0.3768933874824659
New best score: 0.3768933874824659
Epoch 55: train loss: 0.38524927426820504
valid loss: 0.3762990965543549
New best score: 0.3762990965543549
Epoch 56: train loss: 0.38443353883281034
valid loss: 0.37535335162623984
New best score: 0.37535335162623984
Epoch 57: train loss: 0.3837052441520855
valid loss: 0.3749958235220831
New best score: 0.3749958235220831
Epoch 58: train loss: 0.38290596316011183
valid loss: 0.3742534691518773
New best score: 0.3742534691518773
Epoch 59: train loss: 0.3822552053752866
valid loss: 0.37333267306695217
New best score: 0.37333267306695217
Epoch 60: train loss: 0.3815679804031981
valid loss: 0.3731067414980769
New best score: 0.3731067414980769
Epoch 61: train loss: 0.38101293354599697
valid loss: 0.372067863840223
New best score: 0.372067863840223
Epoch 62: train loss: 0.3802933061840885
valid loss: 0.3714882905365991
New best score: 0.3714882905365991
Epoch 63: train loss: 0.3796952187901017
valid loss: 0.3709707405397801
New best score: 0.3709707405397801
Epoch 64: train loss: 0.3791553959905759
valid loss: 0.3706924600516512
New best score: 0.3706924600516512
Epoch 65: train loss: 0.37854866244710883
valid loss: 0.3700746950067458
New best score: 0.3700746950067458
Epoch 66: train loss: 0.37798203368373856
valid loss: 0.3694668825369715
New best score: 0.3694668825369715
Epoch 67: train loss: 0.3774965272977749
valid loss: 0.3690996943438639
New best score: 0.3690996943438639
Epoch 68: train loss: 0.3769960572968022
valid loss: 0.3686452254734404
New best score: 0.3686452254734404
Epoch 69: train loss: 0.37646223467918927
valid loss: 0.3680194248430064
New best score: 0.3680194248430064
Epoch 70: train loss: 0.37601271881428094
valid loss: 0.36788663092206736
New best score: 0.36788663092206736
Epoch 71: train loss: 0.3755262392086919
valid loss: 0.3672549909744106
New best score: 0.3672549909744106
Epoch 72: train loss: 0.3749947243051365
valid loss: 0.3667607526473009
New best score: 0.3667607526473009
Epoch 73: train loss: 0.3745634045815149
valid loss: 0.36628531810364434
New best score: 0.36628531810364434
Epoch 74: train loss: 0.37411142332945907
valid loss: 0.36622899013464566
New best score: 0.36622899013464566
Epoch 75: train loss: 0.37372889710202045
valid loss: 0.36578597017650394
New best score: 0.36578597017650394
Epoch 76: train loss: 0.3733352996537152
valid loss: 0.36549377529347526
New best score: 0.36549377529347526
Epoch 77: train loss: 0.37285123603065884
valid loss: 0.36517465775781643
New best score: 0.36517465775781643
Epoch 78: train loss: 0.37245363994264696
valid loss: 0.3646077791524064
New best score: 0.3646077791524064
Epoch 79: train loss: 0.37203873899083295
valid loss: 0.3642017390395774
New best score: 0.3642017390395774
Epoch 80: train loss: 0.37175256421301606
valid loss: 0.3638398566044094
New best score: 0.3638398566044094
Epoch 81: train loss: 0.37134953726432063
valid loss: 0.3634167999192014
New best score: 0.3634167999192014
Epoch 82: train loss: 0.3709514387536003
valid loss: 0.36295943159223254
New best score: 0.36295943159223254
Epoch 83: train loss: 0.3705764208879343
valid loss: 0.36283708996460085
New best score: 0.36283708996460085
Epoch 84: train loss: 0.37014006422992873
valid loss: 0.36238899123473245
New best score: 0.36238899123473245
Epoch 85: train loss: 0.36990586698169237
valid loss: 0.3623995320393088
1 iterations since best score.
Epoch 86: train loss: 0.3695502413105554
valid loss: 0.3618717197674871
New best score: 0.3618717197674871
Epoch 87: train loss: 0.36921520776206174
valid loss: 0.3613973431085628
New best score: 0.3613973431085628
Epoch 88: train loss: 0.3689540654819736
valid loss: 0.36140266564048706
1 iterations since best score.
Epoch 89: train loss: 0.36862950323302707
valid loss: 0.3608671872342219
New best score: 0.3608671872342219
Epoch 90: train loss: 0.36836055966795744
valid loss: 0.3606637365179635
New best score: 0.3606637365179635
Epoch 91: train loss: 0.3680474031039907
valid loss: 0.3603602769270621
New best score: 0.3603602769270621
Epoch 92: train loss: 0.3676915493282716
valid loss: 0.3602089701454496
New best score: 0.3602089701454496
Epoch 93: train loss: 0.36756731669487963
valid loss: 0.35985519713391373
New best score: 0.35985519713391373
Epoch 94: train loss: 0.36728893448358285
valid loss: 0.3597481974161388
New best score: 0.3597481974161388
Epoch 95: train loss: 0.36700058066024377
valid loss: 0.3596342912951454
New best score: 0.3596342912951454
Epoch 96: train loss: 0.36675196672374843
valid loss: 0.3593450021222641
New best score: 0.3593450021222641
Epoch 97: train loss: 0.3664314620923358
valid loss: 0.3591256910985936
New best score: 0.3591256910985936
Epoch 98: train loss: 0.3662416543775945
valid loss: 0.3590364758922754
New best score: 0.3590364758922754
Epoch 99: train loss: 0.3659238473122252
valid loss: 0.3586511149595344
New best score: 0.3586511149595344
Epoch 100: train loss: 0.36580749696572923
valid loss: 0.35853858080392326
New best score: 0.35853858080392326
Epoch 101: train loss: 0.36555497986522734
valid loss: 0.3583731103138845
New best score: 0.3583731103138845
Epoch 102: train loss: 0.3652697747170811
valid loss: 0.35791740759474333
New best score: 0.35791740759474333
Epoch 103: train loss: 0.36510542584992733
valid loss: 0.357564813598909
New best score: 0.357564813598909
Epoch 104: train loss: 0.36488343900635867
valid loss: 0.3574086686952518
New best score: 0.3574086686952518
Epoch 105: train loss: 0.3645800205934116
valid loss: 0.3588905628587379
1 iterations since best score.
Epoch 106: train loss: 0.3644165340561712
valid loss: 0.35713441704140336
New best score: 0.35713441704140336
Epoch 107: train loss: 0.3641442490125477
valid loss: 0.3570101023371754
New best score: 0.3570101023371754
Epoch 108: train loss: 0.36390998686020964
valid loss: 0.3570574991038588
1 iterations since best score.
Epoch 109: train loss: 0.36367379285637325
valid loss: 0.3565490502640198
New best score: 0.3565490502640198
Epoch 110: train loss: 0.3634785708346285
valid loss: 0.3563823215948428
New best score: 0.3563823215948428
Epoch 111: train loss: 0.36325681463140375
valid loss: 0.3560527459031246
New best score: 0.3560527459031246
Epoch 112: train loss: 0.36312379888891033
valid loss: 0.35614496834291137
1 iterations since best score.
Epoch 113: train loss: 0.3629203543893238
valid loss: 0.35565979868336456
New best score: 0.35565979868336456
Epoch 114: train loss: 0.3627093475076938
valid loss: 0.3556141742917358
New best score: 0.3556141742917358
Epoch 115: train loss: 0.36245119580233304
valid loss: 0.3555297355834252
New best score: 0.3555297355834252
Epoch 116: train loss: 0.36233158876859434
valid loss: 0.35528882447161964
New best score: 0.35528882447161964
Epoch 117: train loss: 0.3620295404362177
valid loss: 0.3550981194432316
New best score: 0.3550981194432316
Epoch 118: train loss: 0.3619585951815144
valid loss: 0.3548639331196175
New best score: 0.3548639331196175
Epoch 119: train loss: 0.3617405699954206
valid loss: 0.3550969279528967
1 iterations since best score.
Epoch 120: train loss: 0.3615904108516117
valid loss: 0.3545777801444622
New best score: 0.3545777801444622
Epoch 121: train loss: 0.3614249893287856
valid loss: 0.35460314793013487
1 iterations since best score.
Epoch 122: train loss: 0.361224607915313
valid loss: 0.35458590122845657
2 iterations since best score.
Epoch 123: train loss: 0.36105165147644613
valid loss: 0.3542227226528314
New best score: 0.3542227226528314
Epoch 124: train loss: 0.36089479367660066
valid loss: 0.3539815934466534
New best score: 0.3539815934466534
Epoch 125: train loss: 0.3607355942860616
valid loss: 0.35401103999771055
1 iterations since best score.
Epoch 126: train loss: 0.360593699246474
valid loss: 0.35378003074823183
New best score: 0.35378003074823183
Epoch 127: train loss: 0.3604586847824531
valid loss: 0.35374672082278247
New best score: 0.35374672082278247
Epoch 128: train loss: 0.36026581016370945
valid loss: 0.35388875315423873
1 iterations since best score.
Epoch 129: train loss: 0.36007167088370023
valid loss: 0.35342369677264834
New best score: 0.35342369677264834
Epoch 130: train loss: 0.35987311892254176
valid loss: 0.3533464732717295
New best score: 0.3533464732717295
Epoch 131: train loss: 0.3598369659132985
valid loss: 0.3530454443614991
New best score: 0.3530454443614991
Epoch 132: train loss: 0.3596282069416393
valid loss: 0.35290176399418566
New best score: 0.35290176399418566
Epoch 133: train loss: 0.35945622198440375
valid loss: 0.3533968297184491
1 iterations since best score.
Epoch 134: train loss: 0.35930171876746886
valid loss: 0.352829405486258
New best score: 0.352829405486258
Epoch 135: train loss: 0.3591677751071594
valid loss: 0.3526372389715226
New best score: 0.3526372389715226
Epoch 136: train loss: 0.359064665425348
valid loss: 0.3525837041641194
New best score: 0.3525837041641194
Epoch 137: train loss: 0.35886832957741865
valid loss: 0.3522841656305751
New best score: 0.3522841656305751
Epoch 138: train loss: 0.35870904294528194
valid loss: 0.35225988093946803
New best score: 0.35225988093946803
Epoch 139: train loss: 0.3585920189979199
valid loss: 0.35207713433627874
New best score: 0.35207713433627874
Epoch 140: train loss: 0.35844638561883346
valid loss: 0.3520351732852029
New best score: 0.3520351732852029
Epoch 141: train loss: 0.3581896108320521
valid loss: 0.3525604487116871
1 iterations since best score.
Epoch 142: train loss: 0.3581589228735371
valid loss: 0.35182255013067215
New best score: 0.35182255013067215
Epoch 143: train loss: 0.3579721470180023
valid loss: 0.3518180005211648
New best score: 0.3518180005211648
Epoch 144: train loss: 0.3577889849932198
valid loss: 0.35163149548684314
New best score: 0.35163149548684314
Epoch 145: train loss: 0.3576514876196535
valid loss: 0.3514987884649162
New best score: 0.3514987884649162
Epoch 146: train loss: 0.3574727186167445
valid loss: 0.35132194807946354
New best score: 0.35132194807946354
Epoch 147: train loss: 0.35737212919710243
valid loss: 0.3518874969150199
1 iterations since best score.
Epoch 148: train loss: 0.3571610676683842
valid loss: 0.3510494019815831
New best score: 0.3510494019815831
Epoch 149: train loss: 0.35705440558393414
valid loss: 0.35092813877460083
New best score: 0.35092813877460083
Epoch 150: train loss: 0.3569017581171561
valid loss: 0.35103738451264593
1 iterations since best score.
Epoch 151: train loss: 0.35687340736161227
valid loss: 0.35078356940238203
New best score: 0.35078356940238203
Epoch 152: train loss: 0.3566489354431287
valid loss: 0.351060890369728
1 iterations since best score.
Epoch 153: train loss: 0.35646914444279715
valid loss: 0.35075386410853904
New best score: 0.35075386410853904
Epoch 154: train loss: 0.35635819458482826
valid loss: 0.35059281462202957
New best score: 0.35059281462202957
Epoch 155: train loss: 0.3562699848105757
valid loss: 0.3503138803556317
New best score: 0.3503138803556317
Epoch 156: train loss: 0.35617095665083787
valid loss: 0.3504037611797208
1 iterations since best score.
Epoch 157: train loss: 0.3560048634075982
valid loss: 0.3503424207532341
2 iterations since best score.
Epoch 158: train loss: 0.3559037697132869
valid loss: 0.35010807908297886
New best score: 0.35010807908297886
Epoch 159: train loss: 0.3558188352598515
valid loss: 0.3501646858584034
1 iterations since best score.
Epoch 160: train loss: 0.35570161739795203
valid loss: 0.34974523794129897
New best score: 0.34974523794129897
Epoch 161: train loss: 0.35554915552613386
valid loss: 0.34962316972961843
New best score: 0.34962316972961843
Epoch 162: train loss: 0.3553889135671619
valid loss: 0.349606013542316
New best score: 0.349606013542316
Epoch 163: train loss: 0.3552543936906308
valid loss: 0.3494946970314276
New best score: 0.3494946970314276
Epoch 164: train loss: 0.3551593191537073
valid loss: 0.34953100366996287
1 iterations since best score.
Epoch 165: train loss: 0.3550806263208845
valid loss: 0.34943127057265716
New best score: 0.34943127057265716
Epoch 166: train loss: 0.35500883899386937
valid loss: 0.3493845041983766
New best score: 0.3493845041983766
Epoch 167: train loss: 0.3548054924202695
valid loss: 0.3494515491802184
1 iterations since best score.
Epoch 168: train loss: 0.3548040342860878
valid loss: 0.3489428101830144
New best score: 0.3489428101830144
Epoch 169: train loss: 0.35459009003798775
valid loss: 0.34909528777247567
1 iterations since best score.
Epoch 170: train loss: 0.3545222410052502
valid loss: 0.3487735234974512
New best score: 0.3487735234974512
Epoch 171: train loss: 0.35444276211480563
valid loss: 0.3489290329113684
1 iterations since best score.
Epoch 172: train loss: 0.35433073894585526
valid loss: 0.34865225776622855
New best score: 0.34865225776622855
Epoch 173: train loss: 0.354227108492678
valid loss: 0.3486745737940887
1 iterations since best score.
Epoch 174: train loss: 0.3540804327446006
valid loss: 0.34847301876610093
New best score: 0.34847301876610093
Epoch 175: train loss: 0.353996581773685
valid loss: 0.34889905400614923
1 iterations since best score.
Epoch 176: train loss: 0.3539140959257833
valid loss: 0.3482982144166863
New best score: 0.3482982144166863
Epoch 177: train loss: 0.3537893352841328
valid loss: 0.34839311771379794
1 iterations since best score.
Epoch 178: train loss: 0.3536900930092394
valid loss: 0.3482122821560323
New best score: 0.3482122821560323
Epoch 179: train loss: 0.35362554246107436
valid loss: 0.34852553967569694
1 iterations since best score.
Epoch 180: train loss: 0.35350341792886164
valid loss: 0.34817046757604253
New best score: 0.34817046757604253
Epoch 181: train loss: 0.3533807491196273
valid loss: 0.3478579554075752
New best score: 0.3478579554075752
Epoch 182: train loss: 0.3533511972963012
valid loss: 0.3475855511068646
New best score: 0.3475855511068646
Epoch 183: train loss: 0.3531828399598029
valid loss: 0.3475934645517276
1 iterations since best score.
Epoch 184: train loss: 0.3531163542266102
valid loss: 0.34748886225979186
New best score: 0.34748886225979186
Epoch 185: train loss: 0.353066695209443
valid loss: 0.3475219822320782
1 iterations since best score.
Epoch 186: train loss: 0.3529354565800034
valid loss: 0.34738321175666453
New best score: 0.34738321175666453
Epoch 187: train loss: 0.3527984747353293
valid loss: 0.3474910751392281
1 iterations since best score.
Epoch 188: train loss: 0.35269127361633124
valid loss: 0.3472975330437467
New best score: 0.3472975330437467
Epoch 189: train loss: 0.35258841543079106
valid loss: 0.34747938613096874
1 iterations since best score.
Epoch 190: train loss: 0.35257175886722186
valid loss: 0.34768702619062747
2 iterations since best score.
Epoch 191: train loss: 0.35244498092745274
valid loss: 0.3471462391113323
New best score: 0.3471462391113323
Epoch 192: train loss: 0.35240889008710763
valid loss: 0.34711034876075597
New best score: 0.34711034876075597
Epoch 193: train loss: 0.35235085171677644
valid loss: 0.3468500987916696
New best score: 0.3468500987916696
Epoch 194: train loss: 0.3522142497804835
valid loss: 0.34691527915782616
1 iterations since best score.
Epoch 195: train loss: 0.3521673695876995
valid loss: 0.3467520169710201
New best score: 0.3467520169710201
Epoch 196: train loss: 0.3520123922688099
valid loss: 0.3468928875167513
1 iterations since best score.
Epoch 197: train loss: 0.3519577576883892
valid loss: 0.3469653481017045
2 iterations since best score.
Epoch 198: train loss: 0.3519127744447661
valid loss: 0.346654592495147
New best score: 0.346654592495147
Epoch 199: train loss: 0.3518416799790089
valid loss: 0.3466361478052504
New best score: 0.3466361478052504
Epoch 200: train loss: 0.35172814831679
valid loss: 0.34668891447815087
1 iterations since best score.
Epoch 201: train loss: 0.3516605096667948
valid loss: 0.3464359102516226
New best score: 0.3464359102516226
Epoch 202: train loss: 0.35161338928894603
valid loss: 0.34623810518634773
New best score: 0.34623810518634773
Epoch 203: train loss: 0.35146604811712157
valid loss: 0.34637316817142927
1 iterations since best score.
Epoch 204: train loss: 0.3514169772826919
valid loss: 0.34636639934745644
2 iterations since best score.
Epoch 205: train loss: 0.3513855440096919
valid loss: 0.34600382748523045
New best score: 0.34600382748523045
Epoch 206: train loss: 0.35120018587285656
valid loss: 0.3462549442476262
1 iterations since best score.
Epoch 207: train loss: 0.35112138801961285
valid loss: 0.3459852658008617
New best score: 0.3459852658008617
Epoch 208: train loss: 0.35110988725781667
valid loss: 0.3461580883609793
1 iterations since best score.
Epoch 209: train loss: 0.3510144509617275
valid loss: 0.34613404322843083
2 iterations since best score.
Epoch 210: train loss: 0.3509096265352023
valid loss: 0.34592601948422813
New best score: 0.34592601948422813
Epoch 211: train loss: 0.35084550259332126
valid loss: 0.34570493792575563
New best score: 0.34570493792575563
Epoch 212: train loss: 0.3507964052046234
valid loss: 0.3456118444275986
New best score: 0.3456118444275986
Epoch 213: train loss: 0.3506889792860808
valid loss: 0.3456960986220772
1 iterations since best score.
Epoch 214: train loss: 0.3506408885947605
valid loss: 0.3456522176825935
2 iterations since best score.
Epoch 215: train loss: 0.3505368314498241
valid loss: 0.34537068623336936
New best score: 0.34537068623336936
Epoch 216: train loss: 0.350509597882486
valid loss: 0.3454063627563539
1 iterations since best score.
Epoch 217: train loss: 0.35038468848564885
valid loss: 0.3460760150939389
2 iterations since best score.
Epoch 218: train loss: 0.3503669098333009
valid loss: 0.34533744100990194
New best score: 0.34533744100990194
Epoch 219: train loss: 0.3502007991531383
valid loss: 0.3452964130320836
New best score: 0.3452964130320836
Epoch 220: train loss: 0.35017206960038977
valid loss: 0.3452372838402055
New best score: 0.3452372838402055
Epoch 221: train loss: 0.3501182178010448
valid loss: 0.34491898435386803
New best score: 0.34491898435386803
Epoch 222: train loss: 0.35007528399418236
valid loss: 0.34484236478154123
New best score: 0.34484236478154123
Epoch 223: train loss: 0.3499769602633343
valid loss: 0.3452564421735826
1 iterations since best score.
Epoch 224: train loss: 0.34994534848980874
valid loss: 0.3448767109646823
2 iterations since best score.
Epoch 225: train loss: 0.3498022082772811
valid loss: 0.344659458516074
New best score: 0.344659458516074
Epoch 226: train loss: 0.3497091270484614
valid loss: 0.344617711602013
New best score: 0.344617711602013
Epoch 227: train loss: 0.3496640003206169
valid loss: 0.3447480450888149
1 iterations since best score.
Epoch 228: train loss: 0.34956770907396567
valid loss: 0.34473640628851177
2 iterations since best score.
Epoch 229: train loss: 0.3495605050035918
valid loss: 0.34430122165406335
New best score: 0.34430122165406335
Epoch 230: train loss: 0.34945341993130413
valid loss: 0.344738097887873
1 iterations since best score.
Epoch 231: train loss: 0.34943006878601207
valid loss: 0.3444186775085053
2 iterations since best score.
Epoch 232: train loss: 0.34933042286914806
valid loss: 0.3448007179902551
3 iterations since best score.
Early stopping
Uma vez treinado, para obter a representação 2D das transações a partir apenas da parte do encoder, a ideia é simplesmente aplicar as duas primeiras camadas do Autoencoder.
def compute_representation(x,model):
x_representation = model.fc1(x)
x_representation = model.relu(x_representation)
x_representation = model.fc2(x_representation)
x_representation = model.relu(x_representation)
return x_representationx_train_representation = []
for x_batch, y_batch in training_generator:
x_train_representation.append(compute_representation(x_batch, small_model).detach().cpu().numpy())x_train_representation = np.vstack(x_train_representation)Após este processo, as representações obtidas dos dados de treinamento estão em 2D:
print(x_train.shape)
print(x_train_representation.shape)torch.Size([66928, 15])
(66928, 2)
As transações podem ser agora visualizadas em um plano (por exemplo, com cores diferentes para fraudes e genuínas)
plt.scatter(x_train_representation[:, 0], x_train_representation[:, 1], c=y_train.numpy(), s=50, cmap='viridis')
Também é possível aplicar um agrupamento K-means e visualizar os clusters:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=10, random_state=SEED)
kmeans.fit(x_train_representation)
y_kmeans = kmeans.predict(x_train_representation)plt.scatter(x_train_representation[:, 0], x_train_representation[:, 1], c=y_kmeans, s=50, cmap='viridis')
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='black', s=200, alpha=0.5)
Detecção de fraude semi-supervisionada¶
Por fim, o autoencoder pode ser usado em um sistema de detecção de fraude em cartão de crédito semi-supervisionado Carcillo et al. (2019). Existem duas formas principais de fazer isso:
W1: A mais natural é manter o autoencoder como está e treiná-lo em todos os dados rotulados e não rotulados disponíveis. Em seguida, combiná-lo com uma rede neural supervisionada treinada apenas em dados rotulados. A combinação pode ser feita agregando a pontuação prevista do modelo supervisionado e a pontuação prevista do modelo não supervisionado (W1A), ou mais elegantemente fornecendo a pontuação de risco não supervisionada do autoencoder (erro de reconstrução) como uma variável adicional ao modelo supervisionado (W1B) como em Alazizi et al. (2020).W2: Outra possibilidade é mudar a arquitetura do autoencoder para um modelo híbrido semi-supervisionado. Mais precisamente, pode-se adicionar, ao autoencoder, neurônios de saída similares aos da rede neural supervisionada da seção anterior, e adicionalmente prevê-los a partir dos neurônios de código. Portanto, a representação aprendida (neurônios de código) será compartilhada entre a rede decodificadora que visa reconstruir a entrada e a rede de previsão que visa prever fraude. A primeira é treinada em todas as amostras e a segunda é treinada apenas em amostras rotuladas. A intuição com esta abordagem é similar ao pré-treinamento em processamento de linguagem natural: aprender uma representação que incorpora a estrutura subjacente nos dados de entrada pode ajudar na resolução de tarefas supervisionadas.
O seguinte explora a abordagem semi-supervisionada W1B. Mas primeiro, vamos reavaliar aqui o modelo supervisionado de linha de base sem a característica de erro de reconstrução. FraudDataset e SimpleFraudMLPWithDropout estão disponíveis nas funções compartilhadas e podem ser usados diretamente aqui.
seed_everything(SEED)
training_set_supervised = FraudDataset(x_train.to(DEVICE), y_train.to(DEVICE))
valid_set_supervised = FraudDataset(x_valid.to(DEVICE), y_valid.to(DEVICE))
training_generator_supervised,valid_generator_supervised = prepare_generators(training_set_supervised,
valid_set_supervised,
batch_size=64)
model_supervised = SimpleFraudMLPWithDropout(len(input_features), 1000, 0.2).to(DEVICE)
optimizer = torch.optim.Adam(model_supervised.parameters(), lr = 0.0001)
criterion = torch.nn.BCELoss().to(DEVICE)
model_supervised,training_execution_time,train_losses_dropout,valid_losses_dropout =\
training_loop(model_supervised,
training_generator_supervised,
valid_generator_supervised,
optimizer,
criterion,
verbose=True)
Epoch 0: train loss: 0.10161001316804161
valid loss: 0.03556653917487202
New best score: 0.03556653917487202
Epoch 1: train loss: 0.03833597035852419
valid loss: 0.026109349807022047
New best score: 0.026109349807022047
Epoch 2: train loss: 0.031094471842315882
valid loss: 0.02396169698420566
New best score: 0.02396169698420566
Epoch 3: train loss: 0.028757975434966342
valid loss: 0.023352081602938026
New best score: 0.023352081602938026
Epoch 4: train loss: 0.02775647486163834
valid loss: 0.022305768956761052
New best score: 0.022305768956761052
Epoch 5: train loss: 0.026740792337858456
valid loss: 0.021572637600223713
New best score: 0.021572637600223713
Epoch 6: train loss: 0.02606928332959859
valid loss: 0.021479292579320935
New best score: 0.021479292579320935
Epoch 7: train loss: 0.025758702903594215
valid loss: 0.02105785213192019
New best score: 0.02105785213192019
Epoch 8: train loss: 0.02527676529854707
valid loss: 0.020694473186187202
New best score: 0.020694473186187202
Epoch 9: train loss: 0.024878843686695656
valid loss: 0.02042211337890374
New best score: 0.02042211337890374
Epoch 10: train loss: 0.02438850605296751
valid loss: 0.020538174796116644
1 iterations since best score.
Epoch 11: train loss: 0.024034218137004692
valid loss: 0.02071835831255535
2 iterations since best score.
Epoch 12: train loss: 0.023670860127248512
valid loss: 0.01998928964819983
New best score: 0.01998928964819983
Epoch 13: train loss: 0.023701557650517523
valid loss: 0.01986558492743293
New best score: 0.01986558492743293
Epoch 14: train loss: 0.02331948666341414
valid loss: 0.01986974315244521
1 iterations since best score.
Epoch 15: train loss: 0.023050426844735388
valid loss: 0.01970138840245012
New best score: 0.01970138840245012
Epoch 16: train loss: 0.022976456373844503
valid loss: 0.01949228905777503
New best score: 0.01949228905777503
Epoch 17: train loss: 0.022786046317435738
valid loss: 0.01982322550668824
1 iterations since best score.
Epoch 18: train loss: 0.022582473735731044
valid loss: 0.01974369095577324
2 iterations since best score.
Epoch 19: train loss: 0.02253310805256523
valid loss: 0.019359889266824176
New best score: 0.019359889266824176
Epoch 20: train loss: 0.022279470434334897
valid loss: 0.01928481163261102
New best score: 0.01928481163261102
Epoch 21: train loss: 0.02220114628115694
valid loss: 0.018997078554964335
New best score: 0.018997078554964335
Epoch 22: train loss: 0.022127013866091592
valid loss: 0.01905235069170289
1 iterations since best score.
Epoch 23: train loss: 0.022129482317989224
valid loss: 0.018972578141940095
New best score: 0.018972578141940095
Epoch 24: train loss: 0.02179307807468405
valid loss: 0.01934589187568817
1 iterations since best score.
Epoch 25: train loss: 0.021895541540831398
valid loss: 0.018781205812657426
New best score: 0.018781205812657426
Epoch 26: train loss: 0.02153568957303695
valid loss: 0.018873276155635388
1 iterations since best score.
Epoch 27: train loss: 0.021719574671969652
valid loss: 0.01871486084059878
New best score: 0.01871486084059878
Epoch 28: train loss: 0.021623164488258195
valid loss: 0.01849896589324611
New best score: 0.01849896589324611
Epoch 29: train loss: 0.021195488194819277
valid loss: 0.018997153041558596
1 iterations since best score.
Epoch 30: train loss: 0.021170051902644763
valid loss: 0.01968524302457729
2 iterations since best score.
Epoch 31: train loss: 0.02115491109416708
valid loss: 0.01879670942823092
3 iterations since best score.
Early stopping
predictions = []
for x_batch, y_batch in valid_generator_supervised:
predictions.append(model_supervised(x_batch.to(DEVICE)).detach().cpu().numpy())
predictions_df=valid_df
predictions_df['predictions']=np.vstack(predictions)
performance_assessment(predictions_df, top_k_list=[100])Agora, para a abordagem semi-supervisionada W1B, vamos calcular o erro de reconstrução de todas as transações com nosso primeiro autoencoder (armazenado em model) e adicioná-lo como uma nova variável em train_df e valid_df.
loader_params = {'batch_size': 64,
'num_workers': 0}
training_generator = torch.utils.data.DataLoader(training_set, **loader_params)
valid_generator = torch.utils.data.DataLoader(valid_set, **loader_params)
train_reconstruction = per_sample_mse(model, training_generator)
valid_reconstruction = per_sample_mse(model, valid_generator)
train_df["reconstruction_error"] = train_reconstruction
valid_df["reconstruction_error"] = valid_reconstructionEm seguida, podemos reavaliar o modelo supervisionado com esta variável extra.
seed_everything(SEED)
input_features_new = input_features + ["reconstruction_error"]
# Rescale the reconstruction error
(train_df, valid_df)=scaleData(train_df, valid_df, ["reconstruction_error"])
x_train_new = torch.FloatTensor(train_df[input_features_new].values)
x_valid_new = torch.FloatTensor(valid_df[input_features_new].values)
training_set_supervised_new = FraudDataset(x_train_new.to(DEVICE), y_train.to(DEVICE))
valid_set_supervised_new = FraudDataset(x_valid_new.to(DEVICE), y_valid.to(DEVICE))
training_generator_supervised,valid_generator_supervised = prepare_generators(training_set_supervised_new,
valid_set_supervised_new,
batch_size=64)
model_supervised = SimpleFraudMLPWithDropout(len(input_features_new), 100, 0.2).to(DEVICE)
optimizer = torch.optim.Adam(model_supervised.parameters(), lr = 0.0001)
criterion = torch.nn.BCELoss().to(DEVICE)
model_supervised,training_execution_time,train_losses_dropout,valid_losses_dropout = \
training_loop(model_supervised,
training_generator_supervised,
valid_generator_supervised,
optimizer,
criterion,
verbose=True)
predictions = []
for x_batch, y_batch in valid_generator_supervised:
predictions.append(model_supervised(x_batch).detach().cpu().numpy())
Epoch 0: train loss: 0.32470558333009425
valid loss: 0.11669875736770734
New best score: 0.11669875736770734
Epoch 1: train loss: 0.0857971908175609
valid loss: 0.050325598816076914
New best score: 0.050325598816076914
Epoch 2: train loss: 0.055031552282206526
valid loss: 0.03683824896140665
New best score: 0.03683824896140665
Epoch 3: train loss: 0.045474566717366785
valid loss: 0.031574366707863705
New best score: 0.031574366707863705
Epoch 4: train loss: 0.03988730701053405
valid loss: 0.028506962655753386
New best score: 0.028506962655753386
Epoch 5: train loss: 0.03588366161686427
valid loss: 0.0264507318495727
New best score: 0.0264507318495727
Epoch 6: train loss: 0.03320539464736019
valid loss: 0.025167095382784395
New best score: 0.025167095382784395
Epoch 7: train loss: 0.03146339780281531
valid loss: 0.024275742485722313
New best score: 0.024275742485722313
Epoch 8: train loss: 0.03083236553407066
valid loss: 0.02372574291110568
New best score: 0.02372574291110568
Epoch 9: train loss: 0.029903344949351242
valid loss: 0.023402261280561568
New best score: 0.023402261280561568
Epoch 10: train loss: 0.029085144788573495
valid loss: 0.02301961904330576
New best score: 0.02301961904330576
Epoch 11: train loss: 0.02864163257867226
valid loss: 0.022839933189008732
New best score: 0.022839933189008732
Epoch 12: train loss: 0.028412688680235332
valid loss: 0.022551339802133745
New best score: 0.022551339802133745
Epoch 13: train loss: 0.02834755417122461
valid loss: 0.022378979152821697
New best score: 0.022378979152821697
Epoch 14: train loss: 0.028343526197305343
valid loss: 0.022222696035805213
New best score: 0.022222696035805213
Epoch 15: train loss: 0.027864306476447966
valid loss: 0.022193545799402144
New best score: 0.022193545799402144
Epoch 16: train loss: 0.027414113502855098
valid loss: 0.0219534132029108
New best score: 0.0219534132029108
Epoch 17: train loss: 0.027424028700433072
valid loss: 0.02181996635156251
New best score: 0.02181996635156251
Epoch 18: train loss: 0.02662210316247223
valid loss: 0.021762580478747115
New best score: 0.021762580478747115
Epoch 19: train loss: 0.026635378260048814
valid loss: 0.02163417828167519
New best score: 0.02163417828167519
Epoch 20: train loss: 0.026724288395666526
valid loss: 0.02153022467486988
New best score: 0.02153022467486988
Epoch 21: train loss: 0.0266051148182408
valid loss: 0.021428093735047213
New best score: 0.021428093735047213
Epoch 22: train loss: 0.02637773595953335
valid loss: 0.021339995185513803
New best score: 0.021339995185513803
Epoch 23: train loss: 0.026257544278254445
valid loss: 0.021252412970885228
New best score: 0.021252412970885228
Epoch 24: train loss: 0.026126052476430087
valid loss: 0.021180965348218103
New best score: 0.021180965348218103
Epoch 25: train loss: 0.02579458606234408
valid loss: 0.021089692087589554
New best score: 0.021089692087589554
Epoch 26: train loss: 0.025870972849209625
valid loss: 0.02096897741255498
New best score: 0.02096897741255498
Epoch 27: train loss: 0.02589873712250329
valid loss: 0.02103838359115167
1 iterations since best score.
Epoch 28: train loss: 0.025474642118506745
valid loss: 0.02083245238971189
New best score: 0.02083245238971189
Epoch 29: train loss: 0.025491673881757868
valid loss: 0.020914757669053444
1 iterations since best score.
Epoch 30: train loss: 0.0256901814166704
valid loss: 0.02079701650928441
New best score: 0.02079701650928441
Epoch 31: train loss: 0.025314893825050894
valid loss: 0.02063066685404323
New best score: 0.02063066685404323
Epoch 32: train loss: 0.025559447194898346
valid loss: 0.02062068326803321
New best score: 0.02062068326803321
Epoch 33: train loss: 0.024862300820050344
valid loss: 0.020600306137866987
New best score: 0.020600306137866987
Epoch 34: train loss: 0.025080274871548718
valid loss: 0.020477301164280846
New best score: 0.020477301164280846
Epoch 35: train loss: 0.024728723903396744
valid loss: 0.020394465477394114
New best score: 0.020394465477394114
Epoch 36: train loss: 0.02477897367222915
valid loss: 0.020449772248645134
1 iterations since best score.
Epoch 37: train loss: 0.024465490879030653
valid loss: 0.020325674156434426
New best score: 0.020325674156434426
Epoch 38: train loss: 0.024305174552148163
valid loss: 0.020269202150511326
New best score: 0.020269202150511326
Epoch 39: train loss: 0.024521953303208416
valid loss: 0.020168634172646034
New best score: 0.020168634172646034
Epoch 40: train loss: 0.024144744264793513
valid loss: 0.020071419583928714
New best score: 0.020071419583928714
Epoch 41: train loss: 0.024092775663578203
valid loss: 0.020062985963854797
New best score: 0.020062985963854797
Epoch 42: train loss: 0.02412362778172018
valid loss: 0.020077789380454302
1 iterations since best score.
Epoch 43: train loss: 0.023811501132976087
valid loss: 0.01995381725687391
New best score: 0.01995381725687391
Epoch 44: train loss: 0.02424977031820427
valid loss: 0.019959632811630195
1 iterations since best score.
Epoch 45: train loss: 0.02389407654877852
valid loss: 0.0198583653335373
New best score: 0.0198583653335373
Epoch 46: train loss: 0.023958714262081085
valid loss: 0.01977933693201347
New best score: 0.01977933693201347
Epoch 47: train loss: 0.023485491898673876
valid loss: 0.019806338451762016
1 iterations since best score.
Epoch 48: train loss: 0.023657646779875568
valid loss: 0.019662209351603045
New best score: 0.019662209351603045
Epoch 49: train loss: 0.023470603387796607
valid loss: 0.01968898415804683
1 iterations since best score.
Epoch 50: train loss: 0.02365986756685708
valid loss: 0.019617491648048976
New best score: 0.019617491648048976
Epoch 51: train loss: 0.02301738877784297
valid loss: 0.01950973152880216
New best score: 0.01950973152880216
Epoch 52: train loss: 0.023529816942643837
valid loss: 0.019513023327883395
1 iterations since best score.
Epoch 53: train loss: 0.023395457049479162
valid loss: 0.01949332637045675
New best score: 0.01949332637045675
Epoch 54: train loss: 0.02303883458951125
valid loss: 0.01939637301988452
New best score: 0.01939637301988452
Epoch 55: train loss: 0.022967305407017097
valid loss: 0.01937846771538095
New best score: 0.01937846771538095
Epoch 56: train loss: 0.023021493925660472
valid loss: 0.01932469207037729
New best score: 0.01932469207037729
Epoch 57: train loss: 0.02324649085298298
valid loss: 0.019319333965365924
New best score: 0.019319333965365924
Epoch 58: train loss: 0.02314090387805331
valid loss: 0.01927059471538504
New best score: 0.01927059471538504
Epoch 59: train loss: 0.022600235849646513
valid loss: 0.019282025675024694
1 iterations since best score.
Epoch 60: train loss: 0.022965760435352554
valid loss: 0.019262573485965002
New best score: 0.019262573485965002
Epoch 61: train loss: 0.023083728506856634
valid loss: 0.019118402978720885
New best score: 0.019118402978720885
Epoch 62: train loss: 0.022604351701886245
valid loss: 0.019093919451643657
New best score: 0.019093919451643657
Epoch 63: train loss: 0.02272556185217959
valid loss: 0.01905925034906695
New best score: 0.01905925034906695
Epoch 64: train loss: 0.0222361646619328
valid loss: 0.01899794363760252
New best score: 0.01899794363760252
Epoch 65: train loss: 0.022313779764221074
valid loss: 0.018973210823080944
New best score: 0.018973210823080944
Epoch 66: train loss: 0.022522902168711046
valid loss: 0.018901191251937687
New best score: 0.018901191251937687
Epoch 67: train loss: 0.02248352280253434
valid loss: 0.01889178021709165
New best score: 0.01889178021709165
Epoch 68: train loss: 0.022433675548692106
valid loss: 0.018912809526501987
1 iterations since best score.
Epoch 69: train loss: 0.02257502525739895
valid loss: 0.018815524044034422
New best score: 0.018815524044034422
Epoch 70: train loss: 0.0224518446423368
valid loss: 0.018792384044302862
New best score: 0.018792384044302862
Epoch 71: train loss: 0.02226468713430556
valid loss: 0.018732086603804567
New best score: 0.018732086603804567
Epoch 72: train loss: 0.022387760058183395
valid loss: 0.01883075698622365
1 iterations since best score.
Epoch 73: train loss: 0.022133301173819384
valid loss: 0.01867632728383006
New best score: 0.01867632728383006
Epoch 74: train loss: 0.022178997785715745
valid loss: 0.018700476872729636
1 iterations since best score.
Epoch 75: train loss: 0.022028937389144593
valid loss: 0.018650301263280863
New best score: 0.018650301263280863
Epoch 76: train loss: 0.02214035027425373
valid loss: 0.018606594060496758
New best score: 0.018606594060496758
Epoch 77: train loss: 0.021738268898102858
valid loss: 0.018632269502983842
1 iterations since best score.
Epoch 78: train loss: 0.02227861989753848
valid loss: 0.01854319557435607
New best score: 0.01854319557435607
Epoch 79: train loss: 0.021809139837872374
valid loss: 0.018610031961443035
1 iterations since best score.
Epoch 80: train loss: 0.022240891229284725
valid loss: 0.018547307454874037
2 iterations since best score.
Epoch 81: train loss: 0.022066849491217958
valid loss: 0.01848699482949196
New best score: 0.01848699482949196
Epoch 82: train loss: 0.021692594942564668
valid loss: 0.018455498772571525
New best score: 0.018455498772571525
Epoch 83: train loss: 0.02205857191164488
valid loss: 0.01839941353727987
New best score: 0.01839941353727987
Epoch 84: train loss: 0.021860865075639797
valid loss: 0.0183856724618929
New best score: 0.0183856724618929
Epoch 85: train loss: 0.021753365356460868
valid loss: 0.018383686461923593
New best score: 0.018383686461923593
Epoch 86: train loss: 0.021993174024765874
valid loss: 0.018376381002758412
New best score: 0.018376381002758412
Epoch 87: train loss: 0.021596283111213768
valid loss: 0.018388316551951153
1 iterations since best score.
Epoch 88: train loss: 0.021463176303113105
valid loss: 0.018383121337420993
2 iterations since best score.
Epoch 89: train loss: 0.02156794395123699
valid loss: 0.0182802003695085
New best score: 0.0182802003695085
Epoch 90: train loss: 0.021446433153811905
valid loss: 0.018424906315602608
1 iterations since best score.
Epoch 91: train loss: 0.02153544440147882
valid loss: 0.01828304048184855
2 iterations since best score.
Epoch 92: train loss: 0.02158625805340921
valid loss: 0.01830057208871601
3 iterations since best score.
Early stopping
predictions_df=valid_df
predictions_df['predictions']=np.vstack(predictions)
performance_assessment(predictions_df, top_k_list=[100])As três métricas são muito próximas, com ou sem a característica adicional. Elas foram respectivamente de 0,859, 0,646 e 0,28 para 0,861, 0,651 e 0,276. A conclusão é, portanto, atenuada e não mostra um benefício significativo desta modelagem semi-supervisionada. No entanto, tenha em mente que, na prática em um cenário diferente, pode haver um benefício, especialmente se a quantidade de dados não rotulados disponíveis for muito maior do que a quantidade de dados rotulados.
Observe também que existem várias direções para melhoria. Por exemplo, esta técnica semi-supervisionada pode ser aprimorada treinando dois autoencoders separados, para cada classe, e usando ambos os erros de reconstrução como variáveis adicionais.
Conclusão¶
Os autoencoders fazem parte da grande família de modelos de aprendizado profundo. Seu objetivo é aprender representações para reconstruir variáveis descritivas, portanto foram amplamente usados para problemas de aprendizado não supervisionado. A detecção de anomalias, e em particular a detecção de fraude, pode ser abordada com técnicas não supervisionadas ou semi-supervisionadas.
Nesta seção, usamos o autoencoder, e em particular seu erro de reconstrução, como indicador de risco de fraude. Usado isoladamente (método não supervisionado), ele detecta pontos de dados que estão distantes do restante da distribuição, o que permite detectar muitas fraudes, mas também introduz muitos alertas falsos (por exemplo, transações genuínas que têm características raras). Portanto, obtém uma AUC ROC razoável, mas métricas baseadas em precisão baixas. Usado como uma variável extra em um método supervisionado (uso semi-supervisionado), pode permitir aumentar o desempenho em configurações específicas.
- An, J., & Cho, S. (2015). Variational autoencoder based anomaly detection using reconstruction probability. Special Lecture on IE, 2(1), 1–18.
- Zhou, C., & Paffenroth, R. C. (2017). Anomaly detection with robust deep autoencoders. Proceedings of the 23rd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, 665–674.
- Carcillo, F., Le Borgne, Y.-A., Caelen, O., Kessaci, Y., Oblé, F., & Bontempi, G. (2019). Combining unsupervised and supervised learning in credit card fraud detection. Information Sciences.
- Veeramachaneni, K., Arnaldo, I., Korrapati, V., Bassias, C., & Li, K. (2016). AIundefined̂ 2: training a big data machine to defend. 2016 IEEE 2nd International Conference on Big Data Security on Cloud (BigDataSecurity), IEEE International Conference on High Performance and Smart Computing (HPSC), and IEEE International Conference on Intelligent Data and Security (IDS), 49–54.
- Alazizi, A., Habrard, A., Jacquenet, F., He-Guelton, L., & Oblé, F. (2020). Dual Sequential Variational Autoencoders for Fraud Detection. IDA, 14–26.