FinancIA¶

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.

In [ ]:
# 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
In [2]:
# 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

In [3]:
# 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.

In [4]:
# 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)
In [5]:
# 
df_train.head()
Out[5]:
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

|

Imagen 1: Primeras filas del dastaset
|

Limpiamos el texto.¶

Veamos las primeras cinco filas de los datos, podemos ver lo siguientes valores.

  • id: Identificador único de la noticia
  • text: Texto o titulo de la noticia
  • target:
  • tag : Esta etiqueta se creo para separar la noticia de testeo y entrenamiento
  • len: Tamaño del texto
  • Consumer_sentiment: Este es el sentimiento, que el titular de la noticia genera para el consumidor. Puede dividirse en Negativo, Neutro o Positivo
  • Companies_sentimient: Este es setimiento, que el titular de la noticia genera en la compañia. Puede dividirse en Negativo, Neutro o positivo
  • target_sentimient: sentimiento general asociado con la noticia

Variable objectivo.¶

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.

In [6]:
pd.get_dummies(df_train[["target_sentiment", "companies_sentiment", "consumers_sentiment"]], columns=["target_sentiment", "companies_sentiment", "consumers_sentiment"]).iloc[0].astype(int)
Out[6]:
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

|

Imagen 2: Vector de caracteristica.
|

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.

Análisis exploratorio¶

Varaiable target_sentiment¶

In [43]:
df_train.target_sentiment.value_counts().plot(kind="bar")
Out[43]:
<Axes: xlabel='target_sentiment'>

|

Imagen 3: Frecuencia de las etiquetas para target_sentimet
|

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

In [44]:
df_train.boxplot(column="len", by="target_sentiment")
Out[44]:
<Axes: title={'center': 'len'}, xlabel='target_sentiment'>

|

Imagen 4: Boxplot del tamaño del texto por etiqueta target_sentimet
|

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.

In [45]:
df_train.groupby("target_sentiment").len.describe()
Out[45]:
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

|

Imagen 3: Estadisticas descriptivas target_sentimet
|

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.

variable companies_sentiment¶

In [46]:
df_train.companies_sentiment.value_counts().plot(kind="bar")
Out[46]:
<Axes: xlabel='companies_sentiment'>

|

Imagen 4: Frecuencia de las etiquetas para companies_sentiment
|

In [47]:
df_train.groupby("companies_sentiment").len.describe()
Out[47]:
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

|

Imagen 5: Estadisticas descriptivas companies_sentiment
|

In [48]:
df_train.boxplot(column="len", by="companies_sentiment")
Out[48]:
<Axes: title={'center': 'len'}, xlabel='companies_sentiment'>

|

Imagen 6: Boxplot del tamaño del texto por etiqueta companies_sentiment
|

consumers_sentiment¶

In [49]:
df_train.consumers_sentiment.value_counts().plot(kind="bar")
Out[49]:
<Axes: xlabel='consumers_sentiment'>

|

Imagen 7: Frecuencia de las etiquetas para 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

In [50]:
df_train.boxplot(column="len", by="consumers_sentiment")
Out[50]:
<Axes: title={'center': 'len'}, xlabel='consumers_sentiment'>

|

Imagen 8: Boxplot del tamaño del texto por etiqueta consumers_sentiment
|

Conclusiones¶

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.

World Cloud¶

In [51]:
plots_world_cloud(df_train.text, "Word Cloud")

|

Imagen 9: World Cloud de la etiqueta Target Sentiment
|

Target Sentiment¶

In [52]:
plots_world_cloud(df_train[df_train.target_sentiment == "positive"].text, "Word Cloud - target(Positive)")

|

Imagen 10: World Cloud Target Sentiment Positive
|

In [20]:
plots_world_cloud(df_train[df_train.target_sentiment == "neutral"].text, "Word Cloud - target(Neutral)")

|

Imagen 11: World Cloud Target Sentiment Neutra
|

Companies Sentiment¶

In [21]:
plots_world_cloud(df_train[df_train.companies_sentiment == "positive"].text, "Word Cloud - companie(positive)")

|

Imagen 12: World Cloud Target Sentiment Positive
|

In [22]:
plots_world_cloud(df_train[df_train.companies_sentiment == "negative"].text, "Word Cloud - companie(negative)")

|

Imagen 13: World Cloud Target Sentiment Negative
|

Consumer sentiment¶

In [24]:
plots_world_cloud(df_train[df_train.consumers_sentiment == "positive"].text, "Word Cloud - consumers(positive)")

|

Imagen 14: World Cloud Target Sentiment Positive
|

In [25]:
plots_world_cloud(df_train[df_train.consumers_sentiment == "negative"].text, "Word Cloud - consumers(negative)")

|

Imagen 15: World Cloud Target Sentiment Nevative
|

In [26]:
plots_world_cloud(df_train[df_train.consumers_sentiment == "neutral"].text, "Word Cloud - consumers(neutral)")

|

Imagen 16: World Cloud Target Sentiment Neutral
|

Conclusiones¶

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.