Spaces:
Running
Running
nacho
commited on
Commit
路
7bf61c5
1
Parent(s):
11dfe6d
vfs
Browse files- .gitattributes +2 -34
- .idea/.gitignore +8 -0
- .idea/.name +1 -0
- .idea/TFG.iml +10 -0
- .idea/alertDetection.iml +8 -0
- .idea/inspectionProfiles/profiles_settings.xml +6 -0
- .idea/misc.xml +7 -0
- .idea/modules.xml +8 -0
- .idea/vcs.xml +6 -0
- imagenes/Captura1.PNG +0 -0
- imagenes/Captura2.PNG +0 -0
- imagenes/Captura3.PNG +0 -0
- imagenes/Captura4.PNG +0 -0
- imagenes/uoc.png +0 -0
- imagenes/uoc2.png +0 -0
- main.py +90 -0
- modelo_nn_g2.pkl +3 -0
- requirements.txt +0 -0
- secciones/home_page.py +67 -0
- secciones/info_page.py +34 -0
- secciones/model_utils.py +10 -0
- secciones/procesar_textos.py +245 -0
- tfidf_vectorizador2.pkl +3 -0
.gitattributes
CHANGED
@@ -1,35 +1,3 @@
|
|
1 |
-
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
.pkl filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
*.pkl filter=lfs diff=lfs merge=lfs -text
|
3 |
+
tfidf_vectorizador2.pkl filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.idea/.gitignore
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Default ignored files
|
2 |
+
/shelf/
|
3 |
+
/workspace.xml
|
4 |
+
# Editor-based HTTP Client requests
|
5 |
+
/httpRequests/
|
6 |
+
# Datasource local storage ignored files
|
7 |
+
/dataSources/
|
8 |
+
/dataSources.local.xml
|
.idea/.name
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
TFG
|
.idea/TFG.iml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<module type="PYTHON_MODULE" version="4">
|
3 |
+
<component name="NewModuleRootManager">
|
4 |
+
<content url="file://$MODULE_DIR$">
|
5 |
+
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
6 |
+
</content>
|
7 |
+
<orderEntry type="inheritedJdk" />
|
8 |
+
<orderEntry type="sourceFolder" forTests="false" />
|
9 |
+
</component>
|
10 |
+
</module>
|
.idea/alertDetection.iml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<module type="PYTHON_MODULE" version="4">
|
3 |
+
<component name="NewModuleRootManager">
|
4 |
+
<content url="file://$MODULE_DIR$" />
|
5 |
+
<orderEntry type="inheritedJdk" />
|
6 |
+
<orderEntry type="sourceFolder" forTests="false" />
|
7 |
+
</component>
|
8 |
+
</module>
|
.idea/inspectionProfiles/profiles_settings.xml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<component name="InspectionProjectProfileManager">
|
2 |
+
<settings>
|
3 |
+
<option name="USE_PROJECT_PROFILE" value="false" />
|
4 |
+
<version value="1.0" />
|
5 |
+
</settings>
|
6 |
+
</component>
|
.idea/misc.xml
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="Black">
|
4 |
+
<option name="sdkName" value="Python 3.9 (pythonProject1) (2)" />
|
5 |
+
</component>
|
6 |
+
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (pythonProject1) (2)" project-jdk-type="Python SDK" />
|
7 |
+
</project>
|
.idea/modules.xml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="ProjectModuleManager">
|
4 |
+
<modules>
|
5 |
+
<module fileurl="file://$PROJECT_DIR$/.idea/TFG.iml" filepath="$PROJECT_DIR$/.idea/TFG.iml" />
|
6 |
+
</modules>
|
7 |
+
</component>
|
8 |
+
</project>
|
.idea/vcs.xml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="VcsDirectoryMappings">
|
4 |
+
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
5 |
+
</component>
|
6 |
+
</project>
|
imagenes/Captura1.PNG
ADDED
imagenes/Captura2.PNG
ADDED
imagenes/Captura3.PNG
ADDED
imagenes/Captura4.PNG
ADDED
imagenes/uoc.png
ADDED
imagenes/uoc2.png
ADDED
main.py
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import nltk
|
3 |
+
from secciones.procesar_textos import procesar_textos # Aseg煤rate de que esta ruta sea correcta
|
4 |
+
from secciones.home_page import home_page
|
5 |
+
from secciones.info_page import info_page
|
6 |
+
|
7 |
+
|
8 |
+
def main():
|
9 |
+
"""
|
10 |
+
Funci贸n principal que ejecuta la aplicaci贸n Streamlit.
|
11 |
+
|
12 |
+
Esta funci贸n se encarga de configurar la p谩gina, cargar el modelo y el vectorizador, y gestionar el men煤 de
|
13 |
+
navegaci贸n de la aplicaci贸n. Dependiendo de la opci贸n seleccionada en el men煤, renderiza diferentes vistas como
|
14 |
+
la p谩gina de inicio, la p谩gina de an谩lisis de texto o la p谩gina de informaci贸n.
|
15 |
+
|
16 |
+
:return: None. Ejecuta y mantiene activa la aplicaci贸n Streamlit.
|
17 |
+
"""
|
18 |
+
# Configuraci贸n de la p谩gina
|
19 |
+
logo_log_bar = r'imagenes/Captura de pantalla 2024-01-06 a las 17.13.19.png'
|
20 |
+
st.set_page_config(page_title='An谩lisis sentimientos', page_icon=logo_log_bar, layout="wide")
|
21 |
+
|
22 |
+
# Descargar recursos de NLTK
|
23 |
+
@st.cache_data
|
24 |
+
def descargar_recursos_nltk():
|
25 |
+
"""
|
26 |
+
Descarga los recursos necesarios de NLTK.
|
27 |
+
|
28 |
+
Esta funci贸n descarga los componentes 'punkt' y 'stopwords' de NLTK, que son necesarios para tokenizar y
|
29 |
+
preprocesar el texto en las funciones de an谩lisis.
|
30 |
+
|
31 |
+
:return: None.
|
32 |
+
"""
|
33 |
+
nltk.download('punkt')
|
34 |
+
nltk.download('stopwords')
|
35 |
+
|
36 |
+
descargar_recursos_nltk()
|
37 |
+
|
38 |
+
# Men煤 de opciones
|
39 |
+
with st.sidebar:
|
40 |
+
# Imagen y t铆tulo del men煤 centrados
|
41 |
+
st.image("imagenes/uoc.png", width=290) # Tama帽o m谩s grande para el logo
|
42 |
+
st.markdown('<h1 style="text-align: center; color: black;">Men煤 de Navegaci贸n</h2>', unsafe_allow_html=True)
|
43 |
+
|
44 |
+
# Opciones del men煤 con emojis como iconos
|
45 |
+
opciones_menu = {
|
46 |
+
"Home": "馃彔 Home",
|
47 |
+
"Analizar texto": "馃攳 Analizar texto",
|
48 |
+
"Info": "鈩癸笍 Info"
|
49 |
+
}
|
50 |
+
# Valor predeterminado para 'selected'
|
51 |
+
if 'selected' not in st.session_state:
|
52 |
+
st.session_state['selected'] = "Home"
|
53 |
+
|
54 |
+
# Estilo personalizado para los botones
|
55 |
+
btn_style = """
|
56 |
+
<style>
|
57 |
+
.css-2trqyj {
|
58 |
+
display: flex;
|
59 |
+
justify-content: center;
|
60 |
+
align-items: center;
|
61 |
+
font-size: 18px;
|
62 |
+
font-weight: bold;
|
63 |
+
}
|
64 |
+
</style>
|
65 |
+
"""
|
66 |
+
st.markdown(btn_style, unsafe_allow_html=True)
|
67 |
+
|
68 |
+
# Crear botones en la barra lateral para cada opci贸n del men煤
|
69 |
+
for opcion, etiqueta in opciones_menu.items():
|
70 |
+
if st.button(etiqueta, key=opcion, use_container_width=True):
|
71 |
+
st.session_state['selected'] = opcion
|
72 |
+
|
73 |
+
# Vista de informaci贸n
|
74 |
+
if st.session_state['selected'] == "Home":
|
75 |
+
st.image("imagenes/uoc2.png", use_column_width=True)
|
76 |
+
home_page()
|
77 |
+
|
78 |
+
# Analizar texto
|
79 |
+
elif st.session_state['selected'] == "Analizar texto":
|
80 |
+
st.image("imagenes/uoc2.png", use_column_width=True)
|
81 |
+
procesar_textos()
|
82 |
+
|
83 |
+
# Info
|
84 |
+
elif st.session_state['selected'] == "Info":
|
85 |
+
st.image("imagenes/uoc2.png", use_column_width=True)
|
86 |
+
info_page()
|
87 |
+
|
88 |
+
|
89 |
+
if __name__ == "__main__":
|
90 |
+
main()
|
modelo_nn_g2.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:73c1fd2dd7ef4320ff37d6715da5be4b7d12a8074356271ba312267867b059f4
|
3 |
+
size 6107894
|
requirements.txt
ADDED
Binary file (3.77 kB). View file
|
|
secciones/home_page.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
3 |
+
|
4 |
+
def home_page():
|
5 |
+
"""
|
6 |
+
Muestra la p谩gina principal de la aplicaci贸n Streamlit.
|
7 |
+
|
8 |
+
Esta funci贸n se encarga de renderizar la p谩gina de inicio de la aplicaci贸n de detecci贸n temprana de riesgo
|
9 |
+
de suicidio.
|
10 |
+
Incluye secciones que explican el prop贸sito del proyecto, sus objetivos principales y c贸mo utilizar la herramienta.
|
11 |
+
Cada secci贸n est谩 claramente definida y contiene informaci贸n detallada y relevante para el usuario.
|
12 |
+
|
13 |
+
La p谩gina de inicio se estructura en varias secciones, que incluyen:
|
14 |
+
- Una introducci贸n al proyecto y su relevancia.
|
15 |
+
- Los objetivos principales del proyecto.
|
16 |
+
- Instrucciones detalladas sobre c贸mo utilizar la herramienta.
|
17 |
+
|
18 |
+
Las secciones est谩n dise帽adas para proporcionar a los usuarios una comprensi贸n clara del prop贸sito y
|
19 |
+
la funcionalidad de la herramienta, as铆 como guiarlos en su uso efectivo.
|
20 |
+
|
21 |
+
:return: None. Renderiza los componentes de la p谩gina de inicio en la interfaz de usuario de Streamlit.
|
22 |
+
"""
|
23 |
+
st.title("TFG: Detecci贸n Temprana de Riesgo de Suicidio Mediante An谩lisis de mensajes de texto")
|
24 |
+
with st.container():
|
25 |
+
st.write("""
|
26 |
+
Este proyecto emplea t茅cnicas avanzadas de Procesamiento de Lenguaje Natural (PLN) y an谩lisis de datos para
|
27 |
+
explorar y detectar se帽ales de comportamientos autolesivos en mensajes publicados en redes sociales.
|
28 |
+
La iniciativa busca abordar una de las principales causas de preocupaci贸n en la salud mental global,
|
29 |
+
ofreciendo una herramienta innovadora y valiosa para la identificaci贸n temprana de riesgos de suicidio.
|
30 |
+
""")
|
31 |
+
with st.container(border=True):
|
32 |
+
st.header("Objetivos Principales")
|
33 |
+
st.write("""
|
34 |
+
- **An谩lisis Profundo de Comunicaciones Digitales**: Implementaci贸n de algoritmos de PLN para analizar
|
35 |
+
textos y detectar patrones de riesgo en comportamientos y estados emocionales.
|
36 |
+
- **Prevenci贸n de Comportamientos de Riesgo**: Utilizaci贸n de la herramienta como un medio para identificar
|
37 |
+
se帽ales tempranas de crisis emocionales, proporcionando una base s贸lida para intervenciones oportunas y
|
38 |
+
medidas preventivas.
|
39 |
+
- **Evaluaci贸n y Mejora de Estrategias de Prevenci贸n Actuales**: Contribuci贸n a la investigaci贸n y mejora de
|
40 |
+
estrategias de prevenci贸n del suicidio mediante la incorporaci贸n de tecnolog铆as avanzadas de an谩lisis de
|
41 |
+
datos.
|
42 |
+
""")
|
43 |
+
with st.container(border=True):
|
44 |
+
st.header("C贸mo Utilizar la Herramienta")
|
45 |
+
st.write("""
|
46 |
+
1. **Acceso a la herramienta de an谩lisis**: Para acceder a esta propiedad tan solo hay que dirigirse
|
47 |
+
al bot贸n 'Analizar texto' que se encuentra en el men煤 de navegaci贸n.
|
48 |
+
""")
|
49 |
+
st.image("imagenes/Captura1.PNG", use_column_width="auto")
|
50 |
+
st.write("""
|
51 |
+
2. **Ingreso y procesamiento del texto**: Para llevar a cabo nuestro an谩lisis tan solo se debe introducir
|
52 |
+
en el cuadro respectivo el texto a analizar. Haga clic en el bot贸n 'Procesar texto' para que la herramienta
|
53 |
+
procese el texto. La herramienta utiliza modelos de PLN para analizar el contenido y la tonalidad
|
54 |
+
emocional del texto.
|
55 |
+
""")
|
56 |
+
st.write("""
|
57 |
+
**Importante: Por ahora no esta permitido ingresar archivos de texto**
|
58 |
+
""")
|
59 |
+
st.image("imagenes/Captura2.PNG")
|
60 |
+
st.image("imagenes/Captura3.PNG")
|
61 |
+
st.write("""
|
62 |
+
4. **Interpretaci贸n de resultados y acciones sugeridas**: Los resultados proporcionan insights
|
63 |
+
sobre el estado emocional del texto y posibles se帽ales de riesgo. Estos incluyen an谩lisis de sentimientos,
|
64 |
+
emociones y una evaluaci贸n de riesgo de suicidio. Basado en el nivel de riesgo detectado,
|
65 |
+
la herramienta ofrece recomendaciones sobre posibles pasos a seguir.
|
66 |
+
""")
|
67 |
+
st.image("imagenes/Captura4.PNG")
|
secciones/info_page.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
3 |
+
|
4 |
+
def info_page():
|
5 |
+
|
6 |
+
with st.container():
|
7 |
+
st.markdown("""
|
8 |
+
<style>
|
9 |
+
|
10 |
+
.logo {
|
11 |
+
display: inline-block;
|
12 |
+
margin-right: 5px;
|
13 |
+
width: 20px; /* Ajusta el tama帽o del logo aqu铆 */
|
14 |
+
}
|
15 |
+
.about-container{
|
16 |
+
text-align: center;
|
17 |
+
}
|
18 |
+
</style>
|
19 |
+
<div class="about-container" >
|
20 |
+
<h1 >Acerca de este TFG</h1>
|
21 |
+
<p>
|
22 |
+
<h2>Ignacio Mac铆as Mart铆nez</h2><br>
|
23 |
+
<strong>Grado de ciencia de datos aplicada</strong>: Trabajo final de grado 22.536.<br>
|
24 |
+
<strong>Tutora TFG</strong>: Teresa Divorra Vallhonrat.<br>
|
25 |
+
<strong>Profesor responsable de la asignatura</strong>: David Merino Arranz.<br>
|
26 |
+
<strong>Contacto</strong>: /
|
27 |
+
<a href="https://github.com/imaciasm"><img class="logo"
|
28 |
+
src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"/>GitHub</a> \\ /
|
29 |
+
<a href="https://www.linkedin.com/in/imaciasm/"><img class="logo"
|
30 |
+
src="https://upload.wikimedia.org/wikipedia/commons/c/ca/LinkedIn_logo_initials.png"/>LinkedIn</a>
|
31 |
+
\\
|
32 |
+
</p>
|
33 |
+
</div>
|
34 |
+
""", unsafe_allow_html=True)
|
secciones/model_utils.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import joblib
|
2 |
+
import streamlit as st
|
3 |
+
|
4 |
+
|
5 |
+
# Cargar el modelo y el vectorizador
|
6 |
+
@st.cache_data
|
7 |
+
def cargar_modelo_y_vectorizador():
|
8 |
+
modelo = joblib.load('modelo_nn_g2.pkl')
|
9 |
+
tfidf_vectorizador = joblib.load('tfidf_vectorizador2.pkl')
|
10 |
+
return modelo, tfidf_vectorizador
|
secciones/procesar_textos.py
ADDED
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import re
|
4 |
+
import nltk
|
5 |
+
import numpy as np
|
6 |
+
from nltk.tokenize import word_tokenize
|
7 |
+
from nltk.corpus import stopwords
|
8 |
+
from nltk.stem import SnowballStemmer
|
9 |
+
from transformers import pipeline
|
10 |
+
from secciones.model_utils import cargar_modelo_y_vectorizador
|
11 |
+
|
12 |
+
# Descargar recursos de NLTK
|
13 |
+
nltk.download('punkt')
|
14 |
+
nltk.download('stopwords')
|
15 |
+
|
16 |
+
|
17 |
+
# Funci贸n de limpieza y preprocesamiento de texto
|
18 |
+
def clean_text_stemming(text):
|
19 |
+
"""
|
20 |
+
Realiza la limpieza y preprocesamiento de un texto. Convierte el texto a min煤sculas,
|
21 |
+
elimina caracteres no alfab茅ticos, tokeniza, remueve stopwords y aplica stemming.
|
22 |
+
|
23 |
+
:param text: El texto a limpiar y preprocesar.
|
24 |
+
:return: Texto procesado y limpio.
|
25 |
+
"""
|
26 |
+
text = text.lower()
|
27 |
+
text = re.sub(r'[^a-z帽谩茅铆贸煤]', ' ', text)
|
28 |
+
words = word_tokenize(text)
|
29 |
+
stop_words = set(stopwords.words('spanish'))
|
30 |
+
stemmer = SnowballStemmer('spanish')
|
31 |
+
stemmed_text = ' '.join([stemmer.stem(word) for word in words if word not in stop_words])
|
32 |
+
return stemmed_text
|
33 |
+
|
34 |
+
|
35 |
+
# Cargar modelos de Hugging Face para an谩lisis de sentimientos y emociones
|
36 |
+
clasificador_sentimiento = pipeline('sentiment-analysis',
|
37 |
+
model='citizenlab/twitter-xlm-roberta-base-sentiment-finetunned')
|
38 |
+
clasificador_emociones = pipeline("text-classification",
|
39 |
+
model="maxpe/bertin-roberta-base-spanish_sem_eval_2018_task_1")
|
40 |
+
|
41 |
+
|
42 |
+
# Funciones para analizar sentimiento y emociones
|
43 |
+
def analizar_sentimiento(texto):
|
44 |
+
"""
|
45 |
+
Analiza el sentimiento de un texto dado utilizando un modelo preentrenado de Hugging Face.
|
46 |
+
|
47 |
+
:param texto: El texto a analizar.
|
48 |
+
:return: La etiqueta del sentimiento detectado (ej. "Positive", "Negative", "Neutral").
|
49 |
+
Retorna None si ocurre un error.
|
50 |
+
"""
|
51 |
+
try:
|
52 |
+
results = clasificador_sentimiento(texto, truncation=True, max_length=512)
|
53 |
+
top_result = max(results, key=lambda x: x['score'])
|
54 |
+
return top_result['label']
|
55 |
+
except Exception as e:
|
56 |
+
print(f"Error al procesar el texto: {e}")
|
57 |
+
return None
|
58 |
+
|
59 |
+
|
60 |
+
def analizar_emociones(texto):
|
61 |
+
"""
|
62 |
+
Analiza las emociones presentes en un texto utilizando un modelo preentrenado de Hugging Face.
|
63 |
+
|
64 |
+
:param texto: El texto a analizar.
|
65 |
+
:return: La etiqueta de la emoci贸n detectada (ej. "alegr铆a", "tristeza").
|
66 |
+
Retorna None si ocurre un error.
|
67 |
+
"""
|
68 |
+
try:
|
69 |
+
results = clasificador_emociones(texto, truncation=True, max_length=512)
|
70 |
+
top_result = max(results, key=lambda x: x['score'])
|
71 |
+
return top_result['label']
|
72 |
+
except Exception as e:
|
73 |
+
print(f"Error al procesar el texto: {e}")
|
74 |
+
return None
|
75 |
+
|
76 |
+
|
77 |
+
# Normalizaci贸n de la longitud del texto
|
78 |
+
def normalizar_longitud(texto):
|
79 |
+
"""
|
80 |
+
Normaliza la longitud de un texto dividiendo la longitud del texto por una longitud m谩xima observada.
|
81 |
+
|
82 |
+
:param texto: El texto cuya longitud se va a normalizar.
|
83 |
+
:return: Longitud normalizada del texto.
|
84 |
+
"""
|
85 |
+
longitud_maxima_observada = 53352
|
86 |
+
return len(texto) / longitud_maxima_observada
|
87 |
+
|
88 |
+
|
89 |
+
# Obtener caracter铆sticas de polaridad y emociones
|
90 |
+
def obtener_caracteristicas_polaridad(texto):
|
91 |
+
"""
|
92 |
+
Obtiene caracter铆sticas de polaridad (positiva, negativa, neutral) de un texto analizando su sentimiento.
|
93 |
+
|
94 |
+
:param texto: El texto a analizar.
|
95 |
+
:return: Un diccionario con las caracter铆sticas de polaridad en formato binario.
|
96 |
+
"""
|
97 |
+
polaridad = analizar_sentimiento(texto)
|
98 |
+
return {
|
99 |
+
"polarity_Negative": 1 if polaridad == "Negative" else 0,
|
100 |
+
"polarity_Neutral": 1 if polaridad == "Neutral" else 0,
|
101 |
+
"polarity_Positive": 1 if polaridad == "Positive" else 0
|
102 |
+
}
|
103 |
+
|
104 |
+
|
105 |
+
def obtener_caracteristicas_emociones(texto):
|
106 |
+
"""
|
107 |
+
Obtiene caracter铆sticas de emociones (ira, anticipaci贸n, miedo, alegr铆a, tristeza) de un texto.
|
108 |
+
|
109 |
+
:param texto: El texto a analizar.
|
110 |
+
:return: Un diccionario con las caracter铆sticas de emociones en formato binario.
|
111 |
+
"""
|
112 |
+
emocion = analizar_emociones(texto)
|
113 |
+
categorias = ["anger", "anticipation", "fear", "joy", "sadness"]
|
114 |
+
return {f"emotions_{cat}": 1 if emocion == cat else 0 for cat in categorias}
|
115 |
+
|
116 |
+
|
117 |
+
# Funci贸n para realizar predicciones con informaci贸n adicional
|
118 |
+
def predecir_suicidio_con_info(texto, modelo, tfidf_vectorizador):
|
119 |
+
"""
|
120 |
+
Realiza la predicci贸n de comportamiento suicida en un texto dado, utilizando un modelo
|
121 |
+
de machine learning y un vectorizador TF-IDF. Incluye caracter铆sticas adicionales
|
122 |
+
como longitud del texto, polaridad y emociones.
|
123 |
+
|
124 |
+
:param texto: Texto a analizar.
|
125 |
+
:param modelo: Modelo de machine learning para realizar la predicci贸n.
|
126 |
+
:param tfidf_vectorizador: Vectorizador TF-IDF para procesar el texto.
|
127 |
+
:return: Un diccionario con los resultados de la clasificaci贸n y an谩lisis.
|
128 |
+
"""
|
129 |
+
texto_limpio = clean_text_stemming(texto)
|
130 |
+
|
131 |
+
# Obtener caracter铆sticas
|
132 |
+
longitud_normalizada = normalizar_longitud(texto)
|
133 |
+
caracteristicas_polaridad = obtener_caracteristicas_polaridad(texto)
|
134 |
+
caracteristicas_emociones = obtener_caracteristicas_emociones(texto)
|
135 |
+
polaridad = analizar_sentimiento(texto)
|
136 |
+
emocion = analizar_emociones(texto)
|
137 |
+
|
138 |
+
# Vectorizar texto y combinar caracter铆sticas
|
139 |
+
texto_tfidf = tfidf_vectorizador.transform([texto_limpio]).toarray()
|
140 |
+
caracteristicas_adicionales = np.array(
|
141 |
+
[longitud_normalizada] + list(caracteristicas_polaridad.values()) + list(caracteristicas_emociones.values()))
|
142 |
+
features = np.hstack((texto_tfidf, caracteristicas_adicionales.reshape(1, -1)))
|
143 |
+
|
144 |
+
# Aseg煤rate de que el DataFrame tenga los mismos nombres de columnas que se usaron durante el entrenamiento
|
145 |
+
column_names = tfidf_vectorizador.get_feature_names_out().tolist() + ['text_length', 'polarity_Negative',
|
146 |
+
'polarity_Neutral', 'polarity_Positive',
|
147 |
+
'emotions_anger', 'emotions_anticipation',
|
148 |
+
'emotions_fear', 'emotions_joy',
|
149 |
+
'emotions_sadness']
|
150 |
+
features_df = pd.DataFrame(features, columns=column_names)
|
151 |
+
|
152 |
+
# Realizar la predicci贸n
|
153 |
+
pred = modelo.predict(features_df)
|
154 |
+
pred_proba = modelo.predict_proba(features_df)[0]
|
155 |
+
|
156 |
+
# Confianza y nivel de riesgo
|
157 |
+
confianza = abs(pred_proba[1] - pred_proba[0])
|
158 |
+
nivel_riesgo = 'alto' if pred_proba[1] > 0.75 else 'moderado' if pred_proba[1] > 0.5 else 'bajo'
|
159 |
+
accion = 'Se recomienda buscar ayuda profesional inmediatamente.' if nivel_riesgo == 'alto' \
|
160 |
+
else 'Se sugiere monitorear los sentimientos y considerar hablar con un profesional.' \
|
161 |
+
if nivel_riesgo == 'moderado' \
|
162 |
+
else 'Probablemente no hay riesgo inmediato, pero mant茅n una actitud positiva.'
|
163 |
+
|
164 |
+
# Traducciones de las etiquetas de polaridad y emociones al espa帽ol
|
165 |
+
traducciones_polaridad = {
|
166 |
+
"Negative": "Negativa",
|
167 |
+
"Neutral": "Neutral",
|
168 |
+
"Positive": "Positiva"
|
169 |
+
}
|
170 |
+
traducciones_emociones = {
|
171 |
+
"anger": "ira",
|
172 |
+
"anticipation": "Anticipaci贸n",
|
173 |
+
"fear": "Miedo",
|
174 |
+
"joy": "Alegr铆a",
|
175 |
+
"sadness": "Tristeza"
|
176 |
+
}
|
177 |
+
|
178 |
+
# Traducir polaridad y emociones
|
179 |
+
polaridad_traducida = traducciones_polaridad.get(polaridad, polaridad)
|
180 |
+
emocion_traducida = traducciones_emociones.get(emocion, emocion)
|
181 |
+
|
182 |
+
return {
|
183 |
+
"clasificacion": 'suicidio' if pred[0] == 1 else 'no suicidio',
|
184 |
+
"probabilidad_suicidio": pred_proba[1],
|
185 |
+
"confianza": confianza,
|
186 |
+
"nivel_riesgo": nivel_riesgo,
|
187 |
+
"sugerencia_accion": accion,
|
188 |
+
"polaridad": polaridad_traducida,
|
189 |
+
"emocion": emocion_traducida
|
190 |
+
}
|
191 |
+
|
192 |
+
|
193 |
+
def procesar_textos():
|
194 |
+
|
195 |
+
"""
|
196 |
+
Funci贸n principal para procesar textos en la aplicaci贸n Streamlit. Permite al usuario
|
197 |
+
ingresar o subir un texto, y luego utiliza el modelo y el vectorizador para analizarlo.
|
198 |
+
|
199 |
+
:param modelo: Modelo de machine learning para la predicci贸n.
|
200 |
+
:param tfidf_vectorizador: Vectorizador TF-IDF utilizado en el modelo.
|
201 |
+
"""
|
202 |
+
st.title("Analizar Texto")
|
203 |
+
modelo, tfidf_vectorizador = cargar_modelo_y_vectorizador()
|
204 |
+
# Opci贸n para ingresar texto manualmente
|
205 |
+
text_input = st.text_area("Ingrese su texto aqu铆:")
|
206 |
+
|
207 |
+
# Opci贸n para subir un archivo
|
208 |
+
uploaded_file = st.file_uploader("O suba un archivo de texto:", type=["txt"])
|
209 |
+
|
210 |
+
# Bot贸n para procesar el texto
|
211 |
+
if st.button("Procesar Texto"):
|
212 |
+
text_to_process = ""
|
213 |
+
if uploaded_file is not None:
|
214 |
+
# Leer el archivo subido y almacenar su contenido
|
215 |
+
text_to_process = uploaded_file.read().decode("utf-8")
|
216 |
+
elif text_input:
|
217 |
+
# Utilizar el texto ingresado manualmente
|
218 |
+
text_to_process = text_input
|
219 |
+
|
220 |
+
if text_to_process:
|
221 |
+
# Llamar a la funci贸n de predicci贸n con el texto procesado
|
222 |
+
resultado = predecir_suicidio_con_info(text_to_process, modelo, tfidf_vectorizador)
|
223 |
+
|
224 |
+
# Estilos personalizados seg煤n el nivel de riesgo
|
225 |
+
if resultado['nivel_riesgo'] == 'alto':
|
226 |
+
color = "red"
|
227 |
+
elif resultado['nivel_riesgo'] == 'moderado':
|
228 |
+
color = "orange"
|
229 |
+
else:
|
230 |
+
color = "green"
|
231 |
+
|
232 |
+
# Mostrar los resultados con estilos
|
233 |
+
st.markdown(f"<h2 style='color: {color};'>Resultado del An谩lisis:</h2>", unsafe_allow_html=True)
|
234 |
+
st.markdown(f"<b>Nivel de Riesgo:</b> <span style='color: {color};'>{resultado['nivel_riesgo']}</span>",
|
235 |
+
unsafe_allow_html=True)
|
236 |
+
st.markdown(f"<b>Polaridad:</b> {resultado['polaridad']}", unsafe_allow_html=True)
|
237 |
+
st.markdown(f"<b>Emoci贸n:</b> {resultado['emocion']}", unsafe_allow_html=True)
|
238 |
+
st.markdown(f"<b>Clasificaci贸n:</b> {resultado['clasificacion']}", unsafe_allow_html=True)
|
239 |
+
st.markdown(f"<b>Probabilidad de Suicidio:</b> {resultado['probabilidad_suicidio']:.4f}",
|
240 |
+
unsafe_allow_html=True)
|
241 |
+
st.markdown(f"<b>Confianza:</b> {resultado['confianza']:.4f}", unsafe_allow_html=True)
|
242 |
+
|
243 |
+
st.markdown(f"<b>Sugerencia de Acci贸n:</b> {resultado['sugerencia_accion']}", unsafe_allow_html=True)
|
244 |
+
else:
|
245 |
+
st.warning("Por favor, ingrese texto o suba un archivo.")
|
tfidf_vectorizador2.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:247005faccbe8acea43dccbcef558063a46250f489bd7e2ec4dc1ce59961612e
|
3 |
+
size 238915493
|