Comparando Discursos Políticos con Python y PNL

Este código compara dos corpus de texto pertenecientes a dos políticos, identifica las palabras más significativas de cada corpus mediante el vectorizador TF-IDF y calcula una métrica de similitud entre los corpus preprocesados. Finalmente, muestra las palabras significativas y la métrica de similitud en la salida.

De esta forma, se pueden ver las diferencias de enfoque que cada político pone en la comunicación con su electorado, así como los distintos aspectos a los que presta atención en sus campañas o mensajes.

Donald Trump — Mauricio Macri

El código proporcionado realiza las siguientes tareas:

  • Lee dos archivos de texto que contienen el corpus de los políticos.
  • Cada parte del código se explica de la siguiente manera:

    Importación de bibliotecas:

    Se importan las bibliotecas necesarias para procesar texto, calcular el vectorizador TF-IDF y la métrica de similitud.

    import spacy
    import numpy as np
    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.metrics.pairwise import cosine_similarity

    read_file función:

    Esta función toma una ruta de archivo como entrada y devuelve su contenido como una cadena.

    def read_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
    return file.read()

    preprocess función:

    Esta función toma un texto como entrada y realiza las siguientes tareas de preprocesamiento:

  • Carga el es_core_news_sm SpaCy modelo de lenguaje para procesar texto en español.
  • def preprocess(text):
    nlp = spacy.load("es_core_news_sm")
    doc = nlp(text)
    tokens = [token.lemma_ for token in doc if not token.is_stop and not token.is_punct]
    return " ".join(tokens)

    get_significant_words función:

    Esta función toma dos corpus y hace lo siguiente:

  • Crea un vectorizador TF-IDF.
  • def get_significant_words(corpus1, corpus2):
    vectorizer = TfidfVectorizer()
    corpus = [corpus1, corpus2]
    X = vectorizer.fit_transform(corpus)
    feature_names = vectorizer.get_feature_names_out()

    top_n = 10
    significant_words = []
    for i in range(len(corpus)):
    row = np.squeeze(X[i].toarray())
    top_indices = row.argsort()[-top_n:]
    words = [feature_names[idx] for idx in top_indices]
    significant_words.append(words)

    return significant_words

    get_similarity_metric función:

    Esta función toma dos corpus y calcula la métrica de similitud (similitud de coseno) entre ellos. Devuelve la métrica de similitud como un valor entre 0 y 1.

    def get_similarity_metric(corpus1, corpus2):
    vectorizer = TfidfVectorizer()
    X = vectorizer.fit_transform([corpus1, corpus2])
    similarity_matrix = cosine_similarity(X)
    similarity_score = similarity_matrix[0, 1]
    return similarity_score

    Ejecutando el código:

  • Se definen las rutas de los archivos que contienen los corpus de los políticos, y los archivos se leen usando el read_file función.
  • file_path1 = "politician1.txt"
    file_path2 = "politician2.txt"

    corpus_politician1 = read_file(file_path1)
    corpus_politician2 = read_file(file_path2)

    Los corpus son preprocesados ​​usando el preprocess función para eliminar palabras vacías, signos de puntuación y aplicar lematización.

    corpus1_preprocessed = preprocess(corpus_politician1)
    corpus2_preprocessed = preprocess(corpus_politician2)

    Las palabras significativas de cada corpus se obtienen mediante el get_significant_words función.

    significant_words_list = get_significant_words(corpus1_preprocessed, corpus2_preprocessed)

    La métrica de similitud (similitud de coseno) entre los corpus preprocesados ​​se calcula utilizando el get_similarity_metric función.

    similarity_score = get_similarity_metric(corpus1_preprocessed, corpus2_preprocessed)

    Las palabras significativas y la métrica de similitud se imprimen en la salida.

    print(f"Significant words for Politician 1 ({file_path1}):")
    for word in significant_words_list[0]:
    print(f"- {word}")

    print(f"nSignificant words for Politician 2 ({file_path2}):")
    for word in significant_words_list[1]:
    print(f"- {word}")

    print(f"nSimilarity metric between the two corpora: {similarity_score:.4f}")

    Este código compara dos corpus de texto pertenecientes a dos políticos, identifica las palabras más significativas de cada corpus mediante el vectorizador TF-IDF y calcula una métrica de similitud entre los corpus preprocesados. Finalmente, muestra las palabras significativas y la métrica de similitud en la salida.

    Versión completa:

    import spacy
    import numpy as np
    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.metrics.pairwise import cosine_similarity

    def read_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
    return file.read()

    def preprocess(text):
    nlp = spacy.load("es_core_news_sm")
    doc = nlp(text)
    tokens = [token.lemma_ for token in doc if not token.is_stop and not token.is_punct]
    return " ".join(tokens)

    def get_significant_words(corpus1, corpus2):
    vectorizer = TfidfVectorizer()
    corpus = [corpus1, corpus2]
    X = vectorizer.fit_transform(corpus)
    feature_names = vectorizer.get_feature_names_out()

    top_n = 10
    significant_words = []
    for i in range(len(corpus)):
    row = np.squeeze(X[i].toarray())
    top_indices = row.argsort()[-top_n:]
    words = [feature_names[idx] for idx in top_indices]
    significant_words.append(words)

    return significant_words

    def get_similarity_metric(corpus1, corpus2):
    vectorizer = TfidfVectorizer()
    X = vectorizer.fit_transform([corpus1, corpus2])
    similarity_matrix = cosine_similarity(X)
    similarity_score = similarity_matrix[0, 1]
    return similarity_score

    file_path1 = "politician1.txt"
    file_path2 = "politician2.txt"

    corpus_politician1 = read_file(file_path1)
    corpus_politician2 = read_file(file_path2)

    corpus1_preprocessed = preprocess(corpus_politician1)
    corpus2_preprocessed = preprocess(corpus_politician2)

    significant_words_list = get_significant_words(corpus1_preprocessed, corpus2_preprocessed)
    similarity_score = get_similarity_metric(corpus1_preprocessed, corpus2_preprocessed)

    print(f"Significant words for Politician 1 ({file_path1}):")
    for word in significant_words_list[0]:
    print(f"- {word}")

    El Log Odds Ratio con Informative Dirichlet Prior (LODP) es un método poderoso y sólido para comparar el uso de palabras en dos corpus, desarrollado por Monroe et al. en su artículo de 2009 «Fightin’ Words: selección y evaluación de características léxicas para identificar el contenido del conflicto político». El método es particularmente útil para identificar palabras características que distinguen el idioma utilizado en dos textos o conjuntos de textos diferentes.

    En pocas palabras, LODP calcula el logaritmo de la razón de probabilidades de las frecuencias de los términos entre dos corpus al tiempo que incorpora una distribución previa de frecuencias de palabras para tener en cuenta los posibles sesgos y suavizar las estimaciones. Esta información previa generalmente se genera a partir de un conjunto de datos más grande y representativo, lo cual es útil cuando los corpus que se comparan son pequeños o contienen datos escasos.

    LODP se basa en el concepto de un marco bayesiano que utiliza un Dirichlet previo, que es una generalización multivariante de la distribución Beta. Aborda el problema del sobreajuste en el método tradicional de razón de probabilidades logarítmicas mediante la incorporación de conocimientos previos de un conjunto de datos más grande. Esto garantiza que se regularicen las palabras raras o las palabras con proporciones extremas de probabilidades logarítmicas, lo que proporciona una estimación más estable de la importancia de las palabras.

    Los pasos clave en el método LODP son los siguientes:

  • Preprocesar los textos tokenizando, minúsculas y eliminando palabras vacías y signos de puntuación.
  • El método LODP ofrece varias ventajas sobre los métodos tradicionales basados ​​en la frecuencia, como el TF-IDF, al incorporar información previa y al proporcionar una medida de importancia (puntuaciones z) para cada palabra. Esto permite una comparación más confiable de la importancia y el uso de las palabras en dos corpus, lo que la convierte en una herramienta valiosa para el análisis comparativo de textos en el campo del procesamiento del lenguaje natural.

    Sobre la base proporcionada en la explicación anterior, el método LODP también brilla en su capacidad para manejar corpus desequilibrados, donde un corpus puede ser significativamente más grande que el otro. Este desequilibrio a menudo conduce a resultados poco fiables en otras técnicas, pero LODP puede mantener su solidez gracias a la incorporación del informativo Dirichlet previo.

    Una de las fortalezas clave de LODP es su adaptabilidad a varias aplicaciones en el procesamiento del lenguaje natural, como:

  • Análisis comparativo de discursos políticos o manifiestos de partidos.
  • El método LODP también se puede extender para manejar más de dos corpus, haciendo comparaciones por pares y agregando los resultados. Además, LODP se puede utilizar junto con otras técnicas de PNL, como el modelado de temas o el análisis de sentimientos, para proporcionar una comprensión más completa de las diferencias y similitudes entre los corpus.

    El Log Odds Ratio con Informative Dirichlet Prior es un método altamente eficaz y versátil para comparar el uso de palabras en diferentes textos o conjuntos de textos. Su solidez a las variaciones en el tamaño del corpus, la incorporación de información previa y la medida de importancia (puntajes z) lo convierten en una herramienta invaluable para investigadores y profesionales en el campo del procesamiento del lenguaje natural. La capacidad del método LODP para identificar palabras y patrones distintivos contribuye a una comprensión más profunda del lenguaje y la comunicación, lo que permite análisis más informados de una amplia gama de datos basados ​​en texto.

    import numpy as np
    import spacy
    from collections import Counter
    from scipy.sparse import csr_matrix
    from scipy.special import psi
    import matplotlib.pyplot as plt

    def read_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
    return file.read()

    def preprocess(text):
    nlp = spacy.load("es_core_news_sm")
    doc = nlp(text)
    tokens = [token.lemma_ for token in doc if not token.is_stop and not token.is_punct]
    return tokens

    def log_odds_ratio_informative_dirichlet_prior(corpus1, corpus2, prior_corpus, alpha=0.01):
    term_count_corpus1 = Counter(corpus1)
    term_count_corpus2 = Counter(corpus2)
    term_count_prior = Counter(prior_corpus)

    vocab = set(term_count_corpus1) | set(term_count_corpus2) | set(term_count_prior)
    n_terms = len(vocab)

    term_indices = {term: i for i, term in enumerate(vocab)}

    counts1 = np.zeros(n_terms)
    counts2 = np.zeros(n_terms)
    prior_counts = np.zeros(n_terms)

    for term, count in term_count_corpus1.items():
    counts1[term_indices[term]] = count

    for term, count in term_count_corpus2.items():
    counts2[term_indices[term]] = count

    for term, count in term_count_prior.items():
    prior_counts[term_indices[term]] = count

    n1 = counts1.sum()
    n2 = counts2.sum()
    nprior = prior_counts.sum()

    counts1 += alpha * prior_counts
    counts2 += alpha * prior_counts

    log_odds = np.log(counts1) - np.log(counts1.sum()) - np.log(counts2) + np.log(counts2.sum())
    variance = 1 / counts1 + 1 / counts2

    z_scores = log_odds / np.sqrt(variance)

    return {term: z_scores[i] for term, i in term_indices.items()}

    def plot_top_words(z_scores, n=10):
    sorted_terms = sorted(z_scores, key=z_scores.get)
    top_positive_terms = sorted_terms[-n:]
    top_negative_terms = sorted_terms[:n]

    top_positive_scores = [z_scores[term] for term in top_positive_terms]
    top_negative_scores = [z_scores[term] for term in top_negative_terms]

    fig, ax = plt.subplots()

    y_pos = np.arange(n)

    ax.barh(y_pos, top_positive_scores, align='center', color='blue', label='Corpus 1')
    ax.barh(-y_pos - 1, top_negative_scores, align='center', color='red', label='Corpus 2')

    ax.set_yticks(np.hstack((y_pos, -y_pos - 1)))
    ax.set_yticklabels(top_positive_terms + top_negative_terms)
    ax.invert_yaxis()

    ax.set_xlabel('Z-Scores')
    ax.set_title('Top Words by Log Odds Ratio with Informative Dirichlet Prior')
    ax.legend()

    plt.show()

    file_path1 = "politician1.txt"
    file_path2 = "politician2.txt"

    corpus_politician1 = read_file(file_path1)
    corpus_politician2 = read_file(file_path2)

    corpus1_preprocessed = preprocess(corpus_politician1)
    corpus2_preprocessed = preprocess(corpus_politician2)

    # Combine both corpora to create a prior corpus
    prior_corpus = corpus1_preprocessed + corpus2_preprocessed

    z_scores = log_odds_ratio_informative_dirichlet_prior(corpus1_preprocessed, corpus2_preprocessed, prior_corpus)
    plot_top_words(z_scores)

    # Combine both corpora to create a prior corpus
    prior_corpus = corpus1_preprocessed + corpus2_preprocessed

    z_scores = log_odds_ratio_informative_dirichlet_prior(corpus1_preprocessed, corpus2_preprocessed, prior_corpus)
    plot_top_words(z_scores)

    (corpus de demostración que muestra un ejemplo de la salida)

    Si te resultó útil, sígueme para ver las próximas publicaciones.

    ¡Gracias!

    Deja un comentario

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Scroll al inicio