Epistemología
Fundamentar la investigación desde el constructivismo relacional.
Hoja de ruta de la tesis
Una secuencia para fundamentar el trabajo, preparar el material, codificarlo con rigor, analizar los resultados y convertirlos en una tesis clara y verificable.
Fundamentar la investigación desde el constructivismo relacional.
Reunir y ordenar el conjunto de transcripciones que forman la base del estudio.
Preparar las transcripciones protegiendo la identidad y la confidencialidad de los participantes.
Dividir el corpus protegido en unidades consistentes y adecuadas para el análisis.
Entrenar a los jueces, aplicar el sistema de categorías y dejar trazabilidad de las decisiones.
Programar las instrucciones para los modelos IA, ejecutar los programas y documentar todo.
Evaluar codificaciones y contrastar resultados humanos-IA + IA-IA.
Integrar epistemología, método, resultados y discusión en una narrativa académica coherente.
Guía de reproducción
Procedimiento para rehacer el estudio desde cero con los archivos ya en tu ordenador: qué haces en cada paso, los comandos de Terminal y cómo comprobar el resultado.
Orden de trabajo: la guía recorre los 33 pasos en orden, desde la preparación del equipo (paso 1) hasta el cierre y archivo del estudio (paso 33). Los pasos con letra (15a y 17b) se intercalan entre los indicados.
Reglas de oro
04_jueces y 01_original contienen texto de sesiones: no las subas a la nube, no las envíes por correo y consérvalas solo en el ordenador cifrado y en los USB cifrados.codigo, con el entorno activado. Al empezar cada sesión de trabajo, abre Terminal y escribe:cd ~/Desktop/Estudio_HSS/codigo
source ../.venv/bin/activate
El indicador de Terminal debe empezar por (.venv). Si un comando da error, copia el mensaje completo antes de tocar nada.
Quién es quién. D es quien dirige el estudio (tú). J son los dos jueces (A y B). El juez A es quien revisa la segmentación.
Si pierdes archivos. Los scripts, las plantillas y los datos son cosas distintas:
codigo) y las plantillas (06_instrucciones) se restauran desde tu copia de seguridad cifrada, no desde esta página.Qué haces: dejar el Mac listo para trabajar con datos confidenciales.
fdesetup status
Debe responder «FileVault is On.».
Corpus van en el Escritorio (en Terminal, ~/Desktop).Resultado: FileVault activo y nada sincronizado con la nube.
Qué haces: crear las carpetas, copiar los scripts y las plantillas e iniciar el diario.
cd ~/Desktop
mkdir -p Estudio_HSS/{00_admin,01_original/transcripciones,02_protegido}
mkdir -p Estudio_HSS/{03_unidades,04_jueces,05_modelos,06_instrucciones}
mkdir -p Estudio_HSS/{07_ejecuciones,08_resultados,codigo}
Estudio_HSS/codigo los 27 scripts (comun.py, de p04 a p33 y los de los pasos con letra, p14b y p17b) y dentro de Estudio_HSS/06_instrucciones los 7 archivos de plantillas (ver el Anexo). Hazlo con el Finder desde tu copia de los archivos.cd ~/Desktop/Estudio_HSS
printf "# Diario del estudio\n\n" > 00_admin/diario.md
open -e 00_admin/diario.md
Escribe en él una línea como esta y guarda:
- 2026-10-04: Equipo preparado: FileVault activo, sin iCloud, copias cifradas.
Resultado: la carpeta Estudio_HSS con sus subcarpetas, los scripts, las plantillas y el diario.
Comprobación: ls codigo muestra comun.py y los scripts de p04 a p33.
Qué haces: crear un entorno de Python aislado con las bibliotecas.
thinc). Cierra Terminal y ábrela de nuevo. python3.12 --version debe indicar 3.12.x.codigo ya dentro de Estudio_HSS:cd ~/Desktop/Estudio_HSS
python3.12 -m venv .venv
source .venv/bin/activate
python --version
python -m pip install --upgrade pip
pip install pandas numpy scikit-learn openpyxl python-docx spacy matplotlib
python -m spacy download en_core_web_lg
pip freeze > codigo/requirements.txt
python --version debe indicar 3.12.x; si indica otra, no sigas (usa python3.12 para crear el entorno, no python3). Después desactiva la wifi.
python -c "import pandas, sklearn, openpyxl, docx, spacy, matplotlib"
python -c "import spacy; spacy.load('en_core_web_lg')"
Resultado: la carpeta .venv y codigo/requirements.txt.
Qué haces: copiar las 78 transcripciones al estudio, con el código de cada sesión.
La carpeta ~/Desktop/Corpus tiene una subcarpeta por serie con el nombre sin «Therapy Over Time» (Rational Emotive Behavior, Cognitive, Behavioral, Emotion-Focused, Person-Centered, Existential-Humanistic, Brief Dynamic, Psychoanalytic, Accelerated Experiential Dynamic, Constructivist, Narrative, Feminist, Relational-Cultural) y, dentro, 1.docx a 6.docx. En tu caso las transcripciones están en ~/Desktop/Corpus/Original.
python p04_importar.py ~/Desktop/Corpus/Original
El script comprueba las 13 carpetas y las 6 sesiones de cada una; si algo falla, no copia nada y lo indica. Si te dice que una carpeta «no corresponde a ninguna serie», la ruta es la equivocada: usa la carpeta que contiene directamente las 13 subcarpetas.
Resultado: 78 archivos en 01_original/transcripciones/S01 a S13 y 00_admin/importacion.csv. Termina con «Correcto: 78 transcripciones copiadas en 01_original/transcripciones».
Cuando el paso 5 confirme las 78, guarda la carpeta Corpus solo en el ordenador cifrado y en los USB cifrados, fuera de carpetas sincronizadas.
Qué haces: limpiar las transcripciones, comprobar que están las 78 y registrar la huella de cada archivo.
python p05_inventario.py
Si falta algún archivo, el script lo indica («Faltan: S03/S03_s4.docx») y se detiene. Si sobra alguno, lo indica con «Sobran»: bórralo para que en cada serie queden solo sus 6 transcripciones.
chmod -R a-w ../01_original/transcripciones
Resultado: 00_admin/inventario.csv (una fila por sesión) y 00_admin/series.csv. Termina con «Correcto: 78 transcripciones en el inventario».
Qué haces: decir qué etiqueta es el terapeuta y cuál el paciente en cada serie.
python p06_hablantes.py
01_original/hablantes.xlsx. Hay una fila por serie y etiqueta. En la columna amarilla rol escribe:Unknown son el paciente);Nota sobre el formato de tus transcripciones: cada línea empieza con la marca de tiempo pegada al nombre (00:15:20Nombre y un espacio duro antes del texto). El script ya lo entiende. Si el script dice que «no se ha reconocido ninguna etiqueta de hablante», el formato de esa transcripción no es ninguno de los admitidos.
Resultado: hablantes.xlsx con un rol para cada etiqueta.
Qué haces: pasar cada sesión a una tabla de turnos (hablante y texto).
python p07_convertir.py
00_admin/informe_conversion.csv): «líneas sin hablante» (unas pocas son normales), «falta terapeuta o paciente» (revisa los roles de esa serie), «menos de 20 turnos» (transcripción incompleta) y «turnos repetidos» (posible pasaje duplicado). En tu caso hubo avisos en 4 sesiones (S02_s2, S05_s3, S07_s2, S13_s5); los revisaste y los turnos estaban bien.01_original/turnos y compáralas con su .docx: primer y último turno, y algún turno largo.chmod -R u+w ../01_original/transcripciones/S03
open ../01_original/transcripciones/S03/S03_s4.docx
chmod -R a-w ../01_original/transcripciones/S03
python p05_inventario.py
python p07_convertir.py
Resultado: 01_original/turnos/S01_s1.csv y siguientes, con las columnas serie, sesion, turno, hablante (T o P) y texto. El carácter «|» del texto se cambia por «/», porque queda reservado.
Qué haces: elegir al azar una sesión de cada serie para el conjunto de desarrollo (13 sesiones); las otras 65 son la evaluación.
20261004.python p08_sorteo.py 20261004
Resultado: la columna conjunto del inventario dice desarrollo o evaluacion. Hay 13 sesiones de desarrollo y 65 de evaluación. El sorteo no se puede repetir.
Un programa local sustituye los identificadores por códigos estables dentro de cada serie. Después una persona revisa todo el corpus y aprueba cada sesión. Solo lo aprobado pasa al análisis.
| Identificador | Tipo en nombres.xlsx | Código |
|---|---|---|
| Paciente | PACIENTE | [CLIENT] |
| Terapeuta | TERAPEUTA | [THERAPIST] |
| Otras personas | PERSONA | [PERSON_1], [PERSON_2]… |
| Lugares | LUGAR | [PLACE_1]… |
| Organizaciones | ORGANIZACION | [ORGANIZATION_1]… |
| Fechas y detalles que identifican | Revisión manual | Descripción entre corchetes, por ejemplo [DATE] |
Qué haces: anotar a mano los identificadores de 2 sesiones, sin ver lo que hace el programa, para medir después su precisión.
Antes: el paso 11 todavía no se ha ejecutado.
--sesiones 3 elegiría 3):python p09_muestra_control.py 7
Te salieron S09_s1 y S12_s6.
01_original/muestra_control y escribe en la columna identificadores, separados por punto y coma, todos los fragmentos que identifican a una persona, un lugar o una organización, tal como aparecen en el texto. Incluye los nombres del paciente y del terapeuta. No anotes parentescos genéricos («my mom»), expresiones de tiempo relativas («last week»).| texto | identificadores |
|---|---|
| My sister Anna called me from Boston. | Anna; Boston |
| Dr. Greenberg, can I ask you something? | Dr. Greenberg |
| I told my boss at Greenfield Bank. | Greenfield Bank |
Resultado: las dos hojas de la muestra de control, anotadas.
Qué haces: dar al programa la lista de nombres de cada serie.
python p10_nombres.py
01_original/nombres.xlsx. La hoja datos ya trae a cada terapeuta (con sus variantes) y a los pacientes cuya etiqueta es un nombre. Añade, serie por serie: el paciente cuando la etiqueta es genérica (tipo PACIENTE), familiares y otras personas (PERSONA), lugares (LUGAR) y organizaciones (ORGANIZACION).mismo_que para agrupar variantes de una misma persona (Annie con mismo_que Anna).no_sustituir recoge palabras que spaCy confunde con nombres (Mom, God, Mm-hmm, Zoloft). Amplíala cuando lo detectes.Si más adelante se añaden pacientes nuevos, python p10_nombres.py --completar los incorpora sin tocar lo ya escrito.
Resultado: nombres.xlsx completo.
Qué haces: sustituir los identificadores por códigos y crear una hoja de revisión por sesión (tarda unos minutos).
python p11_desidentificar.py
Resultado:
01_original/revision_desidentificacion/S0x_sN.xlsx: una hoja por sesión con turno, hablante, original, cambios y las columnas amarillas texto_final, revisado y nota.01_original/sustituciones/S0x.csv: la correspondencia entre cada nombre y su código (se conserva cifrada).Las hojas que ya existen no se sobrescriben.
Qué haces: medir, una sola vez, cómo funciona la desidentificación automática frente a tu muestra de control. Entre el paso 11 y este no se añaden nombres a nombres.xlsx.
python p12_precision.py
Resultado: 08_resultados/desidentificacion_precision.csv y una línea en el diario, para spaCy solo y para spaCy con la lista de nombres (precisión y sensibilidad). Una sensibilidad baja no detiene el procedimiento: todas las sesiones se revisan a mano.
Qué haces: revisar a mano las 78 hojas de 01_original/revision_desidentificacion y aprobarlas.
texto_final, con original y cambios al lado.texto_final. Si la palabra coincide con un nombre conocido usado con otro sentido (Will como verbo), escribe además mantener en nota.nombres.xlsx (serie y tipo) en lugar de escribir el código a mano. Al terminar una serie, aplica los nombres nuevos a todas sus hojas (las filas que cambian vuelven a quedar sin revisar):python p11_desidentificar.py --actualizar --series S04
texto_final, con una descripción entre corchetes, los detalles que permitirían reconocer a alguien (fechas, nombres de escuelas, edades, años, etc.). Conserva lo que tiene valor clínico.| original | texto_final |
|---|---|
| I was born on May 3rd, 1984. | I was born on [DATE]. |
| I teach at the only music school in [PLACE_1]. | I teach at [A MUSIC SCHOOL] in [PLACE_1]. |
| My wife was on the news after the 2011 flood. | My wife was on the news after [A LOCAL EVENT]. |
si en revisado.python p13_aprobar.py --revisor EC
El script aprueba las sesiones en las que todas las filas están revisadas, ningún texto_final está vacío, no queda ningún nombre conocido (salvo en filas con mantener) y las filas coinciden con las del original. Las demás aparecen como pendientes, con el motivo.
Resultado: 02_protegido/S0x_sN.csv de cada sesión aprobada. Termina con «Total aprobadas: 78 de 78» (así te salió). Una vez fijadas las unidades en el paso 17, el corpus protegido ya no puede cambiarse.
La unidad de análisis es la oración gramatical del terapeuta, con al menos sujeto y verbo, según las reglas de Hill (2020, Web Form F), adaptadas de Auld y White (1956). Python propone la división y un solo juez (A) la revisa. Esa segmentación queda fijada y es común a jueces y modelos. El acuerdo entre jueces se mide después, en la codificación. Es una limitación que se declara en la tesis: la segmentación no tiene una medida de acuerdo entre personas.
Si algún día la revisaran dos jueces, basta cambiar JUECES_SEGMENTACION en codigo/comun.py a ("A", "B") y hacer también el paso 16.
Qué haces: el programa corta cada turno del terapeuta y crea las hojas del juez.
python p14_segmentar.py
El programa divide cada turno en oraciones y pone un // entre las cláusulas principales unidas por and, or, but, nor o por punto y coma, y separa right? / is that right? al final. Marca con NU: las anotaciones entre corchetes y las facilitaciones mínimas (mm-hmm, yeah, right, okay, sure, I see) que no responden a una pregunta directa. Python no puede aplicar el resto de las reglas (elipsis, comienzos fallidos, interrupciones, muletillas): las decide el juez en el paso 15.
Resultado: una hoja por sesión en 04_jueces/segmentacion/juez_A/S01_s1.xlsx … S13_s6.xlsx. No se sobrescriben las hojas que ya existen; si quieres regenerarlas, borra antes la carpeta juez_A.
Qué haces: guardar aparte la propuesta automática de segmentación, para tener dos versiones de cada sesión: la propuesta de Python (intacta) y tu revisión (la hoja que editas).
Para qué sirve: medir cuánto cambias la propuesta (tasa de edición, paso 17b) y ver qué errores comete el segmentador, para mejorar sus reglas en futuras investigaciones y que cada vez requiera menos revisión manual.
Cuándo hacerlo: justo después del paso 14 y antes de editar las hojas. Si ya has editado algunas, sigue siendo posible: el paso 14 nunca sobrescribe una hoja que ya existe, y la propuesta es determinista (mismo texto protegido, mismo programa y misma versión de spaCy). Este script vuelve a generarla en otra carpeta y no lee ni modifica tus hojas.
cd ~/Desktop/Estudio_HSS/codigo
source ../.venv/bin/activate
python p14b_copia_propuesta.py
Resultado: 04_jueces/propuesta_python/segmentacion/juez_A/S0x_sN.xlsx (78 hojas). Debe decir «78 hojas de propuesta creadas». Si lo repites, dice 0: las hojas existentes no se tocan.
Reglas:
04_jueces/segmentacion/juez_A. No abras ni modifiques propuesta_python.comun.py a mitad del proceso, la propuesta regenerada podría diferir de la original. Por eso conviene ejecutar este paso justo después del paso 14.propuesta_python contiene texto del corpus ya desidentificado: es confidencial. Mantenla en el ordenador cifrado, fuera de carpetas sincronizadas y de repositorios, y consérvala cifrada con el resto del corpus.04_jueces/segmentacion/juez_A: la propuesta se recupera, tu revisión no.Qué haces: revisar los cortes de las 78 hojas de 04_jueces/segmentacion/juez_A. Quien revisa es el juez A, sin codificar.
Cómo es la hoja. Cada fila es un turno del terapeuta. Columnas: turno; paciente_antes (solo contexto: te dice si el terapeuta responde a una pregunta directa); texto (el turno original, no se toca); segmentacion (amarilla: el mismo turno ya cortado, cada // marca el final de una unidad); comentario (amarilla, libre). Hay una hoja instrucciones con el resumen.
Qué haces con cada hoja:
datos.segmentacion.| Quiero… | Qué hago |
|---|---|
| Dejar el turno como está | No toco la celda |
| Quitar un corte | Borro el // |
| Añadir un corte | Escribo // entre las dos palabras, con un espacio a cada lado |
| Marcar un trozo que no es unidad (facilitación mínima, comienzo fallido, anotación) | Escribo NU: delante del trozo, al principio de la celda o justo después de un // |
| Marcar un trozo ininteligible | Escribo NA: delante del trozo |
comentario, guarda y cierra el archivo.Ejemplo. El programa propone:
We have some time to talk today and I thought that maybe, uh, you could tell me what brings you here. // I would like to hear it in your own words, // if you feel like it.
«and I thought…» es una segunda cláusula principal (se corta antes de and) y el corte antes de «if you feel like it» sobra, porque es una subordinada sin principal propia. Lo dejas así:
We have some time to talk today // and I thought that maybe, uh, you could tell me what brings you here. // I would like to hear it in your own words, if you feel like it.
Reglas de decisión (en este orden, la primera que se cumpla decide):
NA: delante.paciente_antes: si el paciente acaba de hacer una pregunta directa, es una unidad (sin marca); si no, NU:.// antes de la conjunción.//.Casos habituales:
| Caso | Antes | Después |
|---|---|---|
| Una sola unidad (un solo sujeto con dos verbos) | You went to the store and bought milk. |
Igual |
| Subordinada dentro de la unidad | When you said that, I felt sad. |
Igual |
| Dos principales con and | I hear that you were sad, and you didn't know what to do. |
I hear that you were sad, // and you didn't know what to do. |
| Tres cláusulas | You felt sad and you wanted to cry, but you held it in. |
You felt sad // and you wanted to cry, // but you held it in. |
| Adverbio conjuntivo | You wanted to leave; however, you stayed. |
You wanted to leave; // however, you stayed. |
| Cortó de más (subordinada) | Because you were afraid, // you left. |
Because you were afraid, you left. |
| Cortó de más (I think) | I think you were upset // and you wanted to leave. |
I think you were upset and you wanted to leave. |
| Facilitación pegada a otra frase | Mm-hmm, so what did you do then? |
NU: Mm-hmm, // so what did you do then? |
| Facilitación que responde a una pregunta directa del paciente | NU: Mm-hmm. (propuesta) |
Mm-hmm. (quitas NU:) |
| Confirmación final | You felt trapped, right? |
You felt trapped, // right? |
| Comienzo fallido | So when you, uh, when you said that ... // you felt alone. |
So when you, uh, when you said that ... you felt alone. |
| Enunciado cortado pero con sentido claro | And he would ask her to write the... |
Igual (es unidad) |
| Enunciado cortado sin sentido claro | The little girl ... |
NU: The little girl ... |
| Muletillas (you know, I guess, um, uh) | Some, you know, very serious thing may be, you know, happening. |
Igual (no se cortan) |
Caso raro (cláusula interrumpida por otra independiente): I wanted to ask ... well, what I really wonder is how you felt ... about the meeting. Según Hill son dos unidades, pero la hoja no permite partir una unidad en trozos separados: no cortes y escribe parentética en comentario.
Consejos para las 78 hojas:
// entre ellas y NU: delante de la que no lo sea.python p17_fijar_unidades.py: si una celda no reproduce el texto, te dice sesión y turno. Si no hay errores, crea 03_unidades/unidades.csv; cuando termines las 78 hojas, repítelo con --forzar para que recoja todos los cambios.Terminado cuando: las 78 hojas están revisadas y python p17_fijar_unidades.py --forzar no da errores.
Referencia: Hill, C. E. (2020). Helping skills: Facilitating exploration, insight, and action (5.ª ed.). APA. Las reglas proceden de Web Form F.
Este paso solo se hace si la segmentación la revisan dos jueces. Con un solo juez, python p16_acuerdo_segmentacion.py lo indica y se detiene: pasa al paso 17.
Qué haces: cuando las 78 hojas estén revisadas, fijar una segmentación única, común a jueces y modelos.
python p17_fijar_unidades.py --forzar
(Sin --forzar si es la primera vez que se ejecuta.) Si una hoja tiene un error (una celda segmentacion que no reproduce el texto del turno), el script lo enumera por sesión y turno y se detiene; el juez lo corrige y se repite el paso.
Resultado: 03_unidades/unidades.csv (una fila por unidad: unidad, serie, sesion, turno, conjunto, texto, estado, analizable), la columna unidades del inventario y 08_resultados/inventario_unidades.csv. Los identificadores son S07_s3_t0042_u02 (sesión, turno y número de unidad).
Dos jueces con formación en psicoterapia y competencia en inglés codifican cada unidad con una de las doce categorías del HSS (Hill, 2020). Al menos uno de ellos es ajeno a la elaboración de las instrucciones de los modelos. Hay tres rondas:
| Ronda | Sesiones | Para qué sirve |
|---|---|---|
| entrenamiento | De desarrollo, por tandas | Alcanzar el 80 % de acuerdo y fijar las reglas de decisión |
| evaluacion | Las 65 de evaluación | Referencia humana para el acuerdo entre jueces (H1) y para evaluar los modelos |
| recodificacion | Las 13 de desarrollo, con las reglas definitivas | Describir las seis sesiones de cada serie y servir de referencia en el desarrollo de los modelos |
Qué haces: comparar, turno a turno, la propuesta de Python (paso 15a) con tu versión revisada. Da la tasa de edición (cuánto trabajo humano queda) y una lista de los patrones que más corriges, que son las reglas candidatas para mejorar el segmentador en futuras investigaciones.
python p17b_tasa_edicion.py
Si vas a medias y quieres una cifra provisional, limita el cálculo a lo que ya hayas terminado (las sesiones que aún no has revisado cuentan como «sin cambios»):
python p17b_tasa_edicion.py --series S01 S02
python p17b_tasa_edicion.py --sesiones S01_s1 S01_s2
Resultado:
08_resultados/edicion_segmentacion_resumen.csv: turnos cambiados (%), cortes quitados y añadidos, precisión, exhaustividad y F1 de los cortes, marcas NU/NA.08_resultados/edicion_segmentacion_sesiones.csv: las mismas cifras por sesión.08_resultados/edicion_segmentacion_patrones.csv: palabras junto a los cortes cambiados (por ejemplo, «corte añadido antes de and»), solo patrones que se repiten 3 veces o más. Son datos agregados.04_jueces/propuesta_python/cambios_detalle.csv: cada cambio con su contexto. Confidencial: contiene texto del corpus; no sale del equipo cifrado.Cómo leerlo (y para qué usarlo):
proponer_segmentos en comun.py.Quién: D.
06_instrucciones/categorias.json con un editor de texto plano. Comprueba la grafía de las doce categorías principales y sustituye los subtipos por los del Web Form E (los de la plantilla son provisionales). Respeta el formato: comillas rectas, comas entre elementos y ninguna coma tras el último. Comprueba que sigue siendo válido (muestra su contenido si lo es, y si no, la línea del error):python -m json.tool ../06_instrucciones/categorias.json
python p18_hojas_codificacion.py --ronda entrenamiento \
--sesiones S01_s2 S05_s4 S09_s1
Resultado: un libro por sesión y juez en 04_jueces/codificacion/entrenamiento/juez_A y juez_B, con tres hojas: datos (una fila por unidad analizable, con terapeuta_marcado y las columnas amarillas categoria, subtipo, duda, comentario), sesion (la transcripción completa) y tiempo (minutos dedicados, celda B1). Cada juez recibe solo su carpeta. Durante el entrenamiento los jueces eligen siempre el subtipo cuando la categoría lo tiene.
Quién: J, por separado; J + J y D en las reuniones.
python p19_acuerdo_jueces.py --ronda entrenamiento \
--sesiones S01_s2 S05_s4 S09_s1
04_jueces/acuerdo/acuerdo_entrenamiento_FECHA.xlsx. Las reglas de decisión que acuerden se guardan en 00_admin/reglas_de_decision.md, sin texto de las sesiones.Resultado: reglas de decisión y decisión sobre los subtipos anotadas en el diario, con el acuerdo de cada tanda y la fecha en que se alcanzó el criterio.
Quién: D prepara las hojas; J codifica.
python p18_hojas_codificacion.py --ronda evaluacion
sesion), sin ver las hojas del otro juez ni las salidas de los modelos y sin comentar casos concretos hasta el paso 22. Anota los minutos de cada sesión en la hoja tiempo.El acuerdo de evaluación no se calcula hasta que los dos jueces han terminado todas las sesiones.
Resultado: 130 libros codificados.
Quién: D.
python p19_acuerdo_jueces.py --ronda evaluacion --consenso
El script comprueba que cada unidad tiene una categoría válida y que cada subtipo corresponde a su categoría; si hay errores, los enumera y el juez los corrige. Después guarda en 04_jueces/acuerdo/acuerdo_evaluacion_FECHA.xlsx el porcentaje de acuerdo, la kappa de Cohen con su intervalo del 95 %, el acuerdo por categoría y la matriz de confusión; guarda las huellas de las hojas; y crea en 04_jueces/consenso/evaluacion una hoja por sesión para la reunión de consenso.
chmod -R a-w ../04_jueces/codificacion/evaluacion
Comprobación: el archivo de acuerdo existe, con su fecha, antes de la primera reunión de consenso.
Quién: J + J y D.
04_jueces/consenso/evaluacion, los jueces discuten las unidades con coincide igual a no y eligen la categoría acordada y, si se codifican, el subtipo en subtipo_consenso. Si no llegan a un acuerdo, marcan si en sin_consenso y explican el motivo en nota (esas unidades no se asignan a Other).python p22_consenso.py --ronda evaluacion
Resultado: 04_jueces/consenso_evaluacion.csv.
Quién: J, J + J y D.
Se repiten los pasos 20 a 22 con la ronda recodificacion (hojas nuevas, no se reutilizan las del entrenamiento):
python p18_hojas_codificacion.py --ronda recodificacion
python p19_acuerdo_jueces.py --ronda recodificacion --consenso
python p22_consenso.py --ronda recodificacion
La primera se ejecuta al empezar; la segunda, cuando los dos jueces han terminado; la tercera, después de la reunión de consenso.
Resultado: 04_jueces/consenso_recodificacion.csv.
Se comparan modelos de pesos abiertos de al menos dos familias, ejecutados sin conexión y sin modificar sus pesos. Una configuración combina un modelo con una versión de las instrucciones (sin ejemplos o con ejemplos). Cada ejecución añade un nivel de contexto y un número de repetición.
| Nivel | --contexto |
Qué recibe el modelo | Uso |
|---|---|---|---|
| Unidad aislada | aislada | Solo la oración | Comparación principal (H4) |
| Intercambio inmediato | intercambio | El turno del terapeuta con la unidad entre >> y <<, y los turnos del paciente anterior y siguiente | Comparación principal (H4) y selección de la configuración |
| Sesión completa | sesion | Toda la sesión, con los turnos numerados, y al final el turno con la unidad señalada | Complementaria |
Cada ejecución escribe un archivo MODELO__PLANTILLA__CONTEXTO__eN.jsonl en 07_ejecuciones/desarrollo o 07_ejecuciones/evaluacion, sin texto de las sesiones.
Quién: D, con conexión y sin ningún archivo del corpus abierto.
pip install llama-cpp-python
python -c "import llama_cpp as l; print(l.llama_supports_gpu_offload())"
pip freeze > requirements.txt
Debe responder True. Si responde False, reinstala con Metal:
CMAKE_ARGS="-DGGML_METAL=on" pip install --force-reinstall --no-cache-dir \
llama-cpp-python
.gguf en 05_modelos y regístralos (calcula la huella de cada uno):python p24_modelos.py
00_admin/modelos.xlsx la familia, la cuantización, la fuente y la licencia de cada modelo. Desactiva la wifi.Resultado: 00_admin/modelos.xlsx con nombre, tamaño y huella SHA-256 de cada modelo.
Quién: D. El juez ajeno a la elaboración de las instrucciones no participa.
06_instrucciones/definiciones.txt escribe en inglés la definición de cada categoría (Web Form E) y las reglas de decisión que los jueces fijaron hasta el final del entrenamiento (paso 19). No incorpores las que se acordaron después, al discutir unidades de evaluación. No incluyas texto de las sesiones.plantilla_sistema.txt contiene las variables $categorias, $definiciones, $ejemplos y $formato; las tres plantilla_usuario_* usan $unidad, $turno, $paciente_antes, $terapeuta_marcado, $paciente_despues y $sesion. Se puede ajustar el texto, pero no el nombre de las variables.python p25_ejemplos.py 25
Elige al azar, para cada categoría, una unidad de desarrollo en la que los dos jueces coincidieron desde el principio, y guarda su identificador y categoría en 06_instrucciones/ejemplos.xlsx, sin texto (con --por_categoria 2 elige dos). Revisa cada ejemplo en la hoja de consenso de su sesión; si alguno no es claro, sustituye su identificador por el de otra unidad con la misma categoría y anota el cambio en el diario.
06_instrucciones/dominios.json fija la correspondencia entre categorías y dominios (exploración, insight, acción) a partir de Hill (2020), antes de analizar. Anota la versión definitiva en el diario.Resultado: 06_instrucciones completo.
Quién: D.
python p26_codificar_modelo.py --modelo simulado --plantilla con_ejemplos \
--contexto intercambio --ronda desarrollo --semilla 1 --limite 20
python p26_codificar_modelo.py --modelo MODELO.gguf --plantilla con_ejemplos \
--contexto intercambio --ronda desarrollo --semilla 1 \
--limite 20 --detalle
python p26_codificar_modelo.py --modelo MODELO.gguf --plantilla con_ejemplos \
--contexto sesion --ronda desarrollo --semilla 1 --limite 5 --detalle
Comprueba que el modelo se carga en la GPU (Metal) y que su ventana de entrenamiento (n_ctx_train) no es menor que --n_ctx (16384 por defecto). Abre Monitor de Actividad y anota la memoria del proceso python.
08_resultados/inventario_unidades.csv) y por el número de ejecuciones del nivel (paso 30).rm -r ../07_ejecuciones/desarrollo
Resultado: tiempo por unidad y memoria de cada modelo, anotados en el diario.
Quién: D.
caffeinate -i python p26_codificar_modelo.py --modelo MODELO.gguf \
--plantilla sin_ejemplos --contexto intercambio \
--ronda desarrollo --semilla 11
caffeinate -i python p26_codificar_modelo.py --modelo MODELO.gguf \
--plantilla con_ejemplos --contexto intercambio \
--ronda desarrollo --semilla 11
caffeinate -i impide que el Mac entre en reposo. Mantén el equipo conectado a la corriente; si una ejecución se interrumpe, repite la misma orden y continúa donde se quedó.
--n_ctx).mkdir -p ../07_ejecuciones/anteriores/v1
mv ../07_ejecuciones/desarrollo ../07_ejecuciones/anteriores/v1/
Anota cada cambio en el diario.
Resultado: un archivo por modelo y versión de las instrucciones en 07_ejecuciones/desarrollo.
Quién: D.
python p28_seleccion.py
Resultado: 08_resultados/seleccion_desarrollo.csv, ordenada de mejor a peor, con macro-F1, kappa, proporción de fallos y segundos por unidad. La primera fila es la configuración principal; las demás son las de sensibilidad. Anota la elección en el diario.
Quién: D.
Fija las instrucciones, el formato de salida y los parámetros antes de abrir la evaluación. Ejecuta el script con la configuración principal (primera fila de seleccion_desarrollo.csv), las demás como sensibilidad y los parámetros definitivos. Añade --subtipos si en el paso 19 se decidió codificar los subtipos:
python p29_congelar.py --principal MODELO_A.gguf:con_ejemplos \
--sensibilidad MODELO_A.gguf:sin_ejemplos \
MODELO_B.gguf:con_ejemplos MODELO_B.gguf:sin_ejemplos \
--temperatura 0 --semillas 11 12 13 --n_ctx 16384 --semilla_bootstrap 2026
La congelación no se puede repetir: comprueba la orden antes de ejecutarla.
Resultado: 00_admin/congelacion.json, con las configuraciones, los parámetros y la huella SHA-256 de todos los archivos de 06_instrucciones, de los modelos y de p26 y comun.py. Los archivos de 06_instrucciones quedan como solo lectura. Desde este momento no cambia nada en ellos: antes de cada ejecución de evaluación el script compara las huellas y se detiene si algo es distinto.
Quién: D.
Lanza las ejecuciones, empezando por la configuración principal. Cada configuración se ejecuta tres veces en cada nivel de contexto (en total 36 ejecuciones con dos modelos y dos versiones de las instrucciones):
| Configuración | Contexto | Ejecuciones (semillas) |
|---|---|---|
| Principal | intercambio y aislada | 1, 2 y 3 (11, 12 y 13) |
| Principal | sesion | 1, 2 y 3 (11, 12 y 13) |
| Cada configuración de sensibilidad | intercambio, aislada y sesion | 1, 2 y 3 (11, 12 y 13) |
Una ejecución:
caffeinate -i python p26_codificar_modelo.py --modelo MODELO_A.gguf \
--plantilla con_ejemplos --contexto intercambio \
--ronda evaluacion --ejecucion 1 --semilla 11
Las nueve ejecuciones de una configuración seguidas (se escribe tal cual en Terminal; añade --subtipos al final si procede; repite cambiando el modelo y la plantilla para cada configuración):
for E in 1 2 3; do
for C in intercambio aislada sesion; do
caffeinate -i python p26_codificar_modelo.py --modelo MODELO_A.gguf \
--plantilla con_ejemplos --contexto $C --ronda evaluacion \
--ejecucion $E --semilla $((10 + E))
done
done
El script se niega a ejecutar una configuración que no está congelada, si ha cambiado algún archivo o si no coinciden temperatura, ventana de contexto, subtipos o semilla. Las salidas inválidas se registran como fallos y no se corrigen a mano.
Resultado: los archivos de cada ejecución en 07_ejecuciones/evaluacion. La línea «Hecho» de cada ejecución indica los fallos; anótalos en el diario.
Quién: D.
python p31_analisis.py
Toma como referencia el consenso de evaluación, cuenta las salidas inválidas como desacuerdos, excluye las unidades sin consenso solo de las comparaciones con el consenso y calcula intervalos del 95 % con 2000 remuestreos de series completas, con la semilla congelada. Repetirlo da los mismos números.
Resultado: 08_resultados/resultados.xlsx (hojas: jueces, modelos, por_categoria, confusiones, por_serie, contexto, entre_modelos, estabilidad, cobertura, perfiles, categorias_por_sesion, perfiles_modelo, tiempo_memoria, sesion_completa), la figura 08_resultados/perfiles_por_sesion.png y 08_resultados/etiquetas_por_unidad.csv (sin texto).
Cómo leerlo: kappa superior a .60 y .80 = acuerdo sustancial y casi perfecto (Landis y Koch, 1977), junto con la incertidumbre y la frecuencia de cada categoría. Con 13 series, los intervalos tienen alcance descriptivo.
Quién: D.
python p32_comprobar_salidas.py
Busca, en las carpetas que no deben contener texto de las sesiones y que podrían depositarse (00_admin, codigo, 06_instrucciones, 07_ejecuciones, 08_resultados), cualquier secuencia de ocho palabras seguidas que aparezca en las sesiones. Si encuentra alguna, muestra dónde está: elimina el fragmento y repite la comprobación. Hazla también antes de enviar cualquier resultado fuera del equipo.
Resultado: el mensaje «Correcto» y una línea en el diario.
Quién: D.
python p33_cierre.py
Las huellas se guardan en 08_resultados/huellas_cierre.csv y el cierre se anota en el diario. Todo lo demás se conserva en el archivo privado cifrado y sin conexión; antes de la defensa, comprueba con la fuente de la colección que sus condiciones de uso permiten conservar el corpus.
Resultado: se conserva todo el estudio, con y sin texto, en el archivo privado cifrado, y queda anotado en el diario qué materiales sin texto se valora depositar.
06_instruccionesLos 7 archivos de 06_instrucciones (categorias.json, definiciones.txt, dominios.json, plantilla_sistema.txt, plantilla_usuario_aislada.txt, plantilla_usuario_intercambio.txt y plantilla_usuario_sesion.txt) ya deben estar en esa carpeta antes del paso 18. Comprueba que están con ls ~/Desktop/Estudio_HSS/06_instrucciones.
| Problema | Causa | Solución |
|---|---|---|
Error de thinc al instalar spaCy; requirements.txt no existe |
Python 3.9 del Mac, demasiado antiguo | Instalar Python 3.12 y crear el entorno con python3.12 -m venv .venv |
p04: «La carpeta «Original» no corresponde a ninguna serie» |
Ruta equivocada | Usar ~/Desktop/Corpus/Original, la carpeta que contiene las 13 series |
p06: ValueError: 'rol' is not in list |
El script no reconocía el formato 00:15:20Nombre + espacio duro |
Corregido en comun.py (TIEMPO_NOMBRE_PEGADO); si no se reconoce ninguna etiqueta, el script lo dice |
| Avisos de turnos repetidos en S02_s2, S05_s3, S07_s2, S13_s5 | Pasajes repetidos en las transcripciones | Se revisaron y los turnos estaban bien |
| Una organización mal marcada en la revisión (p. ej. Zoloft) | spaCy confunde palabras con nombres | Restituir la palabra en texto_final y marcar si en revisado; añadirla a no_sustituir |
| Una organización sin marcar | El programa no la detectó | Añadirla a nombres.xlsx y ejecutar python p11_desidentificar.py --actualizar --series SXX |
p17: «la celda segmentacion no reproduce el texto» |
Se borró, añadió o cambió alguna palabra, o hay un NU:/NA: en mitad de una unidad |
Comparar con la columna texto: solo se pueden mover // y poner NU:/NA: al principio de un trozo |
Todo el procesamiento es local. No pegues transcripciones ni salidas clínicas en servicios externos.