Ir al contenido principal

Ciencia de datos en marketing: predicción del churn de clientes

Aprende a usar modelos de machine learning en Python para predecir el churn de clientes y convertir los datos de marketing en insights accionables.
Actualizado 31 ago 2026  · 10 min leer

Explorar con IA

ChatGPTClaudePerplexity

 

Introducción 

En los últimos 10-15 años, con el avance de las tecnologías digitales, las estrategias de marketing han cambiado considerablemente. Las grandes marcas y también los mercados más pequeños han recopilado una enorme cantidad de datos sobre transacciones, compras, preferencias, poder adquisitivo, actividad de compra, demografía, reseñas, etc. Todos estos datos ayudan a los equipos de marketing a entender el comportamiento del cliente en cada etapa: desde la intención de compra hasta la compra real y la fidelización. Aquí es donde entra en juego el potencial de la ciencia de datos.

La ciencia de datos convierte los big data de marketing en decisiones prácticas, incluso cuando a primera vista no son tan intuitivas, por ejemplo, ciertos patrones de comportamiento del consumidor y co-ocurrencias que no son evidentes. Como resultado, los equipos de marketing obtienen una visión más nítida de su audiencia objetivo, atraen nuevos clientes y retienen a los existentes, optimizan sus estrategias, aumentan la visibilidad de la empresa, crean campañas publicitarias más efectivas, incorporan nuevos canales y, en definitiva, maximizan notablemente los ingresos.

Uno de los casos de uso más habituales de la ciencia de datos en marketing es la predicción del churn o tasa de abandono de clientes. Vamos a analizarlo en detalle.

Caso de uso de ciencia de datos en marketing: predicción del churn de clientes

El churn de clientes es la tendencia de los usuarios a cancelar la suscripción a un servicio que venían utilizando y, por tanto, dejar de ser clientes. La tasa de churn es el porcentaje de clientes que abandonan dentro de un intervalo de tiempo determinado. Es el indicador opuesto a la tasa de crecimiento de clientes, que mide las altas.

La tasa de churn es un indicador clave de la satisfacción del cliente y de la salud general del negocio. Además del churn natural, que siempre existe en cualquier negocio, o el estacional, típico de algunos servicios, hay otros factores que pueden indicar que algo no va bien y debe corregirse. Algunos de ellos son:

  • ausencia o baja calidad del soporte al cliente,
  • experiencias negativas de los usuarios,
  • cambio a un competidor con mejores condiciones o precios,
  • cambios en las prioridades del cliente,
  • clientes de larga duración que ya no se sienten satisfechos,
  • el servicio no cumple las expectativas,
  • problemas financieros,
  • bloqueos por protección antifraude en los pagos de los clientes.

Una tasa de churn alta supone un problema serio para cualquier empresa por varias razones:

  • Se correlaciona con la pérdida de ingresos.
  • Cuesta mucho más captar nuevos clientes que retener a los que ya tienes. Esto es especialmente cierto en mercados muy competitivos.
  • Si el abandono se debe a un mal servicio, la reputación de la empresa puede verse muy dañada por reseñas negativas en redes sociales o sitios de opinión por parte de exclientes insatisfechos.

La retención es un pilar estratégico para todos los servicios basados en suscripción. Para predecir el churn y tomar medidas preventivas, hay que recopilar y analizar información sobre el comportamiento del cliente (intervalos de compra, tiempo total como cliente, cancelaciones, llamadas y mensajes de seguimiento, actividad online) y detectar qué atributos y combinaciones son característicos de quienes están en riesgo de irse. Saber con antelación qué clientes pueden abandonar pronto, sobre todo si aportan altos ingresos o llevan mucho tiempo, permite centrar los esfuerzos en ellos y diseñar una estrategia eficaz para intentar que se queden. La táctica puede incluir una llamada con una oferta especial: un regalo, un descuento, mejorar la suscripción al mismo precio u otra experiencia personalizada.

Técnicamente, la predicción de churn es un problema típico de clasificación en machine learning, donde etiquetamos a los clientes como "sí" o "no" en cuanto a su riesgo de abandono. Vamos a explorar este caso de uso en Python con datos reales.

Modelaremos el churn en un contexto de telecomunicaciones, donde los clientes pueden tener varios servicios con una operadora bajo un mismo contrato marco. El conjunto de datos incluye características de la actividad de los clientes (limpiadas) y una etiqueta que indica si hubo churn o no.

Veamos los datos y la distribución del churn:

import pandas as pd

telcom = pd.read_csv('telco.csv')
print(f'Number of customers: {telcom.shape[0]:,}\n'
      f'Churn values: {set(telcom['Churn'])}\n\n'
      f'Churn distribution, %:\n{round(telcom.groupby(['Churn']).size()/telcom.shape[0]*100).convert_dtypes()}')
Number of customers: 7,032
Churn values: {0, 1}

Churn distribution, %:
Churn
0    73
1    27
dtype: float64

Un 27% de clientes abandonaron, una cifra bastante alta. A diferencia del caso de uso anterior, este dataset no parece tener un problema grave de desbalanceo de clases.

Ahora vamos a preprocesar los datos para aplicar técnicas de machine learning y predecir el churn. Esto incluye dividir los datos en conjuntos de entrenamiento y prueba y extraer variables de entrada y objetivo:

from sklearn.model_selection import train_test_split

target = ['Churn']
custid = ['customerID']

cols = [col for col in telcom.columns if col not in custid + target]

X = telcom[cols]
y = telcom[target]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

El primer algoritmo que usaremos para predecir las etiquetas de churn y estimar la precisión es un modelo sencillo de regresión logística:

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

lr = LogisticRegression()
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print(f'Test accuracy: {round(accuracy_score(y_test, predictions), 4)}')
Test accuracy: 0.8009

A continuación, añadimos una funcionalidad más a nuestra regresión logística: ejecutarla con regularización L1 para hacer selección de variables a la vez que entrenamos el modelo. Diferentes valores del parámetro C (inverso de la fuerza de regularización) afectan a la precisión del modelo. De momento, fijamos C en 0.025:

lr = LogisticRegression(penalty='l1', C=0.025, solver='liblinear')
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)
print(f'Test accuracy: {round(accuracy_score(y_test, predictions), 4)}')
Test accuracy: 0.7969

Ahora vamos a ajustar el parámetro C de la regularización L1 para encontrar el valor óptimo que reduzca la complejidad del modelo manteniendo un buen rendimiento. Para ello, iteraremos sobre distintos valores de C, construiremos instancias de regresión logística y calcularemos las métricas.

La lista C se ha creado previamente con posibles valores del parámetro. El array l1_metrics tiene 3 columnas: la primera con los valores de C, y las dos siguientes como marcadores de posición para el número de coeficientes no nulos y la precisión del modelo. Probemos este enfoque:

 C  Non-Zero Coeffs  Accuracy
0  1.0000             23.0  0.801479
1  0.5000             22.0  0.799204
2  0.2500             21.0  0.802048
3  0.1000             20.0  0.802617
4  0.0500             18.0  0.802048
5  0.0250             13.0  0.796928
6  0.0100              5.0  0.790102
7  0.0050              3.0  0.783276
8  0.0025              2.0  0.745734

Vemos que los valores más bajos de C reducen el número de coeficientes distintos de cero (es decir, las variables del modelo), con lo que disminuye la complejidad, pero también cae la precisión. Parece que C = 0.05 es el valor óptimo: reduce las variables a 18 y ofrece una precisión ligeramente superior a la del modelo sin regularizar.

Probemos ahora otro algoritmo: un árbol de decisión:

from sklearn.tree import DecisionTreeClassifier

clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)
print(f'Test accuracy: {round(accuracy_score(y_test, predictions), 4)}')
Test accuracy: 0.7275

Para elegir un modelo más preciso evitando el sobreajuste, podemos ajustar la profundidad del árbol (parámetro max_depth) e identificar su valor óptimo. Técnicamente, el proceso es muy similar al ajuste de C en la regresión logística: iteramos sobre varios valores de max_depth, entrenamos un árbol para cada uno y calculamos el rendimiento.

La lista depth_list se ha creado previamente con los posibles valores del parámetro. El array depth_tuning tiene 2 columnas: la primera con las profundidades candidatas y la segunda como marcador para la precisión. Apliquemos este enfoque para encontrar la profundidad óptima:

depth_list = list(range(2, 15))
depth_tuning = np.zeros((len(depth_list), 2))
depth_tuning[:, 0] = depth_list

for index in range(len(depth_list)):
    clf = DecisionTreeClassifier(max_depth=depth_list[index])
    clf.fit(X_train, y_train)
    predictions = clf.predict(X_test)
    depth_tuning[index, 1] = accuracy_score(y_test, predictions)
   
col_names = ['Max_Depth', 'Accuracy']
print(pd.DataFrame(depth_tuning, columns=col_names))
 Max_Depth  Accuracy
0         2.0  0.756542
1         3.0  0.783276
2         4.0  0.782708
3         5.0  0.791809
4         6.0  0.778157
5         7.0  0.780432
6         8.0  0.757110
7         9.0  0.762230
8        10.0  0.763936
9        11.0  0.752560
10       12.0  0.745165
11       13.0  0.732651
12       14.0  0.727531

La precisión aumenta a medida que crece la profundidad hasta cierto punto y luego empieza a caer. Con max_depth = 5, el árbol alcanza la mayor precisión, por lo que podemos considerar este valor como óptimo.

Tras identificar los mejores parámetros para la regresión logística y el árbol de decisión, reconstruyamos los modelos y detectemos e interpretemos los factores que hacen que el churn suba o baje.

Para la regresión logística, vamos a extraer y analizar los exponentes de los coeficientes resultantes:

# Reconstrucción del mejor modelo
lr = LogisticRegression(penalty='l1', C=0.05, solver='liblinear')
lr.fit(X_train, y_train)
predictions = lr.predict(X_test)

# Combinamos nombres de variables y coeficientes en un único dataframe
feature_names = pd.DataFrame(X_train.columns, columns=['Feature'])
log_coef = pd.DataFrame(np.transpose(lr.coef_), columns=['Coefficient'])
coefficients = pd.concat([feature_names, log_coef], axis=1)

# Calculamos los exponentes de los coeficientes
coefficients['Exp_Coefficient'] = np.exp(coefficients['Coefficient'])

# Eliminamos los coeficientes iguales a cero
coefficients = coefficients[coefficients['Coefficient']!=0]
print(coefficients.sort_values(by=['Exp_Coefficient']))
                          Feature  Coefficient  Exp_Coefficient
21                          tenure    -0.907750         0.403431
4                 PhoneService_Yes    -0.820517         0.440204
17               Contract_Two year    -0.595271         0.551413
8                  TechSupport_Yes    -0.418254         0.658195
16               Contract_One year    -0.414158         0.660896
5               OnlineSecurity_Yes    -0.412228         0.662173
6                 OnlineBackup_Yes    -0.143100         0.866667
3                   Dependents_Yes    -0.039299         0.961463
7             DeviceProtection_Yes    -0.017465         0.982687
11            PaperlessBilling_Yes     0.071389         1.073999
1                SeniorCitizen_Yes     0.097904         1.102857
19  PaymentMethod_Electronic check     0.188533         1.207477
22                  MonthlyCharges     0.901454         2.463182

Vemos que la variable con mayor efecto en las probabilidades de abandono es tenure (antigüedad). En general, los exponentes de coeficientes menores que 1 reducen las probabilidades y los mayores que 1 las incrementan.

Para el árbol de decisión, vamos a extraer y representar las reglas if-else:

# Reconstrucción del mejor modelo
clf = DecisionTreeClassifier(max_depth=5)
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)

from sklearn import tree
import graphviz

# Exportamos un objeto graphviz del árbol entrenado
exported = tree.export_graphviz(decision_tree=clf,
                                out_file=None,
                                feature_names=cols,
                                precision=1,
                                class_names=['Not churn', 'Churn'],
                                filled=True)
graph = graphviz.Source(exported)
display(graph)

Árbol de decisión de machine learning

Obtenemos una visualización clara del árbol de decisión que puede interpretarse como un conjunto de reglas if-else desde la raíz. Nuevamente vemos que la antigüedad del cliente (tenure) es la variable más importante que explica el churn. El árbol puede profundizarse con más capas para obtener más información sobre otras variables.

Como siguientes pasos, podemos seguir ajustando parámetros, probar distintos enfoques de partición train/test, aplicar y comparar otros algoritmos de machine learning y analizar diversos tipos de métricas para evaluar el rendimiento.

Si te apetece profundizar en la predicción de churn y otras aplicaciones de ciencia de datos en marketing, este curso de Machine Learning for Marketing in Python es un buen punto de partida.

Temas
Ciencia de datos
Aprendizaje automático
Relacionado
MachineLearningLifecycle

blog

Explicación del ciclo de vida del machine learning

Conoce los pasos de un proyecto estándar de machine learning mientras exploramos los entresijos del ciclo de vida del machine learning utilizando CRISP-ML(Q).
Abid Ali Awan's photo

Abid Ali Awan

10 min

Tutorial

Predicciones bursátiles con LSTM en Python

Descubra las redes de memoria larga a corto plazo (LSTM) en Python y cómo puede utilizarlas para hacer predicciones bursátiles.
Thushan Ganegedara's photo

Thushan Ganegedara

15 min

Tutorial

Aprendizaje automático de datos categóricos con el tutorial de Python

Aprenda los trucos más comunes para manejar datos categóricos y preprocesarlos para construir modelos de aprendizaje automático.
Moez Ali's photo

Moez Ali

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

Clustering k-means

Tutorial

Introducción a k-Means Clustering con scikit-learn en Python

En este tutorial, aprenda a aplicar k-Means Clustering con scikit-learn en Python

Kevin Babitz

8 min

Tutorial

Tutorial sobre el uso de XGBoost en Python

Descubre la potencia de XGBoost, uno de los marcos de machine learning más populares entre los científicos de datos, con este tutorial paso a paso en Python.
Ver MásVer Más