Volver al catálogo
Season 19 22 Episodios 1h 37m 2026

Python Cheminformatics & AI

Edición 2026. Un curso práctico que lleva a los desarrolladores de Python desde los conceptos básicos de química hasta el diseño de sistemas de quimioinformática impulsados por IA. Aprende a utilizar RDKit, scikit-fingerprints y técnicas de deep learning de vanguardia como Graph Neural Networks y Diffusion Models para el descubrimiento de fármacos.

Computación científica Quimioinformática Deep Learning para ciencia
Python Cheminformatics & AI
Reproduciendo ahora
Click play to start
0:00
0:00
1
La molécula digital
Presentamos RDKit y el concepto central de representar la química en Python. Los oyentes aprenderán a inicializar objetos moleculares a partir de cadenas de texto y comprenderán el papel central del framework en el descubrimiento de fármacos con IA.
4m 19s
2
I/O en quimioinformática
Aprende a ingerir y exportar de forma segura datasets químicos masivos. Cubrimos la lectura de archivos SDF y SMILES, el manejo de errores de análisis y la escritura de datos en el disco.
4m 25s
3
Recorrido de grafos moleculares
Descubre cómo se representan las moléculas como estructuras de datos de grafos. Exploramos la iteración sobre átomos, el análisis de enlaces y la identificación de sistemas de anillos dentro de las moléculas.
3m 51s
4
Búsqueda de subestructuras
Domina el arte de consultar moléculas utilizando SMARTS. Repasamos cómo encontrar grupos funcionales y patrones específicos dentro de estructuras químicas complejas.
4m 39s
5
Fingerprinting y similitud molecular
Explora cómo traducir grafos moleculares en vectores de bits matemáticos. Cubrimos las claves MACCS, los Morgan fingerprints y el cálculo de la similitud de Tanimoto.
4m 22s
6
Rompiendo el plano 2D
Pasa de dibujos planos en 2D a geometrías realistas en 3D. Hablamos sobre la adición de hidrógenos explícitos y la generación de confórmeros 3D fiables utilizando ETKDG.
4m 57s
7
Acelerando el Feature Engineering
Conecta la quimioinformática y la ciencia de datos estándar con scikit-fingerprints. Exploramos la generación de más de 30 tipos de fingerprints moleculares directamente dentro de una interfaz de scikit-learn.
4m 54s
8
Quimioinformática de alto rendimiento
Aprende a procesar datasets químicos masivos de manera eficiente. Profundizamos en el uso del paralelismo de CPU con Joblib y en el ahorro de memoria utilizando sparse matrices de SciPy.
5m 12s
9
Pipelines de ML End-to-End
Combina el procesamiento, el fingerprinting y la predicción en una única arquitectura limpia. Construimos pipelines de scikit-learn robustos que integran a la perfección la generación de confórmeros 3D y la predicción de propiedades.
4m 25s
10
Predicción de la afinidad de unión
Explora la realidad de la predicción de la afinidad de unión proteína-ligando. Comparamos el rendimiento de modelos simples basados en árboles en 2D frente a las complejas Graph Neural Networks en 3D.
4m 39s
11
LLMs vs Fingerprints clásicos
Descubre cómo se aplica el NLP a la química. Enfrentamos los vector embeddings de los Large Language Models contra los fingerprints estructurales clásicos de RDKit para predecir la bioactividad.
4m 54s
12
Active Learning para el cribado virtual
Aprende a descubrir iterativamente los mejores candidatos a fármacos sin realizar pruebas exhaustivas. Profundizamos en los bucles de Active Learning y las estrategias de greedy selection para maximizar las tasas de éxito.
4m 47s
13
El desafío del Activity Cliff
Examina la fragilidad de las relaciones estructura-actividad. Hablamos de los 'activity cliffs', donde un pequeño cambio estructural provoca un cambio masivo en la potencia de un fármaco.
3m 52s
14
Similarity-Quantized Relative Learning
Resuelve el problema del activity cliff replanteando cómo aprenden los modelos. Exploramos el framework SQRL, que entrena a la IA para predecir diferencias de propiedades relativas entre pares moleculares estrictamente filtrados.
3m 53s
15
La revolución de la Generative AI
Pasa de predecir propiedades a imaginar moléculas completamente nuevas. Trazamos el panorama de las tareas generativas moleculares: generación De Novo, optimización y generación de confórmeros.
3m 58s
16
La intuición de la difusión molecular
Desglosamos el concepto central de los Diffusion Models sin matemáticas pesadas. Los oyentes comprenderán el proceso hacia adelante (forward process) de añadir ruido a una molécula y el proceso inverso (reverse process) de alucinar nuevas estructuras.
4m 24s
17
Conectando los espacios generativos 2D y 3D
Exploramos cómo la IA representa realmente las moléculas que genera. Comparamos la generación de grafos topológicos planos en 2D con la generación de nubes de puntos geométricas complejas en 3D, y los desafíos de cada uno.
4m 28s
18
Generación Target-Aware y Docking
Descubre el diseño generativo context-aware. Hablamos sobre la generación de moléculas novedosas directamente dentro del bolsillo de unión (binding pocket) de una proteína patológica para maximizar la afinidad de unión.
4m 06s
19
La trampa del tamaño en la evaluación generativa
Aprende por qué los benchmarks estándar para modelos generativos pueden ser profundamente defectuosos. Revelamos el efecto de confusión del tamaño de la biblioteca generada en métricas como la Fréchet ChemNet Distance.
4m 34s
20
Navegando por las alucinaciones De Novo
Clasifica las moléculas generadas por IA de forma inteligente. Exploramos el equilibrio entre exploración y explotación (exploration-exploitation tradeoff) de las probabilidades del modelo, y cómo filtrar las 'alucinaciones químicas' frecuentes y de baja calidad.
4m 03s
21
Restricciones en el sampling de moléculas
Comprende por qué las técnicas de NLP fallan en la química. Comparamos el Temperature sampling con Top-k y Top-p, y por qué el vocabulario químico restringido lo cambia todo.
4m 28s
22
Desplegando quimioinformática en la nube
Lleva tu pipeline de IA a producción. Hablamos sobre el empaquetado de RDKit y modelos de machine learning en contenedores Docker y el escalado de cargas de trabajo en la infraestructura de la nube.
4m 09s

Episodios

1

La molécula digital

4m 19s

Presentamos RDKit y el concepto central de representar la química en Python. Los oyentes aprenderán a inicializar objetos moleculares a partir de cadenas de texto y comprenderán el papel central del framework en el descubrimiento de fármacos con IA.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 1 de 22. Antes de poder predecir la toxicidad de un fármaco con un modelo de machine learning, tienes que resolver un problema fundamental. Necesitas una forma de enseñarle a Python qué es realmente una molécula. Los tipos de datos estándar, como los strings y las listas, no entienden de átomos, enlaces ni estructuras de anillos. Para salvar esa brecha, necesitas un traductor universal entre la química y el código. Eso es exactamente lo que ofrece RDKit, introduciendo el concepto de la molécula digital. RDKit es el toolkit de quimioinformática open-source estándar de la industria. En el fondo, es una librería de C++ de alto rendimiento, pero expone una interfaz de Python enorme e intuitiva. Existe porque representar estructuras químicas computacionalmente es sorprendentemente difícil. Matemáticamente, una molécula es un grafo. Los átomos son nodos, y los enlaces químicos son aristas que conectan esos nodos. Si intentas construir un parser de grafos custom desde cero cada vez que quieras analizar datos químicos, te pasarás todo el tiempo haciendo debugging de edge cases. RDKit abstrae esa complejidad, gestionando la lógica del grafo por debajo. Para meter una molécula en Python, primero necesitas una representación en texto de su estructura. El formato más común es un string SMILES. SMILES usa caracteres estándar para representar la conectividad química. Por ejemplo, un átomo de carbono aislado es simplemente una C mayúscula. El benceno, que es un anillo de seis carbonos con enlaces dobles alternos, se escribe como una c minúscula, el número uno, cuatro caracteres c minúscula más, y una c minúscula final seguida de un número uno para cerrar el anillo. Aquí está la clave. Ese string SMILES es simplemente texto plano. Para Python, es indistinguible de una contraseña o de un path de archivo. No puedes calcular el peso molecular a partir de un raw string. Para hacer química de verdad, debes convertirlo en un objeto molécula de RDKit. Esto lo manejas importando el módulo Chem de RDKit. Luego, llamas a una función específica diseñada para crear una molécula a partir de un string SMILES, y le pasas tu variable de texto. Cuando le pasas el string SMILES del benceno a esta función, RDKit hace el trabajo pesado. Parsea el texto, construye el grafo de nodos y aristas, asigna los órdenes de enlace y valida reglas químicas básicas como las valencias atómicas. Si el string representa una molécula válida, la función devuelve un objeto molécula. Si le pasas una estructura químicamente imposible o un typo, la función falla de forma segura. Imprime un warning en tu consola y devuelve un objeto null. Por esto, siempre deberías comprobar si tu objeto molécula realmente existe antes de pasarlo al siguiente paso de tu programa. Una vez que tienes ese objeto molécula validado en memoria, se desbloquea todo el ecosistema de RDKit. Ya no estás trabajando con texto; estás trabajando con un grafo químico computable. La conclusión esencial aquí es que los strings SMILES son estrictamente para almacenamiento y transferencia de datos, pero los objetos molécula de RDKit son para computación. Todo lo que haces en química computacional empieza haciendo esa conversión. Si quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon; nos ayuda muchísimo. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue construyendo!
2

I/O en quimioinformática

4m 25s

Aprende a ingerir y exportar de forma segura datasets químicos masivos. Cubrimos la lectura de archivos SDF y SMILES, el manejo de errores de análisis y la escritura de datos en el disco.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 2 de 22. Una sola coordenada que falte en un dataset de un millón de moléculas puede hacer crashear todo tu pipeline. Si asumes que cada registro de texto en el fichero de tu proveedor es química perfectamente formateada, tu script de Python acabará lanzando una exception fatal a mitad de un trabajo de diez horas. Defenderse de los datos sucios al mover estructuras dentro y fuera de tus scripts es obligatorio, y eso es exactamente lo que resolvemos hoy con el I/O en Quimioinformática. Cuando recibes un structure-data file estándar, o SDF, lleno de posibles ligandos, necesitas una forma de parsearlo. En RDKit, la herramienta por defecto para esto es el SD molecule supplier. Lo inicializas pasándole la ruta del fichero como un string. Este objeto supplier actúa de forma muy parecida a una list de Python. Puedes iterar sobre él en un loop, puedes pedirle su longitud total, y puedes sacar un registro específico por su número de index. Lo hace escaneando el fichero rápidamente para encontrar dónde empieza cada molécula, permitiéndote saltar de un lado a otro por los datos. A veces no puedes escanear por adelantado. Si estás pasando datos directamente desde un web stream, o leyendo un fichero gzipped enorme chunk a chunk, no tienes random access. Para estas situaciones, usas el forward SD molecule supplier. En lugar de una ruta de fichero, le pasas un file object abierto. Este forward supplier es un iterator estricto. Lee una molécula, la parsea, e inmediatamente pasa a la siguiente. No puedes pedirle su longitud, y no puedes pedir la molécula número cincuenta sin haber leído las primeras cuarenta y nueve. Cambias flexibilidad por un bajo uso de memoria y compatibilidad con el stream. Aquí está la clave. Independientemente del supplier que uses, RDKit no lanza una exception de Python cuando encuentra una molécula corrupta. Si un bloque de texto en tu fichero tiene una valencia inválida o un error de formato, RDKit sacará un mensaje de error por la consola, pero el objeto de Python real que devuelve para esa iteración del loop será simplemente el tipo None. Si coges ese objeto None e intentas calcular su peso o escribirlo en un fichero nuevo, tu script crasheará. Gestionar esto es sencillo pero crítico. La primerísima línea dentro de tu loop de parseo siempre debe comprobar si la molécula devuelta es None. Si es None, usas el statement continue para saltar al siguiente registro. Esto filtra silenciosamente los datos basura y mantiene tu pipeline en ejecución. Una vez que hayas parseado y filtrado de forma segura tus moléculas válidas, normalmente necesitas guardar los resultados. Para esto, usas el SD writer. Inicializas el writer pasándole la ruta del fichero de salida deseado. Dentro de tu loop seguro, justo después de tu check de None, le pasas el objeto de molécula válida al writer usando su método write. Una vez que el loop termina de procesar cada ligando, llamas al método close en el writer para asegurar que todos los datos se vuelquen al disco de forma segura. También puedes envolver el writer en un context manager estándar de Python para que se cierre automáticamente cuando termine el bloque. Para juntar todo esto en un script de limpieza de datos, primero, crea tu SD writer para el fichero de salida. Segundo, crea tu SD molecule supplier para el fichero de entrada. Recorre el supplier en un loop. Comprueba si el elemento actual es None, y si es así, sáltatelo. Si es válido, pásaselo al writer. Cierra el writer al final. Trata siempre los datasets de química externos como inherentemente sucios; verificar que una molécula parseada no sea None es la póliza de seguro más barata que tu código tendrá jamás. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue desarrollando!
3

Recorrido de grafos moleculares

3m 51s

Descubre cómo se representan las moléculas como estructuras de datos de grafos. Exploramos la iteración sobre átomos, el análisis de enlaces y la identificación de sistemas de anillos dentro de las moléculas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 3 de 22. Para un ordenador, una molécula no es un objeto físico que ocupa espacio. Es estrictamente un grafo de nodos y aristas esperando a ser parseado. Si no puedes navegar eficientemente por ese grafo subyacente, no puedes analizar la estructura química. Esto nos lleva directamente al recorrido de grafos moleculares. En RDKit, un objeto molécula actúa como contenedor principal para esta estructura de datos de grafo. Para inspeccionar los nodos, usas el método GetAtoms. Esto devuelve una secuencia iterable que contiene todos los objetos átomo de la molécula. Puedes escribir un simple bucle para recorrer esta secuencia uno a uno. Para un escenario concreto, supón que necesitas extraer los números atómicos de todos tus nodos. Dentro de tu bucle, puedes llamar al método GetIdx para encontrar el identificador numérico único del átomo actual, y al método GetAtomicNum para averiguar exactamente de qué elemento químico se trata. Al iterar, procesas cada nodo sistemáticamente. Los nodos por sí solos no definen la química. También necesitas las aristas que los conectan, a las que accedes usando el método GetBonds. Al igual que con los átomos, esto proporciona una secuencia iterable de objetos enlace. Un enlace conoce su lugar exacto en el grafo. Al llamar a los métodos GetBeginAtomIdx y GetEndAtomIdx en un objeto enlace, extraes los identificadores numéricos específicos de los dos átomos que conecta. También puedes leer el tipo de enlace, determinando si es una conexión simple, doble o aromática. Aquí está la clave. RDKit trata los enlaces como objetos de primera clase en la jerarquía del grafo, lo que significa que los consultas de forma independiente en lugar de extraerlos de las propiedades de los átomos. Navegar por nodos y aristas individuales es lógica estándar de grafos, pero los grafos químicos frecuentemente presentan ciclos, mejor conocidos como anillos. No necesitas escribir tus propios algoritmos de recorrido para encontrar ciclos. RDKit precalcula estos ciclos cuando se instancia la molécula. Accedes a estos datos a través del método GetRingInfo. Esto devuelve un objeto dedicado de información de anillos en lugar de una simple lista. Si tu tarea es simplemente contar el número de anillos en la molécula, llamas al método NumRings directamente sobre este objeto de información de anillos. Cuando necesites detalles estructurales más profundos, puedes pedirle a este mismo objeto la propiedad AtomRings. Esto te da una colección de secuencias, donde cada secuencia contiene los índices exactos de los átomos que forman un anillo específico en el grafo. Incluso puedes pasarle un índice de átomo al objeto de información de anillos para preguntar si ese nodo específico participa en un anillo de un tamaño particular, como un ciclo de cinco o seis miembros. Recorrer una molécula se trata, en última instancia, de encadenar estas operaciones básicas. Obtienes la información de los anillos para comprobar la macroestructura, iteras sobre los átomos para leer datos a nivel de nodo como los números atómicos, e iteras sobre los enlaces para mapear las conexiones específicas de las aristas. Una vez que dejas de ver una molécula como una entidad física y empiezas a verla como una colección predecible de nodos indexados, aristas y ciclos precalculados, extraer propiedades estructurales se convierte en una tarea estándar de parsing de datos. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
4

Búsqueda de subestructuras

4m 39s

Domina el arte de consultar moléculas utilizando SMARTS. Repasamos cómo encontrar grupos funcionales y patrones específicos dentro de estructuras químicas complejas.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 4 de 22. No intentarías parsear miles de logs de texto sin usar expresiones regulares. Del mismo modo, no deberías intentar filtrar bases de datos químicas sin patrones SMARTS. Encontrar grupos funcionales específicos en grandes datasets requiere una lógica estructural dedicada, y eso es precisamente lo que proporciona el Substructure Searching. Supongamos que tienes una librería de fármacos candidatos. Tu objetivo es marcar y aislar cualquier molécula que contenga un grupo funcional tóxico específico y conocido. Primero, defines ese grupo tóxico usando un string SMARTS. SMARTS es una extensión de SMILES diseñada específicamente para hacer queries de patrones moleculares, lo que te permite especificar wildcards, tipos de enlaces específicos o estructuras de anillo. Pasas este string de texto a la función de RDKit que crea una molecule a partir de SMARTS. Esto genera tu objeto query. Tus moléculas objetivo, los fármacos candidatos, ya son objetos molecule estándar de RDKit. Para filtrar la librería, tomas una molécula candidata y llamas al método llamado has substructure match. Pasas tu objeto query a este método. Evalúa la molécula candidata comparándola con el patrón y devuelve un valor boolean simple. True significa que el grupo tóxico existe en algún lugar dentro de la candidata. False significa que está limpia. Dado que este método detiene la búsqueda en el momento en que encuentra un único match válido, está altamente optimizado. Puedes iterar esta comprobación boolean por toda tu librería para dividir rápidamente un dataset masivo en subconjuntos seguros y marcados. Ahora bien, ¿qué sucede si simplemente saber que el grupo tóxico está presente no es suficiente? Quizás la toxicidad aumenta con la cantidad de veces que aparece el grupo, o necesitas aislar la ubicación exacta de los átomos tóxicos para un biólogo estructural. Para esto, usas el método llamado get substructure matches, en plural. Llamas a este método en tu molécula candidata, pasándole de nuevo el objeto query. En lugar de un boolean, este método obliga al motor de búsqueda a mapear cada posible ocurrencia del patrón. Devuelve una tupla que contiene otras tuplas. Cada tupla interna representa un match completo de tu patrón. Los números enteros dentro de estas tuplas son los índices exactos de los átomos dentro de la molécula candidata. Aquí reside la clave. El orden de estos índices refleja a la perfección el orden de los átomos definidos en tu string SMARTS original. Esto significa que siempre sabrás con exactitud qué átomo del objetivo corresponde a cada parte de tu query. Si el grupo tóxico aparece tres veces en el candidato, obtienes tres tuplas internas. Puedes contar las tuplas para determinar la frecuencia del patrón, o pasar esos índices de átomos específicos a una función de dibujo para resaltar visualmente las regiones tóxicas. Si solo necesitas los índices de los átomos del primer match que encuentra, puedes usar el método en singular get substructure match para ahorrar tiempo de procesamiento. También debes tener en cuenta la estereoquímica. Por defecto, el substructure matching de RDKit ignora la quiralidad por completo. Tanto un enlace en cuña como un enlace discontinuo generarán un match para una query SMARTS básica. Si la toxicidad de tu objetivo solo se produce con un estereoisómero específico, este comportamiento por defecto generará falsos positivos en tu análisis de fármacos. Para solucionarlo, pasas un argumento llamado use chirality y lo pones en true al llamar a cualquiera de los métodos de matching. RDKit aplicará entonces las reglas estereoquímicas según la configuración específica definida en tu query. La verdadera potencia del Substructure Searching reside en que mapea una query de texto puramente lógica directamente sobre la topología física de tu dataset, salvando la distancia entre los patrones abstractos de strings y las coordenadas atómicas concretas. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue desarrollando!
5

Fingerprinting y similitud molecular

4m 22s

Explora cómo traducir grafos moleculares en vectores de bits matemáticos. Cubrimos las claves MACCS, los Morgan fingerprints y el cálculo de la similitud de Tanimoto.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 5 de 22. Los modelos de IA no entienden realmente de átomos y enlaces. Solo entienden de números. Si quieres que un algoritmo compare dos estructuras, necesitas una forma de traducir la química a matemáticas. El fingerprinting y la similitud molecular son exactamente la forma de salvar esa brecha. Una molécula en RDKit es esencialmente un grafo matemático. Los átomos actúan como nodos y los enlaces como aristas. Para hacer cálculos rápidos en estos grafos, los convertimos en bit vectors, que son simplemente arrays largos de unos y ceros. Este array se llama fingerprint. La lógica es muy sencilla. Si una característica estructural específica existe en la molécula, un bit específico en el array cambia a uno. Si esa característica no está, el bit se queda en cero. Al convertir grafos moleculares complejos en bit vectors estándar, podemos compararlos fácilmente de forma matemática. RDKit ofrece varios algoritmos de fingerprinting. El fingerprint por defecto de RDKit usa un enfoque topológico. Analiza rutas lineales a través de la molécula. El sistema empieza en un átomo y recorre los enlaces conectados hasta una longitud específica, normalmente entre uno y siete enlaces. Cada ruta única que encuentra se pasa por una función de hashing, que asigna esa ruta a una posición específica en el bit vector. Aunque las rutas topológicas son útiles, la quimioinformática moderna se basa muchísimo en los Morgan fingerprints, a menudo llamados circular fingerprints. En lugar de trazar rutas lineales, los algoritmos de Morgan analizan el vecindario que irradia hacia afuera desde cada átomo. Al generar un Morgan fingerprint, tienes que definir un radio. Un radio de cero significa que el algoritmo solo registra los átomos individuales. Un radio de uno captura cada átomo más sus vecinos conectados inmediatos. Un radio de dos expande ese círculo un enlace más allá. El algoritmo cataloga todos estos entornos circulares superpuestos, les aplica un hash, y cambia los bits correspondientes a uno. Normalmente, plegamos estos hashes en un vector de longitud fija, como dos mil cuarenta y ocho bits, para mantener un uso de memoria predecible. Los Morgan fingerprints con un radio de dos son el estándar de la industria porque capturan a la perfección los grupos funcionales y el contexto químico local. Veamos un escenario concreto. Tienes dos moléculas ligeramente diferentes. Quizás comparten una gran estructura central, pero una tiene un grupo metilo extra unido. Quieres cuantificar cuánto se solapan. Primero, lees ambas moléculas en RDKit. Después, generas un Morgan fingerprint para cada una, configurando el radio a dos. Ahora tienes dos bit vectors distintos. Para calcular cuánto se parecen, calculas su Tanimoto similarity. Aquí está la clave. La Tanimoto similarity ignora los ceros. Solo le importan las características que están realmente presentes. Las matemáticas son simples: intersección sobre unión. RDKit cuenta el número de bits a uno en ambos fingerprints, y lo divide entre el número total de bits a uno en cualquiera de los fingerprints. Si los dos vectores coinciden perfectamente, el Tanimoto score es uno coma cero. Si no comparten ninguna característica en absoluto, el score es cero coma cero. Para nuestras dos moléculas que difieren en un solo grupo metilo, los entornos circulares alrededor del núcleo coincidirán en su mayoría, mientras que los entornos cerca de la mutación serán diferentes. Podrías obtener un Tanimoto score de cero coma ochenta y cinco, dándote un valor numérico preciso de su solapamiento estructural. Ten en cuenta que mapear una molécula compleja a un array fijo de bits significa perder algunos datos, y un Tanimoto score alto garantiza solapamiento estructural, no equivalencia biológica. Gracias por pasar unos minutos conmigo. Hasta la próxima, cuídate.
6

Rompiendo el plano 2D

4m 57s

Pasa de dibujos planos en 2D a geometrías realistas en 3D. Hablamos sobre la adición de hidrógenos explícitos y la generación de confórmeros 3D fiables utilizando ETKDG.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 6 de 22. Un dibujo bidimensional puede quedar genial en una pantalla, pero los fármacos existen en un espacio tridimensional. Si ignoras la geometría, ignoras la realidad. Hoy, vamos a romper el plano 2D y a generar coordenadas 3D adecuadas para tus moléculas. Cuando lees una molécula a partir de un string SMILES estándar, no tiene coordenadas en absoluto. Es estrictamente un grafo topológico de átomos conectados. Incluso si cargas una estructura desde un archivo de dibujo 2D, esas coordenadas solo están espaciadas para facilitar la lectura humana. Para hacer docking, calcular el área superficial o ejecutar simulaciones físicas, necesitas una estructura 3D físicamente realista. El primer paso fundamental antes de generar cualquier geometría 3D es añadir los hidrógenos. En un string SMILES estándar, los hidrógenos son implícitos. Se tratan como una propiedad básica de los átomos pesados, simplemente para rellenar los requisitos de valencia. Pero en el espacio físico, los hidrógenos ocupan un volumen real. Crean impedimento estérico y dictan los ángulos de los enlaces a su alrededor. Si intentas calcular una estructura 3D sin añadir explícitamente los hidrógenos primero, la geometría resultante colapsará sobre sí misma y los ángulos de enlace estarán completamente mal. RDKit proporciona una función llamada AddHs que convierte esos hidrógenos implícitos en nodos reales dentro de tu grafo molecular, con sus enlaces incluidos. Siempre debes ejecutar esta función antes de pasar a 3D. Una vez que tienes una molécula completa, necesitas calcular sus coordenadas espaciales. Como los enlaces simples pueden rotar libremente, un ligando flexible no tiene una única forma estática. Puede adoptar muchas formas diferentes, conocidas como conformaciones. Para generar una conformación viable, RDKit utiliza un método por defecto llamado ETKDG. Esto significa Experimental Torsion-angle Preference with Distance Geometry. Aquí está la clave. Los métodos de generaciones anteriores se basaban totalmente en matemáticas puras. Utilizaban la geometría de distancias para adivinar las posiciones atómicas basándose en longitudes y ángulos de enlace conocidos. Esto a menudo daba lugar a formas raras y de alta energía que requerían una gran limpieza computacional. ETKDG resuelve esto combinando las matemáticas de la geometría de distancias con reglas empíricas derivadas de la Cambridge Structural Database. Sabe cómo prefieren doblarse y retorcerse realmente las moléculas físicas reales, y obliga al algoritmo de geometría a respetar esas preferencias naturales. Pongamos un escenario concreto. Tienes un ligando muy flexible, y necesitas entender todas las diferentes formas en las que podría plegarse para encajar en el binding pocket de una proteína. Generar una sola conformación no es suficiente para capturar ese comportamiento. Necesitas un ensemble. RDKit maneja esto con una función llamada EmbedMultipleConfs. Le pasas tu molécula con sus hidrógenos explícitos, y especificas que quieres cincuenta conformers. RDKit ejecutará entonces el algoritmo ETKDG cincuenta veces por separado, partiendo de diferentes random seeds, para generar cincuenta geometrías 3D distintas. Almacena estas cincuenta formas dentro del objeto de la molécula original. No te devuelve cincuenta moléculas separadas; obtienes una sola molécula que contiene cincuenta conjuntos de coordenadas distintos. Luego, puedes hacer un loop por estos conjuntos de coordenadas para medir distancias o calcular energías. Como ETKDG está fuertemente basado en datos cristalográficos del mundo real, las estructuras iniciales que proporciona suelen ser de muy alta calidad directamente al salir de la función. Una molécula no es un dibujo plano, y rara vez es una única forma rígida; es un objeto dinámico, y hacer un muestreo de sus múltiples conformers te da los verdaderos límites de su comportamiento físico. Si quieres ayudar a que el programa siga adelante, puedes apoyarnos buscando DevStoriesEU en Patreon. Eso es todo por este episodio. ¡Gracias por escuchar, y a seguir programando!
7

Acelerando el Feature Engineering

4m 54s

Conecta la quimioinformática y la ciencia de datos estándar con scikit-fingerprints. Exploramos la generación de más de 30 tipos de fingerprints moleculares directamente dentro de una interfaz de scikit-learn.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 7 de 22. Escribir bucles personalizados de extracción de fingerprints para cada nuevo proyecto es tedioso y propenso a errores. Si cambias de un fingerprint ECFP a una MACCS key, de repente tienes que reescribir todo tu bloque de preprocessing. Scikit-fingerprints es una librería que resuelve esto haciendo que la feature extraction molecular sea tan sencilla como llamar a un transform estándar de scikit-learn. Las moléculas se representan fundamentalmente como grafos. Sin embargo, la mayoría de los algoritmos de machine learning requieren vectores multidimensionales. Los fingerprints moleculares son los algoritmos de feature extraction que salvan esta brecha, codificando la información estructural en arrays numéricos. El problema es que las herramientas open-source estándar para calcular estos fingerprints, como RDKit, Open Babel o el Chemistry Development Kit, están escritas en C++ o Java. Sus wrappers de Python no se integran de forma nativa con la API de scikit-learn. Acabas escribiendo data loaders personalizados, format converters y bucles propensos a errores solo para que tus datos tengan un formato que un clasificador pueda consumir. Scikit-fingerprints cambia esta arquitectura. Implementa más de 30 fingerprints moleculares diferentes como transformers estándar y stateless de scikit-learn. Todas las clases de fingerprints heredan de las clases base de scikit-learn. Esto significa que se integran directamente en los pipelines de machine learning y feature unions estándar. Considera un workflow estándar. Normalmente, escribirías un bucle personalizado de veinte líneas en RDKit para iterar sobre un dataset, validar las moléculas, extraer fingerprints circulares y apilar los resultados en un array. Con esta librería, reemplazas todo ese bloque de boilerplate con un solo paso. Creas un objeto llamado ECFP Fingerprint y lo pasas directamente a un pipeline de scikit-learn justo antes de tu modelo de random forest. Cuando llamas al método fit en tu pipeline con tus training data y variables objetivo, el transformer del fingerprint procesa los inputs y devuelve un array denso de NumPy directamente al modelo. Aquí está la clave. No necesitas convertir tus representaciones de texto en objetos molecule de RDKit antes de pasárselas al transformer. Para cualquier fingerprint bidimensional basado en la topología de un grafo, el método transform acepta directamente una lista estándar de Python de strings SMILES. La librería gestiona la conversión interna automáticamente. Dado que los strings SMILES no siempre son únicos ni químicamente válidos, la librería también proporciona una clase Molecule Standardizer. Esta clase aplica los pasos de sanitization recomendados por RDKit para garantizar la calidad de los datos antes de que empiece la extracción. La librería también admite fingerprints tridimensionales que se basan en la conformación espacial. Estos algoritmos espaciales requieren objetos molecule de RDKit con conformers calculados. Generar conformers puede ser inestable, por lo que el paquete incluye una clase Conformer Generator que utiliza un algoritmo específico conocido como ETKDG versión 3. Esto proporciona defaults fiables que maximizan la eficiencia para moléculas simples y minimizan los errores de cálculo en compuestos complejos. Pones el Conformer Generator al inicio de tu pipeline, lo sigues con un transformer de fingerprints tridimensionales, y terminas con un imputer para gestionar los missing values. Al encapsular la lógica química compleja dentro de clases transformer estándar, la librería abstrae el boilerplate específico del dominio. Configuras opciones como la longitud del vector de output o si quieres una variante binaria o de conteo simplemente pasándole parámetros al constructor del transformer. El resultado es que ajustar los hiperparámetros para los fingerprints moleculares se vuelve tan sencillo como ajustar la profundidad de un decision tree. Eso es todo por hoy. ¡Hasta la próxima!
8

Quimioinformática de alto rendimiento

5m 12s

Aprende a procesar datasets químicos masivos de manera eficiente. Profundizamos en el uso del paralelismo de CPU con Joblib y en el ahorro de memoria utilizando sparse matrices de SciPy.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 8 de 22. Calcular subestructuras complejas en un dataset masivo puede provocar fácilmente errores de out-of-memory en tu máquina, a menos que sepas exactamente cómo gestionar tu huella de datos. La técnica que resuelve esto es la Quimioinformática de Alto Rendimiento. Cuando extraes features de una molécula, a menudo usas fingerprints basados en subestructuras. El fingerprint de Klekota-Roth es un ejemplo clásico. Para calcularlo, tu máquina comprueba una molécula contra miles de patrones químicos predefinidos, conocidos como patrones SMARTS. Escanea el grafo molecular una y otra vez para ver si existen grupos funcionales o motivos estructurales específicos. Hacer esto secuencialmente para unas pocas moléculas está bien. Hacerlo para un dataset de cuatrocientas mil moléculas es un cuello de botella computacional severo. El cálculo de fingerprints moleculares es una tarea embarrassingly parallel. El análisis estructural de una molécula tiene cero dependencias del análisis de la siguiente molécula en tu dataset. Como no comparten estado, puedes calcularlos de forma totalmente simultánea. Para escalar esto de forma efectiva en Python, utilizas Joblib, dependiendo específicamente del executor Loky. Cuando inicias el proceso, el dataset de entrada se divide en chunks que corresponden exactamente a los cores de CPU que tienes disponibles. Si tienes un procesador de 16 cores, tus moléculas de entrada se dividen en 16 batches separados. Cada worker de Python coge un batch y empieza a ejecutar el pattern matching de SMARTS de forma independiente. El obstáculo técnico con el multiprocessing en Python suele ser el coste de mover datos entre los workers y el proceso principal. Loky evita esto usando memory mapping. En lugar de serializar los arrays de los fingerprints finales y enviarlos a través de inter-process communication, los workers escriben directamente en un espacio de memoria compartida. Para fingerprints computacionalmente pesados como Klekota-Roth, distribuir la carga de trabajo entre 16 cores produce un speedup de casi quince veces. Eso soluciona el tiempo de procesamiento. El segundo cuello de botella crítico es la memoria del sistema. Un solo vector de fingerprint de Klekota-Roth es largo. Si procesas cientos de miles de moléculas, generas una matriz de resultados enorme. Por defecto, las librerías numéricas devuelven este resultado como un array denso de NumPy. Cada posición en esa matriz reserva memoria, independientemente de si el valor es un uno o un cero. Los fingerprints químicos son abrumadoramente sparse. Normalmente, solo el uno o el dos por ciento de las features estructurales solicitadas están realmente presentes en una molécula dada. La gran mayoría de tu matriz resultante consiste en ceros. Almacenar esos ceros es lo que provoca los errores de out-of-memory en datasets grandes. La solución es cambiar el formato de salida a una sparse matrix de SciPy, usando específicamente el formato Compressed Sparse Row. Una sparse matrix cambia fundamentalmente cómo se almacenan los datos. En lugar de construir un grid rígido en memoria, solo registra los valores de los elementos que no son cero junto con sus coordenadas de fila y columna. Imagina un escenario del mundo real usando el dataset PCBA, que contiene poco menos de cuatrocientas cuarenta mil moléculas. Ejecutas el cálculo del fingerprint de Klekota-Roth en todo el dataset usando tus 16 cores. La ejecución en paralelo termina de forma eficiente. Si dejas el output como un array denso por defecto, esta única matriz consumirá algo más de dos Gigabytes de RAM. Al indicarle al cálculo que devuelva un sparse array de SciPy en su lugar, ese mismo dataset reduce su huella a tan solo 23 Megabytes. Consigues una reducción de memoria de ochenta y ocho veces sin perder ni un solo dato de información química, y la representación sparse no afecta negativamente a tu tiempo de computación en absoluto. Aquí está la clave. No necesitas un cluster de computación masivo para procesar cientos de miles de moléculas, siempre que dejes de pagar el impuesto de memoria por almacenar ceros y te asegures de que tu paso de datos se salte el overhead de la inter-process communication estándar. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue desarrollando!
9

Pipelines de ML End-to-End

4m 25s

Combina el procesamiento, el fingerprinting y la predicción en una única arquitectura limpia. Construimos pipelines de scikit-learn robustos que integran a la perfección la generación de confórmeros 3D y la predicción de propiedades.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 9 de 22. Un script complejo de cribado virtual 3D solía requerir cientos de líneas de código frágil. Tenías que generar manualmente conformadores, gestionar fallos, calcular múltiples descriptores y unir los arrays antes incluso de tocar un modelo. Ahora, puedes diseñar todo el proceso en una única y elegante definición de pipeline utilizando pipelines de Machine Learning end-to-end. En Machine Learning, un pipeline es una secuencia de pasos de procesamiento de datos y un estimador final agrupados en un único objeto. En quimioinformática, especialmente con datos estructurales 3D, el preprocesamiento es notoriamente fragmentado. Coges los strings SMILES en crudo, calculas coordenadas 3D, ejecutas optimizaciones de force field, extraes features, corriges los missing values y, finalmente, entrenas un clasificador. Hacer esto manualmente implica escribir bucles a medida y estructuras de datos intermedias que se rompen fácilmente y provocan memory leaks. Vamos a ver cómo construir un pipeline completo de scikit-learn que lleva los strings SMILES en crudo directamente a un clasificador Random Forest. El primer paso de la secuencia es la generación de conformadores. Inicializas un generador de conformadores y lo pasas como la primera etapa del pipeline. Lee el input 2D y calcula las estructuras 3D. Puedes configurarlo para optimizar la geometría usando un force field como MMFF94. Paraleliza automáticamente este trabajo pesado en todos los cores de la CPU disponibles. Ahora, la segunda parte de esto es la extracción de features. Para tareas 3D, combinar diferentes descriptores geométricos captura más información molecular. Usas un feature union de scikit-learn para calcular los fingerprints GETAWAY y WHIM simultáneamente. Ambas clases de fingerprints actúan como transformers stateless en el pipeline. Cogen los conformadores 3D del paso anterior, calculan sus respectivos descriptores en paralelo y concatenan los resultados en una única feature matrix ancha. A continuación, tienes que gestionar los fallos de cálculo. Los algoritmos de descriptores 3D a veces fallan al procesar moléculas muy complejas o tensionadas, lo que resulta en missing values en tu matriz. El pipeline gestiona esto sin necesidad de un error handling a medida. Metes un simple imputer justo después del feature union. Si un cálculo de GETAWAY o WHIM devuelve un missing value, el imputer lo detecta y lo reemplaza con la media de esa feature en todo tu dataset. Finalmente, rematas el pipeline con tu modelo predictivo, que en este caso es un clasificador Random Forest. Para diseñar esto en código, llamas a la función make pipeline. Dentro de esa llamada a la función, pasas tu generador de conformadores. A continuación, pasas el feature union que contiene tus fingerprints GETAWAY y WHIM. Después viene el simple imputer y, por último, el clasificador Random Forest. Asignas toda esta secuencia a una única variable. Cuando llamas al método fit en esa variable del pipeline, pasas tus strings SMILES de entrenamiento en crudo y tus target labels. Los strings fluyen secuencialmente a través del generador de conformadores, hacia el feature union para el fingerprinting, a través del imputer para limpiar los datos, y directos al clasificador para el entrenamiento. A la hora de evaluar, llamar al método predict en tus strings SMILES de test fuerza a los nuevos datos a seguir exactamente la misma ruta. Aquí está la clave. El estado y el enrutamiento de datos se gestionan completamente por el objeto pipeline, lo que significa que nunca mantienes arrays densos intermedios en memoria ni escribes data loaders a medida para tus conformadores. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue programando!
10

Predicción de la afinidad de unión

4m 39s

Explora la realidad de la predicción de la afinidad de unión proteína-ligando. Comparamos el rendimiento de modelos simples basados en árboles en 2D frente a las complejas Graph Neural Networks en 3D.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 10 de 22. Conectas una enorme graph neural network tridimensional, pasándole las coordenadas espaciales de cada átomo en el pocket de una proteína. Luego ejecutas un sencillo gradient boosted decision tree que solo mira el esquema bidimensional del fármaco. El benchmark termina, y tu modelo espacial de vanguardia acaba de ser superado por un algoritmo de hace dos décadas. La razón por la que tu red tan pesada falló está en cómo manejamos la predicción de la binding affinity. Predecir la binding affinity es el proceso computacional de estimar con qué fuerza una molécula pequeña, o ligando, se une a una proteína target específica. En el drug discovery, encontrar una molécula que se una fuertemente es el objetivo principal. Para ello, los ingenieros suelen seguir uno de dos caminos. El primero es muy complejo. Usas redes neuronales tridimensionales como GraphNet o TensorNet. Estos modelos ingieren la conformación exacta de unión del complejo proteína-ligando. Utilizan capas de message passing para aprender las distancias espaciales precisas y las features mecánico-cuánticas entre los átomos del fármaco y los átomos del pocket de la proteína. El segundo camino ignora por completo la proteína. Descartas las coordenadas espaciales y usas un modelo bidimensional clásico como XGBoost. El input aquí es simplemente un vector concatenado de fingerprints moleculares. Calculas las features estructurales solo a partir del ligando, transformando esencialmente el dibujo bidimensional del compuesto químico en un array de números, y le pasas eso directamente al modelo tree-based. Para ver cómo se comparan estos enfoques, los investigadores los ejecutan contra test sets estandarizados. Uno de los más reveladores es el benchmark Merck FEP. Este dataset simula un escenario común de virtual screening llamado serie congénere. En una serie congénere, todos los ligandos probados comparten exactamente el mismo scaffold químico central y se unen exactamente al mismo sitio en una única proteína target. Las únicas diferencias entre las moléculas son pequeñas variaciones estructurales, como diferentes ramificaciones químicas unidas al núcleo principal. Aquí está la clave. Al evaluarlos en el dataset de Merck, los modelos tridimensionales pesados lograron un score de correlación de alrededor de cero coma tres. El sencillo modelo bidimensional XGBoost obtuvo un score significativamente mayor, alcanzando cero coma cuatro cinco. El decision tree, computacionalmente barato, superó claramente a las graph neural networks avanzadas. Esto pasa por aquello en lo que los modelos se ven obligados a centrarse. En una serie congénere, la proteína target y el binding pocket no cambian. El modelo tridimensional gasta enormes recursos computacionales mapeando un entorno espacial que permanece estático en cada uno de los test cases. Peor aún, estos modelos son altamente sensibles a pequeñas variaciones en las coordenadas atómicas. Un ligero cambio arbitrario en cómo se coloca un átomo de hidrógeno durante la preparación de los datos introduce noise que distrae a la graph network. El modelo bidimensional triunfa precisamente porque es ciego a la proteína. Al mirar solo las features del ligando, se basa en las únicas variables que realmente cambian de un test al siguiente. El decision tree correlaciona esas variaciones estructurales directas del fármaco con la fuerza de unión final, saltándose por completo el noise del entorno espacial. Los modelos tridimensionales pesados siguen siendo muy valiosos cuando necesitas generalizar a proteínas target completamente diferentes y nunca vistas, donde la geometría del pocket es desconocida. Pero cuando estás optimizando una familia específica de fármacos para un único target conocido, pasarle datos ambientales constantes a una deep network es ineficiente y propenso a errores. La herramienta predictiva más potente suele ser la que filtra el entorno estático y modela únicamente las variables que cambian. Eso es todo por este episodio. ¡Nos vemos en la próxima!
11

LLMs vs Fingerprints clásicos

4m 54s

Descubre cómo se aplica el NLP a la química. Enfrentamos los vector embeddings de los Large Language Models contra los fingerprints estructurales clásicos de RDKit para predecir la bioactividad.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 11 de 22. ¿Y si la mejor manera de describir una molécula a un modelo de machine learning no fuera con una fórmula estructural hecha a mano, sino tratando su string SMILES exactamente igual que una frase en lenguaje natural? Podrías estar gastando valiosos compute cycles generando descriptores químicos complejos, solo para que un modelo de texto te supere. Esa tensión es el núcleo del debate entre los LLMs y los fingerprints clásicos. Al predecir cómo de fuerte se une un ligando a una proteína, tu modelo necesita una descripción matemática del ligando. La ruta tradicional se basa en fingerprints estructurales clásicos calculados por herramientas como RDKit. Pasas una molécula por un algoritmo determinista y recibes un vector estático. Un fingerprint de Morgan cuenta las subestructuras circulares alrededor de los átomos. Las MACCS keys comprueban la molécula contra una lista predefinida de patrones químicos. La limitación de estos fingerprints clásicos es su rigidez. Codifican reglas específicas e inmutables. No puedes hacerles fine-tuning. Si un matiz estructural concreto importa para un binding pocket muy específico, pero el algoritmo de fingerprint no se diseñó explícitamente para capturarlo, esa información se pierde por completo antes incluso de que el modelo predictivo vea los datos. En lugar de hardcodear reglas químicas, podemos usar un Large Language Model químico preentrenado como BioT5, GPT2 o BERT. Estos modelos están preentrenados con millones de strings SMILES. Aprenden la gramática de la química de forma no supervisada. Cuando le pasas un ligando a un LLM, no devuelve una lista fija de grupos funcionales. Devuelve un embedding vectorial rico. Cada carácter o token en ese string SMILES obtiene su propio vector contextual. Para entender la diferencia, fíjate en cómo estas representaciones alimentan a los modelos predictivos. Primero, imagina un modelo XGBoost usando MACCS keys clásicas. Generas el fingerprint MACCS, lo que da como resultado un array binario simple. Le pasas ese vector fijo a XGBoost, que intenta mapear esas features en crudo de presencia o ausencia con la afinidad de unión. En tests de benchmark a través de series congenéricas, esta combinación específica da sistemáticamente el peor rendimiento. Las features hechas a mano son simplemente demasiado toscas. Ahora, cambia esa arquitectura por un embedding de BioT5 pasado a una Transformer head. Primero le pasas el string SMILES en crudo al modelo BioT5. Esto devuelve una secuencia de embeddings por token. Luego pasas esa secuencia a una Transformer head. Aquí está la clave. El Transformer usa un mecanismo de attention. Mira a través de toda la secuencia de embeddings de tokens y aprende dinámicamente qué partes de la molécula importan más para unirse a este target específico. Pondera las features de forma inteligente antes de devolver la afinidad de unión predicha. Si intentas coger esos mismos tokens de BioT5, sumarlos en un vector plano y pasárselos a XGBoost, el rendimiento predictivo cae significativamente. El sum pooling promedia los detalles a nivel de token. La Transformer head triunfa precisamente porque conserva y explota el contexto granular de la representación tipo texto. Este cambio de arrays estáticos a embeddings dinámicos ofrece enormes beneficios prácticos. Los embeddings de LLMs son muy versátiles y se les puede hacer fine-tuning para downstream tasks especializadas. También son mucho más compactos que los enormes vectores de bits clásicos, lo que ahorra memoria al almacenar grandes librerías moleculares. Además, generar embeddings de texto se ejecuta en una GPU, lo que es drásticamente más rápido que calcular fingerprints tradicionales de RDKit en una CPU. La era de decirle manualmente a los algoritmos qué subestructuras químicas importan se está acabando; los modelos que mejor rinden son a los que se les permite leer la molécula y decidir por sí mismos. Si quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon. Gracias por pasarte. Espero que hayas aprendido algo nuevo.
12

Active Learning para el cribado virtual

4m 47s

Aprende a descubrir iterativamente los mejores candidatos a fármacos sin realizar pruebas exhaustivas. Profundizamos en los bucles de Active Learning y las estrategias de greedy selection para maximizar las tasas de éxito.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 12 de 22. Ejecutar simulaciones físicas complejas en un millón de moléculas es increíblemente lento. Necesitas una forma de encontrar los mejores candidatos probando solo una pequeña fracción de tu dataset. Eso es precisamente lo que hace el Active Learning para el Virtual Screening. Cuando evalúas una librería química, calcular afinidades de unión precisas mediante métodos de física computacional es increíblemente costoso. Simplemente no te puedes permitir simular todos y cada uno de los compuestos. En su lugar, pruebas un pequeño batch, usas esos resultados para entrenar un modelo de machine learning, y dejas que ese modelo prediga las afinidades para el resto de la librería. Luego, pruebas las predicciones más prometedoras, actualizas el modelo y repites el proceso. Este ciclo iterativo es el active learning. Veamos un escenario concreto. Estás explorando una serie congénere de diez mil compuestos que actúan sobre una proteína específica, como Tyk2. Tu objetivo es encontrar el top uno por ciento de las moléculas activas. Para hacerlo de manera eficiente, te basas en una estrategia de selección greedy. Una estrategia greedy significa que tu modelo siempre elige los compuestos con las afinidades de unión predichas más altas para la siguiente ronda de pruebas. Configuras tu batch size en sesenta moléculas por ronda. Este número ofrece un equilibrio práctico para un workflow del mundo real. Es lo bastante pequeño como para ejecutar rápidamente simulaciones físicas exigentes en el batch, pero lo bastante grande como para proporcionar una cantidad sustancial de datos nuevos a tu modelo. Ejecutas las pruebas en estos sesenta compuestos para obtener sus afinidades de unión reales, e introduces inmediatamente esos datos en un modelo bidimensional basado en árboles, como XGBoost. El modelo XGBoost aprende los patrones, puntúa las moléculas restantes sin probar en el pool de diez mil compuestos, y selecciona los siguientes sesenta candidatos. Aquí está la clave. La forma en que seleccionas el primer batch de sesenta moléculas determina lo rápido que aprende todo tu sistema. El active learning estándar suele utilizar por defecto un baseline aleatorio. Seleccionas sesenta moléculas completamente al azar, las pruebas y entrenas tu primer modelo. Pero la selección aleatoria le da a tu modelo un punto de partida muy pobre, llenando el training set inicial con compuestos mayoritariamente inactivos. La solución es inicializar el loop de active learning usando una red neuronal tridimensional preentrenada. Este modelo 3D ya ha sido entrenado con un dataset masivo y general de diversos complejos de proteínas y ligandos. Como entiende la física general de la unión basándose en interacciones estructurales, puede puntuar tus diez mil compuestos incluso antes de que empiece el loop de active learning. Primero, usas el modelo 3D preentrenado para predecir las afinidades de todo el pool. Luego, coges las sesenta mejores moléculas identificadas en este prescreening y ejecutas tus simulaciones físicas pesadas sobre ellas. Ahora tienes un dataset inicial altamente enriquecido. Le pasas este dataset inicial de alta calidad a tu modelo XGBoost. A partir de este punto, el modelo XGBoost toma el control del ciclo. Se entrena con los datos verificados, predice el resto del pool, y selecciona de forma greedy los siguientes sesenta candidatos. Esta combinación genera una aceleración masiva en el hit discovery. El modelo 3D general proporciona un punto de partida muy rico, y el modelo XGBoost se adapta rápidamente al espacio químico específico de tu serie congénere. Al inicializar con un modelo 3D preentrenado en lugar de hacer random sampling, puedes encontrar el ochenta por ciento del top uno por ciento de los binders tras probar menos del diez por ciento de todo el dataset. Iniciar tu loop con un prescreening 3D general les da a tus modelos especializados una ventaja insuperable. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue construyendo!
13

El desafío del Activity Cliff

3m 52s

Examina la fragilidad de las relaciones estructura-actividad. Hablamos de los 'activity cliffs', donde un pequeño cambio estructural provoca un cambio masivo en la potencia de un fármaco.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 13 de 22. En química, un solo átomo fuera de lugar puede convertir un fármaco potente que salva vidas en un polvo inerte. Estas caídas repentinas en la potencia biológica se llaman activity cliffs, y son la némesis absoluta de los modelos de IA tradicionales. Un activity cliff ocurre cuando tienes un par de moléculas con una alta similitud estructural, pero con niveles de actividad significativamente diferentes. Imagina un escenario concreto. Tienes dos moléculas que comparten el noventa por ciento de su framework estructural. La primera molécula se une fuertemente a una diana biológica. La segunda molécula es completamente inactiva. La única diferencia física entre ellas es un solo grupo metilo unido a un anillo específico. Para un químico médico humano, esta modificación estructural específica es muy informativa. Le dice exactamente dónde están los límites del bolsillo del receptor. Para un modelo estándar de machine learning, es una disrupción catastrófica. Aquí está la clave. La mayoría de los enfoques de deep learning en quimioinformática están construidos para predecir valores absolutos de propiedades. Tanto si usas una graph neural network como un chemical language model, la arquitectura está diseñada fundamentalmente para mapear estructuras químicas en un espacio matemático continuo. La suposición central hardcoded en estos modelos es que estructuras moleculares similares deberían mapearse a propiedades biológicas similares. Cuando un modelo estándar procesa nuestras dos moléculas casi idénticas, genera representaciones que están justo una al lado de la otra en ese espacio matemático. Como los inputs están muy juntos, el modelo naturalmente genera outputs de predicciones de potencia absoluta casi idénticas para ambas. Los activity cliffs violan fundamentalmente esta suposición de un espacio químico suave y continuo. Representan una discontinuidad severa. El modelo espera una colina suave, pero se encuentra con una caída vertical. Este problema se ve fuertemente amplificado por la naturaleza de los datos de descubrimiento de fármacos. Los datasets experimentales son notoriamente limitados y ruidosos. Cuando entrenas una deep neural network con datos sparse, al modelo le cuesta generalizar. Para minimizar el error general en todo el training set, la red aprende patrones amplios y globales. Suaviza las irregularidades locales. Cuando se encuentra con un activity cliff, el regression objective estándar trata ese salto repentino en la varianza como ruido experimental o un outlier. El modelo ignora la pieza más crítica de información estructural local porque no encaja en la tendencia global. Por esto, predecir los activity cliffs sigue siendo uno de los problemas más difíciles en la predicción de propiedades moleculares. Los modelos se ven obligados a aprender un espacio químico discontinuo directamente de datos limitados. Como se centran completamente en predicciones absolutas para moléculas individuales, ignoran por completo la valiosa información oculta en las diferencias relativas entre matched molecular pairs. En muchos casos, los tree-based models más simples de hecho terminan superando a las redes neuronales complejas en estos datasets simplemente porque los modelos de deep learning hacen over-smooth de las representaciones. La suposición de que estructuras químicas similares siempre producen actividades biológicas similares es un baseline estadístico útil, pero no es una ley física. Los activity cliffs son la realidad brutal y discontinua de las relaciones estructura-actividad, y demuestran que predecir propiedades absolutas en el vacío siempre fallará en los márgenes. Gracias por pasar unos minutos conmigo. Hasta la próxima, cuídate.
14

Similarity-Quantized Relative Learning

3m 53s

Resuelve el problema del activity cliff replanteando cómo aprenden los modelos. Exploramos el framework SQRL, que entrena a la IA para predecir diferencias de propiedades relativas entre pares moleculares estrictamente filtrados.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 14 de 22. En lugar de obligar a una IA a memorizar la potencia absoluta de cada molécula existente, ¿qué pasaría si simplemente le enseñaras a preguntar en qué se diferencia una molécula de su vecino conocido más cercano? Este cambio de perspectiva resuelve un importante problema de generalización en entornos con pocos datos, y es la base de un framework llamado Similarity-Quantized Relative Learning, o SQRL. Normalmente, la predicción de propiedades moleculares trata cada molécula como un data point aislado. El modelo intenta mapear una estructura directamente a un valor de propiedad absoluto. Con datasets pequeños y ruidosos, los modelos de deep learning tienen dificultades para construir un mapa global preciso del espacio químico. Los intentos anteriores de pairwise learning intentaron solucionar esto emparejando cada molécula con todas las demás moléculas del training set. Ese enfoque inunda los datos con comparaciones entre estructuras que no tienen ninguna relación, ahogando la señal local útil. SQRL soluciona esto restringiendo los training data a pares de moléculas que son estructuralmente muy similares. El modelo aprende a predecir la diferencia relativa en sus propiedades, conocida como delta y. Esto se logra mediante un paso específico de matching en el dataset. No le pasas al modelo moléculas individuales. Le pasas pares, pero solo si superan un umbral de similitud estricto. Vamos a repasar la lógica. Empiezas con tu training set estándar de moléculas y sus potencias conocidas. Primero, calculas las distancias entre todas las moléculas usando una métrica como la distancia de Tanimoto sobre los Morgan fingerprints. Aquí está la clave. Estableces un umbral de distancia, alfa. Vamos a usar un umbral de distancia de Tanimoto de cero coma siete. Iteras sobre todos los pares de moléculas posibles. Si la distancia entre la molécula A y la molécula B es cero coma siete o superior, descartas el par por completo. Si la distancia es estrictamente menor que cero coma siete, añades este par a tu nuevo training set relativo. La target variable para este nuevo par ya no es una potencia absoluta. Es la diferencia numérica exacta de potencia entre la molécula A y la molécula B. Ahora entrenas tu red neuronal. La red genera una representación matemática para la molécula A y una representación para la molécula B. Resta la representación de B a la de A. Ese vector de diferencia resultante se pasa por una capa final para predecir el delta y. Al filtrar el ruido de los pares no similares, la red se ve obligada a centrarse exclusivamente en cambios químicos locales de alta señal. Aprende con exactitud cómo una modificación estructural específica altera la actividad. Esto hace que el modelo sea muy sensible a los activity cliffs. Eso cubre el entrenamiento, pero ¿qué pasa al predecir una molécula completamente nueva? Cuando entra una nueva estructura, el sistema escanea los training data originales para encontrar al único vecino estructural más cercano basándose en esa misma métrica de distancia de Tanimoto. La red evalúa la nueva molécula en comparación con este vecino más cercano y predice el delta relativo. Finalmente, coges la potencia absoluta conocida del vecino, le sumas el delta predicho, y tienes tu predicción final. Al restringir el espacio de entrenamiento a pares muy similares, dejas de pedirle al modelo que aprenda todo el universo químico y, en su lugar, lo entrenas para que se convierta en un experto en gradientes químicos locales. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
15

La revolución de la Generative AI

3m 58s

Pasa de predecir propiedades a imaginar moléculas completamente nuevas. Trazamos el panorama de las tareas generativas moleculares: generación De Novo, optimización y generación de confórmeros.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 15 de 22. Durante años, la IA en química era puramente un proceso de criba. Le pasabas a un modelo miles de moléculas existentes, y simplemente predecía cuáles eran las menos malas. Si la molécula ideal no estaba en tu screening library, el modelo no podía ayudarte. La revolución de la IA generativa cambió radicalmente esta dinámica. En lugar de simplemente filtrar lo que ya existe, ahora podemos darle instrucciones a los modelos para que inventen materia química completamente nueva. Este salto de la predicción a la creación se divide en dos grandes tareas generativas moleculares: la generación de novo y la optimización molecular. La generación de novo consiste en crear estructuras moleculares nuevas desde cero. El modelo empieza con una representación de ruido aleatorio y la refina de forma iterativa hasta obtener una estructura química válida. Cuando esto se hace sin ningún tipo de restricción, se llama generación incondicional. El modelo explora libremente el inmenso espacio químico para producir algo completamente nuevo. Aunque eso es útil para un descubrimiento amplio, normalmente necesitas más control. Esto nos lleva a la generación condicional, en concreto a la generación basada en propiedades. Aquí, tú dictas el output. Le pasas restricciones específicas, como una bioactividad target o un nivel de sintetizabilidad requerido, y el modelo restringe su generación a moléculas que cumplan esos criterios. A esto se le suele llamar diseño molecular inverso, porque empiezas con las propiedades que quieres y fuerzas al modelo a trabajar hacia atrás para construir una estructura molecular que las consiga. La generación de novo es potente, pero rara vez empiezas un proyecto sin ningún conocimiento previo. Normalmente, ya tienes un lead compound. Aquí es donde entra en juego la optimización molecular. A diferencia de las tareas de novo, la optimización molecular se centra en modificar una estructura conocida en lugar de partir de cero. Coges una molécula existente y la refinas para mejorar sus propiedades. Supongamos que tienes un scaffold de fármaco moderadamente eficaz. Se une a tu target, pero su bioactividad es demasiado baja para ser un fármaco viable. Usando un modelo generativo, puedes realizar una optimización molecular dirigida. Un enfoque es el scaffold hopping. Le indicas al modelo que reemplace el scaffold molecular central por uno nuevo, manteniendo la actividad biológica original. Esto resulta muy eficaz para descubrir compuestos estructuralmente novedosos que eluden las patentes existentes manteniendo intacto su comportamiento funcional. Otro enfoque es el R-group design. En este escenario, bloqueas tu scaffold central y le pides al modelo generativo que optimice automáticamente sus cadenas laterales. El modelo genera nuevos R-groups, buscando las modificaciones específicas de las cadenas laterales que mejoren esa bioactividad deficiente. No estás descartando tu molécula moderadamente eficaz, estás dejando que la IA calcule los ajustes estructurales precisos necesarios para que cruce la línea de meta. Aquí está la clave. La transición de la IA predictiva a la IA generativa significa que ya no estás limitado por las moléculas que tienes a mano. Tanto si estás generando una molécula a medida desde cero como si estás intercambiando algorítmicamente las cadenas laterales de un fármaco existente, estás tratando el espacio químico como un medio programable. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue creando!
16

La intuición de la difusión molecular

4m 24s

Desglosamos el concepto central de los Diffusion Models sin matemáticas pesadas. Los oyentes comprenderán el proceso hacia adelante (forward process) de añadir ruido a una molécula y el proceso inverso (reverse process) de alucinar nuevas estructuras.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 16 de 22. Para enseñar a una IA a inventar una nueva molécula, primero tienes que enseñarle a destruir una por completo. Parece que está totalmente al revés, pero esta destrucción sistemática es exactamente el mecanismo que se usa para generar nuevos fármacos desde cero. Esta es la intuición principal de los Denoising Diffusion Probabilistic Models. El diseño molecular tradicional requiere muchísimo trabajo. Si quieres automatizar el descubrimiento de nuevos compuestos, necesitas un modelo capaz de explorar un inmenso espacio químico sin generar resultados inválidos y sin sentido. Los primeros deep generative models intentaron mapear este espacio directamente. Los Denoising Diffusion Probabilistic Models, o DDPMs, toman un camino diferente. Tratan la generación molecular como un problema de denoising progresivo. El framework se divide en dos cadenas de Markov distintas: el forward process y el reverse process. El forward process trata estrictamente sobre la degradación de datos. Coges un fármaco válido y conocido de tu training set. A lo largo de una secuencia fija de pasos, difuminas progresivamente sus coordenadas atómicas inyectando ruido gaussiano puro. La cantidad de ruido que añades en cada paso está controlada por un hyperparameter schedule establecido. En el paso uno, perturbas los átomos ligeramente. La molécula está un poco distorsionada, pero sigue siendo claramente reconocible. Para el paso cincuenta, la estructura está gravemente deformada. Para el paso final, normalmente denominado paso T, la molécula original ha desaparecido por completo. Te quedas con una nube aleatoria de ruido gaussiano sin estructura. Este forward process no requiere una red neuronal. Es una corrupción matemática estricta. Cumple un propósito vital porque genera el ground truth para nuestra training data. Aquí está la clave. Como controlamos la cantidad exacta de ruido añadido en cada paso, tenemos un registro perfecto, paso a paso, de cómo se desintegró la molécula. El reverse process es donde entra en juego la red neuronal. El modelo se entrena para recorrer ese camino exacto hacia atrás. Le pasamos a la red una molécula corrupta en un time step específico. Luego le pedimos que prediga el ruido específico que se añadió para llegar a ese estado. Evaluamos el modelo comparando su predicción de ruido con el ruido real que inyectamos durante la fase forward. Actualizamos los parámetros del modelo para minimizar esa diferencia. Con el tiempo, la red aprende a hacer denoising de los datos paso a paso, restaurando gradualmente la distribución de datos original. Para generar una molécula completamente nueva, ejecutas este reverse process desde cero. Primero, tomas un sample de una nube completamente aleatoria de ruido gaussiano. Luego, le pasas ese ruido a tu red neuronal entrenada, junto con el número del paso inicial. La red evalúa el input, predice la corrección estructural necesaria y devuelve una nube de átomos con un poco menos de ruido. Repites en loop este proceso de sustracción. Vuelves a pasar el nuevo output a la red para el siguiente paso hacia abajo. Con cada iteración, la nube aleatoria se compacta. El modelo elimina el ruido continuamente. A medida que retrocedes hacia el paso cero, las coordenadas atómicas encajan en su lugar y emerge una estructura química válida. Sacas una molécula completamente nueva a partir de la estática inicial. El modelo no se limita a memorizar una base de datos de fármacos existentes; simplemente aprende el proceso universal de eliminar el caos para dejar atrás una química estable. Si te gustaría apoyar el programa, puedes buscar DevStoriesEU en Patreon. ¡Gracias por escuchar, y sigue construyendo!
17

Conectando los espacios generativos 2D y 3D

4m 28s

Exploramos cómo la IA representa realmente las moléculas que genera. Comparamos la generación de grafos topológicos planos en 2D con la generación de nubes de puntos geométricas complejas en 3D, y los desafíos de cada uno.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 17 de 22. Una cosa es que un modelo dibuje un graph plano en 2D de una molécula. Otra muy distinta, y una auténtica pesadilla de ingeniería, es generar una point cloud geométrica estable de átomos en 3D. Puedes hacer que un modelo generativo construya una point cloud en 3D preciosa de un fármaco que encaje perfectamente en el pocket de una proteína diana, solo para ver cómo todo se desmorona en el post-processing cuando el sistema no logra adivinar dónde deberían ir los enlaces covalentes reales. La solución a esta desconexión es unir los espacios generativos 2D y 3D. En química generativa, las modalidades de datos dictan lo que tu modelo puede entender. La primera modalidad es el espacio topológico 2D. Piénsalo como un molecular graph estándar. Los nodes representan átomos con tipos específicos, y los edges representan los enlaces químicos que los conectan. El modelo devuelve una adjacency matrix que te dice exactamente qué está conectado con qué. Las Graph Neural Networks manejan esto muy bien. El problema es que las moléculas existen en el mundo físico, no en el papel. Un graph 2D te da la topología de unión, pero ignora por completo la estructura geométrica en 3D. Sin coordenadas espaciales, no puedes calcular con precisión las propiedades cuánticas ni hacer diseño de fármacos basado en la estructura. Para solucionar eso, los modelos pasaron a generar moléculas directamente en el espacio geométrico 3D. Aquí, el output es una point cloud. El modelo define los tipos de átomos y sus coordenadas posicionales exactas X, Y y Z. El obstáculo técnico aquí es mantener la SE 3 equivariance, asegurando que la molécula siga siendo matemáticamente consistente independientemente de cómo se rote o traslade en el espacio. Aquí está la clave. Generar en espacio 3D puro significa que el modelo no genera explícitamente los enlaces químicos. Simplemente coloca los átomos en el espacio. Tienes que inferir la topología de unión después mediante algoritmos de post-processing. Esto introduce errores importantes. Volviendo al escenario del pocket del fármaco, tu modelo podría organizar los átomos en una forma que encaje físicamente con la diana, pero como nunca tuvo en cuenta la topología de unión durante la generación, el paso de post-processing podría inferir enlaces covalentes imposibles. Para moléculas más grandes, generar directamente una estructura 3D estable sin ninguna guía topológica a menudo resulta en una solución subóptima. Esto nos lleva a generar en un espacio conjunto 2D y 3D, lo que produce una estructura molecular completa simultáneamente. El modelo devuelve los tipos de átomos, la adjacency matrix discreta para los enlaces y las coordenadas espaciales continuas, todo a la vez. Al unir estos dos espacios, las modalidades se restringen y corrigen mutuamente durante el proceso de generación. La topología 2D actúa como un blueprint, guiando la estructura 3D para asegurar que las disposiciones espaciales sean químicamente viables. Al mismo tiempo, la geometría 3D refina el graph 2D sugiriendo patrones de enlace plausibles basados en la proximidad espacial. El principal desafío técnico en este enfoque conjunto es gestionar dos tipos de datos fundamentalmente diferentes. Estás obligando al modelo a manejar estructuras topológicas discretas, como los tipos de enlaces, junto con estructuras geométricas continuas, como los valores de las coordenadas. Diferentes arquitecturas resuelven esto de manera distinta. Un framework llamado JODO trata tanto las estructuras topológicas como las geométricas como variables continuas para procesarlas juntas. Otro modelo, MUDiff, las maneja por separado, aplicando un proceso discreto para la topología y un proceso continuo para la geometría. No puedes generar fármacos nuevos y funcionales de forma fiable adivinando la forma física y esperando que los enlaces químicos se arreglen solos después. La verdadera generación molecular requiere que el blueprinting topológico y el posicionamiento espacial interactúen y se complementen entre sí en la misma computación. Eso es todo por este episodio. ¡Gracias por escuchar, y seguid construyendo!
18

Generación Target-Aware y Docking

4m 06s

Descubre el diseño generativo context-aware. Hablamos sobre la generación de moléculas novedosas directamente dentro del bolsillo de unión (binding pocket) de una proteína patológica para maximizar la afinidad de unión.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 18 de 22. ¿Por qué pedirle a un algoritmo que genere un millón de llaves aleatorias y las pruebe una a una, cuando podría simplemente mirar la cerradura y forjar una llave a medida justo dentro del ojo de la cerradura? El descubrimiento tradicional de fármacos suele basarse en generar enormes librerías de candidatos y filtrarlos, pero eso desperdicia muchísimos recursos computacionales. La Target-Aware Generation y el Docking resuelven esto utilizando directamente la geometría tridimensional del target biológico para construir o colocar moléculas. En estas tareas generativas, trabajamos completamente en el espacio geométrico 3D. La Target-Aware Generation, también conocida como diseño de fármacos basado en la estructura, construye una nueva molécula basándose directamente en la estructura 3D del binding pocket del target. Imagina un escenario concreto con una proteína viral. Esta proteína tiene una cavidad geométrica muy específica. En lugar de generar moléculas en el vacío, un modelo de difusión condicional analiza los límites espaciales exactos y las propiedades químicas de esa cavidad. Luego, hace crecer a medida una nueva estructura de ligando directamente dentro del pocket. El modelo empieza con una nube de coordenadas 3D con ruido y tipos de átomos ubicados dentro del binding site. En pasos sucesivos, elimina el ruido de esta nube. Como la generación está condicionada al pocket del target, el modelo coloca átomos y forma estructuras que complementan la cavidad de forma natural, con el objetivo de garantizar una alta afinidad de interacción. Aquí está la clave. El algoritmo no se limita a adivinar una forma; aprende explícitamente la relación espacial entre el target y los posibles ligandos. Algunos enfoques incluso incorporan retrieval basado en interacciones, extrayendo datos de ligandos conocidos de alta afinidad para guiar aún más la generación de estas moléculas específicas para el target. Eso cubre la generación de una molécula completamente nueva desde cero dentro de un pocket. Pero a menudo tendrás una molécula existente y necesitarás saber exactamente cómo interactúa con un target biológico. Eso nos lleva al docking molecular. El docking molecular predice la pose de unión para evaluar la afinidad y la especificidad. En un framework de difusión, los modelos toman una molécula conocida y una estructura target como inputs. En lugar de generar identidad química, el proceso de difusión opera puramente sobre la orientación espacial de la molécula. El modelo empieza con el ligando en una pose 3D aleatoria y con ruido, y le elimina el ruido de forma iterativa. Refina las coordenadas espaciales de la molécula hasta que se asienta en la configuración de unión correcta dentro del pocket de la proteína. Los modelos de docking avanzados van un paso más allá al tratar al propio target como una entidad flexible. Un modelo llamado Re-Dock utiliza una técnica denominada diffusion bridge para predecir las poses de unión del ligando mientras modela simultáneamente el movimiento de las cadenas laterales del pocket. Esto crea un escenario de docking realista y flexible donde tanto el ligando como el target se adaptan el uno al otro durante la fase de predicción. El cambio crucial aquí es que los modelos de difusión han alejado el diseño estructural de fármacos de las aproximaciones rígidas y aisladas. Al tratar tanto el ligando generado como el pocket biológico como un sistema geométrico continuo y adaptable, el modelo genera de forma nativa como output moléculas y poses que están fundamentadas físicamente en la realidad precisa del entorno del target. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
19

La trampa del tamaño en la evaluación generativa

4m 34s

Aprende por qué los benchmarks estándar para modelos generativos pueden ser profundamente defectuosos. Revelamos el efecto de confusión del tamaño de la biblioteca generada en métricas como la Fréchet ChemNet Distance.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 19 de 22. Evalúas tu nuevo modelo de química generativa haciendo sampling de mil moléculas, y las métricas tienen una pinta terrible. Generas cien mil con ese mismo modelo, y de repente parece de primer nivel. La escala lo cambia todo. Este fenómeno se conoce como la Size Trap en la evaluación generativa. Los pipelines de descubrimiento generativo de fármacos suelen seguir tres etapas. Entrenas, generas y evalúas. Cuando llegas a la etapa de evaluación, te enfrentas a la pregunta básica de cuántos diseños de novo generar para el benchmarking. La práctica habitual suele tirar por batches pequeños, normalmente de mil o diez mil strings SMILES. Luego, los equipos pasan estos batches por métricas de distribución estándar. La más común es la Fréchet ChemNet Distance, o FCD. El FCD mide cómo de cerca están tus moléculas generadas de tu training set en el espacio químico y biológico. Un score de FCD más bajo significa que tu distribución generada se ajusta mucho a tu distribución objetivo. Otra métrica común es la Fréchet Descriptor Distance, o FDD, que compara la distribución de propiedades fisicoquímicas como el peso molecular y el área de superficie topológica. Los equipos también suelen medir la Uniqueness, que es la fracción de diseños generados que son distintos. Aquí está la clave. Todas estas métricas dependen muchísimo del tamaño físico de la librería generada. No miden la calidad absoluta del modelo en el vacío. Cuando haces sampling de solo mil moléculas, tus scores de FCD y FDD serán artificialmente altos. Parece que el modelo ha fallado al aprender la distribución objetivo. Pero si sigues haciendo sampling de ese mismo modelo, llevando el tamaño de la librería más allá de las diez mil, cincuenta mil o cien mil moléculas, el score de FCD cae significativamente. Sigue bajando hasta que finalmente alcanza un plateau. Esto pasa porque el diseño generativo de moléculas implica hacer sampling de una distribución de probabilidad aprendida muy compleja. Una muestra enana de mil moléculas no puede representar adecuadamente todo el alcance del output de ese modelo. Los algoritmos de distancia de Fréchet necesitan una cantidad masiva de muestras para capturar con precisión la forma del espacio generado y compararlo con el espacio de fine-tuning. Imagina un escenario concreto en el que estás comparando una red neuronal recurrente con un transformer. Si evalúas la red recurrente usando cien mil diseños, pero evalúas el transformer usando solo diez mil, la red recurrente probablemente mostrará scores de FCD y FDD muy superiores. Ese gap de rendimiento no tiene nada que ver con la arquitectura. Es puramente un artefacto del tamaño de la muestra. Las métricas no han convergido para la librería más pequeña. Esta trampa funciona al revés cuando te fijas en la diversidad interna. La Uniqueness se comporta de forma completamente distinta a gran escala. Con mil moléculas, casi cada string SMILES válido que genera tu modelo podría ser único. El modelo parece súper creativo. Pero a medida que empujas la generación hacia las cien mil, la Uniqueness cae en picado. El modelo empieza a repetirse. Si rankeas diferentes modelos generativos basándote en la Uniqueness a pequeña escala, las diferencias entre ellos parecen menores. Sube la escala, y el gap entre los modelos se amplía drásticamente. El ranking relativo de tus modelos de hecho se dará la vuelta dependiendo del tamaño de la librería que uses para medirlos. Para solucionar esto, debes tratar el tamaño de la librería como una variable de control estricta en tu pipeline. Nunca puedes comparar de forma fiable el FCD, el FDD o la Uniqueness entre librerías de diferentes tamaños. Para asegurar una evaluación robusta, deberías evaluar librerías que contengan al menos cien mil diseños para que las métricas de distribución converjan del todo. Si tus métricas de evaluación cambian simplemente porque dejas que el sampling loop corra durante más tiempo, estás midiendo el tamaño de la muestra, no la inteligencia del modelo. Eso es todo por este episodio. ¡Gracias por escuchar y sigue desarrollando!
20

Navegando por las alucinaciones De Novo

4m 03s

Clasifica las moléculas generadas por IA de forma inteligente. Exploramos el equilibrio entre exploración y explotación (exploration-exploitation tradeoff) de las probabilidades del modelo, y cómo filtrar las 'alucinaciones químicas' frecuentes y de baja calidad.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 20 de 22. Que una IA generativa suelte una molécula específica diez mil veces no significa que sea un fármaco viable. Podrías pensar que la frecuencia de generación indica calidad o relevancia química. Pues no. Esos outputs tan frecuentes suelen ser el equivalente químico de un large language model alucinando. El mecanismo para resolver esto es navegar por las alucinaciones de novo usando el likelihood del modelo. Cuando generas una librería masiva de un millón de SMILES strings a partir de un modelo de lenguaje químico fine-tuned, tienes que decidir qué moléculas priorizar para futuros estudios. Un enfoque estándar, pero erróneo, es simplemente seleccionar los diseños que el modelo genera con más frecuencia. Esto crea una trampa de conteo. En lugar de descubrir candidatos a fármacos robustos, terminas extrayendo subestructuras básicas y repetitivas, como anillos de benceno aislados, aminas simples y éteres básicos. Estas son alucinaciones estructurales recurrentes. El modelo las genera constantemente no porque sean de alta calidad, sino porque son sintácticamente simples de construir. Para exponer y filtrar estas alucinaciones, evalúas tu librería usando el likelihood del modelo. El likelihood es una métrica que captura lo bien que una secuencia generada se alinea con la distribución de probabilidad que el modelo aprendió durante el entrenamiento. Para un modelo autorregresivo, lo calculas multiplicando la probabilidad de muestreo de cada token individual en el SMILES string generado. Primero, calculas el likelihood score para el millón de diseños generados. Después, ordenas toda la librería basándote en estos scores. Finalmente, divides la librería ordenada en diez grupos iguales, o deciles, que van desde el likelihood más bajo hasta el más alto. Aquí es donde se pone interesante. Analizar estos deciles revela un estricto tradeoff entre exploración y explotación. El décimo decil contiene las generaciones con el likelihood más alto. Estos diseños representan la explotación. Tienen una validez química extremadamente alta, y sus scaffolds genéricos de Bemis-Murcko coinciden mucho con las moléculas activas conocidas de tus datos de entrenamiento. El modelo está explotando a tope lo que ya sabe que funciona. La desventaja es que a estos diseños de primer nivel les falta novedad. Contienen muy pocas subestructuras nuevas porque el modelo va a lo seguro. Bajando a los deciles intermedios, encuentras un equilibrio. La novedad y las subestructuras únicas alcanzan su pico en este rango medio, mientras que la validez sigue siendo aceptable. Pero cuando bajas al primer decil —el diez por ciento de las moléculas con los likelihood scores más bajos en absoluto— caes en la trampa de conteo. Si aíslas los diseños que el modelo generó más de diez veces en todo el run del millón de moléculas, casi todos se agrupan en este decil inferior. Tienen likelihoods del modelo increíblemente bajos, y sin embargo aparecen con una frecuencia masiva. Su similitud estructural con tu training set es terrible, y su validez química general se desploma. Al agrupar tu librería de esta manera, demuestras matemáticamente que la frecuencia es una señal falsa de calidad. Puedes descartar sistemáticamente los bins de bajo likelihood y alta frecuencia, y centrar tu screening computacional en los deciles intermedios, donde ocurre la verdadera exploración química. Los outputs más frecuentes de un modelo químico generativo suelen ser los peores, pero filtrar tu librería por deciles de likelihood transforma ese ruido en un mapa preciso de dónde está explorando el modelo y dónde simplemente está alucinando. Eso es todo por este episodio. ¡Gracias por escuchar y sigue construyendo!
21

Restricciones en el sampling de moléculas

4m 28s

Comprende por qué las técnicas de NLP fallan en la química. Comparamos el Temperature sampling con Top-k y Top-p, y por qué el vocabulario químico restringido lo cambia todo.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 21 de 22. En el procesamiento del lenguaje natural, el Top-p sampling produce textos sumamente creativos. Pero si aplicas esa misma lógica a la generación de moléculas, tu IA solo imprimirá anillos de carbono idénticos para siempre. El motivo se reduce a las restricciones de sampling de moléculas. Cuando un modelo de lenguaje químico genera una SMILES string, construye la molécula token a token. El modelo predice una distribución de probabilidad para el siguiente token, y tienes que extraer una opción específica de esa distribución. En la generación de texto, los desarrolladores se apoyan muchísimo en el Top-k y Top-p sampling para tomar esta decisión. Top-k restringe el modelo a los k tokens más probables en términos absolutos. Top-p restringe la selección al grupo más pequeño de tokens cuyas probabilidades combinadas superan un porcentaje objetivo p. Si aplicas estos métodos a un modelo de lenguaje químico, fallan estrepitosamente. Si usas Top-k sampling con k igual a 3 en una LSTM entrenada con dianas farmacológicas, tu modelo sufrirá un mode collapse severo. Generará moléculas químicamente válidas, pero serán completamente repetitivas. Aquí está la clave del asunto. El fallo proviene del tamaño del vocabulario químico. Un modelo de texto selecciona entre cientos de miles de palabras. Un modelo de lenguaje químico usa un alfabeto muy restringido. Solo tiene un puñado de elementos como carbono, oxígeno y nitrógeno, además de syntax tokens para ramificaciones y cierres de anillos. Como el alfabeto químico es minúsculo, y como la química válida requiere reglas de sintaxis rígidas como cerrar cada anillo abierto, un subconjunto muy pequeño de tokens domina absolutamente la distribución de probabilidad. El carbono y los tokens estructurales básicos son casi siempre altamente probables. Cuando aplicas Top-k o Top-p sampling, cortas la larga cola de la distribución de probabilidad. El modelo se ve obligado a elegir exclusivamente de esa estrecha banda de tokens dominantes. Se queda atrapado en una trampa de filtrado, repitiendo los mismos scaffolds básicos una y otra vez. Para escapar de esta trampa, tienes que usar Temperature sampling. En lugar de filtrar tokens, el Temperature sampling aplica un parámetro de suavizado a los scores brutos de la red neuronal antes de calcular las probabilidades finales. Esto altera la forma de toda la distribución. Imagina un escenario en el que estás ejecutando un modelo LSTM fine-tuned para generar nuevos candidatos a fármacos. Ajustas el parámetro de Temperature, T, para encontrar el equilibrio entre validez y diversidad. Si pones T bajo, alrededor de 0,5, la distribución de probabilidad presenta un pico muy pronunciado. El modelo explota muchísimo los tokens más probables. Tu output tendrá una validez química altísima, pero a las estructuras les faltará novedad. Imitarán muy de cerca al training set. Si aumentas T hasta 1,5 o 2,0, aplanas la distribución de probabilidad. Ahora, los tokens menos probables tienen una posibilidad matemática de ser seleccionados. Tu modelo empieza a explorar nuevo espacio químico. El número de subestructuras únicas en tu biblioteca generada se dispara. Encuentras moléculas muy novedosas. La contrapartida es que las temperaturas más altas aumentan la aleatoriedad, lo que lleva al modelo a cometer más errores de sintaxis, reduciendo el porcentaje total de SMILES strings válidas. No puedes trasladar a ciegas las estrategias de generación de texto al diseño molecular. Como el vocabulario químico es inherentemente limitado, el Temperature scaling sigue siendo la palanca más eficaz para equilibrar la estricta validez química frente a la exploración de nuevas estructuras. Gracias por acompañarme. Espero que hayas aprendido algo nuevo.
22

Desplegando quimioinformática en la nube

4m 09s

Lleva tu pipeline de IA a producción. Hablamos sobre el empaquetado de RDKit y modelos de machine learning en contenedores Docker y el escalado de cargas de trabajo en la infraestructura de la nube.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. Quimioinformática e IA con Python, episodio 22 de 22. Has creado un pipeline de descubrimiento de fármacos con IA de última generación en tu portátil, pero ¿cómo analizas mil millones de moléculas en un fin de semana? La respuesta es hacer deploy de la quimioinformática en el cloud. Trasladar un modelo de un entorno local a una arquitectura cloud distribuida suele fallar en la capa de dependencias. RDKit no es una librería pura de Python. Es un codebase grande en C++ que requiere dependencias a nivel de sistema, sobre todo las librerías Boost de C++. Si aprovisionas servidores cloud genéricos y ejecutas scripts de instalación estándar, es frecuente que te encuentres con errores de compilador o falten shared object files. La documentación oficial de RDKit destaca que hacer la build desde source requiere un toolchain de C++ específico. Aunque existen pip wheels precompilados, la forma más robusta de garantizar que todas las dependencias subyacentes cuadren es usar Conda. Sin embargo, instalar Conda dinámicamente en miles de cloud workers temporales lleva demasiado tiempo e introduce inestabilidad en la red durante el scale-up. Aquí está la clave. Evitas por completo el problema de las dependencias metiendo tu pipeline en un contenedor Docker. Escribes un archivo de configuración que especifica un sistema operativo base. Dentro de ese contenedor, instalas un entorno Conda ligero, haces pull de los binarios compilados de RDKit y añades tus frameworks de machine learning como PyTorch o XGBoost. Finalmente, copias los pesos de tu modelo preentrenado en la imagen. Hacer la build de esta imagen congela todo el stack en un único artefacto inmutable. El proveedor cloud solo necesita saber cómo ejecutar un contenedor Docker estándar. Las complejas dependencias de C++ quedan bloqueadas de forma segura en su interior. Para procesar millones de moléculas, separas tu flujo de datos de tus compute workers usando una message queue en el cloud. Divides tu dataset masivo de strings SMILES en chunks más pequeños y manejables. Colocas estos chunks en un object storage en el cloud y envías un mensaje con la ubicación del chunk a la queue. Luego, apuntas un servicio de cloud compute escalable a esta queue. Para workloads pesados acelerados por GPU, haces deploy de tu contenedor usando un servicio como AWS Batch. Para inferencia más ligera basada en CPU, las plataformas de contenedores serverless como Google Cloud Run o AWS Lambda lo gestionan a la perfección. Configuras el servicio de compute para que escale automáticamente según la profundidad de la queue. Si hay cincuenta mil mensajes en espera, el cloud controller levanta miles de contenedores Docker idénticos simultáneamente. Cada contenedor se conecta a la queue y reclama un mensaje. Descarga el chunk correspondiente de strings SMILES. RDKit convierte los SMILES en grafos moleculares, calcula los descriptores necesarios y los pasa a tu modelo de machine learning para la inferencia. El contenedor escribe las moléculas con mayor puntuación directamente en una base de datos cloud gestionada. Una vez procesado el chunk, el worker elimina el mensaje de la queue y coge el siguiente. Cuando la queue está vacía, la infraestructura cloud termina los contenedores automáticamente. Solo pagas por los segundos exactos de compute que tu código realmente consumió. Escalar la quimioinformática rara vez va de escribir estructuras de bucle más rápidas en Python; va de empaquetar tu entorno de forma fiable y usar una arquitectura cloud desacoplada para procesar datos en paralelo. Con esto terminamos nuestra serie sobre Quimioinformática e IA con Python. Te animo a leer la documentación oficial de RDKit sobre la instalación, a probar a containerizar un script sencillo de forma práctica, o a visitar devstories dot eu para sugerir temas para futuras series. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue creando!