Este código compara dos corpus de texto pertenecientes a dos políticos, identifica las palabras más significativas en cada corpus utilizando 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 manera se pueden ver las diferencias de foco que pone cada uno en la comunicación a sus electorados y sobre qué, en forma diferenciada, ponen atención en sus campañas o mensajes.
El código proporcionado realiza las siguientes tareas:
A continuación, se explica cada parte del código:
Importación de bibliotecas:
Se importan las bibliotecas necesarias para procesar el 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
Función read_file
:
Esta función recibe la ruta de un archivo de texto y devuelve su contenido como una cadena de texto.
def read_file(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
return file.read()
Función preprocess
:
Esta función recibe un texto y realiza las siguientes tareas de preprocesamiento:
es_core_news_sm
de spaCy 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)
Función get_significant_words
:
Esta función recibe dos corpus y realiza lo siguiente:
top_n
palabras con los mayores pesos TF-IDF para cada corpus.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
Función get_similarity_metric
:
Esta función recibe dos corpus y calcula la métrica de similitud (cosine similarity) 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
Ejecución del código:
read_file
.file_path1 = "politico1.txt"
file_path2 = "politico2.txt"corpus_politico1 = read_file(file_path1)
corpus_politico2 = read_file(file_path2)
Se preprocesan los corpus utilizando la función preprocess
para eliminar palabras vacías, signos de puntuación y aplicar la lematización.
corpus1_preprocessed = preprocess(corpus_politico1)
corpus2_preprocessed = preprocess(corpus_politico2)
Se obtienen las palabras significativas de cada corpus utilizando la función get_significant_words
.
significant_words_list = get_significant_words(corpus1_preprocessed, corpus2_preprocessed)
Se calcula la métrica de similitud (cosine similarity) entre los corpus preprocesados utilizando la función get_similarity_metric
.
similarity_score = get_similarity_metric(corpus1_preprocessed, corpus2_preprocessed)
Se imprimen las palabras significativas y la métrica de similitud en la salida.
print(f"Palabras significativas del político 1 ({file_path1}):")
for word in significant_words_list[0]:
print(f"- {word}")print(f"nPalabras significativas del político 2 ({file_path2}):")
for word in significant_words_list[1]:
print(f"- {word}")
print(f"nMétrica de similitud entre los dos corpus: {similarity_score:.4f}")
Código completo:
# Importa las bibliotecas necesarias
import spacy
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity# Función para leer archivos de texto
def read_file(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
return file.read()
# Función para preprocesar el texto: lematización y eliminación de palabras vacías y signos de puntuación
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)
# Función para obtener las palabras significativas de dos corpus utilizando el 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
# Función para calcular la métrica de similitud (cosine similarity) entre dos corpus
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
# Rutas de los archivos de texto que contienen los corpus de los políticos
file_path1 = "politico1.txt"
file_path2 = "politico2.txt"
# Lee los corpus de los archivos
corpus_politico1 = read_file(file_path1)
corpus_politico2 = read_file(file_path2)
# Preprocesa los corpus
corpus1_preprocessed = preprocess(corpus_politico1)
corpus2_preprocessed = preprocess(corpus_politico2)
# Obtiene las palabras significativas de cada corpus
significant_words_list = get_significant_words(corpus1_preprocessed, corpus2_preprocessed)
# Calcula la métrica de similitud entre los corpus
similarity_score = get_similarity_metric(corpus1_preprocessed, corpus2_preprocessed)
# Imprime las palabras significativas y la métrica de similitud
print(f"Palabras significativas del político 1 ({file_path1}):")
for word in significant_words_list[0]:
print(f"- {word}")
print(f"nPalabras significativas del político 2 ({file_path2}):")
for word in significant_words_list[1]:
print(f"- {word}")
print(f"nMétrica de similitud entre los dos corpus: {similarity_score:.4f}")
En caso de querer ver la representación en un diagrama de Venn:
#pip install matplotlib-vennimport spacy
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import matplotlib.pyplot as plt
from matplotlib_venn import venn2
# ... (Las funciones y el código anterior se mantienen igual)
# Visualización de palabras significativas con un diagrama de Venn
politico1_words = set(significant_words_list[0])
politico2_words = set(significant_words_list[1])
plt.figure()
venn2([politico1_words, politico2_words], set_labels=('Político 1', 'Político 2'))
plt.title("Palabras significativas de los políticos")
plt.show()
La razón de probabilidades logarítmicas con prior informativo de Dirichlet (LODP, por sus siglas en inglés) es un método poderoso y robusto para comparar el uso de palabras en dos corpus, desarrollado por Monroe et al. en su artículo de 2009 “Fightin’ Words: Lexical Feature Selection and Evaluation for Identifying the Content of Political Conflict”. El método es particularmente útil para identificar palabras características que distinguen el lenguaje utilizado en dos textos o conjuntos de textos diferentes.
En resumen, el LODP calcula la razón de probabilidades logarítmicas de las frecuencias de términos entre dos corpus, incorporando una distribución previa de las frecuencias de palabras para tener en cuenta posibles sesgos y suavizar las estimaciones. Esta distribució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 prior de Dirichlet, 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 al incorporar conocimientos previos de un conjunto de datos más grande. Esto garantiza que las palabras raras o las palabras con razones de probabilidades logarítmicas extremas se regularicen, proporcionando una estimación más estable de la importancia de las palabras.
Los pasos clave en el método LODP son los siguientes:
El método LODP ofrece varias ventajas sobre los métodos tradicionales basados en frecuencias, como el TF-IDF, al incorporar información previa y al proporcionar una medida de significancia (z-scores) para cada palabra. Esto permite una comparación más confiable de la importancia y el uso de palabras en dos corpus, convirtiéndolo en una herramienta valiosa para el análisis comparativo de textos en el campo del procesamiento del lenguaje natural.
Construyendo sobre la base proporcionada en la explicación anterior, el método LODP también destaca 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 confiables en otras técnicas, pero el LODP puede mantener su solidez gracias a la incorporación del prior informativo de Dirichlet.
Una de las principales fortalezas de LODP es su adaptabilidad a diversas aplicaciones en el procesamiento del lenguaje natural, como:
El método LODP también se puede extender para manejar más de dos corpus, realizando comparaciones por pares y agregando los resultados. Además, LODP se puede utilizar junto con otras técnicas de NLP, 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.
La razón de probabilidades logarítmicas con prior informativo de Dirichlet es un método altamente efectivo y versátil para comparar el uso de palabras en diferentes textos o conjuntos de textos. Su solidez frente a las variaciones en el tamaño del corpus, la incorporación de información previa y la medida de significancia (z-scores) 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 pltdef 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 = "politico1.txt"
file_path2 = "politico2.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)
Si te ha sido de utilidad, por favor sígueme para poder ver próximas publicaciones. Gracias!
[post_relacionado id=»1524″]