Edizione 2026. Un corso pratico che accompagna gli sviluppatori Python dai concetti base della chimica fino alla progettazione di sistemi di cheminformatics guidati dall'IA. Scopri come utilizzare RDKit, scikit-fingerprints e tecniche di deep learning all'avanguardia come Graph Neural Networks e Diffusion Models per il drug discovery.
Calcolo ScientificoCheminformaticaDeep Learning per la Scienza
Introduciamo RDKit e il concetto fondamentale della rappresentazione chimica in Python. Gli ascoltatori impareranno a inizializzare oggetti molecolari a partire da stringhe e a comprendere il ruolo centrale del framework nel drug discovery tramite IA.
3m 30s
2
I/O nella Cheminformatics
Scopri come importare ed esportare in sicurezza enormi dataset chimici. Tratteremo la lettura di file SDF e SMILES, la gestione degli errori di parsing e la scrittura dei dati su disco.
3m 54s
3
Attraversamento del grafo molecolare
Scopri come le molecole vengono rappresentate come strutture dati a grafo. Esploriamo l'iterazione sugli atomi, l'analisi dei legami e l'identificazione dei sistemi di anelli all'interno delle molecole.
3m 29s
4
Ricerca di sottostrutture
Padroneggia l'arte di interrogare le molecole usando SMARTS. Vedremo passo dopo passo come trovare specifici gruppi funzionali e pattern all'interno di strutture chimiche complesse.
3m 55s
5
Fingerprinting e similarità molecolare
Esplora come tradurre i grafi molecolari in vettori di bit matematici. Tratteremo le MACCS keys, i Morgan fingerprints e il calcolo della Tanimoto similarity.
3m 59s
6
Rompere il piano 2D
Passa dai disegni piatti in 2D a geometrie 3D realistiche. Discuteremo l'aggiunta di idrogeni espliciti e la generazione di conformeri 3D affidabili utilizzando ETKDG.
4m 28s
7
Accelerare il Feature Engineering
Collega la cheminformatics e la data science standard con scikit-fingerprints. Esploriamo la generazione di oltre 30 tipi di fingerprint molecolari direttamente all'interno di un'interfaccia scikit-learn.
4m 04s
8
Cheminformatics ad alte prestazioni
Scopri come elaborare enormi dataset chimici in modo efficiente. Approfondiremo l'utilizzo del parallelismo CPU con Joblib e il risparmio di memoria tramite le matrici sparse di SciPy.
4m 36s
9
Pipeline ML End-to-End
Combina elaborazione, fingerprinting e previsione in un'unica architettura pulita. Costruiremo pipeline scikit-learn robuste che integrano perfettamente la generazione di conformeri 3D e la previsione delle proprietà.
3m 58s
10
Prevedere l'affinità di legame
Esplora la realtà della previsione dell'affinità di legame proteina-ligando. Confronteremo le prestazioni di semplici modelli ad albero 2D con quelle delle complesse Graph Neural Networks 3D.
4m 21s
11
LLM contro Fingerprint classici
Scopri come il Natural Language Processing si applica alla chimica. Metteremo a confronto i vector embeddings dei Large Language Models con i classici fingerprint strutturali di RDKit per prevedere la bioattività.
4m 13s
12
Active Learning per il Virtual Screening
Scopri come individuare iterativamente i migliori candidati farmaci senza test esaustivi. Approfondiremo i cicli di Active Learning e le strategie di selezione greedy per massimizzare i tassi di successo.
4m 22s
13
La sfida degli Activity Cliff
Esamina la fragilità delle relazioni struttura-attività. Discuteremo degli 'activity cliffs', situazioni in cui un minuscolo cambiamento strutturale causa un'enorme variazione nella potenza di un farmaco.
3m 32s
14
Similarity-Quantized Relative Learning
Risolvi il problema degli activity cliff ripensando al modo in cui i modelli apprendono. Esploriamo il framework SQRL, che addestra l'IA a prevedere le differenze relative di proprietà tra coppie molecolari rigorosamente filtrate.
3m 38s
15
La rivoluzione della Generative AI
Passa dalla previsione delle proprietà all'immaginazione di molecole completamente nuove. Tracceremo il panorama dei task generativi molecolari: generazione De Novo, ottimizzazione e generazione di conformeri.
3m 27s
16
L'intuizione della Molecular Diffusion
Analizziamo il concetto centrale dei Diffusion Models senza la matematica pesante. Gli ascoltatori comprenderanno il forward process di aggiunta di rumore a una molecola e il reverse process di allucinazione di nuove strutture.
3m 51s
17
Unire gli spazi generativi 2D e 3D
Esploriamo come l'IA rappresenta effettivamente le molecole che genera. Confronteremo la generazione di grafi topologici 2D piatti con la generazione di complesse point cloud geometriche 3D, e le relative sfide.
4m 28s
18
Generazione Target-Aware e Docking
Scopri il design generativo context-aware. Discuteremo la generazione di nuove molecole direttamente all'interno della tasca di legame di una proteina patologica per massimizzare l'affinità di legame.
3m 31s
19
La trappola delle dimensioni nella Generative Evaluation
Scopri perché i benchmark standard per i modelli generativi possono essere profondamente imperfetti. Riveleremo l'effetto confondente delle dimensioni della libreria generata su metriche come la Fréchet ChemNet Distance.
4m 16s
20
Navigare le allucinazioni De Novo
Classifica le molecole generate dall'IA in modo intelligente. Esploriamo il tradeoff exploration-exploitation delle likelihood del modello e come filtrare le 'allucinazioni chimiche' frequenti e di bassa qualità.
3m 56s
21
Vincoli nel Molecule Sampling
Comprendi perché le tecniche di NLP falliscono nella chimica. Confronteremo il Temperature sampling con Top-k e Top-p, e perché il vocabolario chimico vincolato cambia tutto.
4m 05s
22
Deploy di Cheminformatics nel Cloud
Porta la tua pipeline IA in produzione. Discuteremo il packaging di RDKit e dei modelli di machine learning all'interno di container Docker e la scalabilità dei carichi di lavoro sull'infrastruttura cloud.
3m 49s
Episodi
1
La molecola digitale
3m 30s
Introduciamo RDKit e il concetto fondamentale della rappresentazione chimica in Python. Gli ascoltatori impareranno a inizializzare oggetti molecolari a partire da stringhe e a comprendere il ruolo centrale del framework nel drug discovery tramite IA.
Ciao, sono Alex di DEV STORIES DOT EU. Python, Chemoinformatica e AI, episodio 1 di 22. Prima di poter prevedere la tossicità di un farmaco con un modello di machine learning, devi risolvere un problema fondamentale. Devi trovare un modo per insegnare a Python cos'è effettivamente una molecola. I data type standard come string e list non comprendono atomi, legami o strutture ad anello. Per colmare questa lacuna, ti serve un traduttore universale tra chimica e codice. Questo è esattamente ciò che offre RDKit, introducendo il concetto di molecola digitale.
RDKit è il toolkit di chemoinformatica open-source standard del settore. Alla base, è una libreria C++ ad alte prestazioni, ma espone un'interfaccia Python enorme e intuitiva. Esiste perché rappresentare le strutture chimiche a livello computazionale è sorprendentemente difficile. Matematicamente, una molecola è un grafo. Gli atomi sono i nodi e i legami chimici sono gli edge che collegano questi nodi. Se provi a costruire un parser di grafi custom da zero ogni volta che vuoi analizzare dati chimici, finirai per passare tutto il tuo tempo a fare debugging degli edge case. RDKit astrae questa complessità, gestendo la logica del grafo sotto il cofano.
Per portare una molecola in Python, ti serve innanzitutto una rappresentazione testuale della sua struttura. Il formato più comune è una string SMILES. SMILES utilizza caratteri standard per rappresentare la connettività chimica. Ad esempio, un atomo di carbonio isolato è semplicemente una C maiuscola. Il benzene, che è un anello a sei atomi di carbonio con doppi legami alternati, si scrive con una c minuscola, il numero uno, altre quattro c minuscole e una c minuscola finale seguita da un numero uno per chiudere l'anello.
Ecco il punto chiave. Quella string SMILES è semplicemente plain text. Per Python, è indistinguibile da una password o da un file path. Non puoi calcolare il peso molecolare da una raw string. Per fare della vera chimica, devi convertirla in un object molecola di RDKit. Puoi farlo importando il modulo Chem da RDKit. Quindi, chiami una funzione specifica progettata per creare una molecola da una string SMILES, e le passi la tua variabile di testo.
Quando passi la string SMILES del benzene a questa funzione, RDKit fa il lavoro pesante. Fa il parsing del testo, costruisce il grafo di nodi ed edge, assegna gli ordini di legame e valida le regole chimiche di base come le valenze atomiche. Se la string rappresenta una molecola valida, la funzione restituisce un object molecola. Se le passi una struttura chimicamente impossibile o un typo, la funzione fallisce in modo sicuro. Stampa un warning nella tua console e restituisce un object null. Per questo motivo, dovresti sempre verificare che il tuo object molecola esista effettivamente prima di passarlo allo step successivo del tuo programma.
Una volta che hai in memoria quell'object molecola validato, l'intero ecosistema di RDKit si sblocca. Non stai più lavorando con del testo; stai lavorando con un grafo chimico computabile. Il concetto fondamentale da ricordare è che le string SMILES servono esclusivamente per lo storage e il trasferimento dei dati, mentre gli object molecola di RDKit sono destinati al calcolo. Tutto ciò che fai in chimica computazionale inizia con questa conversione.
Se ti va di supportare lo show, puoi cercare DevStoriesEU su Patreon: ci aiuta tantissimo. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
2
I/O nella Cheminformatics
3m 54s
Scopri come importare ed esportare in sicurezza enormi dataset chimici. Tratteremo la lettura di file SDF e SMILES, la gestione degli errori di parsing e la scrittura dei dati su disco.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e AI con Python, episodio 2 di 22. Una singola coordinata mancante in un dataset da un milione di molecole può mandare in crash la tua intera pipeline. Se presumi che ogni record di testo nel file del vendor sia chimica formattata perfettamente, il tuo script Python finirà per lanciare un'exception fatale a metà di un job di dieci ore. Difenderti dai dati sporchi mentre sposti strutture dentro e fuori dai tuoi script è obbligatorio, ed è esattamente ciò che risolviamo oggi con l'I/O in Chemoinformatica.
Quando ricevi uno standard structure-data file, o SDF, pieno di potenziali ligandi, ti serve un modo per parsarlo. In RDKit, il tool di default per questo è l'SD molecule supplier. Lo inizializzi passando il file path come string. Questo oggetto supplier si comporta in modo molto simile a una list Python. Puoi farci un loop sopra, puoi chiedere la sua lunghezza totale e puoi estrarre un record specifico tramite il suo numero di index. Lo fa scansionando rapidamente il file per trovare dove inizia ogni molecola, permettendoti di saltare da una parte all'altra dei dati.
A volte non puoi scansionare in anticipo. Se stai facendo piping di dati direttamente da un web stream, o stai leggendo un enorme file gzippato chunk per chunk, non hai random access. Per queste situazioni, usi il forward SD molecule supplier. Invece di un file path, gli passi un file object aperto. Questo forward supplier è un iterator rigoroso. Legge una molecola, la parsa e passa immediatamente alla successiva. Non puoi chiedere la sua lunghezza, e non puoi chiedere la cinquantesima molecola senza aver letto le prime quarantanove. Scambi la flessibilità per un basso utilizzo di memoria e la compatibilità con gli stream.
Ecco il punto chiave. Indipendentemente da quale supplier usi, RDKit non solleva un'exception Python quando incontra una molecola corrotta. Se un blocco di testo nel tuo file ha una valenza non valida o un typo di formattazione, RDKit darà in output un messaggio di errore sulla console, ma l'effettivo object Python che restituisce per quell'iterazione del loop sarà semplicemente il type None.
Se prendi quell'object None e provi a calcolare il suo peso o a scriverlo in un nuovo file, il tuo script andrà in crash. Gestire questa cosa è semplice ma fondamentale. La primissima riga all'interno del tuo loop di parsing deve sempre verificare se la molecola restituita è None. Se è None, usi lo statement continue per saltare al record successivo. Questo filtra silenziosamente i dati spazzatura e mantiene la tua pipeline in esecuzione.
Una volta che hai parsato e filtrato in sicurezza le tue molecole valide, di solito devi salvare i risultati. Per questo, usi l'SD writer. Inizializzi il writer passando il file path di output desiderato. All'interno del tuo loop sicuro, subito dopo il tuo check su None, passi il molecule object valido al writer usando il suo metodo write. Una volta che il loop finisce di processare ogni ligando, chiami il metodo close sul writer per assicurarti che tutti i dati facciano il flush su disco in modo sicuro. Puoi anche wrappare il writer in un context manager Python standard, così si chiude automaticamente quando finisce il blocco.
Per mettere insieme tutto questo per uno script di data cleaning, per prima cosa crea il tuo SD writer per il file di output. Secondo, crea il tuo SD molecule supplier per il file di input. Fai un loop sul supplier. Controlla se l'item corrente è None e, se lo è, saltalo. Se è valido, passalo al writer. Chiudi il writer alla fine. Considera sempre i dataset chimici esterni come intrinsecamente sporchi; verificare che una molecola parsata non sia None è la polizza assicurativa più economica che il tuo codice avrà mai.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
3
Attraversamento del grafo molecolare
3m 29s
Scopri come le molecole vengono rappresentate come strutture dati a grafo. Esploriamo l'iterazione sugli atomi, l'analisi dei legami e l'identificazione dei sistemi di anelli all'interno delle molecole.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e AI con Python, episodio 3 di 22. Per un computer, una molecola non è un oggetto fisico che occupa spazio. È strettamente un grafo di nodi e archi in attesa di essere parsato. Se non riesci a navigare in modo efficiente in questo grafo sottostante, non puoi analizzare la struttura chimica. Questo ci porta direttamente al traversal del grafo molecolare.
In RDKit, un oggetto molecola funge da contenitore primario per questa struttura dati a grafo. Per ispezionare i nodi, usi il metodo GetAtoms. Questo restituisce una sequenza iterabile che contiene tutti gli oggetti atomo nella molecola. Puoi scrivere un semplice loop per scorrere questa sequenza un elemento alla volta. Per uno scenario concreto, supponi di dover estrarre i numeri atomici di tutti i tuoi nodi. All'interno del tuo loop, puoi chiamare il metodo GetIdx per trovare l'identificatore numerico univoco per l'atomo corrente, e il metodo GetAtomicNum per scoprire esattamente di quale elemento chimico si tratta. Iterando, processi ogni nodo in modo sistematico.
I nodi da soli non definiscono la chimica. Ti servono anche gli archi che li collegano, a cui accedi usando il metodo GetBonds. Proprio come per gli atomi, questo fornisce una sequenza iterabile di oggetti bond. Un bond conosce la sua posizione esatta nel grafo. Chiamando i metodi GetBeginAtomIdx e GetEndAtomIdx su un oggetto bond, estrai gli identificatori numerici specifici dei due atomi che collega. Puoi anche leggere il tipo di bond, determinando se si tratta di una connessione singola, doppia o aromatica. Ecco il punto chiave. RDKit tratta i bond come oggetti di prima classe nella gerarchia del grafo, il che significa che puoi interrogarli in modo indipendente anziché estrarli dalle proprietà degli atomi.
Navigare tra singoli nodi e archi è logica standard dei grafi, ma i grafi chimici presentano spesso cicli, meglio noti come anelli. Non hai bisogno di scrivere i tuoi algoritmi di traversal per la ricerca dei cicli. RDKit precalcola questi cicli quando la molecola viene istanziata. Accedi a questi dati tramite il metodo GetRingInfo. Questo restituisce un oggetto ring info dedicato, anziché una semplice lista.
Se il tuo compito è semplicemente contare il numero di anelli nella molecola, chiami il metodo NumRings direttamente su questo oggetto ring info. Quando hai bisogno di dettagli strutturali più approfonditi, puoi richiedere a questo stesso oggetto la property AtomRings. Questo ti fornisce una collection di sequenze, in cui ogni sequenza contiene gli indici atomici esatti che compongono uno specifico anello nel grafo. Puoi persino passare un indice atomico all'oggetto ring info per chiedere se quel nodo specifico partecipa a un anello di una particolare dimensione, come un ciclo a cinque o sei membri.
Fare il traversal di una molecola consiste essenzialmente nel concatenare queste operazioni di base. Recuperi le ring info per controllare la macrostruttura, fai un loop sugli atomi per leggere i dati a livello di nodo come i numeri atomici, e fai un loop sui bond per mappare le connessioni specifiche degli archi. Una volta che smetti di vedere una molecola come un'entità fisica e inizi a vederla come una collection prevedibile di nodi, archi e cicli precalcolati indicizzati, l'estrazione delle proprietà strutturali diventa un'attività standard di data parsing. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
4
Ricerca di sottostrutture
3m 55s
Padroneggia l'arte di interrogare le molecole usando SMARTS. Vedremo passo dopo passo come trovare specifici gruppi funzionali e pattern all'interno di strutture chimiche complesse.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e IA con Python, episodio 4 di 22. Non proveresti a parsare migliaia di text log senza usare le regular expression. Allo stesso modo, non dovresti provare a filtrare database chimici senza i pattern SMARTS. Trovare gruppi funzionali specifici in grandi dataset richiede una logica strutturale dedicata, ed è esattamente ciò che offre il Substructure Searching.
Supponi di avere una library di potenziali farmaci. Il tuo obiettivo è flaggare e isolare qualsiasi molecola che contenga uno specifico gruppo funzionale tossico noto. Per prima cosa, definisci quel gruppo tossico usando una string SMARTS. SMARTS è un'estensione di SMILES progettata specificamente per fare query su pattern molecolari, permettendoti di specificare wildcard, tipi di legame specifici o strutture ad anello. Passi questa text string alla funzione RDKit che crea una molecola da SMARTS. Questo genera il tuo query object. Le tue molecole target, i potenziali farmaci, sono già dei molecule object standard di RDKit.
Per filtrare la library, prendi una molecola candidata e chiami il metodo chiamato has substructure match. Passi il tuo query object a questo metodo. Questo valuta la molecola candidata rispetto al pattern e restituisce un semplice valore boolean. True significa che il gruppo tossico esiste da qualche parte all'interno del candidato. False significa che è pulito. Poiché questo metodo interrompe la ricerca nel momento in cui trova un singolo match valido, è altamente ottimizzato. Puoi mettere in loop questo check boolean su tutta la tua library per dividere rapidamente un dataset enorme in subset sicuri e flaggati.
Ora, e se sapere semplicemente che il gruppo tossico è presente non fosse abbastanza? Magari la tossicità scala con il numero di volte in cui il gruppo appare, o hai bisogno di isolare la posizione esatta degli atomi tossici per un biologo strutturale. Per questo, usi il metodo chiamato get substructure matches, al plurale. Lo chiami sulla tua molecola candidata, passando di nuovo il query object. Invece di un boolean, questo metodo forza il motore di ricerca a mappare ogni possibile occorrenza del pattern.
Restituisce una tuple contenente altre tuple. Ogni tuple interna rappresenta un match completo del tuo pattern. Gli integer all'interno di queste tuple sono gli indici esatti degli atomi all'interno della molecola candidata. Ecco il punto chiave. L'ordine di quegli indici rispecchia perfettamente l'ordine degli atomi definiti nella tua string SMARTS originale. Questo significa che sai sempre esattamente quale atomo nel target corrisponde a quale parte della tua query. Se il gruppo tossico compare tre volte nel candidato, ottieni tre tuple interne. Puoi contare le tuple per trovare la frequenza del pattern, oppure passare quegli specifici indici degli atomi a una drawing function per evidenziare visivamente le regioni tossiche. Se ti servono solo gli indici degli atomi del primissimo match che trova, puoi usare il metodo singolare get substructure match per risparmiare tempo di elaborazione.
Devi anche tenere conto della stereochimica. Di default, il substructure matching di RDKit ignora completamente la chiralità. Un legame a cuneo e un legame tratteggiato faranno scattare entrambi un match per una query SMARTS di base. Se la tossicità del tuo target si manifesta solo con uno specifico stereoisomero, questo comportamento di default genererà falsi positivi nel tuo drug screen. Per risolvere questo problema, passi un argomento chiamato use chirality e lo imposti a true quando chiami uno qualsiasi dei metodi di matching. RDKit applicherà quindi le regole stereochimiche in base alla configurazione specifica definita nella tua query.
Il vero potere del Substructure Searching è che mappa una text query puramente logica direttamente sulla topologia fisica del tuo dataset, colmando il divario tra string pattern astratti e coordinate atomiche concrete. Questo è tutto per questo episodio. Grazie per aver ascoltato, e continua a sviluppare!
5
Fingerprinting e similarità molecolare
3m 59s
Esplora come tradurre i grafi molecolari in vettori di bit matematici. Tratteremo le MACCS keys, i Morgan fingerprints e il calcolo della Tanimoto similarity.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics e AI, episodio 5 di 22. I modelli di AI in realtà non capiscono atomi e legami. Capiscono solo i numeri. Se vuoi che un algoritmo confronti due strutture, ti serve un modo per tradurre la chimica in matematica. Il fingerprinting e la molecular similarity sono esattamente il modo in cui colmiamo questa lacuna.
Una molecola in RDKit è essenzialmente un grafo matematico. Gli atomi fungono da nodi e i legami da archi. Per eseguire calcoli veloci su questi grafi, li convertiamo in bit vector, che sono semplicemente dei lunghi array di uno e zero. Questo array è chiamato fingerprint. La logica è semplice. Se una specifica feature strutturale è presente nella molecola, un bit specifico nell'array viene settato a uno. Se quella feature è assente, il bit resta a zero. Convertendo i grafi molecolari complessi in bit vector standard, possiamo confrontarli facilmente dal punto di vista matematico.
RDKit fornisce diversi algoritmi di fingerprinting. Il fingerprint di default di RDKit utilizza un approccio topologico. Analizza i path lineari attraverso la molecola. Il sistema parte da un atomo e traccia i path lungo i legami connessi fino a una lunghezza specifica, in genere compresa tra uno e sette legami. Ogni path univoco che trova viene passato a una funzione di hashing, che assegna quel path a una posizione specifica nel bit vector.
Sebbene i path topologici siano utili, la chemoinformatica moderna si basa pesantemente sui Morgan fingerprint, spesso chiamati circular fingerprint. Invece di tracciare path lineari, gli algoritmi di Morgan analizzano l'intorno che si irradia verso l'esterno da ogni singolo atomo. Quando generi un Morgan fingerprint, devi definire un raggio. Un raggio pari a zero significa che l'algoritmo registra solo i singoli atomi. Un raggio pari a uno cattura ogni atomo più i suoi vicini immediatamente connessi. Un raggio pari a due espande quel cerchio di un ulteriore legame. L'algoritmo cataloga tutti questi ambienti circolari sovrapposti, ne fa l'hashing e setta i bit corrispondenti a uno. Di solito, facciamo il folding di questi hash in un vector a lunghezza fissa, come duemilaquarantotto bit, per mantenere prevedibile l'utilizzo della memoria. I Morgan fingerprint con raggio due sono lo standard del settore perché catturano magnificamente i gruppi funzionali e il contesto chimico locale.
Guardiamo uno scenario concreto. Hai due molecole leggermente diverse. Magari condividono una grande struttura di core, ma una ha un gruppo metilico extra attaccato. Vuoi quantificare quanto si sovrappongono. Per prima cosa, leggi entrambe le molecole in RDKit. Poi, generi un Morgan fingerprint per ciascuna, settando il raggio a due. Ora hai due bit vector distinti. Per calcolare quanto sono simili, calcoli la loro Tanimoto similarity.
Ecco l'intuizione chiave. La Tanimoto similarity ignora gli zeri. Le interessano solo le feature che sono effettivamente presenti. La matematica è una semplice intersection over union. RDKit conta il numero di bit settati a uno in entrambi i fingerprint e lo divide per il numero totale di bit settati a uno in almeno uno dei due fingerprint. Se i due vector corrispondono perfettamente, il Tanimoto score è uno punto zero. Se non condividono alcuna feature, lo score è zero punto zero. Per le nostre due molecole che differiscono per un singolo gruppo metilico, gli ambienti circolari attorno al core combaceranno quasi tutti, mentre gli ambienti vicino alla mutazione saranno diversi. Potresti ottenere un Tanimoto score di zero punto otto cinque, dandoti un valore numerico preciso per la loro sovrapposizione strutturale.
Tieni presente che mappare una molecola complessa in un array fisso di bit significa perdere alcuni dati, e un Tanimoto score elevato garantisce la sovrapposizione strutturale, non l'equivalenza biologica.
Grazie per aver passato qualche minuto con me. Alla prossima, stammi bene.
6
Rompere il piano 2D
4m 28s
Passa dai disegni piatti in 2D a geometrie 3D realistiche. Discuteremo l'aggiunta di idrogeni espliciti e la generazione di conformeri 3D affidabili utilizzando ETKDG.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e IA con Python, episodio 6 di 22. Un disegno bidimensionale può sembrare perfetto su uno schermo, ma i farmaci esistono nello spazio tridimensionale. Se ignori la geometria, ignori la realtà. Oggi rompiamo il piano 2D e generiamo le giuste coordinate 3D per le tue molecole.
Quando leggi una molecola da una SMILES string standard, non ha alcuna coordinata. È strettamente un grafo topologico di atomi connessi. Anche se carichi una struttura da un file di disegno 2D, quelle coordinate sono semplicemente distanziate per la leggibilità umana. Per fare docking, calcolare l'area superficiale o eseguire simulazioni fisiche, hai bisogno di una struttura 3D fisicamente realistica.
Il primissimo passo prima di generare qualsiasi geometria 3D è aggiungere gli idrogeni. In una SMILES string standard, gli idrogeni sono impliciti. Vengono trattati come una proprietà di base degli atomi pesanti, semplicemente per riempire i requisiti di valenza. Ma nello spazio fisico, gli idrogeni occupano un volume reale. Creano ingombro sterico e dettano gli angoli dei legami attorno a loro. Se provi a calcolare una struttura 3D senza prima aggiungere esplicitamente gli idrogeni, la geometria risultante collasserà su se stessa e gli angoli di legame saranno completamente sbagliati. RDKit fornisce una funzione chiamata AddHs che converte quegli idrogeni impliciti in veri e propri nodi nel tuo grafo molecolare, completi di legami. Devi sempre eseguire questa funzione prima di passare al 3D.
Una volta che hai una molecola completa, devi calcolare le sue coordinate spaziali. Dato che i legami singoli possono ruotare liberamente, un ligando flessibile non ha una sola forma statica. Può adottare molte forme diverse, conosciute come conformazioni. Per generare una conformazione valida, RDKit usa un metodo di default chiamato ETKDG. Questo sta per Experimental Torsion-angle Preference with Distance Geometry.
Ecco il punto chiave. I metodi di vecchia generazione si basavano interamente sulla matematica pura. Usavano la distance geometry per indovinare le posizioni atomiche basandosi su lunghezze e angoli di legame noti. Questo spesso portava a forme strane e ad alta energia, che richiedevano una pesante pulizia computazionale. ETKDG risolve questo problema combinando la matematica della distance geometry con regole empiriche derivate dal Cambridge Structural Database. Sa come le molecole fisiche reali preferiscono effettivamente piegarsi e torcersi, e forza l'algoritmo di geometria a rispettare quelle preferenze naturali.
Prendi uno scenario concreto. Hai un ligando altamente flessibile, e devi capire tutti i diversi modi in cui potrebbe ripiegarsi per adattarsi a una binding pocket proteica. Generare una singola conformazione non è abbastanza per catturare quel comportamento. Hai bisogno di un ensemble. RDKit gestisce questa cosa con una funzione chiamata EmbedMultipleConfs. Passi la tua molecola con i suoi idrogeni espliciti, e specifichi che vuoi cinquanta conformeri.
RDKit eseguirà quindi l'algoritmo ETKDG cinquanta volte separate, partendo da diversi random seed, per generare cinquanta geometrie 3D distinte. Memorizza tutte e cinquanta queste forme all'interno dell'oggetto molecola originale. Non ottieni indietro cinquanta molecole separate; ottieni una molecola che contiene cinquanta set di coordinate distinti. Puoi quindi fare un loop attraverso questi set di coordinate per misurare le distanze o calcolare le energie. Dato che ETKDG è fortemente informato da dati cristallografici del mondo reale, le strutture iniziali che fornisce sono di solito di altissima qualità appena uscite dalla funzione.
Una molecola non è un disegno piatto, ed è raramente solo una singola forma rigida; è un oggetto dinamico, e campionare i suoi molteplici conformeri ti dà i veri confini del suo comportamento fisico. Se vuoi aiutare a far continuare lo show, puoi supportarci cercando DevStoriesEU su Patreon. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
7
Accelerare il Feature Engineering
4m 04s
Collega la cheminformatics e la data science standard con scikit-fingerprints. Esploriamo la generazione di oltre 30 tipi di fingerprint molecolari direttamente all'interno di un'interfaccia scikit-learn.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e AI con Python, episodio 7 di 22. Scrivere loop custom per l'estrazione dei fingerprint per ogni nuovo progetto è noioso e soggetto a errori. Passi da un fingerprint ECFP a una MACCS key, e all'improvviso devi riscrivere l'intero blocco di preprocessing. Scikit-fingerprints è una libreria che risolve questo problema, rendendo la feature extraction molecolare semplice quanto chiamare una transform standard di scikit-learn.
Le molecole sono fondamentalmente rappresentate come grafi. La maggior parte degli algoritmi di machine learning, però, richiede vettori multidimensionali. I fingerprint molecolari sono gli algoritmi di feature extraction che colmano questo gap, codificando le informazioni strutturali in array numerici. Il problema è che i tool open-source standard per calcolare questi fingerprint, come RDKit, Open Babel o il Chemistry Development Kit, sono scritti in C++ o Java. I loro wrapper Python non si allineano nativamente con l'application programming interface di scikit-learn. Finisci per scrivere data loader custom, convertitori di formato e loop proni agli errori solo per dare ai tuoi dati una forma che un classificatore possa consumare.
Scikit-fingerprints cambia questa architettura. Implementa oltre 30 fingerprint molecolari diversi come transformer standard e stateless di scikit-learn. Tutte le classi dei fingerprint ereditano dalle classi base di scikit-learn. Questo significa che si integrano direttamente nelle pipeline di machine learning standard e nelle feature union.
Prendi un workflow standard. Normalmente, scriveresti un loop custom di venti righe in RDKit per iterare su un dataset, validare le molecole, estrarre i fingerprint circolari e impilare i risultati in un array. Con questa libreria, sostituisci l'intero blocco di boilerplate con un singolo passaggio. Crei un oggetto chiamato ECFP Fingerprint e lo passi direttamente in una pipeline di scikit-learn subito prima del tuo modello random forest. Quando chiami il metodo fit sulla tua pipeline con i tuoi training data e le variabili target, il transformer del fingerprint elabora gli input e restituisce un array NumPy denso direttamente al modello.
Ecco il punto chiave. Non devi convertire le tue rappresentazioni testuali in oggetti molecola di RDKit prima di passarle al transformer. Per qualsiasi fingerprint bidimensionale basato sulla topologia a grafo, il metodo transform accetta direttamente una list Python standard di SMILES strings. La libreria gestisce automaticamente la conversione interna. Dato che le SMILES strings non sono sempre univoche o chimicamente valide, la libreria fornisce anche una classe Molecule Standardizer. Questa classe applica gli step di sanitization raccomandati da RDKit per garantire la data quality prima che inizi l'estrazione.
La libreria supporta anche fingerprint tridimensionali basati sulla conformazione spaziale. Questi algoritmi spaziali richiedono oggetti molecola di RDKit con conformeri calcolati. Generare conformeri può essere instabile, quindi il package include una classe Conformer Generator che utilizza uno specifico algoritmo noto come ETKDG versione 3. Questo fornisce dei default affidabili che massimizzano l'efficienza per le molecole semplici, riducendo al minimo i fallimenti di calcolo sui composti complessi. Metti il conformer generator all'inizio della tua pipeline, lo fai seguire da un transformer di fingerprint tridimensionali, e finisci con un imputer per gestire eventuali valori mancanti.
Incapsulando la complessa logica chimica all'interno di classi transformer standard, la libreria astrae il boilerplate specifico del dominio. Configuri opzioni come la lunghezza del vettore di output o se vuoi una variante binary o count semplicemente passando i parametri al costruttore del transformer. Il risultato è che il tuning degli hyperparameter per i fingerprint molecolari diventa semplice quanto fare il tuning della profondità di un decision tree.
Per questo episodio è tutto. Ci sentiamo alla prossima!
8
Cheminformatics ad alte prestazioni
4m 36s
Scopri come elaborare enormi dataset chimici in modo efficiente. Approfondiremo l'utilizzo del parallelismo CPU con Joblib e il risparmio di memoria tramite le matrici sparse di SciPy.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 8 di 22. Calcolare sottostrutture complesse su un dataset enorme può facilmente mandare in crash la tua macchina con errori di out-of-memory, a meno che tu non sappia esattamente come gestire il tuo data footprint. La tecnica che risolve questo problema è l'High-Performance Cheminformatics.
Quando estrai delle feature da una molecola, usi spesso dei fingerprint basati su sottostrutture. Il fingerprint di Klekota-Roth ne è un classico esempio. Per calcolarlo, la tua macchina confronta una molecola con migliaia di pattern chimici predefiniti, noti come pattern SMARTS. Scansiona ripetutamente il grafo molecolare per vedere se esistono specifici gruppi funzionali o motivi strutturali. Fare questo in modo sequenziale per poche molecole va benissimo. Farlo per un dataset di quattrocentomila molecole rappresenta un grave bottleneck computazionale.
Il calcolo dei fingerprint molecolari è un task embarrassingly parallel. L'analisi strutturale di una molecola ha letteralmente zero dipendenze dall'analisi della molecola successiva nel tuo dataset. Dato che non condividono alcuno stato, puoi calcolarli in modo del tutto simultaneo. Per scalare tutto questo in modo efficace in Python, utilizzi Joblib, affidandoti in particolare all'executor Loky.
Quando avvii il processo, il dataset di input viene diviso in chunk che corrispondono esattamente ai core della tua CPU disponibili. Se hai un processore a 16 core, le tue molecole di input vengono divise in 16 batch separati. Ogni processo worker Python prende un batch e inizia a eseguire il pattern matching SMARTS in modo indipendente. L'ostacolo tecnico con il multiprocessing in Python di solito è il costo dello spostamento dei dati tra i worker e il main process. Loky aggira questo problema usando il memory mapping. Invece di serializzare gli array finali dei fingerprint e inviarli tramite inter-process communication, i worker scrivono direttamente in uno spazio di memoria condivisa. Per fingerprint pesanti dal punto di vista computazionale come Klekota-Roth, distribuire il workload su 16 core produce uno speedup di quasi quindici volte.
Questo gestisce il tempo di elaborazione. Il secondo bottleneck critico è la memoria di sistema.
Un singolo vettore fingerprint di Klekota-Roth è lungo. Se elabori centinaia di migliaia di molecole, generi un'enorme matrice di risultati. Di default, le librerie numeriche restituiscono questo risultato come un dense array NumPy. Ogni singola posizione in quella matrice alloca memoria, indipendentemente dal fatto che il valore sia un uno o uno zero.
I fingerprint chimici sono estremamente sparsi. Di solito, solo l'uno o il due percento delle feature strutturali richieste è effettivamente presente in una data molecola. La stragrande maggioranza della tua matrice risultante è costituita da zeri. Memorizzare quegli zeri è ciò che scatena gli errori di out-of-memory sui grandi dataset. La soluzione è cambiare il formato di output in una sparse matrix SciPy, in particolare usando il formato Compressed Sparse Row. Una sparse matrix cambia radicalmente il modo in cui i dati vengono memorizzati. Invece di costruire una griglia rigida in memoria, registra solo i valori degli elementi diversi da zero insieme alle loro coordinate di riga e colonna.
Considera uno scenario reale usando il dataset PCBA, che contiene poco meno di quattrocentoquarantamila molecole. Esegui il calcolo del fingerprint di Klekota-Roth sull'intero dataset usando i tuoi 16 core. L'esecuzione parallela finisce in modo efficiente. Se lasci l'output come dense array di default, questa singola matrice consumerà poco più di due Gigabyte di RAM. Istruendo invece il calcolo a restituire uno sparse array SciPy, l'esatto stesso dataset scende a un footprint di soli 23 Megabyte. Ottieni una riduzione di memoria di ottantotto volte senza perdere una singola informazione chimica, e la rappresentazione sparsa non ha alcun impatto negativo sui tuoi tempi di calcolo.
Ecco il punto chiave. Non hai bisogno di un enorme compute cluster per elaborare centinaia di migliaia di molecole, a patto che tu smetta di pagare la tassa di memoria per memorizzare zeri e ti assicuri che il passaggio dei tuoi dati salti l'overhead standard della inter-process communication.
Questo è tutto per questo episodio. Grazie per l'ascolto, e keep building!
9
Pipeline ML End-to-End
3m 58s
Combina elaborazione, fingerprinting e previsione in un'unica architettura pulita. Costruiremo pipeline scikit-learn robuste che integrano perfettamente la generazione di conformeri 3D e la previsione delle proprietà.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e AI con Python, episodio 9 di 22. Uno script complesso per lo screening virtuale 3D richiedeva centinaia di righe di codice fragile. Dovevi generare manualmente i conformer, gestire gli errori, calcolare molteplici descriptor e unire gli array prima ancora di toccare un modello. Ora, puoi strutturare l'intero processo in un'unica, elegante definizione di pipeline usando le pipeline ML end-to-end.
Nel machine learning, una pipeline è una sequenza di step di elaborazione dati e un estimator finale raggruppati in un singolo oggetto. In chemoinformatica, specialmente con i dati strutturali 3D, il preprocessing è notoriamente frammentato. Prendi delle stringhe SMILES grezze, calcoli le coordinate 3D, esegui ottimizzazioni con force field, estrai le feature, correggi i missing value e infine addestri un classifier. Farlo manualmente significa scrivere loop custom e strutture dati intermedie che si rompono facilmente e causano memory leak. Vedremo come costruire una pipeline scikit-learn completa che porta le stringhe SMILES grezze direttamente a un classifier Random Forest.
Il primo step della sequenza è la generazione dei conformer. Inizializzi un conformer generator e lo passi come primo stadio della pipeline. Legge l'input 2D e calcola le strutture 3D. Puoi configurarlo per ottimizzare la geometria usando un force field come MMFF94. Parallelizza automaticamente questo lavoro pesante su tutti i core della CPU disponibili.
Ora, la seconda parte è la feature extraction. Per i task 3D, combinare diversi descriptor geometrici cattura più informazioni molecolari. Usi una feature union di scikit-learn per calcolare simultaneamente i fingerprint GETAWAY e WHIM. Entrambe queste classi di fingerprint agiscono come stateless transformer nella pipeline. Prendono i conformer 3D dallo step precedente, calcolano i rispettivi descriptor in parallelo e concatenano i risultati in un'unica, ampia feature matrix.
Successivamente, devi gestire gli errori di calcolo. Gli algoritmi dei descriptor 3D a volte falliscono nell'elaborare molecole molto complesse o in tensione, risultando in missing value nella tua matrice. La pipeline gestisce questo problema senza un error handling custom. Inserisci un simple imputer direttamente dopo la feature union. Se un calcolo GETAWAY o WHIM restituisce un missing value, l'imputer lo intercetta e lo sostituisce con la media di quella feature in tutto il tuo dataset.
Infine, chiudi la pipeline con il tuo modello predittivo, che in questo caso è un classifier Random Forest.
Per strutturare tutto questo nel codice, chiami la funzione make pipeline. All'interno di quella chiamata a funzione, passi il tuo conformer generator. Successivamente, passi la feature union contenente i tuoi fingerprint GETAWAY e WHIM. Poi arriva il simple imputer e, infine, il classifier Random Forest. Assegni questa intera sequenza a una singola variabile.
Quando chiami il metodo fit su quella variabile della pipeline, passi le tue stringhe SMILES di training grezze e le tue label target. Le stringhe fluiscono sequenzialmente attraverso il conformer generator, nella feature union per il fingerprinting, attraverso l'imputer per pulire i dati e direttamente nel classifier per il training. Quando è il momento di valutare, chiamare il metodo predict sulle tue stringhe SMILES di test forza i nuovi dati a seguire esattamente lo stesso percorso.
Ecco il punto chiave. Lo stato e il data routing sono gestiti interamente dall'oggetto pipeline, il che significa che non tieni mai array densi intermedi in memoria o scrivi data loader custom per i tuoi conformer.
Questo è tutto per questo episodio. Grazie per l'ascolto e continua a sviluppare!
10
Prevedere l'affinità di legame
4m 21s
Esplora la realtà della previsione dell'affinità di legame proteina-ligando. Confronteremo le prestazioni di semplici modelli ad albero 2D con quelle delle complesse Graph Neural Networks 3D.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 10 di 22. Assembli una massiccia graph neural network tridimensionale, dandole in pasto le coordinate spaziali di ogni atomo in una tasca proteica. Poi esegui un semplice gradient boosted decision tree che guarda solo lo sketch bidimensionale del farmaco. Il benchmark finisce, e il tuo modello spaziale all'avanguardia è appena stato battuto da un algoritmo di vent'anni fa. Il motivo per cui la tua rete pesante ha fallito è radicato nel modo in cui gestiamo la previsione della binding affinity.
Prevedere la binding affinity è il processo computazionale che stima quanto saldamente una piccola molecola, o ligando, si attacca a uno specifico protein target. Nella drug discovery, trovare una molecola che si lega fortemente è l'intero obiettivo. Per farlo, gli ingegneri in genere prendono una di due strade. La prima è molto complessa. Usi neural network tridimensionali come GraphNet o TensorNet. Questi modelli prendono in input l'esatta conformazione di legame del complesso proteina-ligando. Usano layer di message passing per imparare le precise distanze spaziali e le feature quantomeccaniche tra gli atomi del farmaco e gli atomi della tasca proteica.
La seconda strada ignora completamente la proteina. Scarti le coordinate spaziali e usi un classico modello bidimensionale come XGBoost. L'input qui è solo un vettore concatenato di fingerprint molecolari. Calcoli le feature strutturali solo dal ligando, trasformando essenzialmente il disegno bidimensionale della molecola in un array di numeri, e lo passi direttamente in input al modello tree-based.
Per vedere come si confrontano questi approcci, i ricercatori li fanno girare su test set standardizzati. Uno dei più indicativi è il benchmark Merck FEP. Questo dataset simula un comune scenario di virtual screening chiamato serie congenerica. In una serie congenerica, tutti i ligandi testati condividono esattamente lo stesso scaffold chimico di base e si legano esattamente allo stesso sito su un singolo protein target. Le uniche differenze tra le molecole sono piccole variazioni strutturali, come diverse ramificazioni chimiche attaccate al core principale.
Ecco l'intuizione chiave. Quando valutati sul dataset Merck, i pesanti modelli tridimensionali hanno ottenuto un correlation score intorno a zero virgola tre. Il semplice modello bidimensionale XGBoost ha ottenuto un punteggio significativamente più alto, raggiungendo zero virgola quattro cinque. Il decision tree, computazionalmente economico, ha chiaramente superato le avanzate graph neural network.
Questo succede a causa di ciò su cui i modelli sono costretti a concentrarsi. In una serie congenerica, il protein target e la binding pocket non cambiano. Il modello tridimensionale spende enormi risorse computazionali per mappare un ambiente spaziale che rimane statico in ogni singolo test case. Peggio ancora, questi modelli sono altamente sensibili a minuscole variazioni nelle coordinate atomiche. Un leggero e arbitrario spostamento nel modo in cui viene posizionato un atomo di idrogeno durante la data preparation introduce del rumore che distrae la graph network. Il modello bidimensionale ha successo proprio perché è cieco rispetto alla proteina. Guardando solo le feature del ligando, si affida alle uniche variabili che cambiano effettivamente da un test all'altro. Il decision tree correla quelle dirette variazioni strutturali nel farmaco alla forza di legame finale, bypassando completamente il rumore dell'ambiente spaziale.
I pesanti modelli tridimensionali sono ancora molto preziosi quando devi generalizzare su protein target completamente diversi e mai visti, dove la geometria della tasca è sconosciuta. Ma quando stai ottimizzando una specifica famiglia di farmaci per un singolo target noto, passare dati ambientali costanti in input a una deep network è inefficiente e soggetto a errori. Lo strumento predittivo più potente è spesso quello che filtra via l'ambiente statico e modella solo le variabili che cambiano. Per questo episodio è tutto. Alla prossima!
11
LLM contro Fingerprint classici
4m 13s
Scopri come il Natural Language Processing si applica alla chimica. Metteremo a confronto i vector embeddings dei Large Language Models con i classici fingerprint strutturali di RDKit per prevedere la bioattività.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 11 di 22. E se il modo migliore per descrivere una molecola a un modello di machine learning non fosse con una formula strutturale creata a mano, ma trattando la sua stringa SMILES esattamente come una frase in linguaggio naturale? Potresti sprecare preziosi compute cycle per generare descrittori chimici complessi, solo per farti superare da un modello testuale. Questa tensione è al centro del confronto tra LLM e fingerprint classici.
Quando prevedi quanto saldamente un ligando si lega a una proteina, il tuo modello ha bisogno di una descrizione matematica del ligando. Il metodo tradizionale si basa sui fingerprint strutturali classici calcolati da tool come RDKit. Passi una molecola attraverso un algoritmo deterministico e ottieni un vettore statico. Un fingerprint di Morgan conta le sottostrutture circolari attorno agli atomi. Le chiavi MACCS confrontano la molecola con una lista predefinita di pattern chimici.
Il limite di questi fingerprint classici è la loro rigidità. Codificano regole specifiche e immutabili. Non puoi farci fine-tuning. Se una particolare sfumatura strutturale è importante per una tasca di legame altamente specifica, ma l'algoritmo di fingerprint non è stato esplicitamente progettato per catturarla, quell'informazione viene completamente persa prima ancora che il modello predittivo veda i dati.
Invece di fare l'hardcoding delle regole chimiche, possiamo usare un Large Language Model chimico pre-addestrato come BioT5, GPT2 o BERT. Questi modelli sono pre-addestrati su milioni di stringhe SMILES. Imparano la grammatica della chimica in modo non supervisionato. Quando passi un ligando a un LLM, questo non restituisce una checklist fissa di gruppi funzionali. Restituisce un ricco vector embedding. Ogni carattere o token in quella stringa SMILES ottiene il proprio vettore contestuale.
Per capire la differenza, guarda come queste rappresentazioni alimentano i modelli predittivi. Per prima cosa, considera un modello XGBoost che usa le classiche chiavi MACCS. Generi il fingerprint MACCS, che risulta in un semplice array binario. Passi quel vettore fisso a XGBoost, che cerca di mappare quelle feature grezze di presenza o assenza all'affinità di legame. Nei test di benchmark su serie congeneriche, questa specifica combinazione produce costantemente le performance peggiori. Le feature create a mano sono semplicemente troppo approssimative.
Ora, scambia quell'architettura con un embedding BioT5 passato a una Transformer head. Per prima cosa passi la stringa SMILES grezza al modello BioT5. Questo restituisce una sequenza di embedding per ogni token. Poi passi questa sequenza a una Transformer head. Ecco l'intuizione chiave. Il Transformer usa un meccanismo di attention. Guarda l'intera sequenza di embedding dei token e impara dinamicamente quali parti della molecola contano di più per legarsi a questo specifico target. Pesa le feature in modo intelligente prima di restituire l'affinità di legame predetta.
Se provi a prendere quegli stessi identici token BioT5, sommarli in un unico vettore piatto e passarli a XGBoost, le performance predittive calano significativamente. Il sum pooling fa una media dei dettagli a livello di token. La Transformer head ha successo proprio perché preserva e sfrutta il contesto granulare della rappresentazione testuale.
Questo passaggio da array statici a embedding dinamici offre enormi vantaggi pratici. Gli embedding degli LLM sono estremamente versatili e possono essere sottoposti a fine-tuning per task downstream specializzati. Sono anche molto più compatti degli enormi bit vector classici, il che fa risparmiare memoria quando memorizzi grandi librerie molecolari. Inoltre, la generazione di text embedding gira su GPU, il che è drasticamente più veloce rispetto al calcolo dei tradizionali fingerprint RDKit su CPU.
L'era in cui si diceva manualmente agli algoritmi quali sottostrutture chimiche contano sta finendo; i modelli che performano meglio sono quelli a cui è permesso leggere la molecola e decidere da soli. Se vuoi supportare lo show, puoi cercare DevStoriesEU su Patreon. Grazie per essere stato con noi. Spero tu abbia imparato qualcosa di nuovo.
12
Active Learning per il Virtual Screening
4m 22s
Scopri come individuare iterativamente i migliori candidati farmaci senza test esaustivi. Approfondiremo i cicli di Active Learning e le strategie di selezione greedy per massimizzare i tassi di successo.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics e AI, episodio 12 di 22. Eseguire simulazioni fisiche complesse su un milione di molecole è incredibilmente lento. Hai bisogno di un modo per trovare i candidati in assoluto migliori testando solo una piccolissima frazione del tuo dataset. Questo è esattamente ciò che fa l'Active Learning per il Virtual Screening.
Quando valuti una chemical library, calcolare con precisione le affinità di legame usando metodi di fisica computazionale è incredibilmente costoso. Semplicemente non puoi permetterti di simulare ogni singolo composto. Invece, testi un piccolo batch, usi quei risultati per addestrare un modello di machine learning e lasci che quel modello preveda le affinità per il resto della libreria. Poi testi le previsioni più promettenti, aggiorni il modello e ripeti il processo. Questo ciclo iterativo è l'Active Learning.
Vediamo uno scenario concreto. Stai esplorando una serie congenerica di diecimila composti che hanno come target una proteina specifica, come Tyk2. Il tuo obiettivo è trovare il top uno percento delle molecole attive. Per farlo in modo efficiente, ti affidi a una strategia di selezione greedy. Una strategia greedy significa che il tuo modello seleziona sempre i composti con le affinità di legame previste più alte per il round di test successivo.
Imposti la batch size a sessanta molecole per round. Questo numero rappresenta un compromesso pratico per un workflow del mondo reale. È abbastanza piccolo da permetterti di eseguire rapidamente simulazioni fisiche pesanti sul batch, ma abbastanza grande da fornire un chunk sostanzioso di nuovi dati al tuo modello. Esegui i test su questi sessanta composti per ottenere le loro vere affinità di legame, e dai immediatamente in pasto quei dati a un modello tree-based bidimensionale, come XGBoost. Il modello XGBoost impara i pattern, assegna uno score alle restanti molecole non testate nel pool di diecimila composti, e seleziona i successivi sessanta candidati.
Ecco il punto chiave. Il modo in cui scegli il primissimo batch di sessanta molecole detta la velocità con cui impara l'intero sistema. L'Active Learning standard spesso ripiega su una baseline random. Selezioni sessanta molecole in modo completamente random, le testi e addestri il tuo primo modello. Ma la selezione random dà al tuo modello un pessimo punto di partenza, riempiendo il training set iniziale con composti per lo più inattivi.
La soluzione è inizializzare il loop di Active Learning usando una rete neurale 3D pre-addestrata. Questo modello 3D è già stato addestrato su un dataset generale ed enorme di diversi complessi proteina-ligando. Dato che comprende la fisica generale del legame basata sulle interazioni strutturali, può assegnare uno score ai tuoi diecimila composti prima ancora che il loop di Active Learning inizi.
Per prima cosa, usi il modello 3D pre-addestrato per prevedere le affinità per l'intero pool. Poi, prendi le migliori sessanta molecole identificate da questo prescreening ed esegui su di esse le tue pesanti simulazioni fisiche. Ora hai un set di dati di partenza altamente arricchito. Passi questo dataset iniziale di alta qualità al tuo modello XGBoost. Da questo momento in poi, il modello XGBoost prende il controllo del loop. Si addestra sui dati verificati, fa previsioni sul pool rimanente e seleziona in modo greedy i successivi sessanta candidati.
Questa combinazione genera un'accelerazione enorme nella hit discovery. Il modello 3D generale fornisce un ricco punto di partenza, e il modello XGBoost si adatta rapidamente allo spazio chimico specifico della tua serie congenerica. Inizializzando con un modello 3D pre-addestrato invece che con un random sampling, puoi trovare l'ottanta percento del top uno percento dei binder dopo aver testato meno del dieci percento dell'intero dataset. Iniziare il tuo loop con un prescreening 3D generale dà ai tuoi modelli specializzati un vantaggio iniziale imbattibile.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
13
La sfida degli Activity Cliff
3m 32s
Esamina la fragilità delle relazioni struttura-attività. Discuteremo degli 'activity cliffs', situazioni in cui un minuscolo cambiamento strutturale causa un'enorme variazione nella potenza di un farmaco.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 13 di 22. In chimica, un singolo atomo fuori posto può trasformare un farmaco potente e salvavita in una polvere inerte. Questi improvvisi cali di potenza biologica sono chiamati activity cliff, e rappresentano la nemesi assoluta dei modelli di AI tradizionali.
Un activity cliff si verifica quando hai una coppia di molecole con un'elevata somiglianza strutturale ma livelli di attività significativamente diversi. Considera uno scenario concreto. Hai due molecole che condividono il novanta percento del loro framework strutturale. La prima molecola si lega saldamente a un target biologico. La seconda molecola è completamente inattiva. L'unica differenza fisica tra loro è un singolo gruppo metilico attaccato a uno specifico anello. Per un chimico farmaceutico umano, questa specifica modifica strutturale è estremamente informativa. Gli indica esattamente dove si trovano i confini della tasca del recettore. Per un modello di machine learning standard, è un'interruzione catastrofica.
Ecco il punto chiave. La maggior parte degli approcci di deep learning in chemoinformatica è progettata per prevedere i valori assoluti delle proprietà. Che tu stia usando una graph neural network o un chemical language model, l'architettura è fondamentalmente progettata per mappare le strutture chimiche in uno spazio matematico continuo. L'assunto fondamentale hardcoded in questi modelli è che strutture molecolari simili dovrebbero mappare su proprietà biologiche simili. Quando un modello standard elabora le nostre due molecole quasi identiche, genera rappresentazioni che si trovano una accanto all'altra in quello spazio matematico. Dato che gli input sono vicini, il modello genera naturalmente in output previsioni di potenza assoluta quasi identiche per entrambe.
Gli activity cliff violano fondamentalmente questo presupposto di uno spazio chimico continuo e uniforme. Rappresentano una grave discontinuità. Il modello si aspetta una leggera salita, ma incontra un crollo verticale. Questo problema è fortemente amplificato dalla natura dei dati di drug discovery. I dataset sperimentali sono notoriamente limitati e rumorosi. Quando addestri una deep neural network su dati sparsi, il modello fatica a generalizzare. Per minimizzare l'errore complessivo sull'intero training set, la rete apprende pattern ampi e globali. Smussa le irregolarità locali. Quando incontra un activity cliff, l'obiettivo di regressione standard tratta quel repentino salto di varianza come rumore sperimentale o come un outlier. Il modello ignora l'informazione strutturale locale più critica perché non si adatta al trend globale.
Questo è il motivo per cui prevedere gli activity cliff rimane uno dei problemi più difficili nella predizione delle proprietà molecolari. I modelli sono costretti ad apprendere uno spazio chimico discontinuo direttamente da dati limitati. Poiché si concentrano esclusivamente su predizioni assolute per singole molecole, ignorano completamente le preziose informazioni nascoste nelle differenze relative tra coppie di molecole corrispondenti. In molti casi, modelli tree-based più semplici finiscono per superare le complesse neural network su questi dataset, semplicemente perché i modelli di deep learning fanno over-smoothing delle rappresentazioni.
L'assunto che strutture chimiche simili producano sempre attività biologiche simili è una baseline statistica utile, ma non è una legge fisica. Gli activity cliff rappresentano la brutale e discontinua realtà delle relazioni struttura-attività, e dimostrano che la predizione di proprietà assolute nel vuoto fallirà sempre ai margini. Grazie per aver passato qualche minuto con me. Alla prossima, stammi bene.
14
Similarity-Quantized Relative Learning
3m 38s
Risolvi il problema degli activity cliff ripensando al modo in cui i modelli apprendono. Esploriamo il framework SQRL, che addestra l'IA a prevedere le differenze relative di proprietà tra coppie molecolari rigorosamente filtrate.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics e AI, episodio 14 di 22. Invece di costringere un'AI a memorizzare la potenza assoluta di ogni molecola esistente, e se le insegnassi semplicemente a chiedersi in che modo una molecola differisce dal suo vicino più prossimo conosciuto? Questo cambio di prospettiva risolve un importante problema di generalizzazione in regimi low-data, ed è il fulcro di un framework chiamato Similarity-Quantized Relative Learning, o SQRL.
Normalmente, la predizione delle proprietà molecolari tratta ogni molecola come un data point isolato. Il modello cerca di mappare una struttura direttamente a un valore assoluto della proprietà. Con dataset piccoli e rumorosi, i modelli di deep learning faticano a costruire una mappa globale accurata dello spazio chimico. I precedenti tentativi di pairwise learning hanno cercato di risolvere questo problema accoppiando ogni molecola con ogni altra molecola nel training set. Questo approccio inonda i dati con confronti tra strutture completamente non correlate, soffocando il segnale locale utile. SQRL risolve questo problema limitando i training data a coppie di molecole che sono strutturalmente molto simili. Il modello impara a prevedere la differenza relativa nelle loro proprietà, nota come delta y.
Questo si ottiene attraverso uno specifico step di matching del dataset. Non passi al modello singole molecole. Gli passi delle coppie, ma solo se superano una rigorosa soglia di similarità. Analizziamo la logica. Parti dal tuo training set standard di molecole e dalle loro potenze note. Per prima cosa, calcoli le distanze pairwise tra tutte le molecole utilizzando una metrica come la distanza di Tanimoto sulle Morgan fingerprints.
Ecco l'intuizione chiave. Imposti una soglia di distanza, alfa. Usiamo una soglia di distanza di Tanimoto di zero virgola sette. Iteri su tutte le possibili coppie di molecole. Se la distanza tra la molecola A e la molecola B è zero virgola sette o superiore, scarti la coppia completamente. Se la distanza è strettamente inferiore a zero virgola sette, aggiungi questa coppia al tuo nuovo training set relativo. La target variable per questa nuova coppia non è più una potenza assoluta. È l'esatta differenza numerica di potenza tra la molecola A e la molecola B.
Ora addestri la tua neural network. Il network genera una rappresentazione matematica per la molecola A, e una rappresentazione per la molecola B. Sottrae la rappresentazione di B dalla rappresentazione di A. Quel vettore differenza risultante viene passato attraverso un layer finale per prevedere il delta y. Filtrando il rumore delle coppie dissimili, il network è costretto a concentrarsi esclusivamente sui cambiamenti chimici locali ad alto segnale. Impara esattamente come una specifica modifica strutturale altera l'attività. Questo rende il modello altamente sensibile agli activity cliffs.
Questo copre il training, ma che dire della prediction su una molecola completamente nuova? Quando arriva una nuova struttura, il sistema scansiona i training data originali per trovare il singolo vicino strutturale più prossimo basandosi su quella stessa metrica di distanza di Tanimoto. Il network valuta la nuova molecola rispetto a questo nearest neighbor e prevede il delta relativo. Infine, prendi la potenza assoluta nota del vicino, aggiungi il delta predetto, e hai la tua prediction finale. Limitando il training space a coppie altamente simili, smetti di chiedere al modello di imparare l'intero universo chimico e invece lo addestri a diventare un esperto nei gradienti chimici locali.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
15
La rivoluzione della Generative AI
3m 27s
Passa dalla previsione delle proprietà all'immaginazione di molecole completamente nuove. Tracceremo il panorama dei task generativi molecolari: generazione De Novo, ottimizzazione e generazione di conformeri.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 15 di 22. Per anni, l'AI in chimica è stata puramente un'attività di triage. Davi in pasto a un modello migliaia di molecole esistenti, e lui si limitava a prevedere quali fossero le meno peggio. Se la molecola ideale non era nella tua screening library, il modello non poteva aiutarti. La rivoluzione della Generative AI ha ribaltato radicalmente questa dinamica. Invece di limitarci a filtrare ciò che già esiste, ora possiamo chiedere ai modelli di inventare materia chimica completamente nuova. Questo passaggio dalla previsione alla creazione si suddivide in due principali task generativi molecolari: la de novo generation e la molecular optimization. La de novo generation consiste nel creare nuove strutture molecolari da zero. Il modello parte da una rappresentazione di random noise e la raffina iterativamente fino a ottenere una struttura chimica valida. Quando questo avviene senza alcun vincolo, si chiama unconditional generation. Il modello esplora liberamente il vasto chemical space per produrre qualcosa di completamente nuovo. Anche se questo è utile per una scoperta ad ampio raggio, di solito hai bisogno di più controllo. Questo ci porta alla conditional generation, in particolare alla property-based generation. Qui, sei tu a decidere l'output. Fornisci dei vincoli specifici, come una bioattività target o un livello di sintetizzabilità richiesto, e il modello limita la generazione alle molecole che rispettano quei criteri. Questo viene spesso chiamato inverse molecule design, perché parti dalle proprietà che desideri e costringi il modello a lavorare a ritroso per costruire una struttura molecolare che le possieda. La de novo generation è potente, ma raramente inizi un progetto partendo da zero. Di solito, hai già un lead compound. È qui che entra in gioco la molecular optimization. A differenza dei task de novo, la molecular optimization si concentra sulla modifica di una struttura nota, invece di partire da un foglio bianco. Prendi una molecola esistente e la raffini per migliorarne le proprietà. Supponiamo che tu abbia un drug scaffold moderatamente efficace. Si lega al tuo target, ma la sua bioattività è troppo bassa per farne un farmaco valido. Usando un modello generativo, puoi eseguire una molecular optimization mirata. Un approccio è lo scaffold hopping. Chiedi al modello di sostituire il core molecular scaffold con uno nuovo, mantenendo l'attività biologica originale. Questo è estremamente efficace per scoprire composti strutturalmente nuovi che eludono i brevetti esistenti, mantenendo intatto il comportamento funzionale. Un altro approccio è l'R-group design. In questo scenario, blocchi il tuo core scaffold e chiedi al modello generativo di ottimizzare automaticamente le sue side chain. Il modello genera nuovi R-group, cercando le modifiche specifiche alle side chain che migliorano quella bioattività carente. Non stai scartando la tua molecola moderatamente efficace, stai lasciando che l'AI calcoli i precisi ritocchi strutturali necessari per farle tagliare il traguardo. Ecco il punto chiave. Il passaggio dalla predictive AI alla generative AI significa che non sei più limitato dalle molecole che hai a disposizione. Che tu stia generando una molecola custom da un foglio bianco o scambiando algoritmicamente le side chain di un farmaco esistente, stai trattando il chemical space come un mezzo programmabile. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
16
L'intuizione della Molecular Diffusion
3m 51s
Analizziamo il concetto centrale dei Diffusion Models senza la matematica pesante. Gli ascoltatori comprenderanno il forward process di aggiunta di rumore a una molecola e il reverse process di allucinazione di nuove strutture.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 16 di 22. Per insegnare a un'AI come inventare una nuova molecola, devi prima insegnarle come distruggerne completamente una. Sembra un controsenso, ma questa distruzione sistematica è esattamente il meccanismo usato per generare nuovi farmaci da zero. Questa è l'intuizione fondamentale dei Denoising Diffusion Probabilistic Models.
La progettazione molecolare tradizionale è incredibilmente laboriosa. Se vuoi automatizzare la scoperta di nuovi composti, ti serve un modello in grado di esplorare un vasto spazio chimico senza generare assurdità non valide. I primi modelli generativi deep cercavano di mappare direttamente questo spazio. I Denoising Diffusion Probabilistic Models, o DDPM, seguono una strada diversa. Trattano la generazione molecolare come un problema di denoising progressivo.
Il framework è diviso in due distinte catene di Markov: il processo forward e il processo reverse.
Il processo forward riguarda esclusivamente la degradazione dei dati. Prendi un farmaco valido e noto dal tuo training set. Attraverso una sequenza fissa di step, sfochi progressivamente le sue coordinate atomiche iniettando puro rumore gaussiano. La quantità di rumore aggiunta a ogni step è controllata da una schedule di iperparametri prestabilita. Allo step uno, perturbi leggermente gli atomi. La molecola è un po' distorta, ma ancora chiaramente riconoscibile. Arrivati allo step cinquanta, la struttura è fortemente deformata. Allo step finale, in genere indicato come step T, la molecola originale è completamente scomparsa. Ti ritrovi con una nuvola casuale di rumore gaussiano non strutturato.
Questo processo forward non richiede una rete neurale. È una pura corruzione matematica. Ha uno scopo vitale perché genera la ground truth per i nostri dati di training.
Ecco l'intuizione chiave. Dato che abbiamo controllato l'esatta quantità di rumore aggiunta a ogni singolo step, abbiamo un record perfetto, step by step, di come la molecola si è disintegrata.
Il processo reverse è dove entra in gioco la rete neurale. Il modello viene addestrato per percorrere esattamente quel percorso a ritroso. Diamo in pasto alla rete una molecola corrotta a uno specifico time step. Le chiediamo quindi di predire lo specifico rumore che è stato aggiunto per raggiungere quello stato. Valutiamo il modello confrontando la sua predizione del rumore con il rumore effettivo che abbiamo iniettato durante la fase forward. Aggiorniamo i parametri del modello per minimizzare questa differenza. Col tempo, la rete impara a fare il denoising dei dati step by step, ripristinando gradualmente la distribuzione originale dei dati.
Per generare una molecola completamente nuova, esegui questo processo reverse da zero. Per prima cosa, campioni una nuvola di rumore gaussiano completamente casuale. Poi, passi questo rumore alla tua rete neurale addestrata, insieme al numero dello step iniziale. La rete valuta l'input, predice la correzione strutturale necessaria e restituisce una nuvola di atomi leggermente meno rumorosa.
Metti in loop questo processo di sottrazione. Passi il nuovo output di nuovo alla rete per lo step successivo a scendere. A ogni iterazione, la nuvola casuale si restringe. Il modello rimuove continuamente il rumore. Man mano che torni indietro verso lo step zero, le coordinate atomiche si incastrano al loro posto ed emerge una struttura chimica valida. Tiri fuori una molecola completamente nuova dal rumore statico iniziale.
Il modello non si limita a memorizzare un database di farmaci esistenti; impara semplicemente il processo universale di rimozione del caos per lasciarsi alle spalle una chimica stabile. Se vuoi supportare lo show, puoi cercare DevStoriesEU su Patreon. Grazie per l'ascolto, e continua a sviluppare!
17
Unire gli spazi generativi 2D e 3D
4m 28s
Esploriamo come l'IA rappresenta effettivamente le molecole che genera. Confronteremo la generazione di grafi topologici 2D piatti con la generazione di complesse point cloud geometriche 3D, e le relative sfide.
Ciao, sono Alex di DEV STORIES DOT EU. Chemoinformatica e AI con Python, episodio 17 di 22. Un conto è che un modello disegni un grafo 2D piatto di una molecola. È un incubo ingegneristico completamente diverso generare una point cloud geometrica 3D stabile di atomi. Puoi far sì che un modello generativo costruisca una bellissima point cloud 3D di un farmaco che riempie perfettamente la tasca di una proteina target, solo per vedere tutto crollare in post-processing quando il sistema non riesce a indovinare dove dovrebbero andare i veri legami covalenti. La soluzione a questo scollamento è fare da ponte tra gli spazi generativi 2D e 3D.
Nella chimica generativa, le data modalities dettano ciò che il tuo modello può capire. La prima modalità è lo spazio topologico 2D. Pensalo come un grafo molecolare standard. I nodi rappresentano atomi di tipi specifici e gli edge rappresentano i legami chimici che li collegano. Il modello restituisce in output una matrice di adiacenza che ti dice esattamente cosa è connesso a cosa. Le Graph Neural Networks gestiscono bene questa cosa. Il problema è che le molecole esistono nel mondo fisico, non sulla carta. Un grafo 2D ti dà la topologia di legame, ma ignora completamente la struttura geometrica 3D. Senza coordinate spaziali, non puoi calcolare con precisione le proprietà quantistiche o fare structure-based drug design.
Per risolvere questo problema, i modelli sono passati a generare molecole direttamente nello spazio geometrico 3D. Qui, l'output è una point cloud. Il modello definisce i tipi di atomi e le loro esatte coordinate posizionali X, Y e Z. L'ostacolo tecnico qui è mantenere l'equivarianza SE 3, garantendo che la molecola rimanga matematicamente coerente indipendentemente da come viene ruotata o traslata nello spazio. Ecco l'intuizione chiave. Generare in puro spazio 3D significa che il modello non genera esplicitamente i legami chimici. Posiziona semplicemente gli atomi nello spazio. Devi dedurre la topologia di legame in un secondo momento tramite algoritmi di post-processing. Questo introduce errori enormi. Tornando allo scenario della tasca del farmaco, il tuo modello potrebbe disporre gli atomi in una forma che si adatta fisicamente al target, ma poiché non ha mai considerato la topologia di legame durante la generazione, lo step di post-processing potrebbe dedurre legami covalenti impossibili. Per le molecole più grandi, generare direttamente una struttura 3D stabile senza alcuna guida topologica spesso porta a una soluzione subottimale.
Questo ci porta alla generazione nel joint space 2D e 3D, che produce simultaneamente una struttura molecolare completa. Il modello restituisce in output i tipi di atomi, la matrice di adiacenza discreta per i legami e le coordinate spaziali continue, tutto in una volta. Facendo da ponte tra questi due spazi, le modalità si vincolano e si correggono a vicenda durante il processo di generazione. La topologia 2D funge da blueprint, guidando la struttura 3D per garantire che le disposizioni spaziali siano chimicamente fattibili. Allo stesso tempo, la geometria 3D affina il grafo 2D suggerendo pattern di legame plausibili basati sulla prossimità spaziale.
La principale sfida tecnica in questo approccio congiunto è gestire due tipi di dati fondamentalmente diversi. Stai forzando il modello a gestire strutture topologiche discrete, come i tipi di legame, insieme a strutture geometriche continue, come i valori delle coordinate. Architetture diverse risolvono questo problema in modo diverso. Un framework chiamato JODO tratta sia le strutture topologiche che quelle geometriche come variabili continue per processarle insieme. Un altro modello, MUDiff, le gestisce separatamente, applicando un processo discreto per la topologia e un processo continuo per la geometria.
Non puoi generare in modo affidabile nuovi farmaci funzionali tirando a indovinare la forma fisica e sperando che i legami chimici si sistemino da soli in seguito. La vera generazione molecolare richiede che il blueprinting topologico e il posizionamento spaziale interagiscano e si completino a vicenda nell'esatta stessa computazione. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a costruire!
18
Generazione Target-Aware e Docking
3m 31s
Scopri il design generativo context-aware. Discuteremo la generazione di nuove molecole direttamente all'interno della tasca di legame di una proteina patologica per massimizzare l'affinità di legame.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 18 di 22. Perché chiedere a un algoritmo di generare un milione di chiavi casuali e testarle una per una, quando potrebbe semplicemente guardare la serratura e forgiare una chiave su misura direttamente nella toppa? La drug discovery tradizionale si basa spesso sulla generazione di vaste librerie di candidati per poi filtrarle, ma questo spreca immense risorse computazionali. La Target-Aware Generation e il docking risolvono il problema utilizzando direttamente la geometria 3D del target biologico per costruire o posizionare le molecole.
In questi task generativi, lavoriamo interamente nello spazio geometrico 3D. La target-aware generation, nota anche come structure-based drug design, costruisce una nuova molecola basandosi direttamente sulla struttura 3D della binding pocket di un target. Prendiamo uno scenario concreto con una proteina virale. Questa proteina ha una cavità geometrica molto specifica. Invece di generare molecole nel vuoto, un conditional diffusion model analizza gli esatti confini spaziali e le proprietà chimiche di quella cavità. Quindi, fa crescere su misura la struttura di un nuovo ligando direttamente all'interno della pocket.
Il modello parte da una nuvola di coordinate 3D con noise e tipi di atomi situati all'interno del binding site. Attraverso step successivi, applica il denoising a questa nuvola. Poiché la generazione è condizionata dalla pocket del target, il modello posiziona gli atomi e forma strutture che completano naturalmente la cavità, con l'obiettivo di garantire un'elevata affinità di interazione. Ecco il punto chiave. L'algoritmo non si limita a indovinare una forma; impara esplicitamente la relazione spaziale tra il target e i potenziali binder. Alcuni approcci incorporano persino l'interaction-based retrieval, recuperando dati da ligandi noti ad alta affinità per guidare ulteriormente la generazione di queste molecole target-specific.
Questo copre la generazione da zero di una molecola completamente nuova all'interno di una pocket. Ma spesso avrete a disposizione una molecola esistente e avrete bisogno di sapere esattamente come interagisce con un target biologico. Questo ci porta al molecular docking.
Il molecular docking predice la binding pose per valutare l'affinità e la specificità di legame. In un diffusion framework, i modelli prendono come input una molecola nota e una struttura target. Invece di generare un'identità chimica, il diffusion process opera esclusivamente sull'orientamento spaziale della molecola. Il modello parte dal ligando in una pose 3D casuale e con noise, e applica iterativamente il denoising. Affina le coordinate spaziali della molecola finché non si stabilizza nella corretta binding configuration all'interno della pocket proteica.
I modelli di docking avanzati fanno un ulteriore passo avanti trattando il target stesso come un'entità flessibile. Un modello chiamato Re-Dock utilizza una tecnica chiamata diffusion bridge per prevedere le binding pose del ligando, modellando simultaneamente il movimento delle sidechain della pocket. Questo crea uno scenario di docking realistico e flessibile in cui sia il ligando che il target si adattano l'uno all'altro durante la fase di prediction.
Il cambiamento cruciale qui è che i diffusion model hanno allontanato lo structural drug design da approssimazioni rigide e isolate. Trattando sia il ligando generato che la pocket biologica come un sistema geometrico continuo e adattabile, il modello restituisce nativamente in output molecole e pose che sono fisicamente ancorate alla precisa realtà dell'ambiente target.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continuate a costruire!
19
La trappola delle dimensioni nella Generative Evaluation
4m 16s
Scopri perché i benchmark standard per i modelli generativi possono essere profondamente imperfetti. Riveleremo l'effetto confondente delle dimensioni della libreria generata su metriche come la Fréchet ChemNet Distance.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 19 di 22. Valuti il tuo nuovo modello di chimica generativa campionando mille molecole, e le metriche sembrano pessime. Ne generi centomila da quello stesso identico modello, e all'improvviso sembra di livello mondiale. La scala cambia tutto. Questo fenomeno è chiamato Size Trap nella Generative Evaluation.
Le pipeline di generative drug discovery seguono generalmente tre fasi. Addestri, generi e valuti. Quando arrivi alla fase di valutazione, ti trovi di fronte a una domanda fondamentale: quanti design de novo generare per il benchmarking? La pratica standard spesso ripiega su piccoli batch, in genere mille o diecimila SMILES string. I team poi passano questi batch attraverso metriche distribuzionali standard. La più comune è la Fréchet ChemNet Distance, o FCD. L'FCD misura quanto le tue molecole generate siano vicine al tuo training set nello spazio chimico e biologico. Un punteggio FCD più basso significa che la tua distribuzione generata corrisponde fedelmente alla tua distribuzione target. Un'altra metrica comune è la Fréchet Descriptor Distance, o FDD, che confronta la distribuzione delle proprietà fisico-chimiche come il peso molecolare e la topological surface area. I team misurano di routine anche la Uniqueness, ovvero la frazione di design generati che sono distinti.
Ecco il punto chiave. Tutte queste metriche dipendono fortemente dalla dimensione fisica della library generata. Non misurano la qualità assoluta del modello nel vuoto. Quando campioni solo mille molecole, i tuoi punteggi FCD e FDD saranno artificialmente alti. Il modello sembra non aver imparato la distribuzione target. Ma se continui a campionare da quello stesso identico modello, spingendo la dimensione della library oltre le diecimila, cinquantamila o centomila molecole, il punteggio FCD scende significativamente. Continua a scendere finché alla fine non raggiunge un plateau.
Questo accade perché il design generativo di molecole implica il campionamento da una distribuzione di probabilità appresa altamente complessa. Un minuscolo sample di mille molecole non può rappresentare adeguatamente l'intera portata dell'output di quel modello. Gli algoritmi di Fréchet distance hanno bisogno di un numero enorme di sample per catturare accuratamente la forma dello spazio generato e confrontarla con lo spazio di fine-tuning.
Considera uno scenario concreto in cui stai confrontando una recurrent neural network con un transformer. Se valuti la recurrent neural network usando centomila design, ma valuti il transformer usandone solo diecimila, la recurrent neural network mostrerà probabilmente punteggi FCD e FDD nettamente superiori. Il gap di performance non ha nulla a che fare con l'architettura. È puramente un artefatto della dimensione del sample. Le metriche non sono arrivate a convergenza per la library più piccola.
Questa trappola funziona al contrario quando guardi alla diversità interna. La Uniqueness si comporta in modo completamente diverso su scala. A mille molecole, quasi ogni SMILES string valida che il tuo modello genera potrebbe essere unica. Il modello appare altamente creativo. Ma man mano che spingi la generazione verso le centomila, la Uniqueness crolla drasticamente. Il modello inizia a ripetersi. Se classifichi diversi modelli generativi in base alla Uniqueness su piccola scala, le differenze tra loro sembrano minori. Spingi la scala più in alto, e il gap tra i modelli si allarga drasticamente. Il ranking relativo dei tuoi modelli si capovolgerà a seconda della dimensione della library che usi per misurarli.
Per risolvere questo problema, devi trattare la dimensione della library come una variabile di controllo rigorosa nella tua pipeline. Non puoi mai confrontare in modo affidabile FCD, FDD o Uniqueness tra library di dimensioni diverse. Per garantire una valutazione robusta, dovresti valutare library contenenti almeno centomila design, in modo che le metriche distribuzionali convergano completamente. Se le tue metriche di valutazione cambiano semplicemente perché hai lasciato girare il sampling loop più a lungo, stai misurando la dimensione del sample, non l'intelligenza del modello. Questo è tutto per questo episodio. Grazie per l'ascolto, e keep building!
20
Navigare le allucinazioni De Novo
3m 56s
Classifica le molecole generate dall'IA in modo intelligente. Esploriamo il tradeoff exploration-exploitation delle likelihood del modello e come filtrare le 'allucinazioni chimiche' frequenti e di bassa qualità.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 20 di 22. Solo perché un'AI generativa sputa fuori una molecola specifica diecimila volte, non significa che sia un farmaco valido. Potresti pensare che la frequenza di generazione indichi la qualità o la rilevanza chimica. Non è così. Questi output così frequenti sono spesso l'equivalente chimico di un large language model che ha delle allucinazioni. Il meccanismo per risolvere questo problema consiste nel navigare tra le allucinazioni de novo usando la likelihood del modello.
Quando generi un'enorme libreria di un milione di SMILES strings da un chemical language model fine-tuned, devi decidere a quali molecole dare la priorità per gli studi futuri. Un approccio standard, ma imperfetto, consiste semplicemente nel selezionare i design che il modello restituisce in output più spesso. Questo crea una count trap. Invece di scoprire candidati farmaci robusti, finisci per estrarre sottostrutture basilari e ripetitive come anelli benzenici isolati, ammine semplici ed eteri di base. Queste sono allucinazioni strutturali ricorrenti. Il modello le genera costantemente non perché siano di alta qualità, ma perché sono sintatticamente semplici da costruire.
Per smascherare e filtrare queste allucinazioni, valuti la tua libreria usando la likelihood del modello. La likelihood è una metrica che cattura quanto bene una sequenza generata si allinea con la distribuzione di probabilità che il modello ha imparato durante il training. Per un modello autoregressivo, la calcoli moltiplicando la sampling probability di ogni singolo token nella SMILES string generata. Per prima cosa, calcoli il likelihood score per tutti e un milione i design generati. Successivamente, ordini l'intera libreria in base a questi score. Infine, dividi la libreria ordinata in dieci gruppi uguali, o decili, che vanno dalla likelihood più bassa a quella più alta.
È qui che la cosa si fa interessante. Analizzare questi decili rivela un rigoroso tradeoff tra exploration ed exploitation. Il decimo decile contiene le generazioni con la likelihood più alta. Questi design rappresentano l'exploitation. Hanno una validità chimica estremamente elevata, e i loro scaffold generici di Bemis-Murcko corrispondono fedelmente alle molecole attive note nei tuoi training data. Il modello sta sfruttando pesantemente ciò che sa già che funziona. Il lato negativo è che questi design di alto livello mancano di novità. Contengono pochissime nuove sottostrutture perché il modello va sul sicuro.
Scendendo verso i decili intermedi, trovi un equilibrio. La novità e le sottostrutture uniche raggiungono il picco in questa fascia intermedia, mentre la validità rimane accettabile. Ma quando scendi al primo decile, ovvero il dieci percento delle molecole con i likelihood score più bassi in assoluto, cadi nella count trap. Se isoli i design che il modello ha generato più di dieci volte nell'intera run da un milione di molecole, quasi tutti si raggruppano in questo decile inferiore. Hanno likelihood del modello incredibilmente basse, eppure compaiono con una frequenza enorme. La loro somiglianza strutturale con il tuo training set è pessima, e la loro validità chimica complessiva crolla.
Facendo il binning della tua libreria in questo modo, dimostri matematicamente che la frequenza è un falso segnale di qualità. Puoi scartare sistematicamente i bin a bassa likelihood e alta frequenza, e concentrare il tuo screening computazionale sui decili intermedi, dove avviene la vera esplorazione chimica. Gli output più frequenti di un modello chimico generativo sono spesso i peggiori, ma filtrando la tua libreria in base ai decili di likelihood, quel rumore si trasforma in una mappa precisa di dove il modello sta esplorando e dove invece sta solo avendo allucinazioni.
Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
21
Vincoli nel Molecule Sampling
4m 05s
Comprendi perché le tecniche di NLP falliscono nella chimica. Confronteremo il Temperature sampling con Top-k e Top-p, e perché il vocabolario chimico vincolato cambia tutto.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 21 di 22. Nel natural language processing, il Top-p sampling produce testi incredibilmente creativi. Ma se applichi questa stessa identica logica alla generazione di molecole, la tua AI si limiterà a stampare anelli di carbonio identici all'infinito. Il motivo si riduce ai Molecule Sampling Constraints.
Quando un chemical language model genera una string SMILES, costruisce la molecola un token alla volta. Il modello predice una distribuzione di probabilità per il token successivo, e tu devi estrarre una scelta specifica da quella distribuzione. Nella text generation, gli addetti ai lavori si affidano pesantemente al Top-k e al Top-p sampling per fare questa scelta. Il Top-k limita il modello in assoluto ai k token più probabili. Il Top-p limita la selezione al gruppo più piccolo di token le cui probabilità combinate superano una percentuale target p.
Se applichi questi metodi a un chemical language model, falliscono in modo catastrofico. Se usi il Top-k sampling con k impostato a 3 su una LSTM addestrata su drug target, il tuo modello subirà un grave mode collapse. Darà in output molecole chimicamente valide, ma saranno completamente ripetitive.
Ecco il punto cruciale. Il fallimento deriva dalle dimensioni del vocabolario chimico. Un modello di testo seleziona tra centinaia di migliaia di parole. Un chemical language model usa un alfabeto fortemente vincolato. Ha solo una manciata di elementi come carbonio, ossigeno e azoto, più i token di sintassi per le ramificazioni e le chiusure degli anelli.
Dato che l'alfabeto chimico è minuscolo, e dato che la chimica valida richiede regole di sintassi rigide come chiudere ogni anello aperto, un sottoinsieme molto piccolo di token domina assolutamente la distribuzione di probabilità. Il carbonio e i token strutturali di base sono quasi sempre altamente probabili. Quando applichi il Top-k o il Top-p sampling, tagli via la long tail della distribuzione di probabilità. Il modello è costretto a pescare esclusivamente da quella stretta fascia di token dominanti. Rimane intrappolato in una filtering trap, ripetendo all'infinito gli stessi identici scaffold di base.
Per sfuggire a questa trappola, devi usare il Temperature sampling. Invece di filtrare via i token, il Temperature sampling applica un parametro di smoothing agli score grezzi della rete neurale prima di calcolare le probabilità finali. Questo altera la forma dell'intera distribuzione.
Immagina uno scenario in cui fai girare un modello LSTM fine-tuned per generare nuovi drug candidate. Regoli il parametro Temperature, T, per calibrare il tradeoff tra validità e diversità. Se imposti T su un valore basso, intorno a 0.5, la distribuzione di probabilità forma un picco molto netto. Il modello sfrutta pesantemente i token più probabili. Il tuo output presenterà una validità chimica estremamente alta, ma le strutture mancheranno di novità. Imiteranno da vicino il training set.
Se alzi T fino a 1.5 o 2.0, appiattisci la distribuzione di probabilità. Ora, i token meno probabili hanno una possibilità matematica di essere campionati. Il tuo modello inizia a esplorare nuovo spazio chimico. Il numero di sottostrutture uniche nella tua libreria generata ha un'impennata. Trovi molecole altamente innovative. Il tradeoff è che temperature più alte aumentano la casualità, portando il modello a fare più errori di sintassi, il che riduce la percentuale complessiva di string SMILES valide.
Non puoi portare ciecamente le strategie di text generation nel molecular design. Dato che il vocabolario chimico è intrinsecamente vincolato, il Temperature scaling rimane la singola leva più efficace per bilanciare la rigorosa validità chimica con l'esplorazione di nuove strutture.
Grazie per avermi fatto compagnia. Spero tu abbia imparato qualcosa di nuovo.
22
Deploy di Cheminformatics nel Cloud
3m 49s
Porta la tua pipeline IA in produzione. Discuteremo il packaging di RDKit e dei modelli di machine learning all'interno di container Docker e la scalabilità dei carichi di lavoro sull'infrastruttura cloud.
Ciao, sono Alex di DEV STORIES DOT EU. Python Cheminformatics & AI, episodio 22 di 22. Hai costruito una pipeline di drug discovery basata sull'AI all'avanguardia sul tuo laptop, ma come fai a fare lo screening di un miliardo di molecole nel weekend? La risposta è fare il deploy della chemoinformatica nel cloud.
Spostare un modello da un ambiente locale a un'architettura cloud distribuita di solito fallisce al livello delle dipendenze. RDKit non è una libreria Python pura. È una grande codebase C++ che richiede dipendenze a livello di sistema, in particolare le librerie C++ Boost. Se fai il provisioning di server cloud generici ed esegui script di installazione standard, ti imbatti spesso in errori del compiler o in file shared object mancanti. La documentazione ufficiale di RDKit sottolinea che la build da sorgente richiede una toolchain C++ specifica. Anche se esistono wheel pip precompilate, il modo più robusto per garantire che tutte le dipendenze sottostanti siano allineate è usare Conda. Tuttavia, installare Conda dinamicamente su migliaia di worker cloud temporanei richiede troppo tempo e introduce instabilità di rete durante lo scale-up.
Ecco il punto chiave. Aggiri completamente il problema delle dipendenze incapsulando la tua pipeline in un container Docker. Scrivi un file di configurazione che specifica un sistema operativo di base. All'interno di quel container, installi un ambiente Conda leggero, fai il pull dei binari compilati di RDKit e aggiungi i tuoi framework di machine learning come PyTorch o XGBoost. Infine, copi i pesi del tuo modello pre-addestrato nell'image. Fare la build di questa image congela l'intero stack in un singolo artefatto immutabile. Al cloud provider basta sapere come far girare un container Docker standard. Le complesse dipendenze C++ sono bloccate in modo sicuro all'interno.
Per processare milioni di molecole, separi il tuo flusso di dati dai tuoi compute worker usando una message queue in cloud. Suddividi il tuo enorme dataset di string SMILES in chunk più piccoli e gestibili. Metti questi chunk in un object storage in cloud e invii un messaggio contenente la posizione del chunk alla queue.
A questo punto, punti un servizio di cloud compute scalabile verso questa queue. Per workload pesanti e accelerati da GPU, fai il deploy del tuo container usando un servizio come AWS Batch. Per un'inference più leggera basata su CPU, le piattaforme di container serverless come Google Cloud Run o AWS Lambda sono perfette. Configuri il servizio di compute per scalare automaticamente in base alla profondità della queue. Se ci sono cinquantamila messaggi in attesa, il cloud controller fa lo spin up di migliaia di container Docker identici contemporaneamente.
Ogni container si connette alla queue e prende in carico un messaggio. Scarica il chunk corrispondente di string SMILES. RDKit converte le SMILES in grafi molecolari, calcola i descrittori necessari e li passa al tuo modello di machine learning per l'inference. Il container scrive le molecole con lo score più alto direttamente in un database cloud gestito. Una volta processato il chunk, il worker elimina il messaggio dalla queue e prende quello successivo. Quando la queue è vuota, l'infrastruttura cloud termina automaticamente i container. Paghi solo per gli esatti secondi di compute che il tuo codice ha effettivamente consumato.
Scalare la chemoinformatica raramente significa scrivere strutture di loop più veloci in Python; si tratta di pacchettizzare il tuo ambiente in modo affidabile e di usare un'architettura cloud disaccoppiata per processare i dati in parallelo. Questo conclude la nostra serie su Python Cheminformatics e AI. Ti incoraggio a leggere la documentazione ufficiale di RDKit sull'installazione, a provare a containerizzare un semplice script hands-on, o a visitare devstories dot eu per suggerire argomenti per le prossime serie. Questo è tutto per questo episodio. Grazie per l'ascolto, e continua a sviluppare!
Tap to start playing
Browsers block autoplay
Share this episode
Episode
—
Copy this episode in another language:
Questo sito non utilizza cookie. Il nostro fornitore di hosting potrebbe registrare il tuo indirizzo IP a fini statistici. Scopri di più.