Spaces:
Sleeping
Sleeping
File size: 10,413 Bytes
7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e 7bf61c5 612da4e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
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.")
|