alertDetection / secciones /procesar_textos.py
Nacho86's picture
Update secciones/procesar_textos.py
612da4e verified
raw
history blame
10.4 kB
import streamlit as st
import pandas as pd
import re
import nltk
import numpy as np
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import SnowballStemmer
from transformers import pipeline
from secciones.model_utils import cargar_modelo_y_vectorizador
# Descargar recursos de NLTK
nltk.download('punkt')
nltk.download('stopwords')
# Funci贸n de limpieza y preprocesamiento de texto
def clean_text_stemming(text):
"""
Realiza la limpieza y preprocesamiento de un texto. Convierte el texto a min煤sculas,
elimina caracteres no alfab茅ticos, tokeniza, remueve stopwords y aplica stemming.
:param text: El texto a limpiar y preprocesar.
:return: Texto procesado y limpio.
"""
text = text.lower()
text = re.sub(r'[^a-z帽谩茅铆贸煤]', ' ', text)
words = word_tokenize(text)
stop_words = set(stopwords.words('spanish'))
stemmer = SnowballStemmer('spanish')
stemmed_text = ' '.join([stemmer.stem(word) for word in words if word not in stop_words])
return stemmed_text
# Cargar modelos de Hugging Face para an谩lisis de sentimientos y emociones
clasificador_sentimiento = pipeline('sentiment-analysis',
model='citizenlab/twitter-xlm-roberta-base-sentiment-finetunned')
clasificador_emociones = pipeline("text-classification",
model="maxpe/bertin-roberta-base-spanish_sem_eval_2018_task_1")
# Funciones para analizar sentimiento y emociones
def analizar_sentimiento(texto):
"""
Analiza el sentimiento de un texto dado utilizando un modelo preentrenado de Hugging Face.
:param texto: El texto a analizar.
:return: La etiqueta del sentimiento detectado (ej. "Positive", "Negative", "Neutral").
Retorna None si ocurre un error.
"""
try:
results = clasificador_sentimiento(texto, truncation=True, max_length=512)
top_result = max(results, key=lambda x: x['score'])
return top_result['label']
except Exception as e:
print(f"Error al procesar el texto: {e}")
return None
def analizar_emociones(texto):
"""
Analiza las emociones presentes en un texto utilizando un modelo preentrenado de Hugging Face.
:param texto: El texto a analizar.
:return: La etiqueta de la emoci贸n detectada (ej. "alegr铆a", "tristeza").
Retorna None si ocurre un error.
"""
try:
results = clasificador_emociones(texto, truncation=True, max_length=512)
top_result = max(results, key=lambda x: x['score'])
return top_result['label']
except Exception as e:
print(f"Error al procesar el texto: {e}")
return None
# Normalizaci贸n de la longitud del texto
def normalizar_longitud(texto):
"""
Normaliza la longitud de un texto dividiendo la longitud del texto por una longitud m谩xima observada.
:param texto: El texto cuya longitud se va a normalizar.
:return: Longitud normalizada del texto.
"""
longitud_maxima_observada = 53352
return len(texto) / longitud_maxima_observada
# Obtener caracter铆sticas de polaridad y emociones
def obtener_caracteristicas_polaridad(texto):
"""
Obtiene caracter铆sticas de polaridad (positiva, negativa, neutral) de un texto analizando su sentimiento.
:param texto: El texto a analizar.
:return: Un diccionario con las caracter铆sticas de polaridad en formato binario.
"""
polaridad = analizar_sentimiento(texto)
return {
"polarity_Negative": 1 if polaridad == "Negative" else 0,
"polarity_Neutral": 1 if polaridad == "Neutral" else 0,
"polarity_Positive": 1 if polaridad == "Positive" else 0
}
def obtener_caracteristicas_emociones(texto):
"""
Obtiene caracter铆sticas de emociones (ira, anticipaci贸n, miedo, alegr铆a, tristeza) de un texto.
:param texto: El texto a analizar.
:return: Un diccionario con las caracter铆sticas de emociones en formato binario.
"""
emocion = analizar_emociones(texto)
categorias = ["anger", "anticipation", "fear", "joy", "sadness"]
return {f"emotions_{cat}": 1 if emocion == cat else 0 for cat in categorias}
# Funci贸n para realizar predicciones con informaci贸n adicional
def predecir_suicidio_con_info(texto, modelo, tfidf_vectorizador):
"""
Realiza la predicci贸n de comportamiento suicida en un texto dado, utilizando un modelo
de machine learning y un vectorizador TF-IDF. Incluye caracter铆sticas adicionales
como longitud del texto, polaridad y emociones.
:param texto: Texto a analizar.
:param modelo: Modelo de machine learning para realizar la predicci贸n.
:param tfidf_vectorizador: Vectorizador TF-IDF para procesar el texto.
:return: Un diccionario con los resultados de la clasificaci贸n y an谩lisis.
"""
texto_limpio = clean_text_stemming(texto)
# Obtener caracter铆sticas
longitud_normalizada = normalizar_longitud(texto)
caracteristicas_polaridad = obtener_caracteristicas_polaridad(texto)
caracteristicas_emociones = obtener_caracteristicas_emociones(texto)
polaridad = analizar_sentimiento(texto)
emocion = analizar_emociones(texto)
# Vectorizar texto y combinar caracter铆sticas
texto_tfidf = tfidf_vectorizador.transform([texto_limpio]).toarray()
caracteristicas_adicionales = np.array(
[longitud_normalizada] + list(caracteristicas_polaridad.values()) + list(caracteristicas_emociones.values()))
features = np.hstack((texto_tfidf, caracteristicas_adicionales.reshape(1, -1)))
# Aseg煤rate de que el DataFrame tenga los mismos nombres de columnas que se usaron durante el entrenamiento
column_names = tfidf_vectorizador.get_feature_names_out().tolist() + ['text_length', 'polarity_Negative',
'polarity_Neutral', 'polarity_Positive',
'emotions_anger', 'emotions_anticipation',
'emotions_fear', 'emotions_joy',
'emotions_sadness']
features_df = pd.DataFrame(features, columns=column_names)
# Realizar la predicci贸n
pred = modelo.predict(features_df)
pred_proba = modelo.predict_proba(features_df)[0]
# Confianza y nivel de riesgo
confianza = abs(pred_proba[1] - pred_proba[0])
nivel_riesgo = 'ALTO' if pred_proba[1] > 0.75 else 'MODERADO' if pred_proba[1] > 0.5 else 'BAJO'
accion = 'Se recomienda buscar ayuda profesional inmediatamente.' if nivel_riesgo == 'ALTO' \
else 'Se sugiere monitorear los sentimientos y considerar hablar con un profesional.' \
if nivel_riesgo == 'MODERADO' \
else 'Probablemente no hay riesgo inmediato, pero mant茅n una actitud positiva.'
# Traducciones de las etiquetas de polaridad y emociones al espa帽ol
traducciones_polaridad = {
"Negative": "Negativa",
"Neutral": "Neutral",
"Positive": "Positiva"
}
traducciones_emociones = {
"anger": "ira",
"anticipation": "Anticipaci贸n",
"fear": "Miedo",
"joy": "Alegr铆a",
"sadness": "Tristeza"
}
# Traducir polaridad y emociones
polaridad_traducida = traducciones_polaridad.get(polaridad, polaridad)
emocion_traducida = traducciones_emociones.get(emocion, emocion)
return {
"clasificacion": 'Alerta de riego suicida' if pred[0] == 1 else 'Ausencia de riego de suicidio',
"probabilidad_suicidio": pred_proba[1],
"confianza": confianza,
"nivel_riesgo": nivel_riesgo,
"sugerencia_accion": accion,
"polaridad": polaridad_traducida,
"emocion": emocion_traducida
}
def procesar_textos():
"""
Funci贸n principal para procesar textos en la aplicaci贸n Streamlit. Permite al usuario
ingresar o subir un texto, y luego utiliza el modelo y el vectorizador para analizarlo.
"""
st.title("Analizar Texto")
modelo, tfidf_vectorizador = cargar_modelo_y_vectorizador()
# Opci贸n para ingresar texto manualmente
text_input = st.text_area("Ingrese su texto aqu铆:")
# Opci贸n para subir un archivo
uploaded_file = st.file_uploader("O suba un archivo de texto:", type=["txt"])
# Bot贸n para procesar el texto
if st.button("Procesar Texto"):
text_to_process = ""
if uploaded_file is not None:
# Leer el archivo subido y almacenar su contenido
text_to_process = uploaded_file.read().decode("utf-8")
elif text_input:
# Utilizar el texto ingresado manualmente
text_to_process = text_input
if text_to_process:
# Llamar a la funci贸n de predicci贸n con el texto procesado
resultado = predecir_suicidio_con_info(text_to_process, modelo, tfidf_vectorizador)
# Estilos personalizados seg煤n el nivel de riesgo
if resultado['nivel_riesgo'] == 'ALTO':
color = "red"
elif resultado['nivel_riesgo'] == 'MODERADO':
color = "orange"
else:
color = "green"
# Mostrar los resultados con estilos
st.markdown(f"<h2 style='color: {color};'>Resultado del An谩lisis:</h2>", unsafe_allow_html=True)
st.markdown(f"<b>Grado de Riesgo:</b> <span style='color: {color};'>{resultado['nivel_riesgo']}</span>",
unsafe_allow_html=True)
st.markdown(f"<b>Polaridad:</b> {resultado['polaridad']}", unsafe_allow_html=True)
st.markdown(f"<b>Emoci贸n dominante:</b> {resultado['emocion']}", unsafe_allow_html=True)
st.markdown(f"<b>Clasificaci贸n de riesgo:</b> {resultado['clasificacion']}", unsafe_allow_html=True)
st.markdown(f"<b>Indice de riesgo de suicidio:</b> {resultado['probabilidad_suicidio']:.4f}",
unsafe_allow_html=True)
st.markdown(f"<b>Fiabilidad del an谩lisis:</b> {resultado['confianza']:.4f}", unsafe_allow_html=True)
st.markdown(f"<b>Recomendaciones de seguimiento:</b> {resultado['sugerencia_accion']}",
unsafe_allow_html=True)
else:
st.warning("Por favor, ingrese texto o suba un archivo.")