Ir al contenido principal

Data science en banca: detección de fraude

Descubre cómo se aplica la ciencia de datos en el sector bancario analizando uno de los casos de uso más comunes: la detección de fraude.
Actualizado 31 ago 2026  · 11 min leer

Explorar con IA

ChatGPTClaudePerplexity

Ilustración conceptual de fintech

La banca es uno de esos sectores afortunados en los que históricamente se ha recopilado gran cantidad de datos estructurados, y también uno de los primeros en adoptar tecnologías de ciencia de datos.

¿Cómo se usa la ciencia de datos en banca? Hoy en día, los datos se han convertido en el activo más valioso en este ámbito. La ciencia de datos es imprescindible para que los bancos mantengan el ritmo de sus competidores, atraigan a más clientes, fidelicen a los existentes, tomen decisiones más eficientes basadas en datos, impulsen el negocio, mejoren la eficiencia operativa, optimicen los servicios y productos actuales e introduzcan otros nuevos, refuercen la seguridad y, como resultado de todo ello, aumenten los ingresos. No es de extrañar que gran parte de la demanda de perfiles de data science provenga del sector bancario.

La ciencia de datos permite al sector bancario realizar con éxito numerosas tareas, entre ellas: 

  • análisis de riesgo de inversión
  • predicción del valor del cliente a largo plazo
  • segmentación de clientes
  • predicción de la tasa de abandono
  • marketing personalizado
  • análisis de sentimiento del cliente
  • asistentes virtuales y chatbots

A continuación, vamos a profundizar en uno de los casos de uso más habituales de la ciencia de datos en banca.

Caso de uso de data science en banca: detección de fraude 

Las actividades fraudulentas suponen un problema complejo no solo en banca, sino también en muchos otros ámbitos, como la administración pública, los seguros, el sector público, las ventas y la sanidad. Cualquier negocio que gestione un gran volumen de transacciones online asume un riesgo significativo de fraude. Los delitos financieros adoptan múltiples formas: transacciones fraudulentas con tarjeta de crédito, cheques bancarios falsificados, evasión fiscal, blanqueo de capitales, ciberataques, robo de cuentas de clientes, identidades sintéticas, solicitudes falsas y estafas.

La detección de fraude es un conjunto de medidas proactivas para identificar y prevenir actividades fraudulentas y pérdidas económicas. Sus principales técnicas analíticas pueden dividirse en dos grupos:

  • Estadísticas: cálculo de parámetros estadísticos, regresión, distribuciones de probabilidad, concordancia de datos
  • Inteligencia artificial (IA): minería de datos, aprendizaje automático, deep learning

El aprendizaje automático es un pilar esencial de la detección de fraude. Su caja de herramientas ofrece dos enfoques:

  • Métodos supervisados: k-vecinos más cercanos, regresión logística, máquinas de vectores de soporte, árbol de decisión, random forest, análisis de series temporales, redes neuronales, etc.
  • Métodos no supervisados: análisis de clústeres, análisis de vínculos, mapas autoorganizados, análisis de componentes principales, detección de anomalías, etc.

No existe un algoritmo de aprendizaje automático universal y fiable para detectar fraude. En casos reales, se prueban varias técnicas o combinaciones de ellas, se calcula la precisión predictiva del modelo y se selecciona el enfoque óptimo.

El principal reto de los sistemas de detección de fraude es adaptarse con rapidez a los patrones cambiantes y a las tácticas de los defraudadores, y destapar con agilidad esquemas nuevos y cada vez más elaborados. Los casos de fraude siempre son minoría y quedan bien ocultos entre las transacciones reales.

Preparación del dataset

Vamos a explorar una implementación de machine learning para detectar fraude con tarjetas de crédito usando el lenguaje de programación Python. Trabajaremos con el dataset creditcard_data, una muestra modificada de un dataset de Kaggle sobre Credit Card Fraud Detection. Los datos originales recogen transacciones realizadas con tarjetas de crédito de titulares europeos durante dos días de septiembre de 2013.

Importemos los datos y echemos un vistazo rápido:

import pandas as pd

creditcard_data = pd.read_csv('creditcard_data.csv', index_col=0)
print(creditcard_data.info())
print('\n')
pd.options.display.max_columns = len(creditcard_data)
print(creditcard_data.head(3))
<class 'pandas.core.frame.DataFrame'>
Int64Index: 5050 entries, 0 to 5049
Data columns (total 30 columns):
#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
0   V1      5050 non-null   float64
1   V2      5050 non-null   float64
2   V3      5050 non-null   float64
3   V4      5050 non-null   float64
4   V5      5050 non-null   float64
5   V6      5050 non-null   float64
6   V7      5050 non-null   float64
7   V8      5050 non-null   float64
8   V9      5050 non-null   float64
9   V10     5050 non-null   float64
10  V11     5050 non-null   float64
11  V12     5050 non-null   float64
12  V13     5050 non-null   float64
13  V14     5050 non-null   float64
14  V15     5050 non-null   float64
15  V16     5050 non-null   float64
16  V17     5050 non-null   float64
17  V18     5050 non-null   float64
18  V19     5050 non-null   float64
19  V20     5050 non-null   float64
20  V21     5050 non-null   float64
21  V22     5050 non-null   float64
22  V23     5050 non-null   float64
23  V24     5050 non-null   float64
24  V25     5050 non-null   float64
25  V26     5050 non-null   float64
26  V27     5050 non-null   float64
27  V28     5050 non-null   float64
28  Amount  5050 non-null   float64
29  Class   5050 non-null   int64 
dtypes: float64(29), int64(1)
memory usage: 1.2 MB


        V1        V2        V3        V4        V5        V6        V7  \
0  1.725265 -1.337256 -1.012687 -0.361656 -1.431611 -1.098681 -0.842274  
1  0.683254 -1.681875  0.533349 -0.326064 -1.455603  0.101832 -0.520590  
2  1.067973 -0.656667  1.029738  0.253899 -1.172715  0.073232 -0.745771  

        V8        V9       V10       V11       V12       V13       V14  \
0 -0.026594 -0.032409  0.215113  1.618952 -0.654046 -1.442665 -1.546538  
1  0.114036 -0.601760  0.444011  1.521570  0.499202 -0.127849 -0.237253  
2  0.249803  1.383057 -0.483771 -0.782780  0.005242 -1.273288 -0.269260  

        V15       V16       V17       V18       V19       V20       V21  \
0 -0.230008  1.785539  1.419793  0.071666  0.233031  0.275911  0.414524  
1 -0.752351  0.667190  0.724785 -1.736615  0.702088  0.638186  0.116898  
2  0.091287 -0.347973  0.495328 -0.925949  0.099138 -0.083859 -0.189315  

        V22       V23       V24       V25       V26       V27       V28  \
0  0.793434  0.028887  0.419421 -0.367529 -0.155634 -0.015768  0.010790  
1 -0.304605 -0.125547  0.244848  0.069163 -0.460712 -0.017068  0.063542  
2 -0.426743  0.079539  0.129692  0.002778  0.970498 -0.035056  0.017313  

  Amount  Class 
0  189.00      0 
1  315.17      0 
2   59.98      0 

El dataset contiene las siguientes variables:

  • Variables codificadas numéricamente de V1 a V28, que son los componentes principales obtenidos mediante una transformación PCA. Por motivos de confidencialidad, no se proporciona información sobre las características originales.
  • La variable Amount representa el importe de la transacción.
  • La variable Class indica si la transacción fue fraudulenta (1) o no (0).

Por su propia naturaleza, los casos de fraude son, por suerte, una pequeña minoría en cualquier lista de transacciones. Sin embargo, los algoritmos de aprendizaje automático suelen funcionar mejor cuando las distintas clases del dataset están más o menos equilibradas. De lo contrario, hay pocos datos de los que aprender. A este problema se le llama desequilibrio de clases.

Cálculo del fraude en el dataset

Calculemos el porcentaje de transacciones fraudulentas sobre el total de transacciones en nuestro dataset:

round(creditcard_data['Class'].value_counts()*100/len(creditcard_data)).convert_dtypes()
0    99
1     1
Name: Class, dtype: Int64

y creemos un gráfico para visualizar los puntos de datos de fraude frente a no fraude:

import matplotlib.pyplot as plt
import numpy as np

def prep_data(df):
    X = df.iloc[:, 1:28]
    X = np.array(X).astype(float)
    y = df.iloc[:, 29]
    y = np.array(y).astype(float)
    return X, y

def plot_data(X, y):
    plt.scatter(X[y==0, 0], X[y==0, 1], label='Class #0', alpha=0.5, linewidth=0.15)
    plt.scatter(X[y==1, 0], X[y==1, 1], label='Class #1', alpha=0.5, linewidth=0.15, c='r')
    plt.legend()
    return plt.show()

X, y = prep_data(creditcard_data)

plot_data(X, y)

Transacciones fraudulentas

Uso de SMOTE para reequilibrar los datos 

Podemos confirmar que la proporción de transacciones fraudulentas es muy baja y que estamos ante un caso de desequilibrio de clases. Para solucionarlo, podemos reequilibrar los datos con la técnica de sobremuestreo de la minoría sintética (SMOTE). A diferencia del sobremuestreo aleatorio, SMOTE es algo más sofisticado porque no crea copias exactas de las observaciones. En su lugar, utiliza las características de los vecinos más cercanos de los casos de fraude para generar nuevas muestras sintéticas similares a las observaciones existentes de la clase minoritaria. Apliquemos SMOTE a nuestros datos de tarjeta de crédito:

from imblearn.over_sampling import SMOTE

method = SMOTE()
X_resampled, y_resampled = method.fit_resample(X, y)
plot_data(X_resampled, y_resampled)

Gráfico de SMOTE

Como vemos, con SMOTE obtenemos de repente más observaciones de la clase minoritaria. Para apreciar aún mejor los resultados de este enfoque, vamos a compararlos con los datos originales:

def compare_plot(X, y, X_resampled, y_resampled, method):
    f, (ax1, ax2) = plt.subplots(1, 2)
    c0 = ax1.scatter(X[y==0, 0], X[y==0, 1], label='Class #0',alpha=0.5)
    c1 = ax1.scatter(X[y==1, 0], X[y==1, 1], label='Class #1',alpha=0.5, c='r')
    ax1.set_title('Original set')
    ax2.scatter(X_resampled[y_resampled==0, 0], X_resampled[y_resampled==0, 1], label='Class #0', alpha=.5)
    ax2.scatter(X_resampled[y_resampled==1, 0], X_resampled[y_resampled==1, 1], label='Class #1', alpha=.5,c='r')
    ax2.set_title(method)
    plt.figlegend((c0, c1), ('Class #0', 'Class #1'), loc='lower center', ncol=2, labelspacing=0.)
    plt.tight_layout(pad=3)
    return plt.show()

print(f'Original set:\n'
      f'{pd.value_counts(pd.Series(y))}\n\n'
      f'SMOTE:\n'
      f'{pd.value_counts(pd.Series(y_resampled))}\n')

compare_plot(X, y, X_resampled, y_resampled, method='SMOTE')
Original set:
0.0    5000
1.0      50
dtype: int64


SMOTE:
0.0    5000
1.0    5000
dtype: int64

Gráfico del método SMOTE

Así, el método SMOTE ha equilibrado por completo nuestros datos, y la clase minoritaria ahora tiene el mismo tamaño que la mayoritaria.

Volveremos en breve a la aplicación práctica de SMOTE, pero antes retomemos los datos originales e intentemos detectar los casos de fraude. Siguiendo el enfoque "clásico", tenemos que crear reglas para cazar el fraude. Estas reglas pueden referirse, por ejemplo, a ubicaciones inusuales de las transacciones o a transacciones sospechosamente frecuentes. La idea es definir valores umbral basados en estadísticas comunes, a menudo en las medias de las observaciones, y aplicar esos umbrales a nuestras variables para detectar fraude.

print(creditcard_data.groupby('Class').mean().round(3)[['V1', 'V3']])
        V1     V3
Class             
0      0.035  0.037
1     -4.985 -7.294

En nuestro caso, apliquemos estas condiciones: V1 < -3 y V3 < -5. Después, para estimar el rendimiento de este enfoque, compararemos los casos marcados como fraude con los reales:

creditcard_data['flag_as_fraud'] = np.where(np.logical_and(creditcard_data['V1']<-3, creditcard_data['V3']<-5), 1, 0)
print(pd.crosstab(creditcard_data['Class'], creditcard_data['flag_as_fraud'], rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
Flagged Fraud     0   1
Actual Fraud          
0              4984  16
1                28  22

Aplicación de la regresión logística 

Detectamos 22 de los 50 casos de fraude, pero no conseguimos identificar los otros 28, y además tuvimos 16 falsos positivos. Veamos si las técnicas de aprendizaje automático pueden mejorar esos resultados.

Ahora vamos a implementar un algoritmo sencillo de clasificación por regresión logística sobre nuestros datos de tarjeta de crédito para identificar casos fraudulentos y, después, visualizar los resultados en una matriz de confusión:

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

lr = LogisticRegression()
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print(pd.crosstab(y_test, predictions, rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
Flagged Fraud   0.0  1.0
Actual Fraud           
0.0            1504    1
1.0             1      9

Es importante señalar que aquí tenemos menos observaciones en la matriz de confusión porque solo usamos el conjunto de test para calcular los resultados del modelo, es decir, un 30% del dataset.

Detectamos un porcentaje mayor de fraudes: 90% (9 de 10), frente al 44% anterior (22 de 50). Además, ahora tenemos muchos menos falsos positivos, así que es una mejora.

Volvamos ahora al problema del desequilibrio de clases y comprobemos si podemos mejorar aún más las predicciones combinando la regresión logística con el remuestreo SMOTE. Para hacerlo de forma eficiente y en un solo paso, definiremos un pipeline y lo ejecutaremos sobre nuestros datos:

from imblearn.pipeline import Pipeline

# Defining which resampling method and which ML model to use in the pipeline
resampling = SMOTE()
lr = LogisticRegression()

pipeline = Pipeline([('SMOTE', resampling), ('Logistic Regression', lr)])
pipeline.fit(X_train, y_train)
predictions = pipeline.predict(X_test)
print(pd.crosstab(y_test, predictions, rownames=['Actual Fraud'], colnames=['Flagged Fraud']))
Flagged Fraud   0.0  1.0
Actual Fraud           
0.0            1496    9
1.0               1    9

Como vemos, en nuestro caso SMOTE no ha aportado mejoras: seguimos detectando el 90% de los fraudes y, además, tenemos un número ligeramente mayor de falsos positivos. La explicación es que el remuestreo no conduce necesariamente a mejores resultados en todos los casos. Cuando los fraudes están muy dispersos en los datos, sus vecinos más cercanos no tienen por qué ser también fraudes, así que SMOTE puede introducir sesgos.

Conclusión 

Como posibles siguientes pasos para aumentar la precisión del modelo de regresión logística, podemos ajustar algunos parámetros del algoritmo. También se puede considerar la validación cruzada K-fold en lugar de dividir el dataset en dos partes. Por último, podemos probar otros algoritmos de aprendizaje automático (por ejemplo, árbol de decisión o random forest) y ver si ofrecen mejores resultados. 

Si quieres profundizar en los aspectos teóricos y técnicos de la implementación de modelos de detección de fraude, echa un vistazo a los materiales del curso Fraud Detection in Python.

Temas
Ciencia de datos
Aprendizaje automático
Relacionado

blog

¿Qué es la ciencia de datos? Definición, ejemplos, herramientas y más

La ciencia de datos es un campo interdisciplinar que utiliza métodos, procesos, algoritmos y sistemas científicos para extraer conocimientos e ideas de datos estructurados y sin estructurar.
Matt Crabtree's photo

Matt Crabtree

15 min

blog

Cómo analizar datos para tu empresa en 5 pasos

Descubre los distintos pasos para analizar los datos y extraer valor de ellos, así como los métodos y técnicas que intervienen en el proceso.
Javier Canales Luna's photo

Javier Canales Luna

14 min

blog

¿Qué es el análisis de datos? Una guía experta con ejemplos

Explora el mundo del análisis de datos con nuestra completa guía. Conoce su importancia, proceso, tipos, técnicas, herramientas y principales carreras en 2023
Matt Crabtree's photo

Matt Crabtree

10 min

blog

Análisis deportivo: Cómo utilizan el análisis de datos los distintos deportes

Descubre cómo funciona el análisis deportivo y cómo los distintos deportes utilizan los datos para proporcionar información relevante. Además, descubre qué se necesita para convertirse en analista de datos deportivos.
Kurtis Pykes 's photo

Kurtis Pykes

13 min

blog

Clasificación en machine learning: Introducción

Aprende sobre la clasificación en machine learning viendo qué es, cómo se utiliza y algunos ejemplos de algoritmos de clasificación.
Zoumana Keita 's photo

Zoumana Keita

14 min

Tutorial

Entender el data drift y el model drift: detección de drift en Python

Evita los riesgos del model drift y descubre nuestra guía práctica para monitorizar el data drift.
Moez Ali's photo

Moez Ali

9 min

Ver MásVer Más