Retour au catalogue
Season 19 22 Épisodes 1h 21m 2026

Python Cheminformatics & AI

Édition 2026. Un cours pratique qui guide les développeurs Python des concepts de base de la chimie jusqu'à la conception de systèmes de chémoinformatique pilotés par l'IA. Apprenez à utiliser RDKit, scikit-fingerprints et des techniques de deep learning de pointe telles que les Graph Neural Networks et les Diffusion Models pour la découverte de médicaments.

Calcul scientifique Chemoinformatique Deep Learning pour la science
Python Cheminformatics & AI
Lecture en cours
Click play to start
0:00
0:00
1
La Molécule Numérique
Nous présentons RDKit et le concept fondamental de la représentation de la chimie en Python. Les auditeurs apprendront à initialiser des objets moléculaires à partir de chaînes de caractères et comprendront le rôle central du framework dans la découverte de médicaments par l'IA.
3m 27s
2
Entrées/Sorties en Chémoinformatique
Apprenez à ingérer et exporter en toute sécurité des jeux de données chimiques massifs. Nous abordons la lecture des fichiers SDF et SMILES, la gestion des erreurs d'analyse et l'écriture des données sur le disque.
3m 48s
3
Parcours de Graphes Moléculaires
Découvrez comment les molécules sont représentées sous forme de structures de données de graphe. Nous explorons l'itération sur les atomes, l'analyse des liaisons et l'identification des systèmes cycliques au sein des molécules.
3m 13s
4
Recherche de Sous-structures
Maîtrisez l'art d'interroger les molécules à l'aide de SMARTS. Nous vous guidons dans la recherche de groupes fonctionnels et de motifs spécifiques au sein de structures chimiques complexes.
3m 54s
5
Fingerprinting et Similarité Moléculaire
Découvrez comment traduire des graphes moléculaires en vecteurs de bits mathématiques. Nous abordons les clés MACCS, les Morgan fingerprints et le calcul de la similarité de Tanimoto.
3m 53s
6
Briser le Plan 2D
Passez de dessins 2D plats à des géométries 3D réalistes. Nous discutons de l'ajout d'hydrogènes explicites et de la génération de conformères 3D fiables à l'aide d'ETKDG.
3m 31s
7
Accélérer le Feature Engineering
Faites le pont entre la chémoinformatique et la data science classique avec scikit-fingerprints. Nous explorons la génération de plus de 30 types de fingerprints moléculaires directement dans une interface scikit-learn.
3m 40s
8
Chémoinformatique Haute Performance
Apprenez à traiter efficacement des jeux de données chimiques massifs. Nous nous plongeons dans l'utilisation du parallélisme CPU avec Joblib et l'économie de mémoire grâce aux matrices creuses de SciPy.
4m 11s
9
Pipelines ML de Bout en Bout
Combinez le traitement, le fingerprinting et la prédiction dans une seule architecture propre. Nous construisons des pipelines scikit-learn robustes qui intègrent de manière transparente la génération de conformères 3D et la prédiction de propriétés.
3m 47s
10
Prédire l'Affinité de Liaison
Explorez la réalité de la prédiction de l'affinité de liaison protéine-ligand. Nous comparons les performances de modèles simples basés sur des arbres 2D à celles de Graph Neural Networks 3D complexes.
3m 42s
11
LLMs vs Fingerprints Classiques
Découvrez comment le NLP s'applique à la chimie. Nous opposons les embeddings vectoriels des Large Language Models aux fingerprints structurels classiques de RDKit pour prédire la bioactivité.
3m 59s
12
Active Learning pour le Criblage Virtuel
Apprenez à découvrir de manière itérative les meilleurs candidats médicaments sans tests exhaustifs. Nous plongeons dans les boucles d'Active Learning et les stratégies de sélection gloutonnes pour maximiser les taux de réussite.
3m 49s
13
Le Défi des Activity Cliffs
Examinez la fragilité des relations structure-activité. Nous discutons des 'activity cliffs' — où un changement structurel infime provoque une modification massive de la puissance d'un médicament.
3m 27s
14
Similarity-Quantized Relative Learning
Résolvez le problème des activity cliffs en repensant la façon dont les modèles apprennent. Nous explorons le framework SQRL, qui entraîne l'IA à prédire les différences de propriétés relatives entre des paires moléculaires strictement filtrées.
3m 31s
15
La Révolution de l'IA Générative
Passez de la prédiction de propriétés à l'imagination de molécules entièrement nouvelles. Nous cartographions le paysage des tâches génératives moléculaires : génération De Novo, optimisation et génération de conformères.
3m 16s
16
L'Intuition de la Diffusion Moléculaire
Nous décomposons le concept fondamental des Diffusion Models sans les mathématiques lourdes. Les auditeurs comprendront le processus direct d'ajout de bruit à une molécule et le processus inverse d'hallucination de nouvelles structures.
3m 15s
17
Faire le Pont entre les Espaces Génératifs 2D et 3D
Nous explorons comment l'IA représente réellement les molécules qu'elle génère. Nous comparons la génération de graphes topologiques 2D plats avec la génération de nuages de points géométriques 3D complexes, ainsi que les défis de chacun.
3m 55s
18
Génération Sensible à la Cible et Docking
Découvrez la conception générative sensible au contexte. Nous discutons de la génération de nouvelles molécules directement à l'intérieur de la poche de liaison d'une protéine malade pour maximiser l'affinité de liaison.
4m 01s
19
Le Piège de la Taille dans l'Évaluation Générative
Apprenez pourquoi les benchmarks standards pour les modèles génératifs peuvent être profondément biaisés. Nous révélons l'effet de confusion de la taille de la bibliothèque générée sur des métriques telles que la Fréchet ChemNet Distance.
3m 59s
20
Naviguer dans les Hallucinations De Novo
Classez intelligemment les molécules générées par l'IA. Nous explorons le compromis exploration-exploitation des probabilités du modèle, et comment filtrer les 'hallucinations chimiques' fréquentes et de faible qualité.
3m 46s
21
Contraintes d'Échantillonnage de Molécules
Comprenez pourquoi les techniques de NLP échouent en chimie. Nous comparons le Temperature sampling au Top-k et au Top-p, et pourquoi le vocabulaire chimique contraint change tout.
3m 46s
22
Déployer la Chémoinformatique dans le Cloud
Passez votre pipeline d'IA en production. Nous discutons de l'empaquetage de RDKit et des modèles de machine learning dans des conteneurs Docker et de la mise à l'échelle des charges de travail sur l'infrastructure Cloud.
3m 37s

Épisodes

1

La Molécule Numérique

3m 27s

Nous présentons RDKit et le concept fondamental de la représentation de la chimie en Python. Les auditeurs apprendront à initialiser des objets moléculaires à partir de chaînes de caractères et comprendront le rôle central du framework dans la découverte de médicaments par l'IA.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Cheminformatics et IA en Python, épisode 1 sur 22. Avant de pouvoir prédire la toxicité d'un médicament avec un modèle de machine learning, tu dois résoudre un problème fondamental. Tu as besoin d'un moyen d'apprendre à Python ce qu'est réellement une molécule. Les types de données standards comme les strings et les lists ne comprennent pas les atomes, les liaisons ou les structures cycliques. Pour combler ce vide, tu as besoin d'un traducteur universel entre la chimie et le code. C'est exactement ce que propose RDKit, en introduisant le concept de molécule numérique. RDKit est le toolkit open-source de référence dans l'industrie pour la cheminformatics. À la base, c'est une library C++ haute performance, mais elle expose une interface Python massive et intuitive. Elle existe parce que représenter des structures chimiques informatiquement est étonnamment difficile. Mathématiquement, une molécule est un graphe. Les atomes sont des nodes, et les liaisons chimiques sont les edges qui connectent ces nodes. Si tu essaies de coder un parser de graphe custom from scratch à chaque fois que tu veux analyser des données chimiques, tu vas passer tout ton temps à debugger des edge cases. RDKit abstrait cette complexité, en gérant la logique du graphe sous le capot. Pour importer une molécule dans Python, tu as d'abord besoin d'une représentation texte de sa structure. Le format le plus courant est une string SMILES. SMILES utilise des caractères standards pour représenter la connectivité chimique. Par exemple, un atome de carbone isolé est simplement un C majuscule. Le benzène, qui est un cycle à six carbones avec des doubles liaisons alternées, s'écrit avec un c minuscule, le chiffre 1, quatre autres caractères c minuscules, et un dernier c minuscule suivi d'un chiffre 1 pour fermer le cycle. Voici le point essentiel. Cette string SMILES, c'est juste du plain text. Pour Python, c'est indiscernable d'un mot de passe ou d'un chemin de fichier. Tu ne peux pas calculer le poids moléculaire à partir d'une raw string. Pour faire de la vraie chimie, tu dois la convertir en un objet molécule RDKit. Tu gères ça en important le module Chem de RDKit. Ensuite, tu appelles une fonction spécifique conçue pour créer une molécule à partir d'une string SMILES, et tu lui passes ta variable texte. Quand tu passes la string SMILES du benzène à cette fonction, RDKit fait le plus gros du travail. Il parse le texte, construit le graphe de nodes et d'edges, assigne les ordres de liaison, et valide les règles chimiques de base comme les valences atomiques. Si la string représente une molécule valide, la fonction retourne un objet molécule. Si tu lui passes une structure chimiquement impossible ou une typo, la fonction fail de manière safe. Elle affiche un warning dans ta console et retourne un objet null. À cause de ça, tu devrais toujours vérifier si ton objet molécule existe vraiment avant de le passer à la prochaine étape de ton programme. Une fois que tu as cet objet molécule validé en mémoire, tout l'écosystème RDKit se débloque. Tu ne travailles plus avec du texte ; tu travailles avec un graphe chimique calculable. L'essentiel à retenir ici, c'est que les strings SMILES servent strictement au stockage et au transfert de données, mais les objets molécules RDKit sont faits pour le calcul. Tout ce que tu fais en chimie computationnelle commence par cette conversion. Si tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon — ça nous aide beaucoup. C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
2

Entrées/Sorties en Chémoinformatique

3m 48s

Apprenez à ingérer et exporter en toute sécurité des jeux de données chimiques massifs. Nous abordons la lecture des fichiers SDF et SMILES, la gestion des erreurs d'analyse et l'écriture des données sur le disque.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 2 sur 22. Une seule coordonnée manquante dans un dataset d'un million de molécules peut faire planter tout ton pipeline. Si tu pars du principe que chaque enregistrement texte de ton fichier fournisseur est parfaitement formaté, ton script Python finira par lever une exception fatale au beau milieu d'un job de dix heures. Il est impératif de se prémunir contre la dirty data quand tu fais entrer et sortir des structures de tes scripts, et c'est exactement ce qu'on va voir aujourd'hui avec l'I/O en chemoinformatique. Quand tu reçois un fichier SDF standard rempli de ligands potentiels, tu as besoin d'un moyen de le parser. Dans RDKit, l'outil par défaut pour ça, c'est le SD molecule supplier. Tu l'initialises en lui passant le chemin du fichier sous forme de string. Cet objet supplier se comporte vraiment comme une list Python. Tu peux boucler dessus, tu peux demander sa longueur totale, et tu peux extraire un enregistrement spécifique par son index. Il fait ça en scannant rapidement le fichier pour trouver où commence chaque molécule, ce qui te permet de naviguer dans les données. Parfois, tu ne peux pas scanner à l'avance. Si tu pipes des données directement depuis un stream web, ou que tu lis un énorme fichier gzippé chunk par chunk, tu n'as pas d'accès aléatoire. Pour ces situations, tu utilises le forward SD molecule supplier. Au lieu d'un chemin de fichier, tu lui passes un objet file ouvert. Ce forward supplier est un iterator strict. Il lit une molécule, la parse, et passe immédiatement à la suivante. Tu ne peux pas demander sa longueur, et tu ne peux pas demander la cinquantième molécule sans avoir lu les quarante-neuf premières. Tu sacrifies la flexibilité pour une faible utilisation de la mémoire et une compatibilité avec les streams. Voici le point essentiel. Quel que soit le supplier que tu utilises, RDKit ne lève pas d'exception Python quand il rencontre une molécule corrompue. Si un bloc de texte dans ton fichier a une valence invalide ou une erreur de formatage, RDKit va afficher un message d'erreur dans la console, mais l'objet Python qu'il yield pour cette itération de la boucle sera simplement le type None. Si tu prends cet objet None et que tu essaies de calculer son poids ou de l'écrire dans un nouveau fichier, ton script va planter. Gérer ça est simple mais crucial. La toute première ligne à l'intérieur de ta boucle de parsing doit toujours vérifier si la molécule yieldée est None. Si c'est None, tu utilises l'instruction continue pour passer à l'enregistrement suivant. Ça filtre silencieusement la garbage data et permet à ton pipeline de continuer à tourner. Une fois que tu as parsé et filtré tes molécules valides en toute sécurité, tu as généralement besoin de sauvegarder les résultats. Pour ça, tu utilises le SD writer. Tu initialises le writer en lui passant le chemin du fichier de sortie souhaité. À l'intérieur de ta boucle sécurisée, juste après ton check de None, tu passes l'objet molécule valide au writer en utilisant sa méthode write. Une fois que la boucle a fini de traiter chaque ligand, tu appelles la méthode close sur le writer pour t'assurer que toutes les données sont flushées sur le disque en toute sécurité. Tu peux aussi wrapper le writer dans un context manager Python standard pour qu'il se ferme automatiquement à la fin du bloc. Pour résumer tout ça dans un script de nettoyage de données, premièrement, crée ton SD writer pour le fichier de sortie. Deuxièmement, crée ton SD molecule supplier pour le fichier d'entrée. Boucle sur le supplier. Check si l'élément actuel est None, et si c'est le cas, skippe-le. S'il est valide, passe-le au writer. Ferme le writer à la fin. Considère toujours les datasets de chimie externes comme intrinsèquement dirty ; vérifier qu'une molécule parsée n'est pas None est la police d'assurance la moins chère que ton code n'aura jamais. C'est tout pour aujourd'hui. Merci d'avoir écouté, et continue à développer !
3

Parcours de Graphes Moléculaires

3m 13s

Découvrez comment les molécules sont représentées sous forme de structures de données de graphe. Nous explorons l'itération sur les atomes, l'analyse des liaisons et l'identification des systèmes cycliques au sein des molécules.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Python Cheminformatics et IA, épisode 3 sur 22. Pour un ordinateur, une molécule n'est pas un objet physique occupant de l'espace. C'est strictement un graphe de nœuds et d'arêtes qui attendent d'être parsés. Si tu ne peux pas naviguer efficacement dans ce graphe sous-jacent, tu ne peux pas analyser la structure chimique. Ce qui nous amène directement au parcours de graphe moléculaire. Dans RDKit, un objet molécule sert de conteneur principal pour cette structure de données de graphe. Pour inspecter les nœuds, tu utilises la méthode GetAtoms. Ça te retourne une séquence itérable contenant tous les objets atomes de la molécule. Tu peux écrire une simple boucle pour parcourir cette séquence un par un. Pour un scénario concret, suppose que tu aies besoin d'extraire les numéros atomiques de tous tes nœuds. À l'intérieur de ta boucle, tu peux appeler la méthode GetIdx pour trouver l'identifiant numérique unique de l'atome courant, et la méthode GetAtomicNum pour savoir exactement de quel élément chimique il s'agit. En itérant dessus, tu traites chaque nœud systématiquement. Les nœuds seuls ne définissent pas la chimie. Tu as aussi besoin des arêtes qui les connectent, auxquelles tu accèdes en utilisant la méthode GetBonds. Tout comme pour les atomes, ça te fournit une séquence itérable d'objets bond. Un bond connaît sa place exacte dans le graphe. En appelant les méthodes GetBeginAtomIdx et GetEndAtomIdx sur un objet bond, tu extrais les identifiants numériques spécifiques des deux atomes qu'il connecte. Tu peux aussi lire le bond type, pour déterminer s'il s'agit d'une connexion simple, double ou aromatique. Voici le point clé. RDKit traite les bonds comme des objets de première classe dans la hiérarchie du graphe, ce qui veut dire que tu les interroges indépendamment plutôt que d'aller les chercher dans les propriétés des atomes. Naviguer entre les nœuds et les arêtes individuels est une logique de graphe standard, mais les graphes chimiques présentent souvent des cycles, plus connus sous le nom de rings. Tu n'as pas besoin d'écrire tes propres algorithmes de parcours pour trouver ces cycles. RDKit précalcule ces cycles quand la molécule est instanciée. Tu accèdes à ces données via la méthode GetRingInfo. Ça te retourne un objet ring info dédié, plutôt qu'une simple liste. Si ta tâche est simplement de compter le nombre de rings dans la molécule, tu appelles la méthode NumRings directement sur cet objet ring info. Quand tu as besoin de détails structurels plus poussés, tu peux demander à ce même objet la propriété AtomRings. Ça te donne une collection de séquences, où chaque séquence contient les index exacts des atomes qui composent un ring spécifique dans le graphe. Tu peux même passer un index d'atome à l'objet ring info pour demander si ce nœud spécifique participe à un ring d'une taille particulière, comme un cycle à cinq ou six éléments. Parcourir une molécule, c'est finalement enchaîner ces opérations de base. Tu récupères les ring info pour vérifier la macro-structure, tu boucles sur les atomes pour lire les données au niveau des nœuds comme les numéros atomiques, et tu boucles sur les bonds pour mapper les connexions spécifiques des arêtes. Une fois que tu arrêtes de voir une molécule comme une entité physique et que tu commences à la voir comme une collection prévisible de nœuds indexés, d'arêtes et de cycles précalculés, l'extraction des propriétés structurelles devient une tâche standard de parsing de données. C'est tout pour cet épisode. Merci de ton écoute, et continue à développer !
4

Recherche de Sous-structures

3m 54s

Maîtrisez l'art d'interroger les molécules à l'aide de SMARTS. Nous vous guidons dans la recherche de groupes fonctionnels et de motifs spécifiques au sein de structures chimiques complexes.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 4 sur 22. Tu n'essaierais pas de parser des milliers de logs texte sans utiliser de regular expressions. De même, tu ne devrais pas essayer de filtrer des bases de données chimiques sans utiliser de patterns SMARTS. Trouver des groupes fonctionnels spécifiques dans de grands datasets demande une logique structurelle dédiée, et c'est exactement ce qu'offre le Substructure Searching. Supposons que tu aies une library de candidats médicaments. Ton but est de flagger et d'isoler toute molécule qui contient un groupe fonctionnel toxique spécifique et connu. D'abord, tu définis ce groupe toxique en utilisant une string SMARTS. SMARTS est une extension de SMILES conçue spécifiquement pour requêter des patterns moléculaires, ce qui te permet de spécifier des wildcards, des types de liaisons spécifiques ou des structures cycliques. Tu passes cette string de texte à la fonction RDKit qui crée une molécule à partir du SMARTS. Ça génère ton objet query. Tes molécules cibles, les candidats médicaments, sont déjà des objets molécules RDKit standards. Pour filtrer la library, tu prends une molécule candidate et tu appelles la méthode nommée has substructure match. Tu passes ton objet query à cette méthode. Elle évalue la molécule candidate par rapport au pattern et retourne une simple valeur booléenne. True signifie que le groupe toxique existe quelque part dans le candidat. False signifie qu'il est clean. Comme cette méthode arrête de chercher au moment où elle trouve un seul match valide, elle est très optimisée. Tu peux boucler cette vérification booléenne sur toute ta library pour diviser rapidement un dataset massif en sous-ensembles sûrs et flaggés. Maintenant, que faire si savoir simplement que le groupe toxique est présent ne suffit pas ? Peut-être que la toxicité augmente avec le nombre de fois où le groupe apparaît, ou que tu as besoin d'isoler l'emplacement exact des atomes toxiques pour un biologiste structural. Pour ça, tu utilises la méthode nommée get substructure matches, au pluriel. Tu l'appelles sur ta molécule candidate, en passant à nouveau l'objet query. Au lieu d'un booléen, cette méthode force le moteur de recherche à mapper chaque occurrence possible du pattern. Elle retourne un tuple contenant d'autres tuples. Chaque tuple interne représente un match complet de ton pattern. Les entiers à l'intérieur de ces tuples sont les indices exacts des atomes dans la molécule candidate. Voici le point clé. L'ordre de ces indices reflète parfaitement l'ordre des atomes définis dans ta string SMARTS d'origine. Ça veut dire que tu sais toujours exactement quel atome dans la cible correspond à quelle partie de ta query. Si le groupe toxique apparaît trois fois dans le candidat, tu obtiens trois tuples internes. Tu peux compter les tuples pour trouver la fréquence du pattern, ou passer ces indices d'atomes spécifiques à une fonction de dessin pour surligner visuellement les régions toxiques. Si tu as seulement besoin des indices d'atomes du tout premier match qu'elle trouve, tu peux utiliser la méthode au singulier get substructure match pour gagner du temps de traitement. Tu dois aussi prendre en compte la stéréochimie. Par défaut, le substructure matching de RDKit ignore complètement la chiralité. Une liaison en coin et une liaison en pointillés déclencheront toutes les deux un match pour une query SMARTS de base. Si la toxicité de ta cible ne se produit qu'avec un stéréoisomère spécifique, ce comportement par défaut générera des faux positifs dans ton drug screen. Pour corriger ça, tu passes un argument appelé use chirality et tu le mets sur true quand tu appelles n'importe laquelle des méthodes de matching. RDKit appliquera alors les règles stéréochimiques en fonction de la configuration spécifique définie dans ta query. La véritable puissance du Substructure Searching, c'est qu'il mappe une query texte purement logique directement sur la topologie physique de ton dataset, faisant le pont entre des patterns de strings abstraits et des coordonnées atomiques concrètes. C'est tout pour cette fois. Merci d'avoir écouté, et continue de développer !
5

Fingerprinting et Similarité Moléculaire

3m 53s

Découvrez comment traduire des graphes moléculaires en vecteurs de bits mathématiques. Nous abordons les clés MACCS, les Morgan fingerprints et le calcul de la similarité de Tanimoto.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Python Cheminformatics & IA, épisode 5 sur 22. Les modèles d'IA ne comprennent pas vraiment les atomes et les liaisons. Ils ne comprennent que les nombres. Si tu veux qu'un algorithme compare deux structures, tu dois trouver un moyen de traduire la chimie en maths. Le fingerprinting et la similarité moléculaire, c'est exactement comme ça qu'on fait le lien. Dans RDKit, une molécule est essentiellement un graphe mathématique. Les atomes agissent comme des nœuds, et les liaisons comme des arêtes. Pour faire des calculs rapides sur ces graphes, on les convertit en bit vectors, qui sont juste de longs arrays de uns et de zéros. Cet array s'appelle un fingerprint. La logique est super simple. Si une feature structurelle spécifique existe dans la molécule, un bit spécifique dans l'array passe à un. Si cette feature est absente, le bit reste à zéro. En convertissant des graphes moléculaires complexes en bit vectors standards, on peut facilement les comparer mathématiquement. RDKit propose plusieurs algorithmes de fingerprinting. Le fingerprint RDKit par défaut utilise une approche topologique. Il analyse les chemins linéaires à travers la molécule. Le système part d'un atome et suit les liaisons connectées jusqu'à une longueur spécifique, généralement entre une et sept liaisons. Chaque chemin unique qu'il trouve est passé dans une fonction de hashing, qui assigne ce chemin à une position spécifique dans le bit vector. Même si les chemins topologiques sont utiles, la Cheminformatics moderne repose énormément sur les Morgan fingerprints, qu'on appelle souvent circular fingerprints. Au lieu de tracer des chemins linéaires, les algorithmes de Morgan analysent le voisinage qui rayonne autour de chaque atome. Quand tu génères un Morgan fingerprint, tu dois définir un radius. Un radius de zéro signifie que l'algorithme enregistre uniquement les atomes individuels. Un radius de un capture chaque atome plus ses voisins connectés immédiats. Un radius de deux étend ce cercle d'une liaison supplémentaire. L'algorithme catalogue tous ces environnements circulaires qui se chevauchent, les hash, et passe les bits correspondants à un. Généralement, on fold ces hashes dans un vecteur de longueur fixe, comme deux mille quarante-huit bits, pour garder une utilisation de la mémoire prévisible. Les Morgan fingerprints avec un radius de deux sont le standard de l'industrie parce qu'ils capturent parfaitement les groupes fonctionnels et le contexte chimique local. Prenons un scénario concret. Tu as deux molécules légèrement différentes. Elles partagent peut-être une grande structure de base, mais l'une d'elles a un groupe méthyle supplémentaire attaché. Tu veux quantifier à quel point elles se chevauchent. D'abord, tu lis les deux molécules dans RDKit. Ensuite, tu génères un Morgan fingerprint pour chacune, en réglant le radius sur deux. Tu as maintenant deux bit vectors distincts. Pour calculer à quel point elles se ressemblent, tu calcules leur similarité de Tanimoto. Voici l'idée clé. La similarité de Tanimoto ignore les zéros. Elle ne s'intéresse qu'aux features qui sont réellement présentes. Le calcul est simple, c'est l'intersection sur l'union. RDKit compte le nombre de bits à un dans les deux fingerprints, et divise ça par le nombre total de bits à un dans l'un ou l'autre des fingerprints. Si les deux vecteurs correspondent parfaitement, le score de Tanimoto est de un point zéro. S'ils ne partagent aucune feature du tout, le score est de zéro point zéro. Pour nos deux molécules qui diffèrent par un seul groupe méthyle, les environnements circulaires autour du noyau vont globalement correspondre, alors que les environnements près de la mutation seront différents. Tu pourrais obtenir un score de Tanimoto de zéro point quatre-vingt-cinq, ce qui te donne une valeur numérique précise pour leur chevauchement structurel. Garde à l'esprit que mapper une molécule complexe vers un array de bits fixe implique une perte de données, et qu'un score de Tanimoto élevé garantit un chevauchement structurel, pas une équivalence biologique. Merci d'avoir passé quelques minutes avec moi. À la prochaine, prends soin de toi.
6

Briser le Plan 2D

3m 31s

Passez de dessins 2D plats à des géométries 3D réalistes. Nous discutons de l'ajout d'hydrogènes explicites et de la génération de conformères 3D fiables à l'aide d'ETKDG.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics et IA, épisode 6 sur 22. Un dessin en 2D peut rendre super bien à l'écran, mais les médicaments existent dans un espace en 3D. Si tu ignores la géométrie, tu ignores la réalité. Aujourd'hui, on sort du plan 2D et on génère de vraies coordonnées 3D pour tes molécules. Quand tu lis une molécule à partir d'une SMILES string standard, elle n'a aucune coordonnée. C'est strictement un graphe topologique d'atomes connectés. Même si tu charges une structure depuis un fichier de dessin 2D, ces coordonnées sont juste espacées pour être lisibles par un humain. Pour faire du docking, calculer la surface ou lancer des simulations physiques, tu as besoin d'une structure 3D physiquement réaliste. La toute première étape avant de générer la moindre géométrie 3D, c'est d'ajouter les hydrogènes. Dans une SMILES string standard, les hydrogènes sont implicites. Ils sont traités comme une propriété de base des atomes lourds, remplissant simplement les exigences de valence. Mais dans l'espace physique, les hydrogènes occupent un vrai volume. Ils créent un encombrement stérique, et ils dictent les angles des liaisons autour d'eux. Si tu essaies de calculer une structure 3D sans ajouter explicitement les hydrogènes d'abord, la géométrie qui en résulte va s'effondrer sur elle-même et les angles de liaison seront complètement faux. RDKit fournit une fonction appelée AddHs qui convertit ces hydrogènes implicites en vrais nodes dans ton graphe moléculaire, avec leurs liaisons. Tu dois toujours lancer cette fonction avant de passer à la 3D. Une fois que tu as une molécule complète, tu dois calculer ses coordonnées spatiales. Comme les liaisons simples peuvent tourner librement, un ligand flexible n'a pas qu'une seule forme statique. Il peut adopter plein de formes différentes, qu'on appelle des conformations. Pour générer une conformation viable, RDKit utilise une méthode par défaut appelée ETKDG. Ça signifie Experimental Torsion-angle Preference with Distance Geometry. Voici l'idée clé. Les méthodes d'ancienne génération reposaient entièrement sur des maths pures. Elles utilisaient la distance geometry pour deviner les positions atomiques en se basant sur des longueurs et des angles de liaison connus. Ça donnait souvent des formes bizarres à haute énergie qui demandaient un gros nettoyage computationnel. ETKDG résout ça en combinant les maths de la distance geometry avec des règles empiriques tirées de la Cambridge Structural Database. Il sait comment les vraies molécules physiques préfèrent réellement se plier et se tordre, et il force l'algorithme de géométrie à respecter ces préférences naturelles. Prends un scénario concret. Tu as un ligand très flexible, et tu as besoin de comprendre toutes les différentes façons dont il pourrait se replier pour rentrer dans une binding pocket de protéine. Générer une seule conformation ne suffit pas pour capturer ce comportement. Tu as besoin d'un ensemble. RDKit gère ça avec une fonction appelée EmbedMultipleConfs. Tu lui passes ta molécule avec ses hydrogènes explicites, et tu spécifies que tu veux cinquante conformers. RDKit va alors lancer l'algorithme ETKDG cinquante fois séparément, en partant de différentes random seeds, pour générer cinquante géométries 3D distinctes. Il stocke ces cinquante formes à l'intérieur de l'objet molécule d'origine. Tu ne récupères pas cinquante molécules séparées ; tu obtiens une seule molécule qui contient cinquante sets de coordonnées distincts. Tu peux ensuite faire une loop sur ces sets de coordonnées pour mesurer des distances ou calculer des énergies. Comme ETKDG est fortement basé sur des données cristallographiques du monde réel, les structures initiales qu'il fournit sont généralement de très haute qualité dès la sortie de la fonction. Une molécule n'est pas un dessin plat, et c'est rarement juste une seule forme rigide ; c'est un objet dynamique, et sampler ses multiples conformers te donne les vraies limites de son comportement physique. Si tu veux aider à faire continuer l'émission, tu peux nous soutenir en cherchant DevStoriesEU sur Patreon. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de builder !
7

Accélérer le Feature Engineering

3m 40s

Faites le pont entre la chémoinformatique et la data science classique avec scikit-fingerprints. Nous explorons la génération de plus de 30 types de fingerprints moléculaires directement dans une interface scikit-learn.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 7 sur 22. Écrire des loops d'extraction de fingerprints sur mesure pour chaque nouveau projet, c'est fastidieux et source d'erreurs. Tu passes d'un fingerprint ECFP à une MACCS key, et d'un coup tu dois réécrire tout ton bloc de preprocessing. Scikit-fingerprints est une librairie qui résout ce problème en rendant l'extraction de features moléculaires aussi simple que d'appeler un transform scikit-learn standard. Les molécules sont fondamentalement représentées sous forme de graphes. Or, la plupart des algorithmes de machine learning nécessitent des vecteurs multidimensionnels. Les fingerprints moléculaires sont les algorithmes d'extraction de features qui comblent cet écart, en encodant les informations structurelles dans des arrays numériques. Le problème, c'est que les outils open source standards pour calculer ces fingerprints, comme RDKit, Open Babel ou le Chemistry Development Kit, sont écrits en C++ ou en Java. Leurs wrappers Python ne s'alignent pas nativement avec l'API de scikit-learn. Tu finis par écrire des data loaders sur mesure, des convertisseurs de format et des loops sujettes aux erreurs, juste pour donner à tes données une forme qu'un classifier peut consommer. Scikit-fingerprints change cette architecture. Elle implémente plus de 30 fingerprints moléculaires différents sous forme de transformers scikit-learn standards et stateless. Toutes les classes de fingerprints héritent des classes de base de scikit-learn. Ça veut dire qu'elles se branchent directement dans les pipelines de machine learning et les feature unions standards. Prends un workflow standard. Normalement, tu écrirais une loop sur mesure d'une vingtaine de lignes dans RDKit pour itérer sur un dataset, valider les molécules, extraire les fingerprints circulaires et empiler les résultats dans un array. Avec cette librairie, tu remplaces tout ce bloc de boilerplate par une seule étape. Tu crées un objet appelé ECFP Fingerprint et tu le passes directement dans un pipeline scikit-learn, juste avant ton modèle random forest. Quand tu appelles la méthode fit sur ton pipeline avec tes données de training et tes variables cibles, le transformer de fingerprint traite les inputs et sort un array NumPy dense directement vers le modèle. Voici le point clé. Tu n'as pas besoin de convertir tes représentations textuelles en objets molécules RDKit avant de les passer au transformer. Pour n'importe quel fingerprint en deux dimensions basé sur la topologie du graphe, la méthode transform accepte directement une liste Python standard de strings SMILES. La librairie gère la conversion interne automatiquement. Comme les strings SMILES ne sont pas toujours uniques ou chimiquement valides, la librairie fournit aussi une classe Molecule Standardizer. Cette classe applique les étapes de sanitization recommandées par RDKit pour garantir la qualité des données avant que l'extraction ne commence. La librairie supporte aussi les fingerprints en trois dimensions qui reposent sur la conformation spatiale. Ces algorithmes spatiaux nécessitent par contre des objets molécules RDKit avec des conformères calculés. Générer des conformères peut être instable, donc le package inclut une classe Conformer Generator qui utilise un algorithme spécifique connu sous le nom d'ETKDG version 3. Ça fournit des valeurs par défaut fiables qui maximisent l'efficacité pour les molécules simples, tout en minimisant les échecs de calcul sur les composés complexes. Tu mets le conformer generator au début de ton pipeline, tu le fais suivre d'un transformer de fingerprint en trois dimensions, et tu termines par un imputer pour gérer les valeurs manquantes. En encapsulant la logique chimique complexe dans des classes de transformers standards, la librairie fait abstraction du boilerplate spécifique au domaine. Tu configures des options comme la longueur du vecteur d'output, ou si tu veux une variante binaire ou de comptage, simplement en passant des paramètres au constructeur du transformer. Le résultat, c'est que le tuning des hyperparamètres pour les fingerprints moléculaires devient aussi simple que de régler la profondeur d'un arbre de décision. C'est tout pour aujourd'hui. À la prochaine !
8

Chémoinformatique Haute Performance

4m 11s

Apprenez à traiter efficacement des jeux de données chimiques massifs. Nous nous plongeons dans l'utilisation du parallélisme CPU avec Joblib et l'économie de mémoire grâce aux matrices creuses de SciPy.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 8 sur 22. Calculer des sous-structures complexes sur un énorme dataset peut facilement faire crasher ta machine avec des erreurs out-of-memory, à moins que tu saches exactement comment gérer l'empreinte de tes données. La technique qui résout ça, c'est le High-Performance Cheminformatics. Quand tu extrais des features d'une molécule, tu utilises souvent des fingerprints basés sur des sous-structures. Le fingerprint de Klekota-Roth en est un exemple classique. Pour le calculer, ta machine compare une molécule à des milliers de patterns chimiques prédéfinis, qu'on appelle des patterns SMARTS. Elle scanne le graphe moléculaire en boucle pour voir si des groupes fonctionnels ou des motifs structuraux spécifiques existent. Faire ça de façon séquentielle pour quelques molécules, ça passe. Mais le faire pour un dataset de quatre cent mille molécules, c'est un énorme bottleneck de calcul. Le calcul de fingerprints moléculaires est une tâche embarrassingly parallel. L'analyse structurelle d'une molécule n'a absolument aucune dépendance avec l'analyse de la molécule suivante dans ton dataset. Comme elles ne partagent aucun state, tu peux les calculer de façon complètement simultanée. Pour scaler ça efficacement en Python, tu utilises Joblib, en t'appuyant plus précisément sur l'executor Loky. Quand tu lances le process, le dataset d'input est divisé en chunks qui correspondent exactement à tes cœurs CPU disponibles. Si tu as un processeur à 16 cœurs, tes molécules d'input sont divisées en 16 batches séparés. Chaque process worker Python prend un batch et commence à exécuter le pattern matching SMARTS de manière indépendante. L'obstacle technique avec le multiprocessing en Python, c'est généralement le coût du déplacement des données entre les workers et le main process. Loky contourne ça en utilisant le memory mapping. Au lieu de sérialiser les arrays de fingerprints finaux et de les envoyer via la communication inter-process, les workers écrivent directement dans un espace de mémoire partagée. Pour des fingerprints lourds en calcul comme Klekota-Roth, distribuer la charge de travail sur 16 cœurs offre un speedup de presque quinze fois. Ça, ça règle le temps de traitement. Le deuxième bottleneck critique, c'est la mémoire système. Un seul vecteur de fingerprint Klekota-Roth est long. Si tu traites des centaines de milliers de molécules, tu génères une matrice de résultats massive. Par défaut, les librairies numériques renvoient ce résultat sous forme de dense array NumPy. Chaque position dans cette matrice alloue de la mémoire, peu importe si la valeur est un un ou un zéro. Les fingerprints chimiques sont extrêmement sparse. Généralement, seulement un ou deux pour cent des features structurelles demandées sont réellement présentes dans une molécule donnée. La grande majorité de ta matrice de résultats est constituée de zéros. Stocker ces zéros, c'est ce qui déclenche les erreurs out-of-memory sur les gros datasets. La solution, c'est de passer le format d'output sur une sparse matrix SciPy, en utilisant plus précisément le format Compressed Sparse Row. Une sparse matrix change fondamentalement la façon dont les données sont stockées. Au lieu de construire une grille rigide en mémoire, elle enregistre uniquement les valeurs des éléments non nuls avec leurs coordonnées de ligne et de colonne. Prends un scénario du monde réel utilisant le dataset PCBA, qui contient un peu moins de quatre cent quarante mille molécules. Tu lances le calcul du fingerprint Klekota-Roth sur tout le dataset en utilisant tes 16 cœurs. L'exécution parallèle se termine efficacement. Si tu laisses l'output comme un dense array par défaut, cette seule matrice va consommer un peu plus de deux gigaoctets de RAM. En demandant au calcul de renvoyer un sparse array SciPy à la place, ce même dataset tombe à une empreinte de seulement 23 mégaoctets. Tu obtiens une réduction de mémoire de quatre-vingt-huit fois sans perdre la moindre information chimique, et la représentation sparse n'a absolument aucun impact négatif sur ton temps de calcul. Voici l'idée clé. Tu n'as pas besoin d'un énorme cluster de calcul pour traiter des centaines de milliers de molécules, à condition d'arrêter de payer la taxe mémoire pour stocker des zéros et de t'assurer que ton passage de données évite l'overhead de la communication inter-process standard. C'est tout pour cet épisode. Merci d'avoir écouté, et continue à développer !
9

Pipelines ML de Bout en Bout

3m 47s

Combinez le traitement, le fingerprinting et la prédiction dans une seule architecture propre. Nous construisons des pipelines scikit-learn robustes qui intègrent de manière transparente la génération de conformères 3D et la prédiction de propriétés.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Python Cheminformatics et IA, épisode 9 sur 22. Auparavant, un script complexe de virtual screening 3D nécessitait des centaines de lignes de code fragile. Tu devais générer manuellement les conformers, gérer les erreurs, calculer de multiples descriptors, et assembler les arrays avant même de toucher à un modèle. Maintenant, tu peux architecturer tout le process dans une seule définition de pipeline élégante en utilisant des pipelines ML End-to-End. En machine learning, un pipeline est une séquence d'étapes de data processing et un estimator final regroupés dans un seul objet. En cheminformatics, surtout avec les données structurelles 3D, le preprocessing est notoirement fragmenté. Tu prends des strings SMILES brutes, tu calcules les coordonnées 3D, tu lances des optimisations de force field, tu extrais les features, tu corriges les missing values, et enfin tu entraînes un classifier. Faire ça manuellement, ça veut dire écrire des boucles custom et des data structures intermédiaires qui cassent facilement et font des memory leaks. On va voir ensemble comment construire un pipeline scikit-learn complet qui prend des SMILES brutes et va direct jusqu'à un classifier Random Forest. La première étape de la séquence, c'est la génération de conformers. Tu initialises un conformer generator et tu le passes comme première étape du pipeline. Il lit l'input 2D et calcule les structures 3D. Tu peux le configurer pour optimiser la géométrie en utilisant un force field comme MMFF94. Il parallélise automatiquement ce gros calcul sur tous les cœurs de CPU disponibles. Maintenant, la deuxième partie, c'est la feature extraction. Pour les tâches 3D, combiner différents descriptors géométriques permet de capturer plus d'informations moléculaires. Tu utilises un feature union de scikit-learn pour calculer simultanément les fingerprints GETAWAY et WHIM. Ces deux classes de fingerprints agissent comme des transformers stateless dans le pipeline. Elles prennent les conformers 3D de l'étape précédente, calculent leurs descriptors respectifs en parallèle, et concatènent les résultats dans une seule grande feature matrix. Ensuite, tu dois gérer les erreurs de calcul. Les algorithmes de descriptors 3D échouent parfois à traiter des molécules très complexes ou sous tension, ce qui donne des missing values dans ta matrice. Le pipeline gère ça sans error handling custom. Tu places un simple imputer directement après le feature union. Si un calcul GETAWAY ou WHIM sort une missing value, l'imputer l'attrape et la remplace par la moyenne de cette feature sur tout ton dataset. Enfin, tu termines le pipeline avec ton modèle prédictif, qui dans ce cas est un classifier Random Forest. Pour architecturer ça dans le code, tu appelles la fonction make pipeline. À l'intérieur de cet appel de fonction, tu passes ton conformer generator. Ensuite, tu passes le feature union qui contient tes fingerprints GETAWAY et WHIM. Puis vient le simple imputer, et pour finir, le classifier Random Forest. Tu assignes toute cette séquence à une seule variable. Quand tu appelles la méthode fit sur cette variable de pipeline, tu passes tes strings SMILES d'entraînement brutes et tes target labels. Les strings passent séquentiellement par le conformer generator, dans le feature union pour le fingerprinting, à travers l'imputer pour nettoyer la data, et vont direct dans le classifier pour l'entraînement. Au moment d'évaluer, appeler la méthode predict sur tes strings SMILES de test force la nouvelle data à suivre exactement le même chemin. Voici l'idée clé. Le state et le data routing sont entièrement gérés par l'objet pipeline, ce qui veut dire que tu ne gardes jamais de dense arrays intermédiaires en mémoire, et que tu n'écris pas de data loaders custom pour tes conformers. C'est tout pour cet épisode. Merci de m'avoir écouté, et continue de développer !
10

Prédire l'Affinité de Liaison

3m 42s

Explorez la réalité de la prédiction de l'affinité de liaison protéine-ligand. Nous comparons les performances de modèles simples basés sur des arbres 2D à celles de Graph Neural Networks 3D complexes.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 10 sur 22. Tu montes un énorme graph neural network en 3D, en lui passant les coordonnées spatiales de chaque atome dans une poche protéique. Tu lances ensuite un simple gradient boosted decision tree qui ne regarde que le schéma en 2D du médicament. Le benchmark se termine, et ton modèle spatial dernier cri vient de se faire battre par un algorithme d'il y a vingt ans. La raison pour laquelle ton gros réseau a échoué vient de la façon dont on gère la prédiction de la binding affinity. Prédire la binding affinity, c'est le processus informatique qui estime à quel point une petite molécule, ou ligand, s'attache fermement à une cible protéique spécifique. En drug discovery, trouver une molécule qui se lie fortement, c'est le but ultime. Pour faire ça, les ingénieurs prennent généralement l'une des deux voies suivantes. La première est hyper complexe. Tu utilises des réseaux de neurones en 3D comme GraphNet ou TensorNet. Ces modèles ingèrent la conformation liée exacte du complexe protéine-ligand. Ils utilisent des message passing layers pour apprendre les distances spatiales précises et les features de mécanique quantique entre les atomes du médicament et les atomes de la poche protéique. La deuxième voie ignore complètement la protéine. Tu laisses tomber les coordonnées spatiales et tu utilises un modèle classique en 2D comme XGBoost. Ici, l'input est juste un vecteur concaténé de molecular fingerprints. Tu calcules les features structurelles à partir du ligand seul, ce qui transforme en gros le dessin en 2D de la molécule en un array de nombres, et tu feed ça directement dans le modèle basé sur des arbres. Pour voir comment ces approches se comparent, les chercheurs les font tourner sur des test sets standardisés. L'un des plus parlants est le benchmark Merck FEP. Ce dataset simule un scénario courant de virtual screening appelé série congénérique. Dans une série congénérique, tous les ligands testés partagent exactement le même scaffold chimique de base et se lient exactement au même site sur une seule cible protéique. Les seules différences entre les molécules sont de petites variations structurelles, comme différentes branches chimiques attachées au noyau principal. Voici le point clé. Lors de l'évaluation sur le dataset Merck, les gros modèles en 3D ont atteint un score de corrélation d'environ zéro virgule trois. Le modèle XGBoost simple en 2D a obtenu un score nettement supérieur, atteignant zéro virgule quatre cinq. Le decision tree, très peu coûteux en calcul, a clairement surpassé les graph neural networks avancés. Ça arrive à cause de ce sur quoi les modèles sont forcés de se concentrer. Dans une série congénérique, la cible protéique et la binding pocket ne changent pas. Le modèle en 3D dépense des ressources de calcul massives pour mapper un environnement spatial qui reste statique à travers chaque test case. Pire encore, ces modèles sont hyper sensibles aux minuscules variations des coordonnées atomiques. Un léger décalage arbitraire dans le placement d'un atome d'hydrogène pendant la préparation des données introduit du bruit qui distrait le graph network. Le modèle en 2D réussit précisément parce qu'il est aveugle à la protéine. En ne regardant que les features du ligand, il se base sur les seules variables qui changent vraiment d'un test à l'autre. Le decision tree corrèle ces variations structurelles directes du médicament à la force de liaison finale, en contournant complètement le bruit de l'environnement spatial. Les gros modèles en 3D restent super utiles quand tu as besoin de généraliser sur des cibles protéiques complètement différentes et jamais vues, où la géométrie de la poche est inconnue. Mais quand tu optimises une famille spécifique de médicaments pour une seule cible connue, feeder des données environnementales constantes dans un deep network est inefficace et sujet aux erreurs. L'outil prédictif le plus puissant est souvent celui qui filtre l'environnement statique et ne modélise que les variables qui changent. C'est tout pour aujourd'hui. À la prochaine !
11

LLMs vs Fingerprints Classiques

3m 59s

Découvrez comment le NLP s'applique à la chimie. Nous opposons les embeddings vectoriels des Large Language Models aux fingerprints structurels classiques de RDKit pour prédire la bioactivité.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatique & IA, épisode 11 sur 22. Et si la meilleure façon de décrire une molécule à un modèle de machine learning n'était pas d'utiliser une formule structurelle faite à la main, mais de traiter sa string SMILES exactement comme une phrase en langage naturel ? Tu pourrais gaspiller de précieux cycles de compute à générer des descripteurs chimiques complexes, juste pour te faire battre par un modèle de texte. Cette tension est au cœur du débat entre les LLMs et les fingerprints classiques. Quand tu prédis avec quelle force un ligand se lie à une protéine, ton modèle a besoin d'une description mathématique du ligand. L'approche traditionnelle repose sur des fingerprints structurels classiques calculés par des outils comme RDKit. Tu passes une molécule dans un algorithme déterministe et tu reçois un vecteur statique. Un fingerprint de Morgan compte les sous-structures circulaires autour des atomes. Les MACCS keys vérifient la molécule par rapport à une liste prédéfinie de patterns chimiques. La limite de ces fingerprints classiques, c'est leur rigidité. Ils encodent des règles spécifiques et immuables. Tu ne peux pas les fine-tuner. Si une nuance structurelle particulière est importante pour une binding pocket très spécifique, mais que l'algorithme du fingerprint n'a pas été explicitement conçu pour la capturer, cette information est complètement perdue avant même que le modèle prédictif ne voie les données. Au lieu de hardcoder des règles chimiques, on peut utiliser un Large Language Model chimique pré-entraîné comme BioT5, GPT2 ou BERT. Ces modèles sont pré-entraînés sur des millions de strings SMILES. Ils apprennent la grammaire de la chimie de manière non supervisée. Quand tu passes un ligand à un LLM, il ne sort pas une checklist fixe de groupes fonctionnels. Il sort un embedding vectoriel riche. Chaque caractère ou token dans cette string SMILES obtient son propre vecteur contextuel. Pour comprendre la différence, regarde comment ces représentations alimentent les modèles prédictifs. D'abord, prends un modèle XGBoost qui utilise des MACCS keys classiques. Tu génères le fingerprint MACCS, ce qui donne un simple array binaire. Tu passes ce vecteur fixe à XGBoost, qui essaie de mapper ces features brutes de présence ou d'absence à l'affinité de liaison. Dans les tests de benchmark sur des séries congénériques, cette combinaison spécifique donne systématiquement les pires performances. Les features faites à la main sont tout simplement trop grossières. Maintenant, remplace cette architecture par un embedding BioT5 passé à un Transformer head. D'abord, tu passes la string SMILES brute au modèle BioT5. Ça te retourne une séquence d'embeddings par token. Ensuite, tu passes cette séquence dans un Transformer head. Voici l'idée clé. Le Transformer utilise un mécanisme d'attention. Il regarde toute la séquence d'embeddings de tokens et apprend dynamiquement quelles parties de la molécule comptent le plus pour se lier à cette target spécifique. Il pondère les features intelligemment avant de sortir l'affinité de liaison prédite. Si tu essaies de prendre exactement ces mêmes tokens BioT5, de les additionner pour en faire un seul vecteur plat, et de passer ça à XGBoost, les performances prédictives chutent considérablement. Le sum pooling lisse les détails au niveau du token. Le Transformer head réussit précisément parce qu'il préserve et exploite le contexte granulaire de la représentation de type texte. Ce passage des arrays statiques aux embeddings dynamiques offre d'énormes avantages pratiques. Les embeddings de LLM sont hyper polyvalents et peuvent être fine-tunés pour des tâches downstream spécialisées. Ils sont aussi beaucoup plus compacts que les énormes bit vectors classiques, ce qui économise de la mémoire quand on stocke de grandes bibliothèques moléculaires. En plus, la génération d'embeddings de texte tourne sur un GPU, ce qui est radicalement plus rapide que de calculer des fingerprints RDKit traditionnels sur un CPU. L'époque où l'on disait manuellement aux algorithmes quelles sous-structures chimiques comptent touche à sa fin ; les modèles les plus performants sont ceux qu'on laisse lire la molécule et décider par eux-mêmes. Si tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. Merci d'avoir écouté. J'espère que tu as appris quelque chose de nouveau.
12

Active Learning pour le Criblage Virtuel

3m 49s

Apprenez à découvrir de manière itérative les meilleurs candidats médicaments sans tests exhaustifs. Nous plongeons dans les boucles d'Active Learning et les stratégies de sélection gloutonnes pour maximiser les taux de réussite.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 12 sur 22. Faire tourner des simulations physiques complexes sur un million de molécules, c'est incroyablement lent. Tu as besoin d'un moyen de trouver les tout meilleurs candidats en testant juste une infime partie de ton dataset. C'est exactement ce que fait l'Active Learning pour le Virtual Screening. Quand tu évalues une chimiothèque, calculer des affinités de liaison précises avec des méthodes de physique computationnelle, c'est incroyablement coûteux. Tu ne peux tout simplement pas te permettre de simuler chaque composé un par un. À la place, tu testes un petit batch, tu utilises ces résultats pour entraîner un modèle de machine learning, et tu laisses ce modèle prédire les affinités pour le reste de la chimiothèque. Ensuite, tu testes les prédictions les plus prometteuses, tu mets à jour le modèle, et tu répètes le process. Ce cycle itératif, c'est ça l'Active Learning. Prenons un scénario concret. Tu explores une série congénérique de dix mille composés qui ciblent une protéine spécifique, comme Tyk2. Ton but est de trouver le top un pour cent des molécules les plus actives. Pour faire ça efficacement, tu te reposes sur une stratégie de sélection greedy. Une stratégie greedy, ça veut dire que ton modèle choisit toujours les composés avec les affinités de liaison prédites les plus hautes pour le prochain round de tests. Tu règles ton batch size à soixante molécules par round. Ce nombre offre un bon compromis pratique pour un workflow du monde réel. C'est assez petit pour que tu puisses faire tourner rapidement des simulations physiques exigeantes sur le batch, mais assez grand pour fournir un bon chunk de nouvelles données à ton modèle. Tu lances tes tests sur ces soixante composés pour obtenir leurs vraies affinités de liaison, et tu passes directement ces données à un modèle tree-based en 2D, comme XGBoost. Le modèle XGBoost apprend les patterns, score les molécules non testées restantes dans le pool de dix mille composés, et sélectionne les soixante prochains candidats. Voici le point clé. La façon dont tu choisis le tout premier batch de soixante molécules dicte la vitesse à laquelle tout ton système apprend. L'Active Learning standard utilise souvent par défaut une baseline random. Tu sélectionnes soixante molécules complètement au hasard, tu les testes, et tu entraînes ton premier modèle. Mais la sélection random donne à ton modèle un mauvais point de départ, en remplissant le training set initial avec surtout des composés inactifs. La solution, c'est d'initialiser la loop d'Active Learning en utilisant un neural network 3D pré-entraîné. Ce modèle 3D a déjà été entraîné sur un dataset massif et général de divers complexes protéine-ligand. Comme il comprend la physique générale des liaisons basée sur les interactions structurelles, il peut scorer tes dix mille composés avant même que la loop d'Active Learning ne commence. D'abord, tu utilises le modèle 3D pré-entraîné pour prédire les affinités de tout le pool. Ensuite, tu prends le top soixante des molécules identifiées par ce prescreening et tu fais tourner tes lourdes simulations physiques dessus. Maintenant, tu as un set de données de départ hautement enrichi. Tu passes ce dataset initial de haute qualité à ton modèle XGBoost. À partir de là, le modèle XGBoost prend le relais sur le cycle. Il s'entraîne sur les données vérifiées, fait ses prédictions sur le reste du pool, et sélectionne de façon greedy les soixante prochains candidats. Cette combinaison génère une accélération massive dans le hit discovery. Le modèle 3D général fournit un point de départ riche, et le modèle XGBoost s'adapte rapidement à l'espace chimique spécifique de ta série congénérique. En initialisant avec un modèle 3D pré-entraîné au lieu d'un random sampling, tu peux trouver quatre-vingts pour cent du top un pour cent des binders après avoir testé moins de dix pour cent de tout le dataset. Démarrer ta loop avec un prescreening 3D général donne à tes modèles spécialisés une avance imbattable. C'est tout pour aujourd'hui. Merci d'avoir écouté, et continue à développer !
13

Le Défi des Activity Cliffs

3m 27s

Examinez la fragilité des relations structure-activité. Nous discutons des 'activity cliffs' — où un changement structurel infime provoque une modification massive de la puissance d'un médicament.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 13 sur 22. En chimie, un seul atome mal placé peut transformer un médicament puissant et vital en une poudre inerte. Ces chutes brutales de puissance biologique s'appellent des activity cliffs, et c'est le pire cauchemar des modèles d'AI traditionnels. Un activity cliff se produit quand tu as une paire de molécules avec une forte similarité structurelle mais des niveaux d'activité complètement différents. Prends un scénario concret. Tu as deux molécules qui partagent 90 % de leur framework structurel. La première molécule se lie fortement à une cible biologique. La deuxième molécule est complètement inactive. La seule différence physique entre elles, c'est un seul groupe méthyle attaché à un cycle spécifique. Pour un chimiste médicinal humain, cette modification structurelle spécifique est super informative. Ça lui indique exactement où se trouvent les limites de la poche du récepteur. Pour un modèle de machine learning standard, c'est une perturbation catastrophique. Voici l'idée clé. La plupart des approches de deep learning en cheminformatics sont construites pour prédire des valeurs de propriétés absolues. Que tu utilises un graph neural network ou un chemical language model, l'architecture est fondamentalement conçue pour mapper les structures chimiques dans un espace mathématique continu. L'hypothèse de base hardcodée dans ces modèles, c'est que des structures moléculaires similaires devraient se mapper sur des propriétés biologiques similaires. Quand un modèle standard traite nos deux molécules presque identiques, il génère des représentations qui sont juste à côté l'une de l'autre dans cet espace mathématique. Parce que les inputs sont très proches, le modèle sort naturellement des prédictions de puissance absolue presque identiques pour les deux. Les activity cliffs violent fondamentalement cette hypothèse d'un espace chimique lisse et continu. Ils représentent une discontinuité sévère. Le modèle s'attend à une colline en pente douce, mais il tombe sur une chute verticale. Ce problème est fortement amplifié par la nature des données de drug discovery. Les datasets expérimentaux sont notoirement limités et bruités. Quand tu entraînes un deep neural network sur des données éparses, le modèle a du mal à généraliser. Pour minimiser l'erreur globale sur le training set, le réseau apprend des patterns larges et globaux. Il lisse les irrégularités locales. Quand il rencontre un activity cliff, l'objectif de régression standard traite ce saut soudain de variance comme du bruit expérimental ou un outlier. Le modèle ignore l'information structurelle locale la plus critique parce qu'elle ne colle pas à la tendance globale. C'est pourquoi prédire les activity cliffs reste l'un des problèmes les plus difficiles dans la prédiction des propriétés moléculaires. Les modèles sont forcés d'apprendre un espace chimique discontinu directement à partir de données limitées. Parce qu'ils se concentrent entièrement sur des prédictions absolues pour des molécules uniques, ils ignorent complètement l'information précieuse cachée dans les différences relatives entre les paires moléculaires correspondantes. Dans beaucoup de cas, des tree-based models plus simples finissent en fait par surpasser les neural networks complexes sur ces datasets, tout simplement parce que les modèles de deep learning lissent trop les représentations. L'hypothèse selon laquelle des structures chimiques similaires donnent toujours des activités biologiques similaires est une baseline statistique utile, mais ce n'est pas une loi physique. Les activity cliffs sont la réalité brutale et discontinue des relations structure-activité, et ils prouvent que prédire des propriétés absolues dans le vide échouera toujours à la marge. Merci d'avoir passé quelques minutes avec moi. À la prochaine, porte-toi bien.
14

Similarity-Quantized Relative Learning

3m 31s

Résolvez le problème des activity cliffs en repensant la façon dont les modèles apprennent. Nous explorons le framework SQRL, qui entraîne l'IA à prédire les différences de propriétés relatives entre des paires moléculaires strictement filtrées.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 14 sur 22. Plutôt que de forcer une IA à mémoriser la puissance absolue de chaque molécule existante, et si tu lui apprenais simplement à se demander en quoi une molécule diffère de son plus proche voisin connu ? Ce changement de perspective résout un problème majeur de généralisation dans les régimes low-data, et c'est le cœur d'un framework appelé Similarity-Quantized Relative Learning, ou SQRL. Normalement, la prédiction des propriétés moléculaires traite chaque molécule comme un data point isolé. Le modèle essaie de mapper une structure directement à une valeur de propriété absolue. Avec des datasets petits et bruités, les modèles de deep learning ont du mal à construire une map globale précise de l'espace chimique. Les tentatives précédentes de pairwise learning ont essayé de corriger ça en associant chaque molécule avec toutes les autres molécules du training set. Cette approche inonde les données de comparaisons entre des structures qui n'ont rien à voir, noyant ainsi le signal local utile. SQRL corrige ça en limitant les training data aux paires de molécules qui sont structurellement très similaires. Le modèle apprend à prédire la différence relative de leurs propriétés, qu'on appelle delta y. On y arrive grâce à une étape spécifique de matching du dataset. Tu ne donnes pas au modèle des molécules individuelles. Tu lui donnes des paires, mais seulement si elles passent un threshold de similarité strict. Voyons la logique ensemble. Tu commences avec ton training set standard de molécules et leurs puissances connues. D'abord, tu calcules les distances pairwise entre toutes les molécules en utilisant une métrique comme la distance de Tanimoto sur des Morgan fingerprints. Voici l'idée clé. Tu définis un threshold de distance, alpha. Prenons un threshold de distance de Tanimoto de zéro virgule sept. Tu itères sur toutes les paires de molécules possibles. Si la distance entre la molécule A et la molécule B est de zéro virgule sept ou plus, tu rejettes complètement la paire. Si la distance est strictement inférieure à zéro virgule sept, tu ajoutes cette paire à ton nouveau training set relatif. La target variable pour cette nouvelle paire n'est plus une puissance absolue. C'est la différence numérique exacte de puissance entre la molécule A et la molécule B. Maintenant, tu entraînes ton réseau de neurones. Le réseau génère une représentation mathématique pour la molécule A, et une représentation pour la molécule B. Il soustrait la représentation de B de la représentation de A. Ce vecteur de différence résultant passe par une layer finale pour prédire le delta y. En filtrant le bruit des paires dissemblables, le réseau est forcé de se concentrer exclusivement sur les changements chimiques locaux à fort signal. Il apprend exactement comment un tweak structurel spécifique altère l'activité. Ça rend le modèle hyper sensible aux activity cliffs. Ça couvre le training, mais qu'en est-il de la prédiction pour une toute nouvelle molécule ? Quand une nouvelle structure arrive, le système scanne les training data d'origine pour trouver le voisin structurel le plus proche en se basant sur cette même métrique de distance de Tanimoto. Le réseau évalue la nouvelle molécule par rapport à ce plus proche voisin et prédit le delta relatif. Enfin, tu prends la puissance absolue connue du voisin, tu ajoutes le delta prédit, et tu as ta prédiction finale. En restreignant le training space à des paires très similaires, tu arrêtes de demander au modèle d'apprendre l'univers chimique entier et tu l'entraînes plutôt à devenir un expert des gradients chimiques locaux. C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
15

La Révolution de l'IA Générative

3m 16s

Passez de la prédiction de propriétés à l'imagination de molécules entièrement nouvelles. Nous cartographions le paysage des tâches génératives moléculaires : génération De Novo, optimisation et génération de conformères.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 15 sur 22. Pendant des années, l'IA en chimie s'est limitée à un simple tri. Tu passais à un modèle des milliers de molécules existantes, et il se contentait de prédire les moins mauvaises. Si la molécule idéale n'était pas dans ta screening library, le modèle ne pouvait pas t'aider. La révolution de l'IA générative a fondamentalement inversé cette dynamique. Au lieu de juste filtrer ce qui existe déjà, tu peux maintenant demander aux modèles d'inventer de la matière chimique entièrement nouvelle. Ce passage de la prédiction à la création se divise en deux grandes tâches de génération moléculaire : la génération de novo et l'optimisation moléculaire. La génération de novo consiste à créer de nouvelles structures moléculaires from scratch. Le modèle part d'une représentation de random noise et l'affine de façon itérative pour obtenir une structure chimique valide. Quand tu fais ça sans aucune contrainte, c'est ce qu'on appelle la génération inconditionnelle. Le modèle explore librement le vaste espace chimique pour produire quelque chose d'entièrement nouveau. Même si c'est utile pour la découverte au sens large, tu as généralement besoin de plus de contrôle. C'est là qu'intervient la génération conditionnelle, et plus précisément la génération basée sur les propriétés. Là, c'est toi qui dictes l'output. Tu fournis des contraintes spécifiques, comme une bioactivité cible ou un niveau de synthétisabilité requis, et le modèle restreint sa génération aux molécules qui respectent ces critères. C'est ce qu'on appelle souvent l'inverse molecule design, parce que tu pars des propriétés que tu veux et tu forces le modèle à faire le chemin inverse pour construire une structure moléculaire qui les possède. La génération de novo est puissante, mais tu démarres rarement un projet avec zéro connaissance de base. En général, tu as déjà un lead compound. C'est là qu'intervient l'optimisation moléculaire. Contrairement aux tâches de novo, l'optimisation moléculaire se concentre sur la modification d'une structure connue plutôt que de partir d'une page blanche. Tu prends une molécule existante et tu l'affines pour améliorer ses propriétés. Supposons que tu aies un scaffold de médicament moyennement efficace. Il se lie à ta cible, mais sa bioactivité est trop faible pour être un médicament viable. En utilisant un modèle génératif, tu peux faire de l'optimisation moléculaire ciblée. Une approche est le scaffold hopping. Tu demandes au modèle de remplacer le scaffold moléculaire de base par un nouveau, tout en conservant l'activité biologique d'origine. C'est super efficace pour découvrir des composés structurellement nouveaux qui contournent les brevets existants tout en gardant le comportement fonctionnel intact. Une autre approche, c'est le R-group design. Dans ce scénario, tu verrouilles ton scaffold de base et tu demandes au modèle génératif d'optimiser automatiquement ses chaînes latérales. Le modèle génère de nouveaux R-groups, en cherchant les modifications spécifiques de chaînes latérales qui améliorent cette bioactivité à la traîne. Tu ne jettes pas ta molécule moyennement efficace, tu laisses l'IA calculer les petits ajustements structurels précis nécessaires pour lui faire franchir la ligne d'arrivée. Voici l'idée clé. Le passage de l'IA prédictive à l'IA générative signifie que tu n'es plus limité par les molécules que tu as sous la main. Que tu génères une molécule sur mesure from scratch ou que tu remplaces algorithmiquement les chaînes latérales d'un médicament existant, tu traites l'espace chimique comme un support programmable. C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
16

L'Intuition de la Diffusion Moléculaire

3m 15s

Nous décomposons le concept fondamental des Diffusion Models sans les mathématiques lourdes. Les auditeurs comprendront le processus direct d'ajout de bruit à une molécule et le processus inverse d'hallucination de nouvelles structures.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 16 sur 22. Pour apprendre à une IA à inventer une nouvelle molécule, tu dois d'abord lui apprendre à en détruire une complètement. Ça semble complètement à l'envers, mais cette destruction systématique est exactement le mécanisme utilisé pour générer de nouveaux médicaments from scratch. C'est l'intuition de base des Denoising Diffusion Probabilistic Models. Le design moléculaire traditionnel demande énormément de travail. Si tu veux automatiser la découverte de nouveaux composés, tu as besoin d'un modèle capable d'explorer un vaste espace chimique sans générer de résultats invalides. Les premiers deep generative models essayaient de mapper cet espace directement. Les Denoising Diffusion Probabilistic Models, ou DDPMs, prennent une route différente. Ils traitent la génération de molécules comme un problème de denoising progressif. Le framework est divisé en deux Markov chains distinctes : le forward process et le reverse process. Le forward process sert uniquement à dégrader la data. Tu prends un médicament valide et connu de ton training set. Sur une séquence fixe de steps, tu floutes progressivement ses coordonnées atomiques en injectant du pur bruit gaussien. La quantité de bruit ajoutée à chaque step est contrôlée par un hyperparameter schedule défini. Au step un, tu perturbes légèrement les atomes. La molécule est un peu déformée mais reste clairement reconnaissable. Au step cinquante, la structure est sévèrement altérée. Au step final, généralement noté step T, la molécule d'origine a complètement disparu. Tu te retrouves avec un nuage aléatoire de bruit gaussien non structuré. Ce forward process ne nécessite pas de neural network. C'est une stricte corruption mathématique. Il a un rôle vital car il génère la ground truth pour notre training data. Voici l'idée clé. Comme on a contrôlé la quantité exacte de bruit ajoutée à chaque step, on a un historique parfait, step-by-step, de la façon dont la molécule s'est décomposée. C'est dans le reverse process que le neural network entre en jeu. Le modèle est entraîné pour parcourir exactement ce chemin à l'envers. On passe au network une molécule corrompue à un time step spécifique. On lui demande ensuite de prédire le bruit spécifique qui a été ajouté pour atteindre cet état. On évalue le modèle en comparant sa prédiction de bruit avec le bruit réel qu'on a injecté pendant la phase forward. On met à jour les paramètres du modèle pour minimiser cette différence. Avec le temps, le network apprend à denoise la data step by step, en restaurant progressivement la distribution de la data d'origine. Pour générer une molécule complètement nouvelle, tu exécutes ce reverse process from scratch. D'abord, tu prends un sample d'un nuage complètement aléatoire de bruit gaussien. Ensuite, tu passes ce bruit dans ton neural network entraîné, avec le numéro du step de départ. Le network évalue l'input, prédit la correction structurelle nécessaire, et retourne un nuage d'atomes légèrement moins bruité. Tu boucles sur ce processus de soustraction. Tu repasses le nouvel output dans le network pour le step suivant. À chaque itération, le nuage aléatoire se resserre. Le modèle retire continuellement le bruit. À mesure que tu recules vers le step zéro, les coordonnées atomiques se mettent en place et une structure chimique valide émerge. Tu sors une molécule complètement nouvelle du bruit statique initial. Le modèle ne fait pas que mémoriser une database de médicaments existants ; il apprend simplement le processus universel qui consiste à retirer le chaos pour laisser place à une chimie stable. Si tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. Merci d'avoir écouté, et continue de builder !
17

Faire le Pont entre les Espaces Génératifs 2D et 3D

3m 55s

Nous explorons comment l'IA représente réellement les molécules qu'elle génère. Nous comparons la génération de graphes topologiques 2D plats avec la génération de nuages de points géométriques 3D complexes, ainsi que les défis de chacun.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 17 sur 22. C'est une chose pour un modèle de dessiner un graphe 2D plat d'une molécule. C'est un tout autre cauchemar d'ingénierie de générer un cloud géométrique 3D d'atomes stable. Tu peux avoir un generative model qui construit un magnifique 3D point cloud d'un médicament qui remplit parfaitement une poche protéique cible, juste pour voir le tout s'effondrer en post-processing quand le système n'arrive pas à deviner où les vraies liaisons covalentes devraient aller. La solution à ce décalage, c'est de faire le pont entre les espaces génératifs 2D et 3D. En chimie générative, les modalités des données dictent ce que ton modèle peut comprendre. La première modalité, c'est l'espace topologique 2D. Vois ça comme un graphe moléculaire standard. Les nodes représentent des atomes avec des types spécifiques, et les edges représentent les liaisons chimiques qui les connectent. Le modèle sort une adjacency matrix qui te dit exactement ce qui est connecté à quoi. Les graph neural networks gèrent ça très bien. Le problème, c'est que les molécules existent dans le monde physique, pas sur le papier. Un graphe 2D te donne la topologie des liaisons, mais il ignore complètement la structure géométrique 3D. Sans coordonnées spatiales, tu ne peux pas calculer précisément les propriétés quantiques ou faire du structure-based drug design. Pour corriger ça, les modèles sont passés à la génération de molécules directement dans l'espace géométrique 3D. Ici, l'output est un point cloud. Le modèle définit les types d'atomes et leurs coordonnées de position X, Y et Z exactes. L'obstacle technique ici, c'est de maintenir l'équivariance SE 3, pour s'assurer que la molécule reste mathématiquement cohérente, peu importe comment elle est tournée ou translatée dans l'espace. Voici l'idée clé. Générer dans un espace 3D pur signifie que le modèle ne génère pas explicitement les liaisons chimiques. Il se contente de placer des atomes dans l'espace. Tu dois déduire la topologie des liaisons après coup via des algorithmes de post-processing. Ça introduit des erreurs majeures. Pour en revenir au scénario de la poche protéique, ton modèle pourrait arranger les atomes dans une forme qui correspond physiquement à la cible, mais comme il n'a jamais pris en compte la topologie des liaisons pendant la génération, l'étape de post-processing pourrait déduire des liaisons covalentes impossibles. Pour les molécules plus grandes, générer directement une structure 3D stable sans aucun guidage topologique donne souvent une solution sous-optimale. Ce qui nous amène à la génération dans un espace conjoint 2D et 3D, qui produit simultanément une structure moléculaire complète. Le modèle sort les types d'atomes, la discrete adjacency matrix pour les liaisons, et les coordonnées spatiales continues, tout ça en même temps. En faisant le pont entre ces deux espaces, les modalités se contraignent et se corrigent mutuellement pendant le processus de génération. La topologie 2D agit comme un blueprint, guidant la structure 3D pour s'assurer que les arrangements spatiaux sont chimiquement réalisables. En même temps, la géométrie 3D affine le graphe 2D en suggérant des patterns de liaison plausibles basés sur la proximité spatiale. Le principal défi technique dans cette approche conjointe, c'est de gérer deux types de données fondamentalement différents. Tu forces le modèle à gérer des structures topologiques discrètes, comme les types de liaisons, en même temps que des structures géométriques continues, comme les valeurs de coordonnées. Différentes architectures résolvent ça différemment. Un framework appelé JODO traite les structures topologiques et géométriques comme des variables continues pour les processer ensemble. Un autre modèle, MUDiff, les gère séparément, en appliquant un processus discret pour la topologie et un processus continu pour la géométrie. Tu ne peux pas générer de manière fiable de nouveaux médicaments fonctionnels en devinant la forme physique et en espérant que les liaisons chimiques se fassent toutes seules plus tard. La vraie génération moléculaire exige que le blueprinting topologique et le positionnement spatial interagissent et se complètent dans le même calcul exact. C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !
18

Génération Sensible à la Cible et Docking

4m 01s

Découvrez la conception générative sensible au contexte. Nous discutons de la génération de nouvelles molécules directement à l'intérieur de la poche de liaison d'une protéine malade pour maximiser l'affinité de liaison.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 18 sur 22. Pourquoi demander à un algorithme de générer un million de clés aléatoires et de les tester une par une, alors qu'il pourrait simplement analyser la serrure et forger une clé sur mesure directement à l'intérieur ? La drug discovery traditionnelle repose souvent sur la génération de vastes bibliothèques de candidats et sur leur filtrage, mais ça gaspille d'immenses ressources de calcul. La Target-Aware Generation et le docking résolvent ce problème en utilisant directement la géométrie 3D de la cible biologique pour construire ou positionner des molécules. Dans ces tâches génératives, on travaille entièrement dans un espace géométrique 3D. La Target-Aware Generation, aussi connue sous le nom de structure-based drug design, construit une nouvelle molécule en se basant directement sur la structure 3D d'une binding pocket cible. Prends un scénario concret avec une protéine virale. Cette protéine possède une cavité géométrique très spécifique. Au lieu de générer des molécules dans le vide, un diffusion model conditionnel analyse les limites spatiales exactes et les propriétés chimiques de cette cavité. Il fait ensuite croître sur mesure une nouvelle structure de ligand directement à l'intérieur de la pocket. Le modèle commence avec un nuage de coordonnées 3D noisy et de types d'atomes situés dans le binding site. Au fil des étapes successives, il denoise ce nuage. Comme la génération est conditionnée par la pocket cible, le modèle place les atomes et forme des structures qui complètent naturellement la cavité, dans le but de garantir une forte affinité d'interaction. Et c'est ça l'idée clé. L'algorithme ne se contente pas de deviner une forme ; il apprend explicitement la relation spatiale entre la cible et les binders potentiels. Certaines approches intègrent même du retrieval basé sur les interactions, en tirant des données de ligands connus à haute affinité pour guider encore plus la génération de ces molécules spécifiques à la cible. Ça, c'est pour la génération d'une molécule entièrement nouvelle from scratch à l'intérieur d'une pocket. Mais tu auras souvent une molécule existante et tu auras besoin de savoir exactement comment elle interagit avec une cible biologique. C'est là qu'intervient le molecular docking. Le molecular docking prédit la binding pose pour évaluer l'affinité et la spécificité de liaison. Dans un framework de diffusion, les modèles prennent en input une molécule connue et une structure cible. Au lieu de générer une identité chimique, le processus de diffusion opère uniquement sur l'orientation spatiale de la molécule. Le modèle commence avec le ligand dans une pose 3D aléatoire et noisy, puis il le denoise de façon itérative. Il affine les coordonnées spatiales de la molécule jusqu'à ce qu'elle se stabilise dans la bonne configuration de liaison à l'intérieur de la pocket de la protéine. Les modèles de docking avancés vont encore plus loin en traitant la cible elle-même comme une entité flexible. Un modèle appelé Re-Dock utilise une technique appelée diffusion bridge pour prédire les binding poses du ligand tout en modélisant simultanément le mouvement des sidechains de la pocket. Ça crée un scénario de docking réaliste et flexible où le ligand et la cible s'adaptent l'un à l'autre pendant la phase de prédiction. Le changement fondamental ici, c'est que les diffusion models ont éloigné le structural drug design des approximations rigides et isolées. En traitant à la fois le ligand généré et la pocket biologique comme un système géométrique continu et adaptable, le modèle produit nativement des molécules et des poses physiquement ancrées dans la réalité précise de l'environnement cible. C'est tout pour cet épisode. Merci de m'avoir écouté, et continue de développer !
19

Le Piège de la Taille dans l'Évaluation Générative

3m 59s

Apprenez pourquoi les benchmarks standards pour les modèles génératifs peuvent être profondément biaisés. Nous révélons l'effet de confusion de la taille de la bibliothèque générée sur des métriques telles que la Fréchet ChemNet Distance.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 19 sur 22. Tu évalues ton nouveau modèle de chimie générative en échantillonnant mille molécules, et les metrics sont catastrophiques. Tu en génères cent mille à partir de ce même modèle, et soudain, il a l'air exceptionnel. Le scale change tout. Ce phénomène s'appelle le Size Trap dans l'évaluation générative. Les pipelines de drug discovery générative suivent généralement trois étapes. Tu entraînes, tu génères, et tu évalues. Quand on arrive à l'étape d'évaluation, on fait face à une question basique : combien de designs de novo générer pour le benchmarking ? La pratique standard se limite souvent à de petits batches, typiquement mille ou dix mille strings SMILES. Les équipes passent ensuite ces batches dans des metrics de distribution standards. La plus courante est la Fréchet ChemNet Distance, ou FCD. La FCD mesure à quel point tes molécules générées sont proches de ton training set dans l'espace chimique et biologique. Un score FCD plus bas signifie que ta distribution générée correspond étroitement à ta distribution cible. Une autre metric courante est la Fréchet Descriptor Distance, ou FDD, qui compare la distribution des propriétés physico-chimiques comme le poids moléculaire et la surface topologique. Les équipes mesurent aussi régulièrement l'Uniqueness, c'est-à-dire la fraction de designs générés qui sont distincts. Voici l'idée clé. Toutes ces metrics dépendent fortement de la taille physique de la librairie générée. Elles ne mesurent pas la qualité absolue du modèle de manière isolée. Quand tu échantillonnes juste mille molécules, tes scores FCD et FDD seront artificiellement élevés. On dirait que le modèle a échoué à apprendre la distribution cible. Mais si tu continues d'échantillonner à partir de ce même modèle, en poussant la taille de la librairie au-delà de dix mille, cinquante mille ou cent mille molécules, le score FCD chute significativement. Il continue de diminuer jusqu'à finalement atteindre un plateau. Ça arrive parce que le design génératif de molécules implique d'échantillonner à partir d'une distribution de probabilité apprise très complexe. Un tout petit échantillon de mille molécules ne peut pas représenter correctement toute l'étendue de l'output de ce modèle. Les algorithmes de Fréchet distance ont besoin d'un nombre massif d'échantillons pour capturer avec précision la forme de l'espace généré et la comparer à l'espace de fine-tuning. Prends un scénario concret où tu compares un réseau de neurones récurrent avec un transformer. Si tu évalues le réseau récurrent avec cent mille designs, mais que tu évalues le transformer avec seulement dix mille, le réseau récurrent affichera probablement des scores FCD et FDD nettement supérieurs. L'écart de performance n'a rien à voir avec l'architecture. C'est purement un artefact de la taille de l'échantillon. Les metrics n'ont pas convergé pour la plus petite librairie. Ce piège fonctionne à l'envers quand tu regardes la diversité interne. L'Uniqueness se comporte de manière totalement différente à grande échelle. À mille molécules, presque chaque string SMILES valide que ton modèle génère peut être unique. Le modèle a l'air très créatif. Mais à mesure que tu pousses la génération vers les cent mille, l'Uniqueness chute brutalement. Le modèle commence à se répéter. Si tu classes différents modèles génératifs en te basant sur l'Uniqueness à petite échelle, les différences entre eux ont l'air mineures. Pousse le scale plus haut, et l'écart entre les modèles se creuse considérablement. Le classement relatif de tes modèles va carrément s'inverser selon la taille de la librairie que tu utilises pour les mesurer. Pour corriger ça, tu dois traiter la taille de la librairie comme une variable de contrôle stricte dans ton pipeline. Tu ne peux jamais comparer de manière fiable la FCD, la FDD ou l'Uniqueness entre des librairies de tailles différentes. Pour garantir une évaluation robuste, tu devrais évaluer des librairies contenant au moins cent mille designs pour que les metrics de distribution convergent pleinement. Si tes metrics d'évaluation changent simplement parce que tu as laissé la boucle d'échantillonnage tourner plus longtemps, tu mesures la taille de l'échantillon, pas l'intelligence du modèle. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
20

Naviguer dans les Hallucinations De Novo

3m 46s

Classez intelligemment les molécules générées par l'IA. Nous explorons le compromis exploration-exploitation des probabilités du modèle, et comment filtrer les 'hallucinations chimiques' fréquentes et de faible qualité.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Python Cheminformatics & AI, épisode 20 sur 22. Ce n'est pas parce qu'une IA générative te sort une molécule spécifique dix mille fois que c'est un médicament viable. Tu pourrais penser que la fréquence de génération indique la qualité ou la pertinence chimique. Ce n'est pas le cas. Ces outputs très fréquents sont souvent l'équivalent chimique d'un Large Language Model qui hallucine. Le mécanisme pour résoudre ça, c'est de naviguer dans ces hallucinations de novo en utilisant la likelihood du modèle. Quand tu génères une immense bibliothèque d'un million de strings SMILES à partir d'un modèle de langage chimique fine-tuné, tu dois décider quelles molécules prioriser pour tes études prospectives. Une approche standard, mais imparfaite, c'est de simplement sélectionner les designs que le modèle sort le plus souvent. Ça crée un piège de comptage. Au lieu de découvrir des candidats médicaments robustes, tu finis par extraire des sous-structures basiques et répétitives comme des cycles benzéniques isolés, des amines simples et des éthers basiques. Ce sont des hallucinations structurelles récurrentes. Le modèle les génère constamment, non pas parce qu'elles sont de haute qualité, mais parce qu'elles sont syntaxiquement simples à construire. Pour exposer et filtrer ces hallucinations, tu évalues ta bibliothèque en utilisant la likelihood du modèle. La likelihood est une métrique qui capture à quel point une séquence générée s'aligne avec la distribution de probabilité que le modèle a apprise pendant le training. Pour un modèle autorégressif, tu calcules ça en multipliant la probabilité de sampling de chaque token individuel dans la string SMILES générée. D'abord, tu calcules le score de likelihood pour l'ensemble du million de designs générés. Ensuite, tu tries toute la bibliothèque en fonction de ces scores. Enfin, tu divises la bibliothèque triée en dix groupes égaux, ou déciles, allant de la likelihood la plus faible à la plus élevée. C'est là que ça devient intéressant. L'analyse de ces déciles révèle un tradeoff strict entre exploration et exploitation. Le dixième décile contient les générations avec la plus haute likelihood. Ces designs représentent l'exploitation. Ils ont une validité chimique extrêmement élevée, et leurs scaffolds génériques de Bemis-Murcko correspondent de très près aux molécules actives connues de tes données de training. Le modèle exploite à fond ce qu'il sait qui marche déjà. L'inconvénient, c'est que ces designs de haut niveau manquent de nouveauté. Ils contiennent très peu de nouvelles sous-structures parce que le modèle joue la sécurité. En descendant vers les déciles intermédiaires, tu trouves un équilibre. La nouveauté et les sous-structures uniques atteignent un pic dans cette zone intermédiaire, tandis que la validité reste acceptable. Mais quand tu descends au premier décile — les dix pour cent de molécules avec les scores de likelihood les plus bas — tu tombes dans le piège du comptage. Si tu isoles les designs que le modèle a générés plus de dix fois sur tout le run d'un million de molécules, ils se regroupent presque tous dans ce décile inférieur. Leurs likelihoods de modèle sont incroyablement basses, et pourtant ils apparaissent avec une fréquence massive. Leur similarité structurelle avec ton training set est catastrophique, et leur validité chimique globale s'effondre. En faisant du binning sur ta bibliothèque de cette façon, tu prouves mathématiquement que la fréquence est un faux signal de qualité. Tu peux systématiquement abandonner les bins à faible likelihood et haute fréquence, et concentrer ton screening computationnel sur les déciles intermédiaires, là où se passe la véritable exploration chimique. Les outputs les plus fréquents d'un modèle chimique génératif sont souvent ses pires, mais filtrer ta bibliothèque par déciles de likelihood transforme ce bruit en une carte précise des endroits où le modèle explore et de ceux où il ne fait qu'halluciner. C'est tout pour cet épisode. Merci de ton écoute, et continue à développer !
21

Contraintes d'Échantillonnage de Molécules

3m 46s

Comprenez pourquoi les techniques de NLP échouent en chimie. Nous comparons le Temperature sampling au Top-k et au Top-p, et pourquoi le vocabulaire chimique contraint change tout.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python Cheminformatics et IA, épisode 21 sur 22. En traitement du langage naturel, le Top-p sampling produit des textes super créatifs. Mais applique cette même logique à la génération de molécules, et ton IA va juste print des cycles carbonés identiques à l'infini. La raison s'explique par les Molecule Sampling Constraints. Quand un modèle de langage chimique génère une string SMILES, il construit la molécule un token à la fois. Le modèle prédit une distribution de probabilité pour le prochain token, et tu dois extraire un choix spécifique de cette distribution. En génération de texte, on s'appuie à fond sur le Top-k et le Top-p sampling pour faire ce choix. Le Top-k restreint le modèle aux k tokens les plus probables. Le Top-p restreint la sélection au plus petit groupe de tokens dont les probabilités combinées dépassent un pourcentage cible p. Si tu appliques ces méthodes à un modèle de langage chimique, elles plantent de façon catastrophique. Si tu utilises le Top-k sampling avec k défini sur 3 sur un LSTM entraîné sur des cibles médicamenteuses, ton modèle va subir un mode collapse sévère. Il va output des molécules chimiquement valides, mais elles seront complètement répétitives. Voici l'explication clé. Cet échec vient de la taille du vocabulaire chimique. Un modèle de texte fait sa sélection parmi des centaines de milliers de mots. Un modèle de langage chimique utilise un alphabet hyper contraint. Il n'a qu'une poignée d'éléments comme le carbone, l'oxygène et l'azote, plus des tokens de syntaxe pour les ramifications et les fermetures de cycles. Comme l'alphabet chimique est minuscule, et qu'une chimie valide exige des règles de syntaxe rigides comme la fermeture de chaque cycle ouvert, un tout petit sous-ensemble de tokens domine absolument la distribution de probabilité. Le carbone et les tokens structurels de base sont presque toujours très probables. Quand tu appliques le Top-k ou le Top-p sampling, tu coupes la longue traîne de la distribution de probabilité. Le modèle est forcé de piocher exclusivement dans cette bande étroite de tokens dominants. Il se retrouve coincé dans un piège de filtrage, et répète les mêmes scaffolds de base à l'infini. Pour échapper à ce piège, tu dois utiliser le Temperature sampling. Au lieu de filtrer les tokens, le Temperature sampling applique un paramètre de lissage aux scores bruts du réseau de neurones avant de calculer les probabilités finales. Ça modifie la forme de toute la distribution. Imagine un scénario où tu fais tourner un modèle LSTM fine-tuné pour générer de nouveaux candidats médicaments. Tu ajustes le paramètre de Temperature, T, pour régler le compromis entre validité et diversité. Si tu règles T bas, autour de 0,5, la distribution de probabilité forme un pic très pointu. Le modèle exploite à fond les tokens les plus probables. Ton output aura une validité chimique extrêmement élevée, mais les structures manqueront de nouveauté. Elles vont imiter de très près le dataset d'entraînement. Si tu augmentes T jusqu'à 1,5 ou 2,0, tu aplatis la distribution de probabilité. Maintenant, les tokens les moins probables ont une chance mathématique d'être samplés. Ton modèle commence à explorer un nouvel espace chimique. Le nombre de sous-structures uniques dans ta librairie générée monte en flèche. Tu trouves des molécules super novatrices. Le compromis, c'est que des températures plus élevées augmentent l'aléatoire, ce qui pousse le modèle à faire plus d'erreurs de syntaxe, et ça réduit le pourcentage global de strings SMILES valides. Tu ne peux pas porter aveuglément les stratégies de génération de texte vers le design moléculaire. Parce que le vocabulaire chimique est intrinsèquement contraint, le Temperature scaling reste le levier le plus efficace pour équilibrer une validité chimique stricte avec l'exploration de nouvelles structures. Merci d'avoir écouté. J'espère que tu as appris un truc nouveau.
22

Déployer la Chémoinformatique dans le Cloud

3m 37s

Passez votre pipeline d'IA en production. Nous discutons de l'empaquetage de RDKit et des modèles de machine learning dans des conteneurs Docker et de la mise à l'échelle des charges de travail sur l'infrastructure Cloud.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Python, Chimioinformatique et IA, épisode 22 sur 22. Tu as créé un pipeline de drug discovery basé sur l'IA à la pointe de la technologie sur ton laptop, mais comment tu fais pour screener un milliard de molécules pendant le week-end ? La réponse, c'est de déployer la chimioinformatique dans le cloud. Passer un modèle d'un environnement local à une architecture cloud distribuée, ça plante généralement au niveau de la dependency layer. RDKit n'est pas une library pure Python. C'est une grosse codebase C++ qui demande des dépendances système, en particulier les libraries Boost C++. Si tu provisionnes des serveurs cloud génériques et que tu lances des scripts d'installation standards, tu te prends souvent des erreurs de compilation ou des shared object files manquants. La documentation officielle de RDKit souligne que le build from source nécessite une toolchain C++ spécifique. Même s'il existe des pip wheels précompilés, la méthode la plus robuste pour garantir que toutes les dépendances sous-jacentes s'alignent, c'est d'utiliser Conda. Par contre, installer Conda dynamiquement sur des milliers de cloud workers temporaires, ça prend trop de temps et ça introduit de l'instabilité réseau pendant le scale-up. Voici l'astuce clé. Tu contournes complètement le problème de dépendances en wrappant ton pipeline dans un container Docker. Tu écris un fichier de configuration qui spécifie un OS de base. À l'intérieur de ce container, tu installes un environnement Conda léger, tu pull les binaries RDKit compilés, et tu ajoutes tes frameworks de machine learning comme PyTorch ou XGBoost. Enfin, tu copies les weights de ton modèle pré-entraîné dans l'image. Le build de cette image fige toute la stack dans un seul artefact immuable. Le cloud provider a juste besoin de savoir comment faire tourner un container Docker standard. Les dépendances C++ complexes sont bien verrouillées à l'intérieur. Pour traiter des millions de molécules, tu sépares ton data flow de tes compute workers en utilisant une cloud message queue. Tu partitionnes ton dataset massif de strings SMILES en chunks plus petits et gérables. Tu places ces chunks dans un cloud object storage et tu envoies un message contenant l'emplacement du chunk à la queue. Ensuite, tu pointes un service de cloud compute scalable vers cette queue. Pour les workloads lourds accélérés par GPU, tu déploies ton container avec un service comme AWS Batch. Pour de l'inference plus légère basée sur CPU, les plateformes de containers serverless comme Google Cloud Run ou AWS Lambda gèrent ça parfaitement. Tu configures le service de compute pour qu'il scale automatiquement en fonction de la profondeur de la queue. S'il y a cinquante mille messages en attente, le cloud controller spin up des milliers de containers Docker identiques en même temps. Chaque container se connecte à la queue et récupère un message. Il télécharge le chunk correspondant de strings SMILES. RDKit convertit les SMILES en graphes moléculaires, calcule les descripteurs requis, et les passe à ton modèle de machine learning pour l'inference. Le container écrit directement les molécules avec les meilleurs scores dans une managed cloud database. Une fois que le chunk est traité, le worker supprime le message de la queue et chope le suivant. Quand la queue est vide, l'infrastructure cloud termine les containers automatiquement. Tu ne paies que pour les secondes de compute exactes que ton code a réellement consommées. Scaler la chimioinformatique, c'est rarement une question d'écrire des structures de boucles plus rapides en Python ; c'est plutôt packager ton environnement de manière fiable et utiliser une architecture cloud découplée pour traiter la data en parallèle. Ça conclut notre série sur Python, la chimioinformatique et l'IA. Je t'encourage à lire la documentation officielle de RDKit sur l'installation, à essayer de containeriser un script simple hands-on, ou à visiter devstories dot eu pour suggérer des sujets pour les futures séries. C'est tout pour cet épisode. Merci d'avoir écouté, et keep building !