En este notebook, presentaremos un prototipo de detector de sentimientos de noticias, una aplicación emocionante de la inteligencia artificial en el campo financiero. Nuestro objetivo principal es realizar un análisis exploratorio de texto utilizando técnicas de procesamiento del lenguaje natural (NLP, por sus siglas en inglés) para clasificar las noticias según su tono emocional.
En el prototipo del detector de sentimientos de noticias, se utilizan varias bibliotecas para diferentes tareas. Aquí hay un resumen de las bibliotecas utilizadas:
os: Esta biblioteca proporciona funciones para interactuar con el sistema operativo, como la manipulación de rutas de archivos y directorios.
pathlib: Esta biblioteca proporciona una interfaz orientada a objetos para trabajar con rutas de archivos y directorios de manera más intuitiva.
matplotlib: Esta biblioteca se utiliza para visualizar datos y generar gráficos, como histogramas y gráficos de barras. En el prototipo, se utiliza para visualizar los resultados del análisis exploratorio de texto.
pandas: Esta biblioteca se utiliza para el análisis y manipulación de datos en forma de tablas. En el prototipo, se utiliza para cargar y manipular los datos de las noticias.
spacy: Esta biblioteca es una poderosa herramienta de procesamiento de lenguaje natural (NLP). En el prototipo, se utiliza para acceder a las palabras vacías (stop words) en español, que son palabras comunes pero no aportan información significativa para el análisis de sentimientos.
wordcloud: Esta biblioteca se utiliza para generar nubes de palabras, que son visualizaciones que muestran las palabras más frecuentes en un texto. En el prototipo, se utiliza para visualizar las palabras más frecuentes en las noticias recopiladas.
# Importamos las librerías necesarias
import os
from pathlib import Path
from matplotlib import pyplot as plt
import pandas as pd
from spacy.lang.es.stop_words import STOP_WORDS as es_stopwords
from wordcloud import WordCloud
# Dataset y configuraciones del los proyectos
# Configigurations
path = Path().cwd().parent/"Dataset"
Estas son funciones que usan para hacer análsis de texto, lo importante es entender que lo usamos para plotear nube de palabras
# Funciones usadas para plotear los datos
def plots_world_cloud(df, title, figsize=(10, 10)):
"""This function is used to plot the world cloud"""
text = " ".join(df)
plt.figure(figsize=figsize)
wordcloud = WordCloud(background_color="white", stopwords=es_stopwords).generate(text)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.title(title)
plt.show()
El tamaño del texto es crucial al seleccionar modelos adecuados. La longitud promedio y la variabilidad determinan si se requieren enfoques basados en transformadores y el impacto en los recursos computacionales. Esto optimiza el rendimiento del análisis de sentimientos y el procesamiento de texto.
# Importamos los datasets y los usamos para explorar los datos
df_train = pd.read_csv(path/"train.csv")
df_test = pd.read_csv(path/"test.csv")
df_train["len"] = df_train.text.apply(len)
df_train["tag"] = "train"
df_test["len"] = df_test.text.apply(len)
df_test["tag"] = "test"
df_train = pd.concat([df_train, df_test], axis=0)
#
df_train.head()
id | text | target | target_sentiment | companies_sentiment | consumers_sentiment | len | tag | |
---|---|---|---|---|---|---|---|---|
0 | 69737 | Renfe afronta mañana un nuevo día de paros par... | Renfe | negative | negative | negative | 71 | train |
1 | 71795 | Presupuesto populista con cimientos frágiles | Presupuesto populista | negative | negative | negative | 44 | train |
2 | 77984 | Biden no cree que la OPEP+ vaya a ayudar con l... | OPEP+ | negative | negative | negative | 69 | train |
3 | 82648 | La deuda de las familias cae en 25.000 millone... | deuda de las familias | positive | positive | positive | 91 | train |
4 | 97337 | Bestinver: no hay "momento más inoportuno" par... | Bestinver | negative | negative | negative | 57 | train |
|
Veamos las primeras cinco filas de los datos, podemos ver lo siguientes valores.
El objetivo del modelo es predecir el sentimiento para las variables "target", "companies" y "consumer", donde cada una de ellas se divide en tres categorías: positiva, negativa y neutral. Esto implica que el vector objetivo será de nueve componentes, ya que cada variable tiene tres categorías posibles. El problema de clasificación se convierte en un problema de múltiples etiquetas, lo que significa que una fila en el conjunto de datos puede pertenecer a varias categorías a la vez. El objetivo del modelo será predecir las etiquetas correspondientes a cada una de las nueve combinaciones posibles de sentimientos para las tres variables.
pd.get_dummies(df_train[["target_sentiment", "companies_sentiment", "consumers_sentiment"]], columns=["target_sentiment", "companies_sentiment", "consumers_sentiment"]).iloc[0].astype(int)
target_sentiment_negative 1 target_sentiment_neutral 0 target_sentiment_positive 0 target_sentiment_postive 0 companies_sentiment_negative 1 companies_sentiment_neutral 0 companies_sentiment_positive 0 companies_sentiment_positive 0 consumers_sentiment_negative 1 consumers_sentiment_neutral 0 consumers_sentiment_neutral? 0 consumers_sentiment_positive 0 consumers_sentiment_positive 0 Name: 0, dtype: int32
|
Entiendo. Según la imagen del vector de características, se espera que la red neuronal produzca valores cercanos a 1 para indicar la asociación del texto con una determinada característica o categoría de sentimiento. Esto implica que cuanto más cercano esté el valor a 1, mayor será la probabilidad de que el texto esté relacionado con esa característica específica.
En un problema de clasificación de múltiples etiquetas, donde se busca predecir varias categorías simultáneamente, los valores del vector de características pueden interpretarse como la probabilidad de pertenencia a cada una de las categorías. Por lo tanto, un valor cercano a 1 indica una alta probabilidad de que el texto pertenezca a una categoría en particular.
Es importante tener en cuenta que la interpretación exacta de los valores depende del enfoque y la configuración específica del modelo utilizado. Algunos modelos pueden generar probabilidades directamente a través de una función de activación de salida, como la función sigmoide, mientras que otros pueden producir valores continuos que luego se convierten en probabilidades utilizando un umbral determinado.
En resumen, se espera que la red neuronal produzca valores cercanos a 1 en el vector de características para indicar una mayor asociación con una característica específica o categoría de sentimiento en un problema de clasificación de múltiples etiquetas. Estos valores pueden interpretarse como probabilidades de pertenencia a cada categoría.
df_train.target_sentiment.value_counts().plot(kind="bar")
<Axes: xlabel='target_sentiment'>
|
La imagen 3 anterior muestra que el dataset está desbalanceado, especialmente en la variable "target_sentiment" donde se observa una mayor cantidad de registros con etiquetas positivas en comparación con las etiquetas negativas y neutrales. El desbalance de clases puede tener un impacto en el rendimiento y la capacidad de generalización de los modelos de aprendizaje automático
df_train.boxplot(column="len", by="target_sentiment")
<Axes: title={'center': 'len'}, xlabel='target_sentiment'>
|
Basados en la imagen 4, el tamaño de las oraciones también es un aspecto importante a considerar en el análisis. Según los datos proporcionados, se observa que el tamaño máximo de las oraciones es de 160 caracteres. Esto puede ser útil para determinar la longitud máxima de secuencia que se puede utilizar al entrenar los modelos.
Además, se menciona que los encabezados con sentimiento neutral tienden a ser más cortos en comparación con los encabezados con sentimientos positivos. Esta información es relevante, ya que la longitud de las oraciones puede influir en la forma en que se expresan los sentimientos y en cómo se relacionan con las características específicas del texto.
Si todos los datos en la variable "target_sentiment" son positivos y no se observan datos atípicos, esto puede indicar un desbalance en la distribución de las clases en esta categoría. Es importante tener en cuenta este desbalance al desarrollar y evaluar los modelos de análisis de sentimientos, ya que puede afectar la capacidad de generalización y la precisión de las predicciones.
En resumen, al analizar el tamaño de las oraciones en el conjunto de datos y considerar las características relacionadas con la variable "target_sentiment", es posible tener una comprensión más completa de los datos y tomar decisiones informadas en el desarrollo de modelos de análisis de sentimientos.
df_train.groupby("target_sentiment").len.describe()
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
target_sentiment | ||||||||
negative | 356.0 | 72.870787 | 17.779404 | 22.0 | 63.75 | 74.0 | 82.0 | 159.0 |
neutral | 69.0 | 61.797101 | 21.466513 | 17.0 | 46.00 | 60.0 | 77.0 | 109.0 |
positive | 480.0 | 71.352083 | 17.458779 | 22.0 | 60.00 | 70.0 | 82.0 | 155.0 |
|
En la imagen 5, se puede observar que el tamaño de los textos varía desde un mínimo de 69 caracteres hasta un máximo de 160 caracteres. Esta información es relevante para determinar el tamaño adecuado de secuencia que se utilizará en el modelo.
Dado que existe una variabilidad en la longitud de los textos, es posible aplicar técnicas de padding para estandarizar el tamaño y asegurarse de que todos los textos tengan la misma longitud. El padding implica agregar tokens especiales (como ceros) al inicio o final de los textos más cortos para igualar el tamaño de los textos más largos. Esto es especialmente útil cuando se trabaja con modelos basados en transformadores, ya que estos modelos generalmente requieren que todas las secuencias de entrada tengan la misma longitud.
Aplicar padding garantiza que el modelo pueda procesar todos los textos de manera uniforme y mantener la coherencia en la estructura de entrada. Además, esto permite aprovechar al máximo el poder de los modelos de lenguaje, que están diseñados para capturar patrones y relaciones en datos secuenciales.
df_train.companies_sentiment.value_counts().plot(kind="bar")
<Axes: xlabel='companies_sentiment'>
|
df_train.groupby("companies_sentiment").len.describe()
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
companies_sentiment | ||||||||
negative | 301.0 | 72.269103 | 18.411699 | 22.0 | 61.0 | 71.0 | 83.00 | 159.0 |
neutral | 430.0 | 70.395349 | 18.389644 | 17.0 | 59.0 | 71.5 | 81.00 | 137.0 |
positive | 174.0 | 71.448276 | 16.873044 | 22.0 | 60.0 | 72.0 | 82.75 | 120.0 |
|
df_train.boxplot(column="len", by="companies_sentiment")
<Axes: title={'center': 'len'}, xlabel='companies_sentiment'>
|
df_train.consumers_sentiment.value_counts().plot(kind="bar")
<Axes: xlabel='consumers_sentiment'>
|
En este caso tambien se observa como la clase neutral es la que tiene más registros. La positiva y negativa, son muy parecidas
df_train.boxplot(column="len", by="consumers_sentiment")
<Axes: title={'center': 'len'}, xlabel='consumers_sentiment'>
|
En conclusión, al analizar los datos, se pueden destacar los siguientes puntos:
Desbalance de datos: Existe un desbalance en las etiquetas de la variable "target_sentiment", con una mayor cantidad de registros etiquetados como positivos en comparación con las etiquetas negativas y neutrales. Este desbalance puede requerir técnicas de manejo de clases desbalanceadas durante el entrenamiento del modelo.
Tamaño de los datos: El tamaño de los textos en el conjunto de datos es relativamente pequeño, con una longitud máxima de 160 caracteres. Esto es útil para determinar la longitud máxima de secuencia que se puede utilizar en los modelos de análisis de sentimientos.
Análisis de palabras: Se puede realizar un análisis exploratorio para identificar las palabras más comúnmente utilizadas en el texto y examinar las características asociadas con cada etiqueta de sentimiento.
Padding: Dado que existe variabilidad en la longitud de los textos, se puede aplicar padding para estandarizar el tamaño y asegurarse de que todos los textos tengan la misma longitud. Esto facilita el procesamiento y análisis uniforme de los textos en el modelo de análisis de sentimientos.
plots_world_cloud(df_train.text, "Word Cloud")
|
plots_world_cloud(df_train[df_train.target_sentiment == "positive"].text, "Word Cloud - target(Positive)")
|
plots_world_cloud(df_train[df_train.target_sentiment == "neutral"].text, "Word Cloud - target(Neutral)")
|
plots_world_cloud(df_train[df_train.companies_sentiment == "positive"].text, "Word Cloud - companie(positive)")
|
plots_world_cloud(df_train[df_train.companies_sentiment == "negative"].text, "Word Cloud - companie(negative)")
|
plots_world_cloud(df_train[df_train.consumers_sentiment == "positive"].text, "Word Cloud - consumers(positive)")
|
plots_world_cloud(df_train[df_train.consumers_sentiment == "negative"].text, "Word Cloud - consumers(negative)")
|
plots_world_cloud(df_train[df_train.consumers_sentiment == "neutral"].text, "Word Cloud - consumers(neutral)")
|
Además de los puntos mencionados anteriormente, hay algunas observaciones adicionales sobre el contexto de las noticias:
Contexto europeo: Las noticias se sitúan en un contexto europeo, como se puede inferir de la mención de la zona euro y diferentes empresas europeas. Esto puede ser relevante para comprender el enfoque y las perspectivas económicas presentes en las noticias.
Enfoque económico: Todas las noticias parecen estar centradas en aspectos económicos. Esto sugiere que el contenido se relaciona principalmente con eventos, tendencias y noticias relacionadas con la economía y los mercados financieros.
Sesgo temporal: Se intuye que algunas noticias pueden ser de la época de Trump, lo que indica un sesgo temporal en los datos. Es importante tener en cuenta este sesgo temporal al interpretar y generalizar los resultados del análisis de sentimientos, ya que las condiciones económicas y los eventos pueden haber cambiado desde entonces.
Palabras asociadas a sentimientos negativos y positivos: Algunas palabras en un contexto negativo, como "huelga", "coronavirus" y "crisis", pueden indicar aspectos desfavorables o eventos problemáticos mencionados en las noticias. Por otro lado, palabras relacionadas con sentimientos positivos, como "empleo", "subida" y "recuperación", sugieren una visión más optimista y perspectivas positivas en el contenido.