
- Caso de uso de ciencia de datos en ventas: análisis de sentimiento de clientes
- Preparación del dataset
- Aplicación del método BOW
- Uso de un modelo supervisado de machine learning para predecir el sentimiento
- Conclusión
Los casos de uso de ciencia de datos pueden aplicarse prácticamente a cualquier sector donde se acumule (o pueda acumularse) gran cantidad de datos. Las tiendas y sitios de e‑commerce son donde ocurre la experiencia real de las personas atraídas por las campañas de marketing y donde se recoge la valiosa información de compra de una marca o empresa concreta. Aquí es donde la gente decide si realmente quiere comprar un producto, si le interesa algo que no tenía previsto, cuánto está dispuesta a pagar, si volvería a la tienda y qué opinión dejaría sobre su experiencia.
De hecho, las reseñas de clientes son una fuente sólida de datos para analizar y entender qué se puede cambiar o reforzar en todo el proceso de ventas. Analizar los datos así puede ayudar a reducir costes, mejorar la eficiencia operativa, elevar la experiencia del cliente, destapar nuevas oportunidades, hacer crecer el negocio y, en última instancia, aumentar los ingresos. Veamos más de cerca cómo analizar y modelar esta información tan valiosa con algoritmos de ciencia de datos para obtener insights ocultos y captar el mensaje global de cada cliente.
Caso de uso de ciencia de datos en ventas: análisis de sentimiento de clientes
El análisis de sentimiento de clientes es un proceso automatizado para identificar las emociones de los usuarios cuando utilizan los servicios o productos de una empresa. Suele tratarse de datos textuales no estructurados recogidos de encuestas online, redes sociales, tickets de soporte, formularios de feedback, reseñas de productos, foros, llamadas, correos electrónicos y chatbots. En machine learning, el análisis de sentimiento se realiza mediante procesamiento del lenguaje natural (NLP), que aplica métodos estadísticos y lingüísticos para extraer sentimientos positivos, negativos y neutros directamente del texto. En esencia, devuelve dos parámetros:
- Polaridad: indica si el sentimiento es positivo o negativo.
- Magnitud: indica la intensidad de ese sentimiento.
El análisis de sentimiento es clave para cualquier negocio moderno porque ayuda a obtener insights accionables, detectar y corregir problemas recurrentes que generan insatisfacción, reforzar las funciones del producto o servicio que despiertan emociones positivas y, en general, tomar decisiones más eficientes basadas en datos. A un nivel más granular, nos permite:
- mejorar la atención al cliente y, con ello, su experiencia,
- aumentar la fidelidad,
- reducir la tasa de abandono,
- evolucionar productos y servicios a tiempo,
- optimizar campañas de marketing,
- anticipar nuevas tendencias y mercados,
- mantener una alta reputación de marca,
- incrementar los beneficios.
Como en cualquier tarea de análisis de texto, hay escollos. Por ejemplo, el algoritmo de NLP puede no captar el sarcasmo en algunas reseñas y clasificarlas mal. También puede fallar al interpretar abreviaturas muy específicas o jerga poco común.
Preparación del dataset
Veamos cómo funciona en la práctica con un dataset de reseñas de películas de IMDB:
import pandas as pd
movies = pd.read_csv('movies.csv', index_col=0).reset_index(drop=True)
print(f'Number of reviews: {movies.shape[0]:,}\n')
print(movies.head())
Number of reviews: 7,501
review label
0 This short spoof can be found on Elite's Mille... 0
1 A singularly unfunny musical comedy that artif... 0
2 An excellent series, masterfully acted and dir... 1
3 The master of movie spectacle Cecil B. De Mill... 1
4 I was gifted with this movie as it had such a ... 0
Tenemos dos columnas: una con el texto de cada reseña y otra con la valoración global del sentimiento: positivo (1) o negativo (0).
Calculemos el porcentaje de reseñas positivas y negativas:
round(movies['label'].value_counts()*100/len(movies['label'])).convert_dtypes()
0 50
1 50
Name: label, dtype: Int64
Así, tenemos proporciones casi iguales de reseñas positivas y negativas.
Aplicación del método BOW
El siguiente paso es transformar el texto a formato numérico, ya que un modelo de machine learning solo trabaja con variables numéricas. En concreto, vamos a crear variables que cuenten cuántas veces aparece cada palabra en la reseña correspondiente. El enfoque más básico y directo es bag‑of‑words (BOW), que construye un vocabulario con todas las palabras que aparecen en el documento y cuenta la frecuencia de cada una en cada reseña. Como resultado, obtendremos nuevas variables, una por palabra, con sus frecuencias.
Apliquemos BOW a nuestro dataset:
from sklearn.feature_extraction.text import CountVectorizer
# Creating new features
vect = CountVectorizer(max_features=200)
vect.fit(movies.review)
X_review = vect.transform(movies.review)
X_df = pd.DataFrame(X_review.toarray(), columns=vect.get_feature_names())
# Combining the new features with the label
movies_bow = pd.concat([movies['label'], X_df], axis=1)
print(movies_bow.head())
label 10 about acting action actors actually after again all ... \
0 0 0 0 0 0 0 0 0 0 0 ...
1 0 1 0 1 0 1 0 0 0 3 ...
2 1 0 0 0 0 0 0 1 0 0 ...
3 1 0 0 0 1 0 0 0 0 0 ...
4 0 1 0 0 1 0 0 0 0 3 ...
will with without work world would years you young your
0 0 1 0 0 0 1 0 0 0 0
1 2 7 1 0 0 2 0 3 0 2
2 0 2 0 0 0 0 0 0 1 0
3 0 0 0 0 0 0 0 1 1 0
4 0 2 0 1 0 0 0 0 0 0
[5 rows x 201 columns]
Arriba, aplicamos el parámetro opcional max_features para considerar solo las 200 palabras más frecuentes y evitar un posible sobreajuste del modelo.
Uso de un modelo supervisado de machine learning para predecir el sentimiento
Ahora usaremos un modelo supervisado de machine learning para predecir el sentimiento. Como queremos estimar si el sentimiento de una reseña nueva es positivo o negativo basándonos en reseñas ya etiquetadas, de nuevo tenemos un problema de clasificación. Usemos otra vez una regresión logística y midamos la precisión del modelo:
Accuracy score: 0.754
Confusion matrix:
[[37.62772101 13.23856064]
[11.32829853 37.80541981]]
Vemos que el modelo etiquetó como negativas el 11% de las reseñas que eran positivas y como positivas el 13% de las que eran negativas. Para mejorar la precisión, podemos plantearnos excluir stopwords (palabras con poca información que aparecen con mucha frecuencia, como "about", "will", "you", etc.) y ampliar el tamaño del vocabulario.
Al aplicar BOW, podemos terminar con cientos o miles de variables nuevas en el dataframe. Esto puede llevar a un modelo excesivamente complejo: sobreajustado y con demasiadas variables y parámetros innecesarios. Una forma de mitigarlo es la regularización, que restringe la función del modelo. El parámetro a ajustar aquí es C, que representa la fuerza de la regularización. Probemos 2 valores: 100 y 0.1, y veamos cuál rinde mejor en los datos de test:
lr_1 = LogisticRegression(C=100)
lr_1.fit(X_train, y_train)
predictions_1 = lr_1.predict(X_test)
lr_2 = LogisticRegression(C=0.1)
lr_2.fit(X_train, y_train)
predictions_2 = lr_2.predict(X_test)
print(f'Accuracy score, lr_1 model: {round(accuracy_score(y_test, predictions_1), 3)}\n'
f'Accuracy score, lr_2 model: {round(accuracy_score(y_test, predictions_2), 3)}\n\n'
f'Confusion matrix for lr_1 model, %:\n{confusion_matrix(y_test, predictions_1)/len(y_test)*100}\n\n'
f'Confusion matrix for lr_2 model, %:\n{confusion_matrix(y_test, predictions_2)/len(y_test)*100}')
Accuracy score, lr_1 model: 0.753
Accuracy score, lr_2 model: 0.756
Confusion matrix for lr_1 model, %:
[[37.53887161 13.32741004]
[11.32829853 37.80541981]]
Confusion matrix for lr_2 model, %:
[[37.67214571 13.19413594]
[11.19502443 37.93869391]]
La diferencia en precisión con los valores elegidos de C es poco significativa. Podríamos encontrar un valor que mejore más el rendimiento probando con un rango más amplio. No obstante, aquí solo tenemos 200 variables nuevas, así que el modelo no es tan complejo y la regularización no resulta crítica en este caso.
En lugar de predecir etiquetas 0 o 1 con predict, también podemos predecir probabilidades con predict_proba. Hay que recordar que no podemos aplicar directamente accuracy o la matriz de confusión a probabilidades, ya que estas métricas funcionan con clases. Por tanto, debemos traducirlas a clases: por defecto, una probabilidad mayor o igual que 0.5 se asigna a la clase 1; en caso contrario, a la clase 0.
lr = LogisticRegression()
lr.fit(X_train, y_train)
# Predicting the probability of the 0 class
predictions_prob_0 = lr.predict_proba(X_test)[:, 0]
# Predicting the probability of the 1 class
predictions_prob_1 = lr.predict_proba(X_test)[:, 1]
print(f'First 10 predicted probabilities of class 0: {predictions_prob_0[:10].round(3)}\n'
f'First 10 predicted probabilities of class 1: {predictions_prob_1[:10].round(3)}')
First 10 predicted probabilities of class 0: [0.246 0.143 0.123 0.708 0.001 0.828 0.204 0.531 0.121 0.515]
First 10 predicted probabilities of class 1: [0.754 0.857 0.877 0.292 0.999 0.172 0.796 0.469 0.879 0.485]
Conclusión
Hay muchos otros enfoques útiles que podemos aplicar a nuestro dataset para un análisis de sentimiento más fino:
- usar n‑grams (combinaciones de palabras) en lugar de palabras sueltas para conservar el contexto,
- excluir stopwords,
- limitar el tamaño del vocabulario según frecuencias altas o bajas,
- crear variables numéricas adicionales que describan la longitud de cada reseña o el número de signos de puntuación (esto último a veces correlaciona con la magnitud del sentimiento),
- excluir números, ciertos caracteres o palabras de una longitud concreta, o considerar patrones más complejos,
- aplicar stemming y lematización, es decir, reducir las palabras a sus raíces,
- usar enfoques más sofisticados que BOW para crear el vocabulario, por ejemplo TfIdf (term frequency–inverse document frequency), que tiene en cuenta la frecuencia de una palabra en una reseña respecto al resto.
- utilizar librerías especializadas en análisis de sentimiento, como TextBlob, SentiWordNet o VADER (Valence Aware Dictionary and Sentiment Reasoner).
Si te interesa profundizar en estas y otras técnicas útiles para realizar análisis de sentimiento con impacto, echa un vistazo al curso Sentiment Analysis in Python.


