Detección de comunidades espectrales en gráficos de conocimiento clínico

Introducción

¿Identificamos grupos latentes de pacientes en una cohorte grande? ¿Cómo podemos encontrar similitudes entre pacientes que vayan más allá de los conocidos grupos de comorbilidad asociados con enfermedades específicas? Y lo que es más importante, ¿cómo podemos extraer señales cuantitativas que puedan analizarse, compararse y reutilizarse en diferentes escenarios clínicos?

La información asociada a cohortes de pacientes consta de grandes corpus que se presentan en varios formatos. Los datos suelen ser difíciles de procesar debido a su calidad y complejidad, con síntomas superpuestos, diagnósticos ambiguos y numerosas abreviaturas.

Estos conjuntos de datos suelen estar muy interconectados y proporcionan ejemplos perfectos en los que el uso de gráficos de conocimiento es bastante beneficioso. Un gráfico tiene la ventaja de hacer explícitas las relaciones entre los pacientes y las entidades relacionadas (enfermedades en nuestro caso), preservando todas las conexiones entre estas características.

En un entorno gráfico, estamos reemplazando los métodos de agrupamiento estándar (por ejemplo, k-medias) con algoritmos de detección comunitaria que identifican cómo los grupos de pacientes se organizan a través de síndromes comunes.

Con estas observaciones en mente, llegamos a nuestra pregunta exploratoria:

¿Cómo podemos superponer algoritmos de gráficos con métodos espectrales para revelar una estructura clínicamente significativa en poblaciones de pacientes que los enfoques tradicionales pasan por alto?

Para abordar esta pregunta, construí un proceso de gráficos clínicos de extremo a extremo que genera notas sintéticas, extrae entidades de enfermedades, construye un gráfico de conocimiento de enfermedad-paciente Neo4j, detecta comunidades con el algoritmo de Leiden y analiza su estructura utilizando conectividad algebraica y el vector de Fiedler.

El algoritmo de Leiden divide el gráfico en grupos, pero no proporciona información sobre la estructura interna de estas comunidades.

Aquí es donde la teoría de grafos espectrales cobra relevancia. Asociado a cualquier gráfico, podemos construir matrices como la matriz de adyacencia y el gráfico laplaciano cuyos valores propios y vectores propios codifican información estructural sobre el gráfico. En particular, el segundo valor propio más pequeño del laplaciano (la conectividad algebraica) y su vector propio asociado (el vector de Fiedler) desempeñarán un papel esencial en el próximo análisis.

En este blog, los lectores verán cómo:

se generan las notas clínicas sintéticas, se extraen y analizan las entidades patológicas, se aprovechan las comunidades de Leiden para extraer información sobre la cohorte, la conectividad algebraica mide la fuerza de una comunidad, se aprovecha el vector de Fiedler para dividir aún más las comunidades.

Incluso en un pequeño conjunto de datos sintéticos, algunas comunidades forman síndromes coherentes, mientras que otras reflejan condiciones coincidentes superpuestas. Los métodos espectrales nos brindan una forma precisa de medir estas diferencias y revelar estructuras que de otro modo pasarían desapercibidas. Aunque este proyecto opera con datos sintéticos, el enfoque se generaliza a conjuntos de datos clínicos del mundo real y muestra cómo los conocimientos espectrales complementan los métodos de detección comunitarios.

💡Datos, código e imágenes:

Descargo de responsabilidad de datos: todos los ejemplos de este artículo utilizan un conjunto de datos totalmente sintético de notas clínicas generadas específicamente para este proyecto.

Fuente del código: todo el código, datos sintéticos, cuadernos y archivos de configuración están disponibles en el repositorio complementario de GitHub. El gráfico de conocimiento se crea utilizando Neo4j Desktop con el complemento GDS. Puede reproducir todo el proceso, desde la generación de notas sintéticas hasta el análisis de gráficos de Neo4j y los cálculos espectrales, en Google Colab y/o un entorno Python local.

Imágenes: Todas las figuras y visualizaciones de este artículo fueron creadas por el autor.

Descripción general de la metodología

En esta sección describimos los pasos del proyecto, desde la generación de texto clínico sintético hasta la detección comunitaria y el análisis espectral.

El flujo de trabajo se desarrolla de la siguiente manera:

Generación de datos sintéticos. Produzca un corpus de aproximadamente 740 notas clínicas sintéticas al estilo de la historia de la enfermedad actual (HPI) con enfermedades controladas e instrucciones claras de formato de notas. Extracción y Deduplicación de Entidades. Extraiga entidades de enfermedades utilizando un modelo NER de OpenMed y aplique una capa de deidentificación de coincidencia difusa. Construcción de gráficos de conocimiento. Cree un gráfico bipartito con el esquema Paciente – HAS_DISEASE -> Enfermedad. Detección comunitaria. Aplicar el algoritmo de detección de la comunidad de Leiden para identificar grupos de pacientes que comparten afecciones relacionadas. Análisis espectral. Calcule la conectividad algebraica para medir la homogeneidad interna de cada comunidad y utilice el vector de Fiedler para dividir las comunidades en subgrupos significativos.

Esta breve descripción general establece el flujo analítico completo. La siguiente sección detalla cómo se generaron las notas clínicas sintéticas.

Generación de datos sintéticos

Para este proyecto, generé un corpus de notas clínicas sintéticas utilizando la API OpenAI, trabajando en Google Colab para mayor comodidad. Los detalles completos del aviso y la implementación están disponibles en el repositorio.

Después de varias iteraciones, implementé un mensaje dinámico que selecciona aleatoriamente la edad y el sexo de un paciente para garantizar la variabilidad entre las muestras. A continuación se muestra un resumen de las principales restricciones del mensaje:

Narrativa clínica: narrativas coherentes centradas en 1-2 sistemas de órganos dominantes, con progresión causal natural. Densidad de entidades controlada: cada nota contiene de 6 a 10 condiciones o síntomas significativos, con barreras de seguridad para evitar la sobrecarga de entidades. Controles de diversidad: las enfermedades se muestrean en todo el espectro común a raro en proporciones específicas y los sistemas de órganos primarios se seleccionan de manera uniforme entre 12 categorías. Restricciones de seguridad: no se incluye información de identificación.

Un desafío clave en la construcción de un conjunto de datos sintéticos de este tipo es evitar un gráfico demasiado conectado donde muchos pacientes comparten el mismo puñado de condiciones. Un mensaje más simple puede generar notas individuales relativamente buenas para los pacientes, pero una distribución general deficiente de las enfermedades. Para contrarrestar esto, le pedí específicamente al modelo que pensara en sus elecciones y que restablecera periódicamente su patrón de selección para evitar la repetición. Estas instrucciones aumentan la complejidad de las decisiones del modelo y la generación lenta, pero producen un conjunto de datos más diverso y realista. Generar 1000 muestras con gpt-5-mini tomó aproximadamente 4 horas.

Cada muestra generada incluye dos características: una nota clínica (el texto generado) y un ID de paciente (identificador único asignado durante la generación). Alrededor de 260 entradas estaban en blanco y se eliminaron durante el preprocesamiento, dejando 740 notas, lo cual es suficiente para este miniproyecto.

Para contextualizar, aquí hay una muestra de una nota clínica sintética del conjunto de datos:

"Un hombre de 50 años presenta seis semanas de disnea de esfuerzo progresiva y una tos persistente no productiva que comenzó después de una bronquitis autolimitada… Informa fatiga diurna y ronquidos fuertes con pausas observadas compatibles con apnea obstructiva del sueño; tiene hipertensión bien controlada y un historial de tabaquismo de 25 paquetes al año, pero dejó de fumar hace cinco años. Niega fiebre u ortopnea".

✨Insights: Es conveniente obtener datos sintéticos, especialmente cuando los conjuntos de datos médicos requieren permisos especiales. A pesar de su utilidad para la demostración de conceptos, los datos sintéticos pueden ser poco fiables para sacar conclusiones clínicas y no deben utilizarse para inferencias clínicas.

Una vez preparado el conjunto de datos, el siguiente paso es extraer entidades clínicamente significativas de cada nota.

Extracción y deduplicación de entidades

El objetivo de esta etapa es transformar notas clínicas no estructuradas en datos estructurados. Utilizando un modelo NER biomédico, extraemos las entidades relevantes, que luego se normalizan y deduplican antes de construir los pares de relaciones.

¿Por qué sólo enfermedad NER?

Para este miniproyecto, me centré únicamente en las entidades patológicas, ya que prevalecen en las notas clínicas generadas. Esto mantiene el análisis coherente y nos permite resaltar la relevancia de la conectividad algebraica sin introducir la complejidad adicional de múltiples tipos de entidades.

Selección de modelo

Seleccioné un modelo NER especializado de OpenMed (ver referencia[1]para más detalles), una excelente colección de código abierto de modelos biomédicos de PNL: OpenMed/OpenMed-NER-PathologyDetect-PubMed-109M, un modelo pequeño pero eficaz que extrae entidades de enfermedades. Este modelo equilibra velocidad y calidad, lo que lo hace ideal para experimentaciones rápidas. Con aceleración de GPU (A100, 40 GB), extraer entidades de las 740 notas lleva menos de un minuto; mientras que en la CPU puede tardar entre 3 y 5 minutos.

✨Insights: El uso de aggregation_strategy = "average" evita artefactos de palabras (p. ej., “echin” y “##ococcosis”), lo que garantiza que las entidades estén limpias.

Deduplicación de entidades

La producción de NER sin procesar es confusa por naturaleza: variaciones ortográficas, variantes morfológicas y casi duplicados ocurren con frecuencia (por ejemplo, fiebre, febrícula, fiebres).

Para abordar este problema, apliqué un algoritmo de coincidencia difusa global para deduplicar las entidades extraídas agrupando cadenas similares utilizando la similitud Indel normalizada de RapidFuzz (fuzz.ratio). Dentro de cada grupo, selecciona un nombre canónico, agrega puntuaciones de confianza, cuenta las menciones fusionadas y los pacientes únicos, y devuelve una lista limpia de entidades patológicas únicas. Esto produce un conjunto limpio de enfermedades que es adecuado para la construcción de gráficos de conocimiento.

Resumen del canal de PNL

El pipeline consta de los siguientes pasos:

Carga de datos: cargue el conjunto de datos y suelte registros con notas vacías. Extracción de entidades: aplique el modelo NER a cada nota y recopile menciones de enfermedades. Deduplicación: agrupe entidades similares mediante coincidencias difusas y seleccione formas canónicas. Mapeo canónico: a cada entidad (texto) extraída se le asigna la forma más frecuente como texto_canónico. Asignación de ID de entidad: genere identificadores únicos para cada entidad deduplicada. Generador de relaciones: construye las relaciones que conectan cada id_paciente con las enfermedades canónicas extraídas de su nota_clínica. Exportación CSV: exporta tres archivos limpios para importar Neo4j.

Con estos aportes estructurados producidos, ahora podemos construir el gráfico de conocimiento de Neo4j, detectar comunidades de pacientes y aplicar la teoría del gráfico espectral.

El gráfico de conocimiento

Construcción de gráficos en Neo4j

Construí un gráfico de conocimiento bipartito con dos tipos de nodos, Paciente y Enfermedad, conectados por relaciones HAS_DISEASE. Este esquema simple es suficiente para explorar las similitudes de los pacientes y extraer información de las comunidades.

Figura 1. Esquema del gráfico paciente-enfermedad (creado por el autor).

Utilicé Neo4j Desktop (versión 2025.10.1), que ofrece acceso completo a todas las funciones de Neo4j y es ideal para gráficos de tamaño pequeño y mediano. También necesitaremos instalar el complemento Graph Data Science (GDS), que proporciona los algoritmos utilizados más adelante en este análisis.

Para mantener esta sección enfocada, moví el esquema de creación de gráficos al repositorio Github del proyecto. El proceso lleva menos de 5 minutos utilizando el importador visual de Neo4j Desktop.

Consultar el gráfico de conocimiento

Todas las consultas de gráficos utilizadas en este proyecto se pueden ejecutar directamente en Neo4j Desktop o desde una computadora portátil Jupyter. Para mayor comodidad, el repositorio incluye un cuaderno KG_Analysis.ipynb listo para ejecutar con una clase auxiliar Neo4jConnection que simplifica el envío de consultas Cypher a Neo4j y la recuperación de resultados como DataFrames.

Análisis de gráficos e información

El gráfico de conocimiento incluye 739 nodos de pacientes y 1119 nodos de enfermedad, conectados a través de 6400 relaciones. La siguiente instantánea, que muestra un subconjunto de 5 pacientes y algunas de sus afecciones, ilustra la estructura del gráfico:

Figura 2. Subgráfico de ejemplo que muestra cinco pacientes y sus enfermedades (creado por el autor).

Al examinar la distribución de grados (rango) (el número de relaciones de enfermedades por paciente) encontramos un promedio de casi 9 enfermedades por paciente, que van desde 2 hasta 15. El panel izquierdo muestra la morbilidad, es decir, la distribución de enfermedades por paciente. Para comprender el panorama clínico, el panel derecho destaca las diez enfermedades más comunes. Existe una prevalencia de afecciones cardiopulmonares, lo que indica la presencia de grandes grupos centrados en complicaciones cardíacas y pulmonares.

Figura 3. Análisis de gráficos básicos (creado por el autor).

Estos análisis básicos ofrecen una idea de la estructura del gráfico. A continuación, profundizamos en su topología, identificando sus componentes conectados y analizando comunidades de pacientes y enfermedades.

Detección comunitaria

Componentes conectados

Comenzamos analizando la conectividad general de nuestro gráfico utilizando el algoritmo de componentes débilmente conectados (WCC) en Neo4j. El WCC detecta si dos nodos están conectados a través de un camino, independientemente de la dirección de los bordes que componen el camino.

Primero creamos una proyección gráfica con relaciones no dirigidas y luego aplicamos el algoritmo en modo estadístico para resumir la estructura de los componentes.

project_graph = ''' CALL gds.graph.project( 'paciente-enfermedad-graph', ['Paciente', 'Enfermedad'], {HAS_DISEASE: {orientación: 'UNDIRECTED'}} ) RENDIMIENTO GraphName, NodeCount, RelationshipCount RETURN GraphName, NodeCount, RelationshipCount ''' conn.query(project_graph) wcc_stats = ''' CALL gds.wcc.stats('paciente-enfermedad-gráfico') RENDIMIENTO número de componentes, distribución de componentes RETORNO número de componentes, distribución de componentes ''' conn.query_to_df(wcc_stats)

El conjunto de datos sintéticos utilizado aquí produce un gráfico conectado. Aunque nuestro gráfico contiene un solo componente, asignamos a cada nodo un ID de componente para que esté completo y sea compatible con el caso general.

✨Insights: utilizando el algoritmo allShortestPaths, encontramos que el diámetro de nuestro gráfico conectado es 10. Dado que se trata de un gráfico bipartito (pacientes conectados a través de enfermedades compartidas), la separación máxima entre dos pacientes cualesquiera es 4 pacientes adicionales.

Algoritmos de detección comunitaria

Entre los algoritmos de detección de comunidades disponibles en Neo4j que no requieren información previa sobre las comunidades, nos limitamos a Louvain, Leiden y Label Propagation. Leiden (ver referencia[3]), un algoritmo de detección jerárquico, aborda problemas de desconexión en algunas de las comunidades detectadas por Louvain y es una opción superior. La propagación de etiquetas, un algoritmo basado en difusión, también podría ser una opción razonable; sin embargo, tiende a producir comunidades con menor modularidad que Leiden y es menos robusta entre diferentes ejecuciones (ver referencia[2]). Por estos motivos utilizamos Leiden.

Luego evaluamos la calidad de las comunidades detectadas utilizando:

La modularidad es una métrica para evaluar la calidad de las comunidades formadas por algoritmos de detección de comunidades, generalmente basados ​​en heurísticas. Su valor oscila entre −0,5 y 1, y los valores más altos indican estructuras comunitarias más fuertes (ver referencia[2]). La conductancia es la relación entre las relaciones que apuntan fuera de una comunidad y el número total de relaciones de la comunidad. Cuanto menor es la conductancia, más separada está una comunidad.

Detectar comunidades con el algoritmo de Leiden

Antes de aplicar el algoritmo de detección de comunidades, creamos una proyección gráfica con relaciones no dirigidas denominadas bigComponentGraph.

Para identificar grupos de pacientes que comparten patrones de enfermedad similares, ejecutamos Leiden en modo de escritura, asignando a cada nodo un communityId. Esto nos permite conservar las etiquetas de la comunidad directamente en la base de datos de Neo4j para su posterior exploración. Para garantizar la reproducibilidad, establecemos una semilla aleatoria fija y recopilamos algunas estadísticas clave (se calculan más estadísticas en el cuaderno asociado). Sin embargo, incluso con una semilla fija, la naturaleza estocástica del algoritmo puede provocar ligeras variaciones en los resultados entre ejecuciones.

leiden_write = ''' CALL gds.leiden.write('largeComponentGraph', { writeProperty: 'communityId', randomSeed: 16 }) RENDIMIENTO communityCount, modularidad, modularidades RETURN communityCount, modularidad, modularidades ''' conn.query_to_df(leiden_write)

Resultados de Leiden

El algoritmo de Leiden identificó 13 comunidades con una modularidad de 0,53. Al inspeccionar la lista de modularidades de los registros del algoritmo, vemos que Leiden realizó cuatro iteraciones de optimización, comenzando con una modularidad inicial de 0,48 y mejorando gradualmente con cada paso (la lista completa de valores se puede encontrar en el cuaderno).

✨Insights: Una modularidad de 0,53 indica que las comunidades están moderadamente bien formadas, lo que se espera en este escenario, donde los pacientes suelen compartir las mismas condiciones.

En la siguiente visualización combinada se proporciona un resumen visual de las comunidades de Leiden:

Figura 4. Descripción general de las comunidades de Leiden (creada por el autor).

Evaluación de conductancia

Para evaluar qué tan cohesivas internamente son las comunidades de Leiden, calculamos la conductancia, que se implementa en Neo4j GDS. Una conductancia más baja indica comunidades con menos conexiones externas.

Los valores de conductancia en las comunidades de Leiden oscilan entre 0,12 y 0,44:

Grupos muy cohesivos: 0,12-0,20 Grupos moderadamente cohesivos: 0,24-0,29 Comunidades vagamente definidas: 0,35-0,44

Esta dispersión sugiere una variabilidad estructural entre las comunidades detectadas, algunas con muy pocas conexiones externas mientras que otras tienen casi la mitad de sus conexiones apuntando hacia afuera.

Interpretando el paisaje comunitario

En general, los resultados de Leiden indican una topología comunitaria heterogénea e interesante, con unas pocas comunidades grandes de pacientes que comparten patrones clínicos comunes, varias comunidades de tamaño mediano y un conjunto de comunidades más pequeñas que representan combinaciones más específicas de condiciones.

Figura 5. Comunidad 19 de Leiden: un grupo centrado en el habla y la neurología (creado por el autor).

Por ejemplo, communityId = 19 contiene solo 9 nodos (2 nodos de pacientes y 7 enfermedades) y se basa en dificultades del habla y afecciones neurológicas episódicas. La puntuación de conductancia de la comunidad de 0,41 la sitúa entre las comunidades más conectadas externamente.

✨Insights: Las dos métricas que acabamos de analizar, modularidad y conductancia, brindan dos perspectivas diferentes: la modularidad es un indicador de la presencia de una comunidad, mientras que la conductancia evalúa qué tan bien está separada una comunidad de las demás.

Análisis espectral

En teoría de grafos, la conectividad algebraica nos dice más que solo si un grafo es conexo; revela lo difícil que es romperlo. Antes de profundizar en los resultados, recordemos algunos conceptos matemáticos clave que ayudan a cuantificar qué tan bien se mantiene un gráfico. La conectividad algebraica y sus propiedades fueron analizadas en detalle en referencias.[4]y[5].

Conectividad algebraica y el vector de Fiedler

Introducción a los antecedentes y las matemáticas

Sea G = (V, E) un gráfico finito no dirigido sin bucles ni aristas múltiples. Dado un orden de los vértices w1, … wn, el gráfico laplaciano es la matriz nxn L(G) = [Lij] definida por

[displaystyle {rm L}_{ij} = begin{cases} -1 & {rm si } ; ({rm w}_i, {rm w}_j) in {rm E} ; {rm y} ; {rm i} ne {rm j}\ 0 & {rm si } ; ({rm w}_i, {rm w}_j) notin {rm E} ; {rm y} ; {rm i} ne {rm j} \ {rm deg}({rm w}_i) & {rm si} ; {rm i} = {rm j}end{casos}]

donde deg(wi) representa el grado del vértice wi.

El gráfico laplaciano también se puede expresar como la diferencia L = D – A de dos matrices más simples:

Matriz de grados D: una matriz diagonal con Dii = grados (wi). Matriz de adyacencia A – con Aij = 1 si wi y wj están conectados, y 0 en caso contrario.

💡Nota: Las dos definiciones anteriores son equivalentes.

Valores propios y conectividad algebraica

Para un gráfico con n vértices (donde n es al menos 2), ordenemos los valores propios de su Laplaciano L(G) como

[0 = lambda_1 le lambda_2 = {rm a(G)} le lambda_3 ldots le lambda_n]

La conectividad algebraica a(G) se define como el segundo valor propio laplaciano más pequeño.

El espectro laplaciano revela propiedades estructurales clave del gráfico:
– Valores propios cero: el número de valores propios cero es igual al número de componentes conectados del gráfico.
– Prueba de conectividad: a(G) > 0 significa que el gráfico está conectado, a(G)= 0 si y sólo si el gráfico está desconectado.
– Robustez: valores más grandes de a(G) corresponden a gráficos que están más estrechamente conectados; se requieren más remociones de bordes para desconectarlos.
– Gráfico completo: Para un gráfico completo Kn, la conectividad algebraica es máxima: a(Kn) = n.

El vector de Fiedler

El vector propio asociado con la conectividad algebraica a(G) se conoce como vector de Fiedler. Tiene un componente para cada vértice del gráfico. Los signos de estos componentes, positivos o negativos, dividen naturalmente los vértices en dos grupos, creando una división que minimiza el número de aristas que los conectan. En esencia, el vector de Fiedler revela cómo se dividiría el gráfico si lo separara en dos componentes conectados eliminando el menor número de aristas (ver referencia[8], cap. 22). Llamemos a esta separación, para abreviar, bipartición de Fiedler.

💡 Nota: Algunos componentes del vector de Fiedler pueden ser cero, en cuyo caso representan vértices que se encuentran en el límite entre las dos particiones. En la práctica, dichos nodos se asignan a un lado de forma arbitraria.

A continuación, calculamos tanto la conectividad algebraica como el vector de Fiedler directamente a partir de los datos de nuestro gráfico en Neo4j usando Python.

Cálculo de la conectividad algebraica

Actualmente, Neo4j no proporciona una funcionalidad integrada para calcular la conectividad algebraica, por lo que utilizamos las escasas utilidades de álgebra lineal de Python y SciPy para calcular la conectividad algebraica y el vector de Fiedler. Esto se hace mediante la clase FiedlerComputer, que se describe a continuación:

Clase FiedlerComputer 1. Extraer aristas de Neo4j 2. Asigna ID de nodo a índices enteros – Construir asignaciones de nodo a índice y de índice a nodo 3. Construir gráfico disperso Laplaciano – Construir matriz de adyacencia simétrica – Calcular matriz de grados a partir de sumas de filas de A – Forma Laplaciana L = D – A 4. Calcular cantidades espectrales – Modo global: usar todos los bordes paciente-enfermedad – Modo comunitario: bordes dentro de uno Comunidad de Leiden – Utilice `eigsh()` para calcular los k valores propios más pequeños de L – Conectividad algebraica = el segundo valor propio más pequeño – Vector de Fiedler = el vector propio correspondiente a la conectividad algebraica 5. Opcional: escriba los resultados en Neo4j – Almacene `node.fiedlerValue` – Agregue etiquetas FiedlerPositive / FiedlerNegative

La implementación completa se incluye en el cuaderno KG_Analysis.ipynb en GitHub.

Calcular la conectividad algebraica para una comunidad de Leiden de muestra

Ilustramos el proceso utilizando la comunidad de Leiden = 14, que consta de 34 nodos y 38 aristas.

Extraer y validar aristas. El constructor recibe un objeto de conexión Neo4j que ejecuta Cypher y devuelve Pandas DataFrames.

fc = FiedlerComputer(conn) comm_id = 14 bordes_datos = fc.extract_edges(fc.query_extract_edges, parámetros={'comm_id': comm_id})

Cree asignaciones de índice de nodo <–>. Enumeramos todos los ID de nodo únicos y creamos dos diccionarios: node_to_idx (para crear matrices) e idx_to_node (para escribir los resultados).

directo, inverso, n_nodes = fc.create_mappings(edges_data) >>muestra node_to_idx: [('DIS_0276045d', 0), ('DIS_038a3ace', 1)] >>muestra idx_to_node: [(0, 'DIS_0276045d'), (1, 'DIS_038a3ace')] >>número de nodos: 34

Construya la matriz laplaciana del gráfico. Construimos la matriz laplaciana a partir de los datos del gráfico. Para cada arista no dirigida, insertamos dos entradas, una para cada dirección, de modo que la matriz de adyacencia A sea simétrica. Luego creamos una representación matricial dispersa (csr_matrix), que ahorra memoria para gráficos grandes y dispersos. La matriz de grados D es diagonal y se calcula mediante sumas de filas de la matriz de adyacencia.

laplacian_matrix = fc.build_matrices(edges_data, direct, n_nodes) >>Forma de la matriz laplaciana: (34, 34)

Calcule la conectividad algebraica y el vector de Fiedler. Usamos scipy.sparse.linalg.eigsh para calcular los pocos valores propios y pares de vectores propios más pequeños del laplaciano (hasta k = 4 para mayor eficiencia).

lambda_global, vector_global = fc.compute(mode="global") >>Global λ₂ = 0.1102 >>Rango de vectores de Fiedler: [-0.4431, 0.0081]

Para calcular la conectividad algebraica y el vector de Fiedler asociado para todas las comunidades de Leiden:

resultados = fc.compute_all_communities().sort_values('lambda_2', ascendente=False)

Dado que el número de comunidades es pequeño podemos reproducir todos los resultados en la siguiente tabla. Para completar, también se incluye la conductancia calculada en la sección anterior:

Figura 6. Valores de conductancia y conectividad algebraica para todas las comunidades de Leiden (creado por el autor).

Los valores de conectividad algebraica varían entre 0,03 y 1,00 en las comunidades de Leiden. Las pocas comunidades con a(G) = 1 corresponden a estructuras pequeñas y estrechamente conectadas, típicamente un solo paciente vinculado a varias enfermedades.

En el otro extremo del espectro, las comunidades con a(G) muy bajo (0,03 – 0,07) están poco conectadas y a menudo mezclan patrones de morbilidad múltiple o condiciones heterogéneas.

✨Insights: La conectividad algebraica es una medida de coherencia interna.

Etiquetado de la bipartición espectral en Neo4j

Finalmente, podemos volver a escribir los resultados en Neo4j, etiquetando cada nodo según el signo de su componente vectorial de Fiedler.

fc.label_bipartition(vector_comm, inverse) >>Se agregaron etiquetas de Fiedler a 34 nodos >>Nodos positivos: 22 >>Nodos negativos: 12

Podemos visualizar esta bipartición directamente en Neo4j Explorer/Bloom.

Figura 7. Bipartición de Fiedler de la Comunidad 14 (creada por el autor).

En la visualización, los 12 nodos con componentes Fiedler negativos aparecen en colores más claros, mientras que los nodos restantes, con componentes Fiedler positivos, se muestran en tonos más oscuros.

Interpretando la comunidad 14 usando el vector de Fiedler

La comunidad 14 contiene 34 nodos (6 pacientes, 28 enfermedades) conectados por 38 bordes. Su conductancia de 0,27 sugiere un grupo razonablemente bien formado, pero la conectividad algebraica de a(G) = 0,05 indica que la comunidad se puede dividir fácilmente.

Al calcular el vector de Fiedler (un vector de 34 dimensiones con un componente por nodo) y examinar la bipartición de Fiedler, observamos dos subgrupos conectados (como se muestra en la imagen anterior), que contienen 2 pacientes con valores de Fiedler negativos y 4 pacientes con valores de Fiedler positivos.

Además, es interesante observar que las enfermedades del lado positivo consisten predominantemente en trastornos otorrinolaringológicos, mientras que en el lado negativo se encuentran afecciones neurológicas e infecciosas.

Comentarios finales

Discusión e implicaciones

Los resultados de este análisis muestran que los algoritmos de detección comunitaria por sí solos rara vez capturan la estructura interna de los grupos de pacientes. Dos comunidades pueden compartir temas similares pero diferir completamente en cómo sus condiciones se relacionan entre sí. El análisis espectral hace explícita esta distinción.

Por ejemplo, las comunidades con una conectividad algebraica muy alta (a(G) cercana a 1) a menudo se reducen a estructuras en estrella simples, con un paciente conectado a varias condiciones. Estos son estructuralmente simples pero clínicamente coherentes. Las comunidades de conectividad de rango medio tienden a comportarse como grupos estables y bien formados con síntomas compartidos. Finalmente, las comunidades con menor conectividad revelan grupos heterogéneos que consisten en grupos de morbilidad múltiple o pacientes cuyas condiciones se superponen sólo parcialmente.

Lo más importante es que este trabajo responde afirmativamente a la pregunta rectora de la investigación: ¿Podemos superponer algoritmos de gráficos con métodos espectrales para revelar una estructura clínicamente significativa que la agrupación tradicional no puede?

El objetivo no es reemplazar los algoritmos de detección de comunidades, sino complementarlos con conocimientos matemáticos de la teoría de gráficos espectrales, lo que nos permitirá refinar nuestra comprensión de las agrupaciones clínicas.

Direcciones futuras y escalabilidad

Las preguntas naturales que surgen se refieren a hasta qué punto estas técnicas se pueden aplicar en el mundo real o en entornos de producción. Aunque estos métodos pueden, en principio, usarse en producción, los veo principalmente como herramientas refinadas para el descubrimiento de características, el enriquecimiento de datos, el análisis exploratorio y el descubrimiento de patrones que de otro modo permanecerían ocultos.

Los desafíos clave a escala incluyen:

Manejo de la escasez y el tamaño: Se necesitarían cálculos laplacianos eficientes o métodos de aproximación (por ejemplo, solucionadores propios aleatorios) para el análisis a escala real. Consideraciones de complejidad: los cálculos de valores propios son más costosos que los algoritmos de detección comunitaria. Aplicar múltiples capas de detección de comunidades para reducir los tamaños de los gráficos para los que calculamos el laplaciano es un enfoque práctico que podría ayudar.

Las direcciones prometedoras para la expansión incluyen:

Ampliar la capa de entidad: agregar medicamentos, laboratorios y procedimientos crearía un gráfico más rico y comunidades clínicamente más realistas. Incluir metadatos aumentaría el nivel de información, pero también aumentaría la complejidad y dificultaría la interpretación. Gráficos incrementales y en tiempo real: los conjuntos de datos de pacientes reales no son estáticos. El trabajo futuro podría incorporar la transmisión de actualizaciones laplacianas o métodos espectrales dinámicos para rastrear cómo evolucionan las comunidades con el tiempo.

Conclusión

Este proyecto muestra que combinar la detección comunitaria con el análisis espectral ofrece una forma práctica e interpretable de estudiar poblaciones de pacientes.

Si desea experimentar con este flujo de trabajo:

probar diferentes modelos NER, cambiar el tipo de entidad (por ejemplo, usar síntomas en lugar de enfermedades), experimentar con el parámetro de resolución de Leiden, explorar otros algoritmos de detección comunitaria; una buena alternativa es la propagación de etiquetas, aplicar el proceso para abrir corpus clínicos o simplemente utilizar un dominio o industria completamente diferente.

Comprender cómo se forman las comunidades de pacientes y qué tan estables son puede respaldar aplicaciones posteriores, como el resumen clínico, el descubrimiento de cohortes y los sistemas GraphRAG. Los métodos espectrales proporcionan un conjunto de herramientas transparentes y con base matemática para explorar esas preguntas, y este blog demuestra una manera de comenzar a hacerlo.

Referencias

M. Panahi, OpenMed NER: Transformadores de última generación de código abierto y adaptados al dominio para NER biomédico en 12 conjuntos de datos públicos (2025), https://arxiv.org/abs/2508.01630. S. Sahu, Detección de comunidades con eficiencia de memoria en gráficos grandes mediante bocetos ponderados (2025), https://arxiv.org/abs/2411.02268. VA Traag, L. Waltman, NJ van Eck, De Lovaina a Leiden: garantizar comunidades bien conectadas (2019), https://arxiv.org/pdf/1810.08473. M. Fiedler, Conectividad algebraica de gráficos (1973), Matemáticas checoslovacas. J. (23) 298–305. https://snap.stanford.edu/class/cs224w-readings/fiedler73connectivity.pdf M. Fiedler, Una propiedad de los vectores propios de matrices simétricas no negativas y su aplicación a la teoría de grafos (1975), Matemáticas checoslovacas. J. (25) 607–618. https://eudml.org/doc/12900 NMM de Abreu, Resultados antiguos y nuevos sobre conectividad algebraica de gráficos (2007), Linear Algebra Appl. (423) 53–73. https://www.math.ucdavis.edu/~saito/data/graphlap/deabreu-algconn.pdf JC Urschel, LT Zikatanov, Bisección espectral de gráficos y conectividad (2014), Linear Algebra Appl. (449) 1–16. https://math.mit.edu/~urschel/publications/p2014.pdf SR Bennett, Álgebra lineal para ciencia de datos (2021) Sitio web del libro