Autoencoder Para detección de fraude¶
Integrantes del grupo:
- ALEXANDER OVIEDO FADUL
- MARIA FERNANDA RUIZ PAIPILLA
- NEHEMAN SAMIR JALLER CERCHIARO
- WILLIAM DAVID OBANDO LOPEZ
Asignatura: Deep Learning (NRC-198)
Docente: Juan Carlos Valencia
Corporación Universitaria Minuto de Dios – UNIMINUTO
El autoencoder tiene diferentes aplicaciones algunas son:
Eliminación de ruido
Anonimización de datos
Criptografía y seguridad
Agrupamiento semántico
Generación de nuevos datos
Imputación de datos perdidos
Reducción de dimensionalidad
Identificación de anomalías
En este caso mediante la identificación de anomalías, se identificará el fraude
El autoencoder tiene diferentes aplicaciones una de ellas es a la identificación de anomalías o datos atípicos o en ingles (outliers) es una observación que es numéricamente distante del resto de los datos.
%%html
<p style='text-align: justify;'> <b>Una aplicación del autoencoder es la reducción de ruido en una imagen, se debe tener un dato de entrada, luego un codificador, se comprime la imagen y un decodificador para que la imagen este sin ruido. En este caso el dato de entrada es una imagen con ruido y el dato de salida es la misma imagen sin ruido(ver imagen a continuación) </b> </p>
Una aplicación del autoencoder es la reducción de ruido en una imagen, se debe tener un dato de entrada, luego un codificador, se comprime la imagen y un decodificador para que la imagen este sin ruido. En este caso el dato de entrada es una imagen con ruido y el dato de salida es la misma imagen sin ruido(ver imagen a continuación)

Para el caso de deteccion de fraude la entrada seran las caracteristicas(features) de los datos
Se tiene un archivo.csv que tiene unas caracteristicas y una columna llamada fraud=0 si no es fraudulento el pago bancario,fraud=1 si es fraudulento.
Trabajara con los siguientes datos libres:
Fraud Detection on Bank Payments(Detección de fraude en pagos bancarios) Obtenido de:
Importemos la librería pandas y carguemos el archivo csv
import pandas as pd # importa la librería pandas
dataframe=pd.read_csv('/content/fraude.csv') # lee el archivo csv, utiliza pd.read_csv('nombre_del_archivo.csv') se debe cargar el archivo enviado por el profesor
dataframe # Con el nombre del dataframe en este caso data_frame puede ver su contenido.
| step | customer | age | gender | zipcodeOri | merchant | zipMerchant | category | amount | fraud | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 'C1093826151' | '4' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 4.55 | 0 |
| 1 | 0 | 'C352968107' | '2' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 39.68 | 0 |
| 2 | 0 | 'C2054744914' | '4' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 26.89 | 0 |
| 3 | 0 | 'C1760612790' | '3' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 17.25 | 0 |
| 4 | 0 | 'C757503768' | '5' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 35.72 | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 594638 | 179 | 'C1753498738' | '3' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 20.53 | 0 |
| 594639 | 179 | 'C650108285' | '4' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 50.73 | 0 |
| 594640 | 179 | 'C123623130' | '2' | 'F' | '28007' | 'M349281107' | '28007' | 'es_fashion' | 22.44 | 0 |
| 594641 | 179 | 'C1499363341' | '5' | 'M' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 14.46 | 0 |
| 594642 | 179 | 'C616528518' | '4' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 26.93 | 0 |
594643 rows × 10 columns
los datos tienen 9 columnas(características,features,9 columnas) and a target column(fraude o no fraude). The feature(características de las columnas son :
Step: This feature represents the day from the start of simulation. It has 180 steps so simulation ran for virtually 6 months.
Customer: This feature represents the customer id
zipCodeOrigin: The zip code of origin/source.
Merchant: The merchant's id zipMerchant: The merchant's zip code
Age: Categorized age 0: <= 18, 1: 19-25, 2: 26-35, 3: 36-45, 4: 46:55, 5: 56:65, 6: > 65 U: Unknown
Gender: Gender for customer E : Enterprise, F: Female, M: Male, U: Unknown
Category: Category of the purchase
Fraud: Target variable which shows if the transaction fraudulent(1) or benign(0)
dataframe.head(5) #Muestra las 5 primeras filas
| step | customer | age | gender | zipcodeOri | merchant | zipMerchant | category | amount | fraud | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 'C1093826151' | '4' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 4.55 | 0 |
| 1 | 0 | 'C352968107' | '2' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 39.68 | 0 |
| 2 | 0 | 'C2054744914' | '4' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 26.89 | 0 |
| 3 | 0 | 'C1760612790' | '3' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 17.25 | 0 |
| 4 | 0 | 'C757503768' | '5' | 'M' | '28007' | 'M348934600' | '28007' | 'es_transportation' | 35.72 | 0 |
dataframe.tail() #Muestra las 5 últimas filas
| step | customer | age | gender | zipcodeOri | merchant | zipMerchant | category | amount | fraud | |
|---|---|---|---|---|---|---|---|---|---|---|
| 594638 | 179 | 'C1753498738' | '3' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 20.53 | 0 |
| 594639 | 179 | 'C650108285' | '4' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 50.73 | 0 |
| 594640 | 179 | 'C123623130' | '2' | 'F' | '28007' | 'M349281107' | '28007' | 'es_fashion' | 22.44 | 0 |
| 594641 | 179 | 'C1499363341' | '5' | 'M' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 14.46 | 0 |
| 594642 | 179 | 'C616528518' | '4' | 'F' | '28007' | 'M1823072687' | '28007' | 'es_transportation' | 26.93 | 0 |
Dimensión y nombre de las columnas
print("Shape: ", dataframe.shape)# Dimensión del dataframe:filas y columnas
print("Columnas: ", dataframe.columns)# Nombre de las columnas del dataframe.
Shape: (594643, 10)
Columnas: Index(['step', 'customer', 'age', 'gender', 'zipcodeOri', 'merchant',
'zipMerchant', 'category', 'amount', 'fraud'],
dtype='object')
dataframe['amount'].describe()#Muestra los valores descriptivos de la columna monto de la transacción.
| amount | |
|---|---|
| count | 594643.000000 |
| mean | 37.890135 |
| std | 111.402831 |
| min | 0.000000 |
| 25% | 13.740000 |
| 50% | 26.900000 |
| 75% | 42.540000 |
| max | 8329.960000 |
Imprime información sobre las características o variables
print(dataframe.info())
print("\nConteo de valores únicos:\n")
print(dataframe.nunique())
<class 'pandas.core.frame.DataFrame'> RangeIndex: 594643 entries, 0 to 594642 Data columns (total 10 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 step 594643 non-null int64 1 customer 594643 non-null object 2 age 594643 non-null object 3 gender 594643 non-null object 4 zipcodeOri 594643 non-null object 5 merchant 594643 non-null object 6 zipMerchant 594643 non-null object 7 category 594643 non-null object 8 amount 594643 non-null float64 9 fraud 594643 non-null int64 dtypes: float64(1), int64(2), object(7) memory usage: 45.4+ MB None Conteo de valores únicos: step 180 customer 4112 age 8 gender 4 zipcodeOri 1 merchant 50 zipMerchant 1 category 15 amount 23767 fraud 2 dtype: int64
Valores faltantes
print("Are There Missing Data(hay valores faltantes)? :",dataframe.isnull().any().any())
print(dataframe.isnull().sum())
Are There Missing Data(hay valores faltantes)? : False step 0 customer 0 age 0 gender 0 zipcodeOri 0 merchant 0 zipMerchant 0 category 0 amount 0 fraud 0 dtype: int64
# Cargar las librerias
# data analysis and wrangling
import pandas as pd
import numpy as np
import random as rnd
# operating system
import os
# visualization
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
# Se crea 2 dataframes uno con fraude y otro sin fraude
df_fraud = dataframe.loc[dataframe.fraud == 1]
df_non_fraud = dataframe.loc[dataframe.fraud == 0]
sns.countplot(x="fraud",data=dataframe)
plt.title("Cuenta los pagos con fraude y sin fraude")
plt.show()
print("Número normal de pagos : ",df_non_fraud.fraud.count())
print("Número de fraudes: ",df_fraud.fraud.count())
Número normal de pagos : 587443 Número de fraudes: 7200
Gráfico dinámico o interactivo con la librería plotly
import plotly.express as px
fig = px.histogram(dataframe, x='fraud', histfunc='count')
fig.show()
print("valor promedio de las caracteristicas por categoría monto y fraude",dataframe.groupby('category')[['amount','fraud']].mean())
valor promedio de las caracteristicas por categoría monto y fraude amount fraud category 'es_barsandrestaurants' 43.461014 0.018829 'es_contents' 44.547571 0.000000 'es_fashion' 65.666642 0.017973 'es_food' 37.070405 0.000000 'es_health' 135.621367 0.105126 'es_home' 165.670846 0.152064 'es_hotelservices' 205.614249 0.314220 'es_hyper' 45.970421 0.045917 'es_leisure' 288.911303 0.949900 'es_otherservices' 135.881524 0.250000 'es_sportsandtoys' 215.715280 0.495252 'es_tech' 120.947937 0.066667 'es_transportation' 26.958187 0.000000 'es_travel' 2250.409190 0.793956 'es_wellnessandbeauty' 65.511221 0.047594
# histograma por monto con fraude y sin fraude
plt.hist(df_fraud.amount, alpha=0.5, label='fraude',bins=100)
plt.hist(df_non_fraud.amount, alpha=0.5, label='no fraude',bins=100)
plt.title("Histograma de fraude y no fraude en los pagos")
plt.ylim(0,10000)
plt.xlim(0,1000)
plt.legend()
plt.show()
Las columnas zipCodeOri y zipMerchant tienen la misma información, borrar una columna para que quede una sola información para borrar se utiliza drop
print("Unique zipCodeOri values: ",dataframe.zipcodeOri.nunique())
print("Unique zipMerchant values: ",dataframe.zipMerchant.nunique())
# drop zipcodeori y zipMerchant para tener un valor unico
data_reducida = dataframe.drop(['zipcodeOri','zipMerchant'],axis=1)
Unique zipCodeOri values: 1 Unique zipMerchant values: 1
Observemos las columnas resultantes:
data_reducida.columns
Index(['step', 'customer', 'age', 'gender', 'merchant', 'category', 'amount',
'fraud'],
dtype='object')
# Cambiando las columnas a categoricas
col_categorical = data_reducida.select_dtypes(include= ['object']).columns
for col in col_categorical:
data_reducida[col] = data_reducida[col].astype('category')
# valores categoricos ==> valores numericos# Las categorias se cambian por números.
data_reducida[col_categorical] = data_reducida[col_categorical].apply(lambda x: x.cat.codes)
data_reducida.head(5)
| step | customer | age | gender | merchant | category | amount | fraud | |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 210 | 4 | 2 | 30 | 12 | 4.55 | 0 |
| 1 | 0 | 2753 | 2 | 2 | 30 | 12 | 39.68 | 0 |
| 2 | 0 | 2285 | 4 | 1 | 18 | 12 | 26.89 | 0 |
| 3 | 0 | 1650 | 3 | 2 | 30 | 12 | 17.25 | 0 |
| 4 | 0 | 3585 | 5 | 2 | 30 | 12 | 35.72 | 0 |
Escalar o normalizar el monto del pago a valores en el intervalo (-1,1)
from sklearn.preprocessing import StandardScaler
data_reducida['amount'] = StandardScaler().fit_transform(data_reducida['amount'].values.reshape(-1,1))
Observe la columna amount con valores en el intervalo (-1,1)
data_reducida
| step | customer | age | gender | merchant | category | amount | fraud | |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 210 | 4 | 2 | 30 | 12 | -0.299276 | 0 |
| 1 | 0 | 2753 | 2 | 2 | 30 | 12 | 0.016067 | 0 |
| 2 | 0 | 2285 | 4 | 1 | 18 | 12 | -0.098742 | 0 |
| 3 | 0 | 1650 | 3 | 2 | 30 | 12 | -0.185275 | 0 |
| 4 | 0 | 3585 | 5 | 2 | 30 | 12 | -0.019480 | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 594638 | 179 | 1639 | 3 | 1 | 18 | 12 | -0.155832 | 0 |
| 594639 | 179 | 3369 | 4 | 1 | 18 | 12 | 0.115256 | 0 |
| 594640 | 179 | 529 | 2 | 1 | 31 | 2 | -0.138687 | 0 |
| 594641 | 179 | 1083 | 5 | 2 | 18 | 12 | -0.210319 | 0 |
| 594642 | 179 | 3304 | 4 | 1 | 18 | 12 | -0.098383 | 0 |
594643 rows × 8 columns
Entrenamos el modelo 80% para entrenamiento 20%=0.2=test_size es 20% para prueba o testing.
El autoencoder será entrenado únicamente con registros normales,transacciones no fraudulentas para que de esta forma aprenda a obtener una representación compacta de esos datos normales, no fraudulentos
Mientras que el de validación (test) o prueba tendrá los dos tipos de registros (normales y fraudulentos)
from sklearn.model_selection import train_test_split
X_train, X_test = train_test_split(data_reducida, test_size=0.2, random_state=42)
X_train = X_train[X_train.fraud == 0]
X_train = X_train.drop(['fraud'], axis=1)
X_train = X_train.values
Y_test = X_test['fraud']
X_test = X_test.drop(['fraud'], axis=1)
X_test = X_test.values
AUTOENCODER: 7-6-4-6-7, las funciones de activación son tangente hiperbolica(tanh),y Relu en el siguiente orden:tanh-relu-tanh-relu
dim_entrada = X_train.shape[1]
dim_entrada
7
import numpy as np
np.random.seed(5) # MODIFICADO: valor de n = 5 según instrucciones del docente
from keras.models import Model, load_model
from keras.layers import Input, Dense, Dropout
dim_entrada = X_train.shape[1] # número de elementos de entrada=7 son las 7 características o features
capa_entrada = Input(shape=(dim_entrada,))
# ========== ARQUITECTURA MODIFICADA ==========
# Arquitectura original: 7-6-4-6-7
# Arquitectura modificada: 7-256-6-4-6-256-7 (se agrega capa oculta de 256 neuronas)
# ENCODER
encoder = Dense(256, activation='relu')(capa_entrada) # NUEVA capa oculta con 256 neuronas
encoder = Dropout(0.2)(encoder) # Dropout del 20% para evitar sobreajuste
encoder = Dense(6, activation='tanh')(encoder) # se reduce a 6 características
encoder = Dense(4, activation='relu')(encoder) # cuello de botella: 4 características
# DECODER (simétrico al encoder)
decoder = Dense(6, activation='tanh')(encoder) # aumenta a 6 características
decoder = Dense(256, activation='relu')(decoder) # NUEVA capa simétrica de 256 neuronas
decoder = Dropout(0.2)(decoder) # Dropout del 20%
decoder = Dense(7, activation='relu')(decoder) # salida: 7 (mismas que la entrada)
autoencoder = Model(inputs=capa_entrada, outputs=decoder)
# ========== OPTIMIZADOR MODIFICADO ==========
# Se cambia de SGD/Adam a RMSprop con learning rate de 0.001
from tensorflow.keras.optimizers import RMSprop
optimizador = RMSprop(learning_rate=0.001)
# loss: mse (Mean Squared Error) - error cuadrático medio
autoencoder.compile(optimizer=optimizador, loss='mse')
# ========== ÉPOCAS MODIFICADAS ==========
nits = 150 # MODIFICADO: se aumentan las épocas de 100 a 150
tam_lote = 64 # MODIFICADO: se ajusta el tamaño del lote a 64
autoencoder.fit(X_train, X_train, epochs=nits, batch_size=tam_lote, shuffle=True, validation_data=(X_test,X_test), verbose=1)
Epoch 1/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 30s 3ms/step - loss: 156331.8125 - val_loss: 42063.3711 Epoch 2/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 38043.6523 - val_loss: 25751.1074 Epoch 3/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 30066.0957 - val_loss: 20178.4980 Epoch 4/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 24861.9609 - val_loss: 19700.8516 Epoch 5/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 23751.5508 - val_loss: 20539.5957 Epoch 6/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 18177.8281 - val_loss: 7446.2275 Epoch 7/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 9397.1299 - val_loss: 29170.9062 Epoch 8/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 6682.1177 - val_loss: 29317.9746 Epoch 9/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 5732.4976 - val_loss: 6029.2046 Epoch 10/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 5503.2612 - val_loss: 15776.8076 Epoch 11/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 5049.4653 - val_loss: 11312.9609 Epoch 12/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4868.7217 - val_loss: 31072.2051 Epoch 13/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4646.5112 - val_loss: 9636.6719 Epoch 14/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4615.0728 - val_loss: 28598.3340 Epoch 15/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4454.4058 - val_loss: 18029.5625 Epoch 16/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 21s 3ms/step - loss: 4328.3950 - val_loss: 14127.0361 Epoch 17/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4324.3770 - val_loss: 20995.2207 Epoch 18/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 40s 3ms/step - loss: 4183.5005 - val_loss: 21333.1211 Epoch 19/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4167.6309 - val_loss: 25034.1738 Epoch 20/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4142.0474 - val_loss: 7916.3662 Epoch 21/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4094.0771 - val_loss: 17256.6699 Epoch 22/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4144.3374 - val_loss: 8410.6660 Epoch 23/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4243.6323 - val_loss: 9783.5508 Epoch 24/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 5163.9160 - val_loss: 21763.9062 Epoch 25/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4421.9238 - val_loss: 32424.1348 Epoch 26/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 4262.5034 - val_loss: 6724.6362 Epoch 27/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 24s 3ms/step - loss: 4261.2461 - val_loss: 15722.2939 Epoch 28/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4490.3003 - val_loss: 12715.7500 Epoch 29/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4413.0854 - val_loss: 30337.4844 Epoch 30/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4177.4243 - val_loss: 23822.0430 Epoch 31/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4058.5620 - val_loss: 32526.7227 Epoch 32/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4080.3423 - val_loss: 18249.9004 Epoch 33/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4341.5449 - val_loss: 15674.9053 Epoch 34/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4202.3423 - val_loss: 12955.3477 Epoch 35/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4138.1230 - val_loss: 13610.4023 Epoch 36/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3908.3801 - val_loss: 26040.4297 Epoch 37/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4105.0625 - val_loss: 17958.3809 Epoch 38/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4109.4712 - val_loss: 18394.9355 Epoch 39/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 3948.9966 - val_loss: 25073.2871 Epoch 40/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4030.7063 - val_loss: 16117.3721 Epoch 41/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3861.5505 - val_loss: 17173.4219 Epoch 42/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 5189.9277 - val_loss: 16251.9502 Epoch 43/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 4358.6543 - val_loss: 29480.2754 Epoch 44/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 24s 3ms/step - loss: 4450.6040 - val_loss: 34918.1562 Epoch 45/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4750.9346 - val_loss: 30632.6719 Epoch 46/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3778.5486 - val_loss: 48172.1328 Epoch 47/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3829.9746 - val_loss: 38381.0547 Epoch 48/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4002.6084 - val_loss: 24295.7344 Epoch 49/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3875.8862 - val_loss: 23107.5449 Epoch 50/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4245.8174 - val_loss: 16648.9473 Epoch 51/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 5693.9443 - val_loss: 24418.4688 Epoch 52/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 40s 3ms/step - loss: 4531.4468 - val_loss: 21326.6621 Epoch 53/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3914.0803 - val_loss: 20488.6914 Epoch 54/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 4571.8486 - val_loss: 15747.2041 Epoch 55/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4349.4624 - val_loss: 25881.5234 Epoch 56/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3993.0923 - val_loss: 12133.3086 Epoch 57/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3926.7458 - val_loss: 23796.1172 Epoch 58/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3947.2622 - val_loss: 27778.3359 Epoch 59/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3962.9319 - val_loss: 43067.5273 Epoch 60/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4457.6167 - val_loss: 29561.2695 Epoch 61/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 5204.7695 - val_loss: 20347.1523 Epoch 62/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4626.6772 - val_loss: 15431.1133 Epoch 63/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4455.8164 - val_loss: 30626.0645 Epoch 64/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 4322.0747 - val_loss: 24420.5977 Epoch 65/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4261.9282 - val_loss: 21630.8320 Epoch 66/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4187.0898 - val_loss: 15816.2207 Epoch 67/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4147.2271 - val_loss: 23346.2676 Epoch 68/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3980.2517 - val_loss: 33104.9922 Epoch 69/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3933.9233 - val_loss: 32426.1680 Epoch 70/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3890.9822 - val_loss: 21394.5195 Epoch 71/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3853.8406 - val_loss: 23065.9570 Epoch 72/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3881.4397 - val_loss: 16675.7461 Epoch 73/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3778.8879 - val_loss: 27034.3242 Epoch 74/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3731.1206 - val_loss: 25817.1484 Epoch 75/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3703.3013 - val_loss: 24798.7500 Epoch 76/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3820.3723 - val_loss: 25298.5527 Epoch 77/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3839.1729 - val_loss: 25268.9980 Epoch 78/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3868.1558 - val_loss: 16300.1074 Epoch 79/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3880.7917 - val_loss: 20471.3828 Epoch 80/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3806.1018 - val_loss: 19810.6270 Epoch 81/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3845.9182 - val_loss: 27507.0215 Epoch 82/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3836.0171 - val_loss: 23590.4785 Epoch 83/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3776.9482 - val_loss: 18311.8691 Epoch 84/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 3799.0586 - val_loss: 19323.9766 Epoch 85/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3763.4597 - val_loss: 17410.4297 Epoch 86/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3697.6404 - val_loss: 25838.6504 Epoch 87/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3766.5815 - val_loss: 17948.3945 Epoch 88/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 42s 3ms/step - loss: 3706.9802 - val_loss: 29557.4785 Epoch 89/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3699.7083 - val_loss: 27186.4316 Epoch 90/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3706.5046 - val_loss: 32716.0918 Epoch 91/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3553.6604 - val_loss: 26528.6855 Epoch 92/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3621.7678 - val_loss: 16534.6992 Epoch 93/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3481.5007 - val_loss: 27651.9297 Epoch 94/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3415.4407 - val_loss: 24377.7070 Epoch 95/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3458.7451 - val_loss: 27639.0059 Epoch 96/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 24s 3ms/step - loss: 3409.6555 - val_loss: 29177.8438 Epoch 97/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3412.8354 - val_loss: 17361.3750 Epoch 98/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3273.4055 - val_loss: 31115.0176 Epoch 99/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3192.6909 - val_loss: 14836.9395 Epoch 100/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3116.9038 - val_loss: 21731.4590 Epoch 101/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3123.5676 - val_loss: 32304.1074 Epoch 102/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3054.5938 - val_loss: 29064.2949 Epoch 103/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3032.8213 - val_loss: 28510.5371 Epoch 104/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3051.8333 - val_loss: 15357.7988 Epoch 105/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3084.3745 - val_loss: 18077.0996 Epoch 106/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3078.1145 - val_loss: 24259.5020 Epoch 107/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3096.9019 - val_loss: 18851.5254 Epoch 108/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3068.2346 - val_loss: 25328.3125 Epoch 109/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3182.3794 - val_loss: 33826.0195 Epoch 110/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3130.8777 - val_loss: 30120.7031 Epoch 111/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3184.6978 - val_loss: 21044.8770 Epoch 112/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3203.6943 - val_loss: 26381.0957 Epoch 113/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3131.1228 - val_loss: 20293.8262 Epoch 114/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3189.8057 - val_loss: 28110.1543 Epoch 115/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3241.1799 - val_loss: 11983.8877 Epoch 116/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3212.4624 - val_loss: 18769.8652 Epoch 117/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3201.3660 - val_loss: 21902.7246 Epoch 118/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3174.9858 - val_loss: 13954.1699 Epoch 119/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 3245.0413 - val_loss: 13216.5254 Epoch 120/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3266.9509 - val_loss: 24444.5488 Epoch 121/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3580.7290 - val_loss: 23831.1484 Epoch 122/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3396.9556 - val_loss: 18906.3535 Epoch 123/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3450.0913 - val_loss: 14378.7646 Epoch 124/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3501.6785 - val_loss: 11634.6416 Epoch 125/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3462.2009 - val_loss: 28975.0625 Epoch 126/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3373.2622 - val_loss: 22661.6836 Epoch 127/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3518.9634 - val_loss: 23283.7227 Epoch 128/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3474.5676 - val_loss: 20861.1504 Epoch 129/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3427.5049 - val_loss: 19256.3340 Epoch 130/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3471.6228 - val_loss: 19842.5430 Epoch 131/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3377.6162 - val_loss: 24154.0723 Epoch 132/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3441.6787 - val_loss: 18767.9277 Epoch 133/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3332.1145 - val_loss: 15612.9658 Epoch 134/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 24s 3ms/step - loss: 3769.5171 - val_loss: 20717.6289 Epoch 135/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3828.2727 - val_loss: 20044.2383 Epoch 136/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 22s 3ms/step - loss: 3537.5554 - val_loss: 20376.3164 Epoch 137/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3621.4888 - val_loss: 12364.3906 Epoch 138/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3661.0142 - val_loss: 11637.2998 Epoch 139/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3680.0811 - val_loss: 27063.7266 Epoch 140/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3794.6387 - val_loss: 24099.9707 Epoch 141/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3633.8896 - val_loss: 14799.5117 Epoch 142/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3719.0547 - val_loss: 17766.9941 Epoch 143/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3817.7668 - val_loss: 15373.5996 Epoch 144/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3803.6235 - val_loss: 19731.8887 Epoch 145/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 4093.7158 - val_loss: 25692.9766 Epoch 146/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 24s 3ms/step - loss: 3710.1704 - val_loss: 30892.5000 Epoch 147/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3796.1880 - val_loss: 14336.1016 Epoch 148/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 42s 3ms/step - loss: 3832.8005 - val_loss: 41155.0117 Epoch 149/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 23s 3ms/step - loss: 3755.4014 - val_loss: 13725.5068 Epoch 150/150 7343/7343 ━━━━━━━━━━━━━━━━━━━━ 41s 3ms/step - loss: 3815.7297 - val_loss: 17879.4121
<keras.src.callbacks.history.History at 0x7f2eb83f58b0>
print(autoencoder.summary())
Model: "functional"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ input_layer (InputLayer) │ (None, 7) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 256) │ 2,048 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 256) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 6) │ 1,542 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_2 (Dense) │ (None, 4) │ 28 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_3 (Dense) │ (None, 6) │ 30 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_4 (Dense) │ (None, 256) │ 1,792 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout_1 (Dropout) │ (None, 256) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_5 (Dense) │ (None, 7) │ 1,799 │ └─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 14,480 (56.57 KB)
Trainable params: 7,239 (28.28 KB)
Non-trainable params: 0 (0.00 B)
Optimizer params: 7,241 (28.29 KB)
None
# Predicción X_test -> Autoencoder -> X_pred
#X_test-X_pred=diferencia entre el valor de test y la predicción para ese valor.
X_pred = autoencoder.predict(X_test)
ecm = np.mean(np.power(X_test-X_pred,2), axis=1)#ecm error cuadratico,mean es el promedio
print(X_pred.shape) # power(,2) es la función potencia elevada al cuadrado
# Gráfica precision-recall para determinar el umbral
from sklearn.metrics import confusion_matrix, precision_recall_curve
precision, recall, umbral = precision_recall_curve(Y_test, ecm)
plt.plot(umbral, precision[1:], label="Precision",linewidth=5)
plt.plot(umbral, recall[1:], label="Recall",linewidth=5)
plt.title('Precision y Recall para diferentes umbrales')
plt.xlabel('Umbral')
plt.ylabel('Precision/Recall')
plt.legend()
plt.show()
# 5.3. Matriz de confusión
umbral_fijo = 0.1 # para obtener un recall alto para clasificar la mayor parte de los fraudes
Y_pred = [0 if e > umbral_fijo else 1 for e in ecm]
#Y_pred=0 significa registro normal
#Y_pred=1 significa registro con fraude
# una mayor precision significa menor recall y viceversa
#Fijaremos entonces un umbral de 0.1
#Si el error de la predicción sobrepasa este umbral, asignaremos la categoría “0” (registro fraudulento),
#mientras que si el error es menor o igual al umbral asignaremos la categoría “1” (registro normal):
#error(ecm:error cuadratico medio)
conf_matrix = confusion_matrix(Y_test, Y_pred)
print(conf_matrix)
# Libreria para accuracy y reporte de clasificación
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
print(classification_report(Y_test, Y_pred))
print('Accuracy score:',accuracy_score(Y_test, Y_pred))
3717/3717 ━━━━━━━━━━━━━━━━━━━━ 6s 2ms/step (118929, 7)
[[117512 0]
[ 1417 0]]
precision recall f1-score support
0 0.99 1.00 0.99 117512
1 0.00 0.00 0.00 1417
accuracy 0.99 118929
macro avg 0.49 0.50 0.50 118929
weighted avg 0.98 0.99 0.98 118929
Accuracy score: 0.9880853282210394
/usr/local/lib/python3.12/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. /usr/local/lib/python3.12/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior. /usr/local/lib/python3.12/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
Matriz de confusión:
| Predicción: | Normal | Fraude | |
|---|---|---|---|
| Real: | ----- | ----- | |
| Normal | 117512 | 0 | |
| Fraude | 1417 | 0 |
FP:Falso positivo:normal clasificado fraudulento FN:Falso negativo:fraudulento clasificado normal
TN:Verdaderos negativos:normales clasifica normal
TP:Verdaderos positivos:fraudulentos clasificado fraudulento
Matriz de confusion:
| Predicción: | Normal | Fraude | |
|---|---|---|---|
| Real: | ----- | ----- | |
| Normal | TN | FP | |
| Fraude | FN | TP |
print('Accuracy score:',accuracy_score(Y_test, Y_pred))
Accuracy score: 0.9880853282210394
Accuracy score alto=98% ¿Cómo cambiaría esto? ¿Que significa esa valor ?¿Esta favoreciendo a los registros fraudulentos?
La matriz de confunsión arroja unos valores cero por eso al calcular la medida de precision F-score da indeterminado al dividir por el número cero. ¿Cómo arreglaría esto?
De 118929 datos ,117512 eran normales y fueron clasificados como normales. 1417 eran fraudulentos y se clasificaron como normales.¿Cómo arreglaría esto?
Realice lo siguiente:¶
¿Como mejoraría el modelo anterior? ¿Ese modelo esta funcionando? Los datos estan desbalanceados Numero normal : 587443 Numero de fraudes: 7200¿Cómo lo arreglaria? Los valores que arroja la matriz de confunción ¿estan bien? a ¿que corresponden? varie el valor del umbral para obtener un recall alto,varie el valor del umbral para obtener un precision alto,interprete los resultados .Cambie los valores del encoder y decoder para construir el autoencoder y las funciones de activación. En el ejemplo de arriba esta:AUTOENCODER: 7-6-4-6-7, las funciones de activación son tangente hiperbolica(tanh),y Relu en el siguiente orden:tanh-relu-tanh-relu. Observe los resultados
Ejemplo 7-5-4-5-7
Modifique el tipo de optimizador diferente a optimizer='adam'
Modifique los valores de learning rate, ejemplo lr=0.001
Modifique epochs,batch_size,ejemplo epochs=10, batch_size=120
Agregue una capa oculta al modelo con 256 neuronas.
Modifique Dropout, ejemplo Dropout=0.2. Esto permite excluir aleatoriamente el 20% de las neuronas en el entrenamiento para evitar el sobreajuste
Modifique loss dentro de model.compile(), diferente a loss='categorical_crossentropy'
Imprima las capas de neuronas del modelo print(model.summary())
Guarde el modelo model.save('modeloinicial.h5')# pip install h5py
Guarde los pesos del modelo mediante: model.save_weights('model_pesos.h5')
Analice los resultados
Respuestas del Grupo¶
1. ¿Cuáles son las aplicaciones de un autoencoder?¶
Un autoencoder es una arquitectura de red neuronal no supervisada que aprende a comprimir (codificar) datos en una representación latente y luego reconstruirlos (decodificar). Entre sus principales aplicaciones se encuentran:
- Reducción de dimensionalidad: similar al análisis de componentes principales (PCA), pero capaz de capturar relaciones no lineales entre variables, lo que permite representar datos complejos en espacios de menor dimensión.
- Eliminación de ruido (denoising): los autoencoders aprenden a filtrar el ruido de los datos de entrada, reconstruyendo versiones limpias de señales, imágenes o registros corruptos.
- Detección de anomalías: al entrenarse exclusivamente con datos normales, el autoencoder genera un alto error de reconstrucción ante entradas atípicas, lo que permite identificar fraudes, fallas industriales o intrusiones en redes.
- Generación de datos sintéticos: los autoencoders variacionales (VAE) permiten muestrear nuevos datos del espacio latente, útil para aumentar datasets o crear contenido artificial.
- Compresión de datos: la representación latente puede servir como una forma eficiente de almacenar información con menor costo computacional.
- Imputación de datos faltantes: el modelo puede aprender a predecir valores ausentes a partir de los patrones aprendidos en el espacio latente.
- Segmentación y agrupamiento semántico: las representaciones latentes permiten agrupar datos similares sin necesidad de etiquetas previas.
2. ¿Cómo se realiza la detección de fraudes mediante autoencoder en Python?¶
La detección de fraudes bancarios con autoencoders en Python sigue un flujo bien definido:
- Preparación de datos: se carga el dataset de transacciones, se seleccionan las características relevantes (monto, frecuencia, hora, categoría, etc.) y se aplica escalado (por ejemplo, con
StandardScalerde sklearn) para normalizar las variables. - División del dataset: se separan los datos en conjunto de entrenamiento y prueba. Idealmente, el entrenamiento se realiza solo con transacciones normales para que el modelo aprenda exclusivamente el comportamiento legítimo.
- Construcción del autoencoder: se define la arquitectura usando Keras/TensorFlow, estableciendo capas de codificación (encoder) que comprimen la entrada a un espacio latente de menor dimensión, y capas de decodificación (decoder) simétricas que reconstruyen la entrada original.
- Entrenamiento: se entrena el modelo minimizando el error cuadrático medio (MSE) entre la entrada y la salida reconstruida, usando un optimizador como RMSprop o Adam.
- Cálculo del error de reconstrucción: una vez entrenado, se pasan las transacciones de prueba por el autoencoder y se calcula el MSE para cada registro.
- Definición del umbral: se establece un umbral de anomalía (por ejemplo, usando un percentil del error de reconstrucción). Las transacciones cuyo error supere este umbral se clasifican como sospechosas.
- Evaluación: se analiza la matriz de confusión, la precisión (precision), la sensibilidad (recall) y el F1-score para evaluar el desempeño del modelo en la detección de fraudes.
Modificaciones realizadas en este notebook:¶
| Parámetro | Valor original | Valor modificado |
|---|---|---|
| Semilla (n) | No especificada | 5 |
| Optimizador | SGD | RMSprop |
| Learning rate | 0.01 | 0.001 |
| Épocas | 100 | 150 |
| Batch size | 32 | 64 |
| Arquitectura | 7-6-4-6-7 | 7-256-6-4-6-256-7 |
| Dropout | No aplicaba | 0.2 (20%) |
| Funciones de activación | tanh-relu-tanh-relu | relu-tanh-relu-tanh-relu-relu |
Estas modificaciones buscan mejorar la capacidad del modelo para capturar patrones complejos gracias a la capa adicional de 256 neuronas, prevenir el sobreajuste mediante Dropout, y optimizar la convergencia con RMSprop y un learning rate más adecuado.