Ausgabe 2026. Ein praktischer Kurs, der Python-Entwickler von grundlegenden Chemiekonzepten bis hin zum Entwurf KI-gesteuerter Cheminformatik-Systeme führt. Lerne den Umgang mit RDKit, scikit-fingerprints und modernsten Deep-Learning-Techniken wie Graph Neural Networks und Diffusion Models für die Wirkstoffentdeckung.
Wissenschaftliches RechnenChemoinformatikDeep Learning für die Wissenschaft
Wir stellen RDKit und das Kernkonzept der Darstellung von Chemie in Python vor. Die Zuhörer lernen, wie man molekulare Objekte aus Strings initialisiert und verstehen die zentrale Rolle des Frameworks bei der KI-Wirkstoffentdeckung.
3m 50s
2
I/O in der Cheminformatik
Lerne, wie man riesige chemische Datensätze sicher einliest und exportiert. Wir behandeln das Lesen von SDF- und SMILES-Dateien, den Umgang mit Parse-Fehlern und das Zurückschreiben von Daten auf die Festplatte.
4m 01s
3
Molekulare Graphen-Traversierung
Entdecke, wie Moleküle als Graphen-Datenstrukturen dargestellt werden. Wir untersuchen das Iterieren über Atome, das Analysieren von Bindungen und die Identifizierung von Ringsystemen innerhalb von Molekülen.
4m 02s
4
Substruktursuche
Meistere die Kunst, Moleküle mit SMARTS abzufragen. Wir gehen Schritt für Schritt durch, wie man spezifische funktionelle Gruppen und Muster in komplexen chemischen Strukturen findet.
4m 22s
5
Fingerprinting und molekulare Ähnlichkeit
Erforsche, wie man molekulare Graphen in mathematische Bitvektoren übersetzt. Wir behandeln MACCS keys, Morgan fingerprints und die Berechnung der Tanimoto similarity.
4m 48s
6
Die 2D-Ebene durchbrechen
Der Übergang von flachen 2D-Zeichnungen zu realistischen 3D-Geometrien. Wir diskutieren das Hinzufügen expliziter Wasserstoffatome und die Generierung zuverlässiger 3D-Conformer mit ETKDG.
4m 56s
7
Feature Engineering beschleunigen
Schlage die Brücke zwischen Cheminformatik und Standard-Data-Science mit scikit-fingerprints. Wir untersuchen die Generierung von über 30 Arten molekularer Fingerprints direkt innerhalb eines scikit-learn-Interfaces.
4m 32s
8
High-Performance-Cheminformatik
Lerne, wie man riesige chemische Datensätze effizient verarbeitet. Wir tauchen in die Nutzung von CPU-Parallelität mit Joblib ein und sparen Speicherplatz durch die Verwendung von SciPy Sparse-Matrizen.
4m 30s
9
End-to-End ML-Pipelines
Kombiniere Verarbeitung, Fingerprinting und Vorhersage in einer einzigen sauberen Architektur. Wir bauen robuste scikit-learn-Pipelines, die die 3D-Conformer-Generierung und die Vorhersage von Eigenschaften nahtlos integrieren.
4m 06s
10
Vorhersage der Bindungsaffinität
Erforsche die Realität der Vorhersage von Protein-Ligand-Bindungsaffinitäten. Wir vergleichen die Leistung einfacher 2D-baumbasierter Modelle mit komplexen 3D Graph Neural Networks.
4m 53s
11
LLMs vs. klassische Fingerprints
Entdecke, wie Natural Language Processing in der Chemie angewendet wird. Wir lassen Vektor-Embeddings aus Large Language Models gegen klassische strukturelle RDKit-Fingerprints antreten, um die Bioaktivität vorherzusagen.
4m 34s
12
Active Learning für virtuelles Screening
Lerne, wie man iterativ Top-Wirkstoffkandidaten ohne erschöpfendes Testen entdeckt. Wir tauchen in Active-Learning-Schleifen und Greedy-Selection-Strategien ein, um die Trefferquoten zu maximieren.
3m 45s
13
Die Activity-Cliff-Herausforderung
Untersuche die Fragilität von Struktur-Wirkungs-Beziehungen. Wir diskutieren 'Activity Cliffs' – bei denen eine winzige strukturelle Änderung eine massive Verschiebung der Wirksamkeit eines Medikaments verursacht.
4m 01s
14
Similarity-Quantized Relative Learning
Löse das Activity-Cliff-Problem, indem du überdenkst, wie Modelle lernen. Wir untersuchen das SQRL-Framework, das KI darauf trainiert, relative Eigenschaftsunterschiede zwischen streng gefilterten molekularen Paaren vorherzusagen.
4m 05s
15
Die Revolution der generativen KI
Der Übergang von der Vorhersage von Eigenschaften zur Erschaffung völlig neuer Moleküle. Wir skizzieren die Landschaft molekularer generativer Aufgaben: De-Novo-Generierung, Optimierung und Conformer-Generierung.
3m 44s
16
Die Intuition der molekularen Diffusion
Wir brechen das Kernkonzept von Diffusion Models ohne schwere Mathematik herunter. Die Zuhörer werden den Vorwärtsprozess des Hinzufügens von Rauschen zu einem Molekül und den Rückwärtsprozess des Halluzinierens neuer Strukturen verstehen.
4m 08s
17
Die Überbrückung von generativen 2D- und 3D-Räumen
Wir untersuchen, wie KI die von ihr generierten Moleküle tatsächlich darstellt. Wir vergleichen die Generierung flacher topologischer 2D-Graphen mit der Generierung komplexer geometrischer 3D-Punktwolken und die jeweiligen Herausforderungen.
4m 59s
18
Target-Aware Generierung & Docking
Entdecke kontextbezogenes generatives Design. Wir diskutieren die Generierung neuartiger Moleküle direkt innerhalb der Bindungstasche eines Krankheitsproteins, um die Bindungsaffinität zu maximieren.
4m 13s
19
Die Size Trap in der generativen Evaluierung
Lerne, warum Standard-Benchmarks für generative Modelle zutiefst fehlerhaft sein können. Wir enthüllen den verzerrenden Effekt der generierten Bibliotheksgröße auf Metriken wie die Fréchet ChemNet Distance.
4m 38s
20
Navigieren durch De-Novo-Halluzinationen
Bewerte KI-generierte Moleküle intelligent. Wir untersuchen den Exploration-Exploitation-Tradeoff von Modellwahrscheinlichkeiten und wie man häufige, qualitativ minderwertige 'chemische Halluzinationen' herausfiltert.
4m 25s
21
Einschränkungen beim Molecule Sampling
Verstehe, warum NLP-Techniken in der Chemie versagen. Wir vergleichen Temperature Sampling mit Top-k und Top-p und erklären, warum das eingeschränkte chemische Vokabular alles verändert.
4m 52s
22
Bereitstellung von Cheminformatik in der Cloud
Bringe deine KI-Pipeline in die Produktion. Wir diskutieren das Verpacken von RDKit und Machine-Learning-Modellen in Docker-Container und die Skalierung von Workloads über eine Cloud-Infrastruktur.
4m 10s
Episoden
1
Das digitale Molekül
3m 50s
Wir stellen RDKit und das Kernkonzept der Darstellung von Chemie in Python vor. Die Zuhörer lernen, wie man molekulare Objekte aus Strings initialisiert und verstehen die zentrale Rolle des Frameworks bei der KI-Wirkstoffentdeckung.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 1 von 22. Bevor du die Toxizität eines Medikaments mit einem Machine-Learning-Model vorhersagen kannst, musst du ein grundlegendes Problem lösen. Du brauchst einen Weg, Python beizubringen, was ein Molekül eigentlich ist. Standard-Datentypen wie Strings und Lists verstehen keine Atome, Bindungen oder Ringstrukturen. Um diese Lücke zu schließen, brauchst du einen universellen Übersetzer zwischen Chemie und Code. Genau das bietet RDKit und führt das Konzept des digitalen Moleküls ein.
RDKit ist das branchenübliche Open-Source-Toolkit für die Cheminformatik. Im Kern ist es eine High-Performance C++ Library, aber es bietet ein riesiges, intuitives Python-Interface. Es existiert, weil es überraschend schwierig ist, chemische Strukturen programmatisch darzustellen. Mathematisch gesehen ist ein Molekül ein Graph. Die Atome sind Nodes und die chemischen Bindungen sind Edges, die diese Nodes verbinden. Wenn du jedes Mal einen eigenen Graph-Parser from scratch baust, um chemische Daten zu analysieren, wirst du deine ganze Zeit mit dem Debuggen von Edge Cases verbringen. RDKit abstrahiert diese Komplexität weg und managt die Graph-Logik im Hintergrund.
Um ein Molekül in Python zu bekommen, brauchst du zuerst eine Text-Repräsentation seiner Struktur. Das gängigste Format ist ein SMILES-String. SMILES verwendet Standardzeichen, um die chemische Konnektivität darzustellen. Zum Beispiel ist ein isoliertes Kohlenstoffatom einfach ein großes C. Benzol, also ein Ring aus sechs Kohlenstoffatomen mit abwechselnden Doppelbindungen, wird geschrieben als ein kleines c, die Zahl eins, vier weitere kleine c-Zeichen und ein letztes kleines c, gefolgt von einer Zahl eins, um den Ring zu schließen.
Hier ist die wichtigste Erkenntnis: Dieser SMILES-String ist einfach nur Plain Text. Für Python ist er nicht von einem Passwort oder einem Dateipfad zu unterscheiden. Du kannst das Molekulargewicht nicht aus einem Raw String berechnen. Um echte Chemie zu betreiben, musst du ihn in ein RDKit-Molekül-Object konvertieren. Das machst du, indem du das Chem-Module aus RDKit importierst. Dann rufst du eine spezielle Function auf, die dafür gemacht ist, ein Molekül aus einem SMILES-String zu erstellen, und übergibst ihr deine Text-Variable.
Wenn du dieser Function den Benzol-SMILES-String übergibst, übernimmt RDKit eine Menge Heavy Lifting. Es parst den Text, baut den Node- und Edge-Graph auf, weist Bindungsordnungen zu und validiert grundlegende chemische Regeln wie Atomvalenzen. Wenn der String ein gültiges Molekül repräsentiert, gibt die Function ein Molekül-Object zurück. Wenn du ihr eine chemisch unmögliche Struktur oder einen Tippfehler übergibst, schlägt die Function kontrolliert fehl. Sie printet eine Warnung in deine Console und gibt ein Null-Object zurück. Deshalb solltest du immer checken, ob dein Molekül-Object tatsächlich existiert, bevor du es an den nächsten Schritt deines Programms übergibst.
Sobald du dieses validierte Molekül-Object im Memory hältst, öffnet sich das gesamte RDKit-Ökosystem für dich. Du arbeitest nicht mehr mit Text; du arbeitest mit einem berechenbaren chemischen Graph. Das wichtigste Takeaway hier ist, dass SMILES-Strings ausschließlich für Storage und Datentransfer gedacht sind, RDKit-Molekül-Objects aber für Berechnungen. Alles, was du in der Computational Chemistry machst, beginnt mit dieser Konvertierung.
Wenn du die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen – das hilft uns sehr. Das war’s für diese Folge. Danke fürs Zuhören und keep building!
2
I/O in der Cheminformatik
4m 01s
Lerne, wie man riesige chemische Datensätze sicher einliest und exportiert. Wir behandeln das Lesen von SDF- und SMILES-Dateien, den Umgang mit Parse-Fehlern und das Zurückschreiben von Daten auf die Festplatte.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatik & KI, Folge 2 von 22. Eine einzige fehlende Koordinate in einem Datensatz mit einer Million Molekülen kann deine gesamte Pipeline zum Absturz bringen. Wenn du davon ausgehst, dass jeder Texteintrag in deiner Vendor-Datei perfekt formatierte Chemie ist, wird dein Python-Skript irgendwann mitten in einem zehnstündigen Job eine fatale Exception werfen. Sich vor Dirty Data zu schützen, während du Strukturen in deine Skripte rein- und rausschiebst, ist Pflicht, und genau das lösen wir heute mit I/O in der Cheminformatik.
Wenn du ein Standard-Structure-Data-File, oder SDF, voller potenzieller Liganden bekommst, brauchst du einen Weg, es zu parsen. In RDKit ist das Standard-Tool dafür der SD Molecule Supplier. Du initialisierst ihn, indem du den Dateipfad als String übergibst. Dieses Supplier-Objekt verhält sich sehr ähnlich wie eine Python-Liste. Du kannst darüber iterieren, du kannst seine Gesamtlänge abfragen und du kannst dir einen bestimmten Eintrag über seine Indexnummer herausziehen. Das macht er, indem er das File schnell scannt, um zu finden, wo jedes Molekül anfängt, sodass du in den Daten hin- und herspringen kannst.
Manchmal kannst du nicht im Voraus scannen. Wenn du Daten direkt aus einem Web-Stream pipest oder ein riesiges gezipptes File Chunk für Chunk liest, hast du keinen Random Access. Für diese Situationen nutzt du den Forward SD Molecule Supplier. Statt eines Dateipfads übergibst du ihm ein offenes File-Objekt. Dieser Forward Supplier ist ein strikter Iterator. Er liest ein Molekül, parst es und geht sofort zum nächsten über. Du kannst nicht nach seiner Länge fragen, und du kannst nicht das fünfzigste Molekül abfragen, ohne die ersten neunundvierzig gelesen zu haben. Du tauschst Flexibilität gegen geringen Speicherverbrauch und Stream-Kompatibilität.
Hier ist die entscheidende Erkenntnis. Egal welchen Supplier du benutzt, RDKit wirft keine Python-Exception, wenn es auf ein kaputtes Molekül stößt. Wenn ein Textblock in deinem File eine ungültige Valenz oder einen Formatierungsfehler hat, gibt RDKit eine Fehlermeldung in der Konsole aus, aber das tatsächliche Python-Objekt, das es für diese Loop-Iteration zurückgibt, ist einfach der None-Type.
Wenn du dieses None-Objekt nimmst und versuchst, sein Gewicht zu berechnen oder es in ein neues File zu schreiben, wird dein Skript abstürzen. Das abzufangen ist einfach, aber extrem wichtig. Die allererste Zeile in deiner Parsing-Loop muss immer prüfen, ob das zurückgegebene Molekül None ist. Wenn es None ist, benutzt du das continue-Statement, um zum nächsten Eintrag zu springen. Das filtert die Garbage-Daten stillschweigend heraus und hält deine Pipeline am Laufen.
Sobald du deine gültigen Moleküle sicher geparst und gefiltert hast, musst du die Ergebnisse normalerweise speichern. Dafür benutzt du den SD Writer. Du initialisierst den Writer, indem du deinen gewünschten Output-File-Pfad übergibst. Innerhalb deiner sicheren Loop, direkt nach deinem None-Check, übergibst du das gültige Molekül-Objekt an den Writer, indem du seine write-Methode benutzt. Sobald die Loop jeden Liganden verarbeitet hat, rufst du die close-Methode auf dem Writer auf, um sicherzustellen, dass alle Daten sicher auf die Festplatte geschrieben werden. Du kannst den Writer auch in einen Standard-Python-Context-Manager wrappen, sodass er sich automatisch schließt, wenn der Block endet.
Um das alles für ein Data-Cleaning-Skript zusammenzusetzen: Erstens, erstelle deinen SD Writer für das Output-File. Zweitens, erstelle deinen SD Molecule Supplier für das Input-File. Iteriere durch den Supplier. Prüfe, ob das aktuelle Item None ist, und wenn ja, überspringe es. Wenn es gültig ist, übergib es an den Writer. Schließe den Writer am Ende. Behandle externe Chemie-Datensätze immer als grundsätzlich dirty. Zu verifizieren, dass ein geparstes Molekül nicht None ist, ist die günstigste Versicherung, die dein Code jemals haben wird.
Das war's für diese Folge. Danke fürs Zuhören und keep building!
3
Molekulare Graphen-Traversierung
4m 02s
Entdecke, wie Moleküle als Graphen-Datenstrukturen dargestellt werden. Wir untersuchen das Iterieren über Atome, das Analysieren von Bindungen und die Identifizierung von Ringsystemen innerhalb von Molekülen.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 3 von 22. Für einen Computer ist ein Molekül kein physisches Objekt, das Raum einnimmt. Es ist streng genommen ein Graph aus Nodes und Edges, der darauf wartet, geparst zu werden. Wenn du diesen zugrundeliegenden Graphen nicht effizient navigieren kannst, kannst du die chemische Struktur nicht analysieren. Das bringt uns direkt zum Molecular Graph Traversal.
In RDKit dient ein Molecule Object als primärer Container für diese Graph-Datenstruktur. Um die Nodes zu inspizieren, nutzt du die GetAtoms Methode. Diese gibt eine Iterable Sequence zurück, die alle Atom Objects im Molekül enthält. Du kannst einen einfachen Loop schreiben, um diese Sequence Schritt für Schritt zu durchlaufen. Nehmen wir ein konkretes Szenario: Angenommen, du musst die Atomic Numbers all deiner Nodes extrahieren. Innerhalb deines Loops kannst du die GetIdx Methode aufrufen, um den eindeutigen numerischen Identifier für das aktuelle Atom zu finden, und die GetAtomicNum Methode, um genau herauszufinden, um welches chemische Element es sich handelt. Indem du darüber iterierst, verarbeitest du jeden Node systematisch.
Nodes allein definieren noch nicht die Chemie. Du brauchst auch die Edges, die sie verbinden, auf die du mit der GetBonds Methode zugreifst. Genau wie bei den Atomen liefert dir das eine Iterable Sequence von Bond Objects. Ein Bond kennt seinen genauen Platz im Graphen. Indem du die Methoden GetBeginAtomIdx und GetEndAtomIdx auf einem Bond Object aufrufst, extrahierst du die spezifischen numerischen Identifier der beiden Atome, die es verbindet. Du kannst auch den Bond Type auslesen und so feststellen, ob es sich um eine Einfach-, Doppel- oder aromatische Bindung handelt. Hier ist die wichtigste Erkenntnis: RDKit behandelt Bonds als First-Class Objects in der Graph-Hierarchie. Das bedeutet, dass du sie unabhängig abfragst, anstatt sie aus den Atom Properties herauszusuchen.
Das Navigieren einzelner Nodes und Edges ist Standard-Graph-Logik, aber chemische Graphen enthalten häufig Cycles, besser bekannt als Ringe. Du musst keine eigenen Traversal-Algorithmen zur Cycle-Suche schreiben. RDKit berechnet diese Cycles vorab, wenn das Molekül instanziiert wird. Du greifst über die GetRingInfo Methode auf diese Daten zu. Das gibt ein dediziertes Ring Info Object anstelle einer einfachen List zurück.
Wenn deine Aufgabe einfach nur darin besteht, die Anzahl der Ringe im Molekül zu zählen, rufst du die NumRings Methode direkt auf diesem Ring Info Object auf. Wenn du tiefere strukturelle Details brauchst, kannst du dasselbe Objekt nach der AtomRings Property fragen. Das gibt dir eine Collection von Sequences, wobei jede Sequence die exakten Atom Indices enthält, die einen bestimmten Ring im Graphen bilden. Du kannst dem Ring Info Object sogar einen Atom Index übergeben, um zu fragen, ob dieser spezifische Node an einem Ring einer bestimmten Größe teilnimmt, wie zum Beispiel einem fünf- oder sechsgliedrigen Cycle.
Beim Traversieren eines Moleküls geht es letztendlich darum, diese Basis-Operationen zu chainen. Du holst dir die Ring Info, um die Makrostruktur zu checken, du loopst über Atome, um Node-Level-Daten wie Atomic Numbers zu lesen, und du loopst über Bonds, um die spezifischen Edge-Verbindungen zu mappen. Sobald du aufhörst, ein Molekül als physische Einheit zu sehen, und anfängst, es als eine vorhersehbare Collection von indizierten Nodes, Edges und vorberechneten Cycles zu betrachten, wird das Extrahieren struktureller Properties zu einem Standard Data Parsing Task. Das war's für diese Folge. Danke fürs Zuhören, und keep building!
4
Substruktursuche
4m 22s
Meistere die Kunst, Moleküle mit SMARTS abzufragen. Wir gehen Schritt für Schritt durch, wie man spezifische funktionelle Gruppen und Muster in komplexen chemischen Strukturen findet.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatik & KI, Folge 4 von 22. Du würdest nicht versuchen, Tausende von Text-Logs ohne Regular Expressions zu parsen. Genauso wenig solltest du versuchen, chemische Datenbanken ohne SMARTS-Patterns zu filtern. Das Finden spezifischer funktioneller Gruppen in großen Datasets erfordert eine spezielle Strukturlogik, und genau das bietet das Substructure Searching.
Angenommen, du hast eine Library mit Wirkstoffkandidaten. Dein Ziel ist es, jedes Molekül zu flaggen und zu isolieren, das eine bestimmte, bekannte toxische funktionelle Gruppe enthält. Zuerst definierst du diese toxische Gruppe mit einem SMARTS-String. SMARTS ist eine Erweiterung von SMILES, die speziell für das Querying von Molekül-Patterns entwickelt wurde und es dir ermöglicht, Wildcards, spezifische Bindungstypen oder Ringstrukturen anzugeben. Du übergibst diesen Text-String an die RDKit-Funktion, die ein Molekül aus SMARTS erstellt. Das generiert dein Query-Objekt. Deine Target-Moleküle, die Wirkstoffkandidaten, sind bereits Standard-RDKit-Molekül-Objekte.
Um die Library zu filtern, nimmst du ein Kandidatenmolekül und rufst die Methode namens has substructure match auf. Du übergibst dein Query-Objekt an diese Methode. Sie evaluiert das Kandidatenmolekül gegen das Pattern und gibt einen einfachen Boolean-Wert zurück. True bedeutet, dass die toxische Gruppe irgendwo im Kandidaten existiert. False bedeutet, dass er clean ist. Weil diese Methode die Suche beendet, sobald sie einen einzigen gültigen Match findet, ist sie hochgradig optimiert. Du kannst diesen Boolean-Check in einer Loop über deine gesamte Library laufen lassen, um ein riesiges Dataset schnell in sichere und geflaggte Subsets aufzuteilen.
Was aber, wenn es nicht reicht, einfach nur zu wissen, dass die toxische Gruppe vorhanden ist? Vielleicht skaliert die Toxizität mit der Anzahl, wie oft die Gruppe vorkommt, oder du musst die genaue Position der toxischen Atome für einen Strukturbiologen isolieren. Dafür verwendest du die Methode namens get substructure matches, im Plural. Du rufst sie auf deinem Kandidatenmolekül auf und übergibst wieder das Query-Objekt. Statt eines Booleans zwingt diese Methode die Search Engine, jedes mögliche Vorkommen des Patterns zu mappen.
Sie gibt ein Tuple zurück, das weitere Tuples enthält. Jedes innere Tuple repräsentiert einen kompletten Match deines Patterns. Die Integers in diesen Tuples sind die exakten Atom-Indizes innerhalb des Kandidatenmoleküls. Hier ist der entscheidende Punkt. Die Reihenfolge dieser Indizes spiegelt exakt die Reihenfolge der Atome wider, die in deinem ursprünglichen SMARTS-String definiert wurden. Das bedeutet, du weißt immer genau, welches Atom im Target welchem Teil deiner Query entspricht. Wenn die toxische Gruppe dreimal im Kandidaten auftaucht, bekommst du drei innere Tuples. Du kannst die Tuples zählen, um die Frequenz des Patterns herauszufinden, oder diese spezifischen Atom-Indizes an eine Drawing-Funktion übergeben, um die toxischen Bereiche visuell zu highlighten. Wenn du nur die Atom-Indizes vom allerersten Match brauchst, den sie findet, kannst du die Methode get substructure match im Singular verwenden, um Processing-Zeit zu sparen.
Du musst außerdem die Stereochemie berücksichtigen. By default ignoriert das RDKit Substructure Matching die Chiralität komplett. Eine Wedge-Bond und eine Dash-Bond triggern beide einen Match für eine einfache SMARTS-Query. Wenn deine Target-Toxizität nur bei einem bestimmten Stereoisomer auftritt, wird dieses Default-Verhalten False Positives in deinem Drug Screen generieren. Um das zu fixen, übergibst du ein Argument namens use chirality und setzt es auf true, wenn du eine der Matching-Methoden aufrufst. RDKit erzwingt dann stereochemische Regeln basierend auf der spezifischen Konfiguration, die in deiner Query definiert ist.
Die wahre Power von Substructure Searching ist, dass es eine rein logische Text-Query direkt auf die physikalische Topologie deines Datasets mappt und so die Lücke zwischen abstrakten String-Patterns und konkreten Atomkoordinaten schließt. Das war es für diese Folge. Danke fürs Zuhören und keep building!
5
Fingerprinting und molekulare Ähnlichkeit
4m 48s
Erforsche, wie man molekulare Graphen in mathematische Bitvektoren übersetzt. Wir behandeln MACCS keys, Morgan fingerprints und die Berechnung der Tanimoto similarity.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 5 von 22. AI-Modelle verstehen eigentlich keine Atome und Bindungen. Sie verstehen nur Zahlen. Wenn du willst, dass ein Algorithmus zwei Strukturen vergleicht, brauchst du einen Weg, Chemie in Mathematik zu übersetzen. Fingerprinting und molekulare Ähnlichkeit sind genau der Weg, wie wir diese Lücke schließen.
Ein Molekül in RDKit ist im Wesentlichen ein mathematischer Graph. Die Atome fungieren als Nodes und die Bindungen als Edges. Um schnelle Berechnungen auf diesen Graphen durchzuführen, konvertieren wir sie in Bit-Vektoren, was einfach nur lange Arrays aus Einsen und Nullen sind. Dieses Array wird Fingerprint genannt. Die Logik ist ziemlich simpel. Wenn ein bestimmtes strukturelles Feature im Molekül existiert, wird ein spezifisches Bit im Array auf eins gesetzt. Wenn dieses Feature fehlt, bleibt das Bit auf null. Indem wir komplexe molekulare Graphen in Standard-Bit-Vektoren konvertieren, können wir sie ganz einfach mathematisch vergleichen.
RDKit bietet verschiedene Fingerprinting-Algorithmen. Der Default-Fingerprint von RDKit nutzt einen topologischen Ansatz. Er analysiert lineare Pfade durch das Molekül. Das System startet bei einem Atom und folgt den verbundenen Bindungen bis zu einer bestimmten Länge, typischerweise zwischen einer und sieben Bindungen. Jeder unique Pfad, den es findet, wird durch eine Hashing-Funktion geschickt, die diesen Pfad einer bestimmten Position im Bit-Vektor zuweist.
Obwohl topologische Pfade nützlich sind, verlässt sich die moderne Cheminformatik stark auf Morgan-Fingerprints, die oft auch Circular Fingerprints genannt werden. Anstatt lineare Pfade zu verfolgen, analysieren Morgan-Algorithmen die Nachbarschaft, die von jedem einzelnen Atom nach außen strahlt. Wenn du einen Morgan-Fingerprint generierst, musst du einen Radius definieren. Ein Radius von null bedeutet, dass der Algorithmus nur die einzelnen Atome erfasst. Ein Radius von eins erfasst jedes Atom plus seine direkt verbundenen Nachbarn. Ein Radius von zwei erweitert diesen Kreis um eine weitere Bindung. Der Algorithmus katalogisiert all diese überlappenden zirkulären Umgebungen, hasht sie und setzt die entsprechenden Bits auf eins. Normalerweise falten wir diese Hashes in einen Vektor mit fester Länge, wie zweitausendachtundvierzig Bits, um die Memory Usage vorhersehbar zu halten. Morgan-Fingerprints mit einem Radius von zwei sind der Industriestandard, weil sie funktionelle Gruppen und den lokalen chemischen Kontext wunderbar erfassen.
Lass uns ein konkretes Szenario anschauen. Du hast zwei leicht unterschiedliche Moleküle. Vielleicht teilen sie sich eine große Core-Struktur, aber eines hat eine zusätzliche Methylgruppe angehängt. Du willst quantifizieren, wie sehr sie überlappen. Zuerst liest du beide Moleküle in RDKit ein. Als Nächstes generierst du für jedes einen Morgan-Fingerprint und setzt den Radius auf zwei. Du hast jetzt zwei verschiedene Bit-Vektoren. Um zu berechnen, wie ähnlich sie sind, berechnest du ihre Tanimoto Similarity.
Hier ist die entscheidende Erkenntnis. Die Tanimoto Similarity ignoriert die Nullen. Sie kümmert sich nur um die Features, die tatsächlich vorhanden sind. Die Mathematik ist simple Intersection over Union. RDKit zählt die Anzahl der Bits, die in beiden Fingerprints auf eins gesetzt sind, und teilt das durch die Gesamtzahl der Bits, die in irgendeinem der beiden Fingerprints auf eins gesetzt sind. Wenn die beiden Vektoren perfekt matchen, ist der Tanimoto-Score eins Komma null. Wenn sie gar keine Features teilen, ist der Score null Komma null. Bei unseren beiden Molekülen, die sich durch eine einzige Methylgruppe unterscheiden, werden die zirkulären Umgebungen um den Core größtenteils matchen, während sich die Umgebungen in der Nähe der Mutation unterscheiden. Du bekommst vielleicht einen Tanimoto-Score von null Komma acht fünf, was dir einen präzisen numerischen Wert für ihren strukturellen Overlap gibt.
Behalte im Hinterkopf, dass das Mapping eines komplexen Moleküls auf ein festes Array von Bits bedeutet, dass einige Daten verloren gehen, und ein hoher Tanimoto-Score garantiert strukturellen Overlap, keine biologische Äquivalenz.
Danke, dass du ein paar Minuten mit mir verbracht hast. Bis zum nächsten Mal, mach's gut.
6
Die 2D-Ebene durchbrechen
4m 56s
Der Übergang von flachen 2D-Zeichnungen zu realistischen 3D-Geometrien. Wir diskutieren das Hinzufügen expliziter Wasserstoffatome und die Generierung zuverlässiger 3D-Conformer mit ETKDG.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 6 von 22. Eine zweidimensionale Zeichnung mag auf einem Bildschirm gut aussehen, aber Wirkstoffe existieren im dreidimensionalen Raum. Wenn du die Geometrie ignorierst, ignorierst du die Realität. Heute durchbrechen wir die 2D-Ebene und generieren korrekte 3D-Koordinaten für deine Moleküle.
Wenn du ein Molekül aus einem Standard-SMILES-String einliest, hat es überhaupt keine Koordinaten. Es ist streng genommen nur ein topologischer Graph verbundener Atome. Selbst wenn du eine Struktur aus einer 2D-Zeichnungsdatei lädst, sind diese Koordinaten nur so angeordnet, dass sie für Menschen gut lesbar sind. Um Docking durchzuführen, die Oberfläche zu berechnen oder physikalische Simulationen laufen zu lassen, brauchst du eine physikalisch realistische 3D-Struktur.
Der allererste Schritt, bevor du irgendeine 3D-Geometrie generierst, ist das Hinzufügen von Wasserstoffatomen. In einem Standard-SMILES-String sind Wasserstoffatome implizit. Sie werden als grundlegende Eigenschaft der schweren Atome behandelt und füllen einfach nur die Valenzanforderungen auf. Aber im physikalischen Raum nehmen Wasserstoffatome ein echtes Volumen ein. Sie erzeugen sterische Hinderung und diktieren die Bindungswinkel um sie herum. Wenn du versuchst, eine 3D-Struktur zu berechnen, ohne vorher explizit Wasserstoffatome hinzuzufügen, fällt die resultierende Geometrie in sich zusammen und die Bindungswinkel sind komplett falsch. RDKit bietet eine Funktion namens AddHs, die diese impliziten Wasserstoffatome in tatsächliche Nodes in deinem Molekülgraphen umwandelt, komplett mit Bindungen. Du musst diese Funktion immer ausführen, bevor du zu 3D übergehst.
Sobald du ein vollständiges Molekül hast, musst du seine räumlichen Koordinaten berechnen. Weil Einfachbindungen frei rotieren können, hat ein flexibler Ligand nicht nur eine einzige statische Form. Er kann viele verschiedene Formen annehmen, die als Konformationen bekannt sind. Um eine brauchbare Konformation zu generieren, verwendet RDKit eine Default-Methode namens ETKDG. Das steht für Experimental Torsion-angle Preference with Distance Geometry.
Hier ist die entscheidende Erkenntnis. Methoden der älteren Generation verließen sich komplett auf reine Mathematik. Sie nutzten Distanzgeometrie, um Atompositionen basierend auf bekannten Bindungslängen und -winkeln zu erraten. Das führte oft zu ungünstigen, hochenergetischen Formen, die aufwendiges rechnerisches Cleanup erforderten. ETKDG löst das, indem es die Mathematik der Distanzgeometrie mit empirischen Regeln kombiniert, die aus der Cambridge Structural Database abgeleitet wurden. Es weiß, wie echte, physikalische Moleküle sich tatsächlich am liebsten biegen und verdrehen, und es zwingt den Geometrie-Algorithmus, diese natürlichen Präferenzen zu respektieren.
Nehmen wir ein konkretes Szenario. Du hast einen hochflexiblen Liganden und musst all die verschiedenen Arten verstehen, wie er sich falten könnte, um in eine Protein-Bindungstasche zu passen. Eine einzige Konformation zu generieren, reicht nicht aus, um dieses Verhalten zu erfassen. Du brauchst ein Ensemble. RDKit erledigt das mit einer Funktion namens EmbedMultipleConfs. Du übergibst dein Molekül mit seinen expliziten Wasserstoffatomen und gibst an, dass du fünfzig Konformere haben willst.
RDKit führt den ETKDG-Algorithmus dann fünfzig Mal separat aus, ausgehend von verschiedenen Random Seeds, um fünfzig unterschiedliche 3D-Geometrien zu generieren. Es speichert alle fünfzig dieser Formen innerhalb des ursprünglichen Molekül-Objekts. Du bekommst nicht fünfzig separate Moleküle zurück; du bekommst ein Molekül, das fünfzig verschiedene Koordinatensätze enthält. Du kannst dann durch diese Koordinatensätze loopen, um Abstände zu messen oder Energien zu berechnen. Weil ETKDG stark von echten Kristalldaten geprägt ist, sind die initialen Strukturen, die es liefert, direkt aus der Funktion heraus meist von sehr hoher Qualität.
Ein Molekül ist keine flache Zeichnung und es ist selten nur eine einzige starre Form; es ist ein dynamisches Objekt, und das Sampling seiner multiplen Konformere zeigt dir die wahren Grenzen seines physikalischen Verhaltens. Wenn du helfen willst, die Show am Laufen zu halten, kannst du uns unterstützen, indem du auf Patreon nach DevStoriesEU suchst. Das war's für diese Folge. Danke fürs Zuhören und keep building!
7
Feature Engineering beschleunigen
4m 32s
Schlage die Brücke zwischen Cheminformatik und Standard-Data-Science mit scikit-fingerprints. Wir untersuchen die Generierung von über 30 Arten molekularer Fingerprints direkt innerhalb eines scikit-learn-Interfaces.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 7 von 22. Eigene Fingerprint-Extraction-Loops für jedes neue Projekt zu schreiben, ist mühsam und fehleranfällig. Wechselst du von einem ECFP-Fingerprint zu einem MACCS-Key, musst du plötzlich deinen gesamten Preprocessing-Block neu schreiben. Scikit-fingerprints ist eine Library, die dieses Problem löst, indem sie die Feature-Extraction von Molekülen so einfach macht wie den Aufruf einer Standard-Transform von scikit-learn.
Moleküle werden grundsätzlich als Graphen dargestellt. Die meisten Machine-Learning-Algorithmen benötigen jedoch mehrdimensionale Vektoren. Molekulare Fingerprints sind die Feature-Extraction-Algorithmen, die diese Lücke schließen, indem sie Strukturinformationen in numerische Arrays encoden. Das Problem ist, dass gängige Open-Source-Tools zur Berechnung dieser Fingerprints, wie RDKit, Open Babel oder das Chemistry Development Kit, in C++ oder Java geschrieben sind. Ihre Python-Wrapper sind nicht nativ mit der scikit-learn-API kompatibel. Am Ende schreibst du eigene Data-Loader, Format-Converter und fehleranfällige Loops, nur um deine Daten in eine Form zu bringen, die ein Classifier verarbeiten kann.
Scikit-fingerprints ändert diese Architektur. Es implementiert über 30 verschiedene molekulare Fingerprints als standardmäßige, zustandslose scikit-learn-Transformer. Alle Fingerprint-Klassen erben von den scikit-learn-Base-Classes. Dadurch lassen sie sich direkt in Standard-Machine-Learning-Pipelines und Feature-Unions integrieren.
Stell dir einen Standard-Workflow vor. Normalerweise würdest du in RDKit einen zwanzigzeiligen Custom-Loop schreiben, um über ein Dataset zu iterieren, die Moleküle zu validieren, zirkuläre Fingerprints zu extrahieren und die Ergebnisse in einem Array zu stacken. Mit dieser Library ersetzt du diesen gesamten Block an Boilerplate durch einen einzigen Schritt. Du erstellst ein Objekt namens ECFP Fingerprint und übergibst es direkt in eine scikit-learn-Pipeline, genau vor deinem Random-Forest-Model. Wenn du die fit-Methode deiner Pipeline mit deinen Trainingsdaten und Target-Variablen aufrufst, verarbeitet der Fingerprint-Transformer die Inputs und gibt ein dichtes NumPy-Array direkt an das Model aus.
Hier ist der entscheidende Punkt. Du musst deine Text-Representations nicht in RDKit-Molekül-Objekte konvertieren, bevor du sie an den Transformer übergibst. Für jeden zweidimensionalen Fingerprint, der auf Graphentopologie basiert, akzeptiert die transform-Methode direkt eine Standard-Python-List von SMILES-Strings. Die Library übernimmt die interne Konvertierung automatisch. Da SMILES-Strings nicht immer eindeutig oder chemisch gültig sind, bietet die Library auch eine Molecule-Standardizer-Class. Diese Class wendet die von RDKit empfohlenen Sanitization-Schritte an, um die Datenqualität sicherzustellen, bevor die Extraction beginnt.
Die Library unterstützt außerdem dreidimensionale Fingerprints, die auf räumlicher Konformation basieren. Diese räumlichen Algorithmen benötigen RDKit-Molekül-Objekte mit berechneten Conformern. Da das Generieren von Conformern instabil sein kann, enthält das Package eine Conformer-Generator-Class, die einen spezifischen Algorithmus namens ETKDG Version 3 verwendet. Das liefert zuverlässige Defaults, die die Effizienz für einfache Moleküle maximieren und gleichzeitig Berechnungsfehler bei komplexen Verbindungen minimieren. Du packst den Conformer-Generator an den Anfang deiner Pipeline, gefolgt von einem dreidimensionalen Fingerprint-Transformer, und schließt mit einem Imputer ab, um fehlende Werte zu handhaben.
Indem sie komplexe Chemie-Logik in Standard-Transformer-Classes kapselt, abstrahiert die Library den domänenspezifischen Boilerplate weg. Du konfigurierst Optionen wie die Output-Vector-Länge oder ob du eine Binary- oder Count-Variante möchtest, einfach indem du Parameter an den Transformer-Constructor übergibst. Das Ergebnis ist, dass das Tuning von Hyperparametern für molekulare Fingerprints genauso unkompliziert wird wie das Tuning der Tiefe eines Decision-Trees.
Das war's für diese Folge. Bis zum nächsten Mal!
8
High-Performance-Cheminformatik
4m 30s
Lerne, wie man riesige chemische Datensätze effizient verarbeitet. Wir tauchen in die Nutzung von CPU-Parallelität mit Joblib ein und sparen Speicherplatz durch die Verwendung von SciPy Sparse-Matrizen.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 8 von 22. Die Berechnung komplexer Substrukturen über einen riesigen Datensatz hinweg kann deine Maschine leicht mit Out-of-Memory-Errors zum Absturz bringen, es sei denn, du weißt genau, wie du deinen Data Footprint managst. Die Technik, die das löst, ist High-Performance Cheminformatics.
Wenn du Features aus einem Molekül extrahierst, nutzt du oft Substructure-based Fingerprints. Der Klekota-Roth-Fingerprint ist ein klassisches Beispiel. Um ihn zu berechnen, gleicht deine Maschine ein Molekül mit Tausenden vordefinierter chemischer Muster ab, den sogenannten SMARTS Patterns. Sie scannt den Molecular Graph immer wieder, um zu sehen, ob spezifische funktionelle Gruppen oder Strukturmotive existieren. Das sequenziell für ein paar Moleküle zu machen, ist völlig in Ordnung. Das für einen Datensatz von vierhunderttausend Molekülen zu tun, ist ein massiver Computational Bottleneck.
Die Berechnung molekularer Fingerprints ist eine embarrassingly parallel Task. Die Strukturanalyse eines Moleküls hat absolut null Abhängigkeit zur Analyse des nächsten Moleküls in deinem Datensatz. Weil sie keinen State teilen, kannst du sie komplett gleichzeitig berechnen. Um das in Python effektiv zu skalieren, nutzt du Joblib und verlässt dich dabei speziell auf den Loky Executor.
Wenn du den Prozess startest, wird der Input-Datensatz in Chunks aufgeteilt, die exakt deinen verfügbaren CPU-Cores entsprechen. Wenn du einen 16-Core-Prozessor hast, werden deine Input-Moleküle in 16 separate Batches unterteilt. Jeder Python Worker Process nimmt einen Batch und beginnt unabhängig mit dem SMARTS Pattern Matching. Die technische Hürde beim Multiprocessing in Python sind normalerweise die Kosten für das Verschieben von Daten zwischen den Workern und dem Main Process. Loky umgeht das durch Memory Mapping. Anstatt die finalen Fingerprint Arrays zu serialisieren und über Inter-Process Communication zu senden, schreiben die Worker direkt in einen Shared Memory Space. Bei rechenintensiven Fingerprints wie Klekota-Roth bringt die Verteilung der Workload auf 16 Cores fast einen fünfzehnfachen Speedup.
Damit haben wir die Processing Time im Griff. Der zweite kritische Bottleneck ist der System Memory.
Ein einzelner Klekota-Roth Fingerprint Vector ist lang. Wenn du Hunderttausende von Molekülen verarbeitest, generierst du eine riesige Result Matrix. Standardmäßig geben numerische Libraries dieses Ergebnis als Dense NumPy Array zurück. Jede einzelne Position in dieser Matrix alloziert Memory, unabhängig davon, ob der Wert eine Eins oder eine Null ist.
Chemische Fingerprints sind extrem sparse. Normalerweise sind nur ein bis zwei Prozent der angefragten Structural Features in einem bestimmten Molekül tatsächlich vorhanden. Der Großteil deiner resultierenden Matrix besteht aus Nullen. Genau das Speichern dieser Nullen triggert die Out-of-Memory-Errors bei großen Datensätzen. Der Fix dafür ist, das Output-Format auf eine SciPy Sparse Matrix umzustellen, genauer gesagt auf das Compressed Sparse Row Format. Eine Sparse Matrix ändert grundlegend, wie die Daten gespeichert werden. Anstatt ein starres Grid im Memory aufzubauen, speichert sie nur die Werte der Non-Zero Elements zusammen mit ihren Row und Column Coordinates.
Stell dir ein Real-World-Szenario mit dem PCBA-Datensatz vor, der knapp vierhundertvierzigtausend Moleküle enthält. Du lässt die Klekota-Roth Fingerprint Computation über den gesamten Datensatz mit deinen 16 Cores laufen. Die parallele Execution läuft effizient durch. Wenn du den Output als standardmäßiges Dense Array belässt, wird diese einzelne Matrix etwas mehr als zwei Gigabyte RAM verbrauchen. Indem du die Computation stattdessen anweist, ein SciPy Sparse Array zurückzugeben, schrumpft der Footprint exakt desselben Datensatzes auf nur 23 Megabyte. Du erreichst eine 88-fache Reduzierung beim Memory, ohne auch nur eine einzige chemische Information zu verlieren, und die Sparse Representation wirkt sich überhaupt nicht negativ auf deine Computation Time aus.
Hier ist die entscheidende Erkenntnis: Du brauchst keinen riesigen Compute Cluster, um Hunderttausende von Molekülen zu verarbeiten, vorausgesetzt, du hörst auf, die Memory Tax für das Speichern von Nullen zu zahlen, und stellst sicher, dass dein Data Passing den Standard-Overhead der Inter-Process Communication umgeht.
Das war's für diese Folge. Danke fürs Zuhören und keep building!
9
End-to-End ML-Pipelines
4m 06s
Kombiniere Verarbeitung, Fingerprinting und Vorhersage in einer einzigen sauberen Architektur. Wir bauen robuste scikit-learn-Pipelines, die die 3D-Conformer-Generierung und die Vorhersage von Eigenschaften nahtlos integrieren.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatik & KI, Folge 9 von 22. Ein komplexes 3D Virtual Screening Script brauchte früher hunderte Zeilen fehleranfälligen Code. Du musstest manuell Conformers generieren, Fehler abfangen, mehrere Descriptors berechnen und die Arrays zusammenfügen, bevor du überhaupt ein Model anfassen konntest. Jetzt kannst du den gesamten Prozess in einer einzigen, eleganten Pipeline-Definition mit End-to-End ML Pipelines aufbauen.
Im Machine Learning ist eine Pipeline eine Sequenz von Datenverarbeitungsschritten und einem finalen Estimator, zusammengefasst in einem einzigen Objekt. In der Cheminformatik, besonders bei 3D-Strukturdaten, ist das Preprocessing bekanntermaßen extrem fragmentiert. Du nimmst rohe SMILES Strings, berechnest 3D-Koordinaten, lässt Force-Field-Optimierungen laufen, extrahierst Features, fixt fehlende Werte und trainierst schließlich einen Classifier. Wenn du das manuell machst, musst du Custom Loops und temporäre Datenstrukturen schreiben, die leicht kaputtgehen und Memory Leaks verursachen. Wir schauen uns jetzt an, wie du eine komplette scikit-learn Pipeline baust, die rohe SMILES direkt an einen Random Forest Classifier weiterleitet.
Der erste Schritt in der Sequenz ist die Conformer-Generierung. Du initialisierst einen Conformer Generator und übergibst ihn als erste Stage der Pipeline. Er liest den 2D-Input und berechnet die 3D-Strukturen. Du kannst ihn so konfigurieren, dass er die Geometrie mit einem Force Field wie MMFF94 optimiert. Er parallelisiert diese rechenintensive Aufgabe automatisch über alle verfügbaren CPU-Cores.
Der zweite Teil davon ist die Feature Extraction. Bei 3D-Tasks erfasst die Kombination verschiedener Geometrie-Descriptors mehr molekulare Informationen. Du nutzt eine scikit-learn Feature Union, um die GETAWAY- und WHIM-Fingerprints gleichzeitig zu berechnen. Beide dieser Fingerprint-Klassen fungieren als stateless Transformers in der Pipeline. Sie nehmen die 3D-Conformers aus dem vorherigen Schritt, berechnen ihre jeweiligen Descriptors parallel und verketten die Ergebnisse zu einer einzigen, breiten Feature-Matrix.
Als Nächstes musst du Computation Failures abfangen. 3D-Descriptor-Algorithmen scheitern manchmal daran, hochkomplexe oder gespannte Moleküle zu verarbeiten, was zu Missing Values in deiner Matrix führt. Die Pipeline übernimmt das ganz ohne Custom Error Handling. Du packst einen Simple Imputer direkt hinter die Feature Union. Falls eine GETAWAY- oder WHIM-Berechnung einen Missing Value ausgibt, fängt der Imputer ihn ab und ersetzt ihn durch den Mean dieses Features in deinem Dataset.
Zum Schluss schließt du die Pipeline mit deinem Predictive Model ab, was in diesem Fall ein Random Forest Classifier ist.
Um das im Code aufzubauen, rufst du die make pipeline Funktion auf. Innerhalb dieses Function Calls übergibst du deinen Conformer Generator. Als Nächstes übergibst du die Feature Union, die deine GETAWAY- und WHIM-Fingerprints enthält. Dann kommt der Simple Imputer und ganz am Ende der Random Forest Classifier. Du weist diese gesamte Sequenz einer einzigen Variable zu.
Wenn du die fit Methode auf dieser Pipeline-Variable aufrufst, übergibst du deine rohen Training SMILES Strings und deine Target Labels. Die Strings fließen sequenziell durch den Conformer Generator, in die Feature Union fürs Fingerprinting, durch den Imputer, um die Daten zu bereinigen, und direkt in den Classifier fürs Training. Wenn es Zeit für die Evaluation ist, zwingt der Aufruf der predict Methode auf deinen Test SMILES Strings die neuen Daten dazu, exakt denselben Pfad zu nehmen.
Hier ist der entscheidende Punkt. State und Data Routing werden komplett vom Pipeline-Objekt verwaltet. Das bedeutet, dass du niemals temporäre Dense Arrays im Memory halten oder Custom Data Loaders für deine Conformers schreiben musst.
Das war's für diese Folge. Danke fürs Zuhören und keep building!
10
Vorhersage der Bindungsaffinität
4m 53s
Erforsche die Realität der Vorhersage von Protein-Ligand-Bindungsaffinitäten. Wir vergleichen die Leistung einfacher 2D-baumbasierter Modelle mit komplexen 3D Graph Neural Networks.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 10 von 22. Du baust ein riesiges dreidimensionales Graph Neural Network auf und fütterst es mit den räumlichen Koordinaten für jedes Atom in einer Protein Pocket. Dann lässt du einen simplen Gradient Boosted Decision Tree laufen, der sich nur die zweidimensionale Skizze des Wirkstoffs ansieht. Der Benchmark ist durch, und dein hochmodernes Spatial Model wurde gerade von einem Algorithmus von vor zwanzig Jahren geschlagen. Der Grund, warum dein schweres Netzwerk versagt hat, liegt darin, wie wir Binding Affinity vorhersagen.
Die Vorhersage der Binding Affinity ist der rechnergestützte Prozess, bei dem abgeschätzt wird, wie fest sich ein kleines Molekül, also ein Ligand, an ein spezifisches Protein Target bindet. In der Drug Discovery ist es das absolute Hauptziel, ein Molekül zu finden, das stark bindet. Um das zu erreichen, schlagen Engineers typischerweise einen von zwei Wegen ein. Der erste ist hochkomplex. Du nutzt dreidimensionale Neural Networks wie GraphNet oder TensorNet. Diese Modelle verarbeiten die exakte gebundene Konformation des Protein-Ligand-Komplexes. Sie nutzen Message Passing Layers, um die genauen räumlichen Abstände und quantenmechanischen Features zwischen den Atomen des Wirkstoffs und den Atomen der Protein Pocket zu lernen.
Der zweite Weg ignoriert das Protein komplett. Du lässt die räumlichen Koordinaten weg und nutzt ein klassisches zweidimensionales Modell wie XGBoost. Der Input hier ist einfach ein concatenated Vector aus molekularen Fingerprints. Du berechnest strukturelle Features nur aus dem Liganden, verwandelst im Grunde die zweidimensionale Zeichnung der Chemikalie in ein Array aus Zahlen und fütterst das direkt in das Tree-based Model.
Um zu sehen, wie diese Ansätze im Vergleich abschneiden, lassen Researcher sie gegen standardisierte Test Sets laufen. Einer der aussagekräftigsten ist der Merck FEP Benchmark. Dieses Dataset simuliert ein gängiges Virtual Screening Szenario, das sich Congeneric Series nennt. In einer Congeneric Series teilen sich alle getesteten Liganden exakt dasselbe chemische Core Scaffold und binden an exakt dieselbe Stelle eines einzelnen Protein Targets. Die einzigen Unterschiede zwischen den Molekülen sind kleine strukturelle Variationen, wie zum Beispiel verschiedene chemische Branches, die an den Main Core angehängt sind.
Hier ist die entscheidende Erkenntnis. Bei der Evaluierung auf dem Merck Dataset erreichten die schweren dreidimensionalen Modelle einen Correlation Score von etwa null Komma drei. Das simple zweidimensionale XGBoost-Modell schnitt deutlich besser ab und erreichte null Komma vier fünf. Der rechnerisch günstige Decision Tree hat die fortschrittlichen Graph Neural Networks klar übertroffen.
Das passiert aufgrund dessen, worauf sich die Modelle fokussieren müssen. In einer Congeneric Series verändern sich das Protein Target und die Binding Pocket nicht. Das dreidimensionale Modell verbraucht massive Computational Resources, um ein Spatial Environment zu mappen, das über jeden einzelnen Test Case hinweg statisch bleibt. Noch schlimmer: Diese Modelle sind extrem anfällig für winzige Variationen in den atomaren Koordinaten. Eine leichte, willkürliche Verschiebung bei der Platzierung eines Wasserstoffatoms während der Data Preparation erzeugt Noise, das das Graph Network ablenkt. Das zweidimensionale Modell ist genau deshalb so erfolgreich, weil es blind für das Protein ist. Indem es sich nur die Ligand Features ansieht, verlässt es sich auf die einzigen Variablen, die sich von einem Test zum nächsten tatsächlich ändern. Der Decision Tree korreliert diese direkten strukturellen Variationen im Wirkstoff mit der finalen Bindungsstärke und umgeht das Noise des Spatial Environments komplett.
Schwere dreidimensionale Modelle sind immer noch extrem wertvoll, wenn du über komplett unterschiedliche, ungesehene Protein Targets generalisieren musst, bei denen die Pocket Geometry unbekannt ist. Aber wenn du eine spezifische Familie von Wirkstoffen für ein einziges bekanntes Target optimierst, ist es ineffizient und fehleranfällig, konstante Umgebungsdaten in ein Deep Network zu füttern. Das mächtigste Predictive Tool ist oft dasjenige, das die statische Umgebung herausfiltert und nur die Variablen modelliert, die sich verändern. Das war's für diese Folge. Bis zum nächsten Mal!
11
LLMs vs. klassische Fingerprints
4m 34s
Entdecke, wie Natural Language Processing in der Chemie angewendet wird. Wir lassen Vektor-Embeddings aus Large Language Models gegen klassische strukturelle RDKit-Fingerprints antreten, um die Bioaktivität vorherzusagen.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 11 von 22. Was wäre, wenn der beste Weg, einem Machine-Learning-Modell ein Molekül zu beschreiben, nicht eine handgemachte Strukturformel ist, sondern den SMILES-String genau wie einen Satz in natürlicher Sprache zu behandeln? Du verschwendest vielleicht wertvolle Compute Cycles, um komplexe chemische Deskriptoren zu generieren, nur um dann von einem Textmodell geschlagen zu werden. Diese Spannung ist der Kern von LLMs vs. Classical Fingerprints.
Wenn du vorhersagen willst, wie stark ein Ligand an ein Protein bindet, braucht dein Modell eine mathematische Beschreibung des Liganden. Der traditionelle Weg verlässt sich auf klassische Structural Fingerprints, die von Tools wie RDKit berechnet werden. Du jagst ein Molekül durch einen deterministischen Algorithmus und bekommst einen statischen Vektor zurück. Ein Morgan-Fingerprint zählt zirkuläre Substrukturen um Atome herum. MACCS Keys checken das Molekül gegen eine vordefinierte Liste von chemischen Mustern.
Das Problem dieser klassischen Fingerprints ist ihre Starrheit. Sie encodieren spezifische, unveränderliche Regeln. Du kannst sie nicht finetunen. Wenn eine bestimmte strukturelle Nuance für eine hochspezifische Binding Pocket wichtig ist, der Fingerprint-Algorithmus aber nicht explizit darauf ausgelegt war, sie zu erfassen, geht diese Information komplett verloren, noch bevor das Predictive Model die Daten überhaupt sieht.
Anstatt chemische Regeln zu hardcoden, können wir ein pretrained chemisches Large Language Model wie BioT5, GPT2 oder BERT verwenden. Diese Modelle sind auf Millionen von SMILES-Strings pretrained. Sie lernen die Grammatik der Chemie auf unsupervised Weise. Wenn du einem LLM einen Liganden übergibst, gibt es keine feste Checkliste von funktionellen Gruppen aus. Es liefert ein reichhaltiges Vector Embedding. Jedes Zeichen oder Token in diesem SMILES-String bekommt seinen eigenen Kontext-Vektor.
Um den Unterschied zu verstehen, schau dir an, wie diese Repräsentationen in Predictive Models einfließen. Stell dir zuerst ein XGBoost-Modell vor, das klassische MACCS Keys verwendet. Du generierst den MACCS-Fingerprint, was in einem simplen Binary Array resultiert. Du übergibst diesen festen Vektor an XGBoost, das dann versucht, diese rohen Presence-or-Absence-Features auf die Binding Affinity zu mappen. In Benchmark-Tests über kongenere Serien hinweg liefert diese spezifische Kombination durchweg die schlechteste Performance. Die handgemachten Features sind einfach zu grob.
Tausch diese Architektur nun gegen ein BioT5-Embedding aus, das in einen Transformer Head gefüttert wird. Zuerst übergibst du den rohen SMILES-String an das BioT5-Modell. Das gibt eine Sequenz von Per-Token-Embeddings zurück. Dann übergibst du diese Sequenz an einen Transformer Head. Hier ist die entscheidende Erkenntnis. Der Transformer nutzt einen Attention-Mechanismus. Er schaut sich die gesamte Sequenz der Token-Embeddings an und lernt dynamisch, welche Teile des Moleküls für die Bindung an dieses spezifische Target am wichtigsten sind. Er gewichtet die Features intelligent, bevor er die vorhergesagte Binding Affinity ausgibt.
Wenn du versuchst, genau dieselben BioT5-Tokens zu nehmen, sie zu einem flachen Vektor aufzusummieren und das in XGBoost zu füttern, sinkt die Predictive Performance signifikant. Sum Pooling mittelt die Details auf Token-Ebene heraus. Der Transformer Head ist genau deshalb so erfolgreich, weil er den granularen Kontext der textähnlichen Repräsentation bewahrt und ausnutzt.
Dieser Shift von statischen Arrays zu dynamischen Embeddings bietet massive praktische Vorteile. LLM-Embeddings sind extrem vielseitig und können für spezialisierte Downstream Tasks gefinetuned werden. Sie sind außerdem viel kompakter als riesige klassische Bit-Vektoren, was Memory beim Speichern großer Molekül-Bibliotheken spart. Außerdem läuft das Generieren von Text-Embeddings auf einer GPU, was drastisch schneller ist als das Berechnen traditioneller RDKit-Fingerprints auf einer CPU.
Die Ära, in der man Algorithmen manuell sagen musste, welche chemischen Substrukturen wichtig sind, geht zu Ende; die Modelle, die am besten performen, sind die, die das Molekül selbst lesen und für sich selbst entscheiden dürfen. Wenn du die Show unterstützen willst, kannst du auf Patreon nach DevStoriesEU suchen. Danke fürs Dabeisein. Ich hoffe, du hast etwas Neues mitgenommen.
12
Active Learning für virtuelles Screening
3m 45s
Lerne, wie man iterativ Top-Wirkstoffkandidaten ohne erschöpfendes Testen entdeckt. Wir tauchen in Active-Learning-Schleifen und Greedy-Selection-Strategien ein, um die Trefferquoten zu maximieren.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 12 von 22. Komplexe physikalische Simulationen für eine Million Moleküle laufen zu lassen, ist unglaublich langsam. Du brauchst einen Weg, um die absolut besten Kandidaten zu finden, indem du nur einen winzigen Bruchteil deines Datasets testest. Genau das macht Active Learning für Virtual Screening.
Wenn du eine Chemical Library evaluierst, ist die Berechnung genauer Bindungsaffinitäten mit Computational-Physics-Methoden unglaublich teuer. Du kannst es dir schlichtweg nicht leisten, jedes einzelne Compound zu simulieren. Stattdessen testest du einen kleinen Batch, nutzt diese Ergebnisse, um ein Machine Learning Model zu trainieren, und lässt dieses Model die Affinitäten für den Rest der Library vorhersagen. Danach testest du die vielversprechendsten Predictions, updatest das Model und wiederholst den Prozess. Dieser iterative Cycle ist Active Learning.
Schauen wir uns ein konkretes Szenario an. Du untersuchst eine kongenere Serie von zehntausend Compounds, die auf ein bestimmtes Protein wie Tyk2 abzielen. Dein Ziel ist es, die Top ein Prozent der aktiven Moleküle zu finden. Um das effizient zu machen, verlässt du dich auf eine Greedy Selection Strategy. Eine Greedy Strategy bedeutet, dass dein Model für die nächste Testrunde immer die Compounds mit den höchsten predicted Bindungsaffinitäten auswählt.
Du setzt deine Batch Size auf sechzig Moleküle pro Runde. Diese Zahl ist eine praktische Balance für einen Real-World-Workflow. Sie ist klein genug, damit du anspruchsvolle Physik-Simulationen für den Batch schnell laufen lassen kannst, aber groß genug, um deinem Model einen ordentlichen Chunk an neuen Daten zu liefern. Du lässt deine Tests für diese sechzig Compounds laufen, um ihre wahren Bindungsaffinitäten zu bekommen, und fütterst diese Daten sofort in ein zweidimensionales Tree-based Model wie XGBoost. Das XGBoost-Model lernt die Pattern, scored die restlichen ungetesteten Moleküle im Pool von zehntausend Compounds und wählt die nächsten sechzig Kandidaten aus.
Hier ist der entscheidende Punkt. Wie du den allerersten Batch von sechzig Molekülen auswählst, bestimmt, wie schnell dein gesamtes System lernt. Standard Active Learning nutzt oft eine Random Baseline als Default. Du wählst sechzig Moleküle komplett random aus, testest sie und trainierst dein erstes Model. Aber Random Selection gibt deinem Model einen schlechten Startpunkt und füllt das initiale Training Set hauptsächlich mit inaktiven Compounds.
Die Lösung ist, den Active Learning Loop mit einem pretrained dreidimensionalen Neural Network zu initialisieren. Dieses 3D-Model wurde bereits auf einem riesigen, allgemeinen Dataset von diversen Protein- und Liganden-Komplexen trainiert. Weil es die allgemeine Bindungsphysik basierend auf strukturellen Interaktionen versteht, kann es deine zehntausend Compounds scoren, noch bevor der Active Learning Loop überhaupt beginnt.
Zuerst nutzt du das pretrained 3D-Model, um Affinitäten für den gesamten Pool zu predicten. Dann nimmst du die Top sechzig Moleküle, die durch dieses Prescreening identifiziert wurden, und lässt deine schweren Physik-Simulationen darauf laufen. Jetzt hast du ein stark angereichertes Set an Startdaten. Du übergibst dieses initiale High-Quality-Dataset an dein XGBoost-Model. Ab diesem Punkt übernimmt das XGBoost-Model den Cycle. Es trainiert auf den verifizierten Daten, predicted den restlichen Pool und wählt greedy die nächsten sechzig Kandidaten aus.
Diese Kombination erzeugt eine massive Beschleunigung in der Hit Discovery. Das allgemeine 3D-Model liefert einen starken Startpunkt, und das XGBoost-Model adaptiert sich schnell an den spezifischen Chemical Space deiner kongeneren Serie. Indem du mit einem pretrained 3D-Model statt mit Random Sampling initialisierst, kannst du achtzig Prozent der Top ein Prozent der Binder finden, nachdem du weniger als zehn Prozent des gesamten Datasets getestet hast. Deinen Loop mit einem allgemeinen 3D-Prescreening zu starten, gibt deinen spezialisierten Models einen unschlagbaren Vorsprung.
Das war's für diese Folge. Danke fürs Zuhören und keep building!
13
Die Activity-Cliff-Herausforderung
4m 01s
Untersuche die Fragilität von Struktur-Wirkungs-Beziehungen. Wir diskutieren 'Activity Cliffs' – bei denen eine winzige strukturelle Änderung eine massive Verschiebung der Wirksamkeit eines Medikaments verursacht.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 13 von 22. In der Chemie kann ein einziges Atom an der falschen Stelle ein wirksames, lebensrettendes Medikament in ein wirkungsloses Pulver verwandeln. Diese plötzlichen Abfälle der biologischen Wirksamkeit werden als Activity Cliffs bezeichnet und sind der absolute Albtraum traditioneller AI-Modelle.
Ein Activity Cliff entsteht, wenn du zwei Moleküle mit hoher struktureller Ähnlichkeit, aber deutlich unterschiedlichen Aktivitätsniveaus hast. Stell dir ein konkretes Szenario vor: Du hast zwei Moleküle, die 90 Prozent ihres strukturellen Frameworks teilen. Das erste Molekül bindet fest an ein biologisches Target. Das zweite Molekül ist völlig inaktiv. Der einzige physikalische Unterschied zwischen ihnen ist eine einzelne Methylgruppe an einem bestimmten Ring. Für einen menschlichen Medizinalchemiker ist diese spezifische strukturelle Modifikation extrem informativ. Sie zeigt ihm genau, wo die Grenzen der Rezeptortasche liegen. Für ein Standard-Machine-Learning-Modell ist es eine katastrophale Störung.
Hier ist die entscheidende Erkenntnis. Die meisten Deep-Learning-Ansätze in der Cheminformatik sind darauf ausgelegt, absolute Eigenschaftswerte vorherzusagen. Egal, ob du ein Graph Neural Network oder ein Chemical Language Model verwendest, die Architektur ist grundlegend darauf ausgelegt, chemische Strukturen in einen kontinuierlichen mathematischen Raum zu mappen. Die zentrale Annahme, die in diese Modelle hardcoded ist, lautet, dass ähnliche Molekülstrukturen auf ähnliche biologische Eigenschaften gemappt werden sollten. Wenn ein Standardmodell unsere beiden nahezu identischen Moleküle verarbeitet, generiert es Representations, die in diesem mathematischen Raum direkt nebeneinander liegen. Weil die Inputs nah beieinander liegen, liefert das Modell als Output natürlich nahezu identische absolute Vorhersagen für beide.
Activity Cliffs verletzen diese Annahme eines glatten, kontinuierlichen chemischen Raums grundlegend. Sie stellen eine starke Diskontinuität dar. Das Modell erwartet einen sanften Hügel, trifft aber auf einen vertikalen Abfall. Dieses Problem wird durch die Natur von Drug-Discovery-Daten extrem verstärkt. Experimentelle Datasets sind bekanntermaßen limitiert und noisy. Wenn du ein Deep Neural Network auf spärlichen Daten trainierst, hat das Modell Schwierigkeiten zu generalisieren. Um den Gesamtfehler über das Training Set zu minimieren, lernt das Network breite, globale Patterns. Es glättet die lokalen Unregelmäßigkeiten. Wenn es auf ein Activity Cliff stößt, behandelt das Standard-Regression-Objective diesen plötzlichen Sprung in der Varianz als experimentelles Noise oder als Outlier. Das Modell ignoriert die wichtigste lokale Strukturinformation, da sie nicht zum globalen Trend passt.
Deshalb bleibt die Vorhersage von Activity Cliffs eines der schwierigsten Probleme bei der Molecular Property Prediction. Die Modelle sind gezwungen, einen diskontinuierlichen chemischen Raum direkt aus begrenzten Daten zu lernen. Weil sie sich komplett auf absolute Predictions für einzelne Moleküle fokussieren, ignorieren sie die wertvollen Informationen völlig, die in den relativen Unterschieden zwischen Matched Molecular Pairs verborgen sind. In vielen Fällen performen einfachere Tree-based Models auf diesen Datasets am Ende tatsächlich besser als komplexe Neural Networks, ganz einfach, weil Deep-Learning-Modelle die Representations over-smoothen.
Die Annahme, dass ähnliche chemische Strukturen immer zu ähnlichen biologischen Aktivitäten führen, ist eine nützliche statistische Baseline, aber kein physikalisches Gesetz. Activity Cliffs sind die brutale, diskontinuierliche Realität von Structure-Activity Relationships, und sie beweisen, dass die Vorhersage absoluter Eigenschaften im luftleeren Raum an den Rändern immer scheitern wird. Danke, dass du ein paar Minuten mit mir verbracht hast. Bis zum nächsten Mal, mach's gut.
14
Similarity-Quantized Relative Learning
4m 05s
Löse das Activity-Cliff-Problem, indem du überdenkst, wie Modelle lernen. Wir untersuchen das SQRL-Framework, das KI darauf trainiert, relative Eigenschaftsunterschiede zwischen streng gefilterten molekularen Paaren vorherzusagen.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 14 von 22. Anstatt eine AI die absolute Wirkstärke jedes existierenden Moleküls auswendig lernen zu lassen, was wäre, wenn du ihr einfach beibringst, zu fragen, wie sich ein Molekül von seinem nächsten bekannten Nachbarn unterscheidet? Dieser Perspektivwechsel löst ein zentrales Generalisierungsproblem in Low-Data-Regimes und ist der Kern eines Frameworks namens Similarity-Quantized Relative Learning, oder SQRL.
Normalerweise behandelt die Molecular Property Prediction jedes Molekül als isolierten Data Point. Das Modell versucht, eine Struktur direkt einem absoluten Eigenschaftswert zuzuordnen. Bei kleinen, verrauschten Datasets haben Deep Learning Models Schwierigkeiten, eine genaue globale Karte des chemischen Raums zu erstellen. Frühere Ansätze beim Pairwise Learning haben versucht, das zu beheben, indem sie jedes Molekül mit jedem anderen Molekül im Training Set gepaart haben. Dieser Ansatz überflutet die Daten mit Vergleichen zwischen völlig unzusammenhängenden Strukturen, wodurch das nützliche lokale Signal untergeht. SQRL löst das, indem es die Training Data auf Molekülpaare beschränkt, die sich strukturell sehr ähnlich sind. Das Modell lernt, die relative Differenz ihrer Eigenschaften – bekannt als Delta Y – vorherzusagen.
Das wird durch einen speziellen Dataset-Matching-Schritt erreicht. Du fütterst das Modell nicht mit einzelnen Molekülen. Du gibst ihm Paare, aber nur, wenn sie einen strengen Similarity Threshold überschreiten. Lass uns die Logik mal durchgehen. Du startest mit deinem Standard-Training-Set aus Molekülen und ihren bekannten Wirkstärken. Zuerst berechnest du die Pairwise Distances zwischen allen Molekülen mit einer Metrik wie der Tanimoto-Distanz auf Morgan Fingerprints.
Hier ist der entscheidende Punkt. Du setzt einen Distance Threshold, Alpha. Nehmen wir mal einen Tanimoto Distance Threshold von null Komma sieben. Du iterierst durch alle möglichen Molekülpaare. Wenn die Distanz zwischen Molekül A und Molekül B null Komma sieben oder höher ist, verwirfst du das Paar komplett. Ist die Distanz strikt kleiner als null Komma sieben, fügst du dieses Paar deinem neuen relativen Training Set hinzu. Die Target Variable für dieses neue Paar ist keine absolute Wirkstärke mehr. Es ist die exakte numerische Differenz in der Wirkstärke zwischen Molekül A und Molekül B.
Jetzt trainierst du dein Neural Network. Das Netzwerk generiert eine mathematische Representation für Molekül A und eine Representation für Molekül B. Es subtrahiert die Representation von B von der Representation von A. Dieser resultierende Difference Vector wird durch einen finalen Layer geleitet, um das Delta Y vorherzusagen. Indem das Noise von unähnlichen Paaren herausgefiltert wird, wird das Netzwerk gezwungen, sich ausschließlich auf lokale, High-Signal chemische Veränderungen zu fokussieren. Es lernt genau, wie ein spezifischer struktureller Tweak die Aktivität verändert. Das macht das Modell extrem sensibel für Activity Cliffs.
Das deckt das Training ab, aber was ist mit der Prediction für ein brandneues Molekül? Wenn eine neue Struktur reinkommt, scannt das System die originalen Training Data, um den einen nächsten strukturellen Nachbarn basierend auf derselben Tanimoto-Distanz-Metrik zu finden. Das Netzwerk evaluiert das neue Molekül gegen diesen Nearest Neighbor und sagt das relative Delta voraus. Schließlich nimmst du die bekannte absolute Wirkstärke des Nachbarn, addierst das vorhergesagte Delta, und du hast deine finale Prediction. Indem du den Training Space auf sehr ähnliche Paare beschränkst, hörst du auf, vom Modell zu verlangen, das gesamte chemische Universum zu lernen, und trainierst es stattdessen darauf, ein Experte für lokale chemische Gradienten zu werden.
Das war's für diese Folge. Danke fürs Zuhören und keep building!
15
Die Revolution der generativen KI
3m 44s
Der Übergang von der Vorhersage von Eigenschaften zur Erschaffung völlig neuer Moleküle. Wir skizzieren die Landschaft molekularer generativer Aufgaben: De-Novo-Generierung, Optimierung und Conformer-Generierung.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 15 von 22. Jahrelang war AI in der Chemie reine Triage. Du hast ein Model mit Tausenden von existierenden Molekülen gefüttert, und es hat einfach vorhergesagt, welche am wenigsten furchtbar waren. Wenn das ideale Molekül nicht in deiner Screening Library war, konnte dir das Model nicht helfen. Die Generative AI Revolution hat diese Dynamik grundlegend auf den Kopf gestellt. Anstatt nur das zu filtern, was bereits existiert, können wir Models jetzt anweisen, völlig neue chemische Substanzen zu erfinden. Dieser Wandel von Prediction zu Creation teilt sich in zwei große molekulare generative Tasks auf: De Novo Generation und Molecular Optimization. De Novo Generation bedeutet, neuartige Molekülstrukturen von Grund auf neu zu erstellen. Das Model startet mit einer Representation von Random Noise und verfeinert diese iterativ zu einer validen chemischen Struktur. Wenn das ohne Constraints passiert, nennt man das Unconditional Generation. Das Model erkundet den riesigen chemischen Raum völlig frei, um etwas komplett Neues zu erzeugen. Das ist zwar nützlich für breite Discovery, aber meistens brauchst du mehr Kontrolle. Das bringt uns zur Conditional Generation, genauer gesagt zur Property-based Generation. Hier diktierst du den Output. Du gibst spezifische Constraints vor, wie zum Beispiel eine Target-Bioaktivität oder ein bestimmtes Level an Synthetisierbarkeit, und das Model beschränkt seine Generation auf Moleküle, die diese Kriterien erfüllen. Das wird oft als Inverse Molecule Design bezeichnet, weil du mit den gewünschten Properties startest und das Model zwingst, rückwärts zu arbeiten, um eine Molekülstruktur zu konstruieren, die diese liefert. De Novo Generation ist mächtig, aber du startest ein Projekt selten mit null Vorwissen. Meistens hast du bereits ein Lead Compound. Hier kommt Molecular Optimization ins Spiel. Im Gegensatz zu De Novo Tasks konzentriert sich Molecular Optimization darauf, eine bekannte Struktur zu modifizieren, anstatt bei null anzufangen. Du nimmst ein existierendes Molekül und verfeinerst es, um seine Properties zu verbessern. Angenommen, du hast ein mäßig wirksames Drug Scaffold. Es bindet an dein Target, aber seine Bioaktivität ist zu niedrig, um ein brauchbares Medikament zu sein. Mit einem generativen Model kannst du gezielte Molecular Optimization durchführen. Ein Ansatz ist Scaffold Hopping. Du weist das Model an, das Core Molecular Scaffold durch ein neues zu ersetzen, während die ursprüngliche biologische Aktivität erhalten bleibt. Das ist extrem effektiv, um strukturell neuartige Compounds zu entdecken, die bestehende Patente umgehen und gleichzeitig das funktionale Verhalten intakt halten. Ein anderer Ansatz ist R-Group Design. In diesem Szenario fixierst du dein Core Scaffold und weist das generative Model an, seine Side Chains automatisch zu optimieren. Das Model generiert neue R-Groups und sucht nach den spezifischen Side Chain Modifications, die diese schwächelnde Bioaktivität verbessern. Du verwirfst dein mäßig wirksames Molekül nicht, sondern lässt die AI die präzisen strukturellen Tweaks berechnen, die nötig sind, um es über die Ziellinie zu bringen. Hier ist die entscheidende Erkenntnis: Der Übergang von Predictive AI zu Generative AI bedeutet, dass du nicht mehr auf die Moleküle beschränkt bist, die du gerade zur Hand hast. Egal, ob du ein Custom-Molekül von Grund auf neu generierst oder algorithmisch die Side Chains eines bestehenden Medikaments austauschst – du behandelst den chemischen Raum als programmierbares Medium. Das war's für diese Folge. Danke fürs Zuhören und keep building!
16
Die Intuition der molekularen Diffusion
4m 08s
Wir brechen das Kernkonzept von Diffusion Models ohne schwere Mathematik herunter. Die Zuhörer werden den Vorwärtsprozess des Hinzufügens von Rauschen zu einem Molekül und den Rückwärtsprozess des Halluzinierens neuer Strukturen verstehen.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 16 von 22. Um einer AI beizubringen, wie sie ein neues Molekül erfindet, musst du ihr zuerst beibringen, wie sie eines komplett zerstört. Das wirkt komplett verkehrt, aber genau diese systematische Zerstörung ist der Mechanismus, der genutzt wird, um neuartige Medikamente from scratch zu generieren. Das ist die Kernidee von Denoising Diffusion Probabilistic Models.
Traditionelles Moleküldesign ist extrem arbeitsintensiv. Wenn du die Entdeckung neuer Verbindungen automatisieren willst, brauchst du ein Model, das einen riesigen chemischen Raum erkunden kann, ohne invaliden Nonsens zu generieren. Frühe Deep Generative Models haben versucht, diesen Raum direkt abzubilden. Denoising Diffusion Probabilistic Models, oder DDPMs, gehen einen anderen Weg. Sie behandeln die Molekülgenerierung als ein progressives Denoising-Problem.
Das Framework ist in zwei separate Markov Chains unterteilt: den Forward Process und den Reverse Process.
Beim Forward Process geht es strikt um Data Degradation. Du nimmst ein valides, bekanntes Medikament aus deinem Training Set. Über eine feste Abfolge von Steps verwischst du die Atomkoordinaten schrittweise, indem du reines Gaussian Noise injizierst. Die Menge an Noise, die in jedem Step hinzugefügt wird, wird durch einen festgelegten Hyperparameter Schedule gesteuert. In Step eins störst du die Atome nur leicht. Das Molekül ist ein bisschen verzerrt, aber immer noch klar erkennbar. Bei Step fünfzig ist die Struktur schon stark deformiert. Beim finalen Step, typischerweise als Step T bezeichnet, ist das ursprüngliche Molekül komplett verschwunden. Was dir bleibt, ist eine zufällige Wolke aus unstrukturiertem Gaussian Noise.
Dieser Forward Process braucht kein Neural Network. Es ist eine strikte mathematische Korruption. Er erfüllt einen extrem wichtigen Zweck, denn er generiert die Ground Truth für unsere Training Data.
Hier ist die entscheidende Insight: Weil wir die exakte Menge an Noise kontrolliert haben, die in jedem einzelnen Step hinzugefügt wurde, haben wir eine perfekte Step-by-Step-Aufzeichnung darüber, wie das Molekül auseinandergefallen ist.
Beim Reverse Process kommt das Neural Network ins Spiel. Das Model wird darauf trainiert, genau diesen Pfad rückwärts zu gehen. Wir füttern das Network mit einem korrumpierten Molekül an einem bestimmten Time Step. Dann lassen wir es das spezifische Noise predicten, das hinzugefügt wurde, um diesen Zustand zu erreichen. Wir evaluieren das Model, indem wir seine Noise Prediction mit dem tatsächlichen Noise vergleichen, das wir in der Forward Phase injiziert haben. Wir updaten die Model Parameters, um diese Differenz zu minimieren. Mit der Zeit lernt das Network, die Daten Step by Step zu denoisen und die ursprüngliche Data Distribution nach und nach wiederherzustellen.
Um ein komplett neues Molekül zu generieren, führst du diesen Reverse Process from scratch aus. Zuerst samplest du eine völlig zufällige Wolke aus Gaussian Noise. Dann übergibst du dieses Noise zusammen mit der Starting Step Number an dein trainiertes Neural Network. Das Network evaluiert den Input, predictet die nötige Strukturkorrektur und gibt eine etwas weniger noisy Atomwolke zurück.
Du loopst diesen Subtraction Process. Du übergibst den neuen Output für den nächsten Step nach unten wieder zurück ans Network. Mit jeder Iteration verdichtet sich die zufällige Wolke. Das Model entfernt kontinuierlich das Noise. Während du rückwärts in Richtung Step null gehst, rasten die Atomkoordinaten ein und eine valide chemische Struktur entsteht. Du ziehst ein komplett neues Molekül aus dem anfänglichen Static.
Das Model merkt sich nicht einfach nur eine Database existierender Medikamente; es lernt schlichtweg den universellen Prozess, Chaos zu entfernen, um stabile Chemie zu hinterlassen. Wenn du die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Danke fürs Zuhören und keep building!
17
Die Überbrückung von generativen 2D- und 3D-Räumen
4m 59s
Wir untersuchen, wie KI die von ihr generierten Moleküle tatsächlich darstellt. Wir vergleichen die Generierung flacher topologischer 2D-Graphen mit der Generierung komplexer geometrischer 3D-Punktwolken und die jeweiligen Herausforderungen.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 17 von 22. Es ist eine Sache, wenn ein Modell einen flachen 2D-Graphen eines Moleküls zeichnet. Ein völlig anderer Engineering-Albtraum ist es, eine stabile, geometrische 3D-Atomwolke zu generieren. Du kannst ein Generative Model eine wunderschöne 3D Point Cloud eines Wirkstoffs bauen lassen, die perfekt in eine Target Protein Pocket passt, nur um dann zuzusehen, wie das Ganze im Post-Processing zusammenfällt, weil das System nicht erraten kann, wo die eigentlichen kovalenten Bindungen hingehören. Die Lösung für diese Diskrepanz ist das Bridging von 2D und 3D Generative Spaces.
In der Generative Chemistry bestimmen die Datenmodalitäten, was dein Modell verstehen kann. Die erste Modalität ist der topologische 2D-Raum. Stell dir das wie einen Standard-Molecular-Graph vor. Nodes repräsentieren Atome mit bestimmten Typen, und Edges repräsentieren die chemischen Bindungen, die sie verbinden. Das Modell liefert als Output eine Adjacency Matrix, die dir genau sagt, was mit was verbunden ist. Graph Neural Networks können damit gut umgehen. Das Problem ist, dass Moleküle in der physischen Welt existieren und nicht auf dem Papier. Ein 2D-Graph gibt dir zwar die Bindungstopologie, aber er ignoriert die geometrische 3D-Struktur komplett. Ohne räumliche Koordinaten kannst du Quanteneigenschaften nicht präzise berechnen oder Structure-Based Drug Design durchführen.
Um das zu beheben, sind Modelle dazu übergegangen, Moleküle direkt im geometrischen 3D-Raum zu generieren. Hier ist der Output eine Point Cloud. Das Modell definiert die Atomtypen und ihre exakten X-, Y- und Z-Positionskoordinaten. Die technische Hürde dabei ist die Beibehaltung der SE 3 Equivariance, um sicherzustellen, dass das Molekül mathematisch konsistent bleibt, egal wie es im Raum rotiert oder translatiert wird. Hier ist die entscheidende Erkenntnis. Das Generieren im reinen 3D-Raum bedeutet, dass das Modell die chemischen Bindungen nicht explizit generiert. Es platziert einfach nur Atome im Raum. Du musst die Bindungstopologie danach durch Post-Processing-Algorithmen ableiten. Das führt zu massiven Fehlern. Um auf das Drug-Pocket-Szenario zurückzukommen: Dein Modell ordnet die Atome vielleicht in einer Form an, die physikalisch in das Target passt, aber weil es die Bindungstopologie während der Generation nie berücksichtigt hat, könnte der Post-Processing-Schritt unmögliche kovalente Bindungen ableiten. Bei größeren Molekülen führt das direkte Generieren einer stabilen 3D-Struktur ohne topologische Guidance oft zu einer suboptimalen Lösung.
Das bringt uns zum Generieren im 2D und 3D Joint Space, was gleichzeitig eine komplette Molekülstruktur produziert. Das Modell liefert die Atomtypen, die diskrete Adjacency Matrix für die Bindungen und die kontinuierlichen räumlichen Koordinaten alle auf einmal als Output. Durch das Bridging dieser beiden Spaces schränken und korrigieren sich die Modalitäten während des Generation-Prozesses gegenseitig. Die 2D-Topologie fungiert als Blueprint und leitet die 3D-Struktur an, um sicherzustellen, dass die räumlichen Anordnungen chemisch machbar sind. Gleichzeitig verfeinert die 3D-Geometrie den 2D-Graphen, indem sie plausible Bindungsmuster basierend auf räumlicher Nähe vorschlägt.
Die größte technische Herausforderung bei diesem Joint-Ansatz ist das Managen von zwei grundlegend unterschiedlichen Datentypen. Du zwingst das Modell, diskrete topologische Strukturen wie Bindungstypen zusammen mit kontinuierlichen geometrischen Strukturen wie Koordinatenwerten zu verarbeiten. Verschiedene Architekturen lösen das unterschiedlich. Ein Framework namens JODO behandelt sowohl die topologischen als auch die geometrischen Strukturen als kontinuierliche Variablen, um sie gemeinsam zu verarbeiten. Ein anderes Modell, MUDiff, behandelt sie separat und wendet einen diskreten Prozess für die Topologie und einen kontinuierlichen Prozess für die Geometrie an.
Du kannst nicht zuverlässig neue, funktionelle Medikamente generieren, indem du die physikalische Form errätst und hoffst, dass sich die chemischen Bindungen später von selbst ergeben. Echte Molecular Generation erfordert, dass topologisches Blueprinting und Spatial Positioning in exakt derselben Computation interagieren und sich gegenseitig ergänzen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
18
Target-Aware Generierung & Docking
4m 13s
Entdecke kontextbezogenes generatives Design. Wir diskutieren die Generierung neuartiger Moleküle direkt innerhalb der Bindungstasche eines Krankheitsproteins, um die Bindungsaffinität zu maximieren.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 18 von 22. Warum solltest du einen Algorithmus eine Million zufällige Schlüssel generieren und sie einzeln testen lassen, wenn er sich auch einfach direkt das Schloss ansehen und einen maßgeschneiderten Schlüssel direkt im Schlüsselloch schmieden könnte? Die traditionelle Wirkstoffforschung verlässt sich oft darauf, riesige Libraries von Kandidaten zu generieren und diese dann herauszufiltern, aber das verschwendet immense Rechenressourcen. Target-Aware Generation and Docking löst das, indem es die dreidimensionale Geometrie des biologischen Targets direkt nutzt, um Moleküle zu bauen oder zu platzieren.
Bei diesen generativen Tasks arbeiten wir komplett im geometrischen 3D-Raum. Target-Aware Generation, auch bekannt als Structure-Based Drug Design, baut ein neues Molekül direkt basierend auf der 3D-Struktur einer Target Binding Pocket. Nehmen wir mal ein konkretes Szenario mit einem viralen Protein. Dieses Protein hat eine hochspezifische geometrische Cavity. Anstatt Moleküle im Vakuum zu generieren, analysiert ein Conditional Diffusion Model die exakten räumlichen Grenzen und chemischen Eigenschaften dieser Cavity. Dann lässt es eine neuartige Liganden-Struktur direkt in der Pocket maßgeschneidert heranwachsen.
Das Modell startet mit einer Cloud aus noisy 3D-Koordinaten und Atomtypen, die sich innerhalb der Binding Site befinden. In aufeinanderfolgenden Schritten wird diese Cloud dann denoised. Weil die Generation auf die Target Pocket conditioned ist, platziert das Modell Atome und bildet Strukturen, die die Cavity natürlich ergänzen, mit dem Ziel, eine hohe Interaction Affinity zu garantieren. Hier ist die Key Insight: Der Algorithmus rät nicht einfach nur eine Form; er lernt explizit die räumliche Beziehung zwischen dem Target und potenziellen Bindern. Einige Ansätze integrieren sogar Interaction-Based Retrieval und ziehen Daten von bekannten High-Affinity-Liganden heran, um die Generation dieser Target-spezifischen Moleküle weiter zu steuern.
Das deckt die Generation eines komplett neuen Moleküls from scratch innerhalb einer Pocket ab. Aber oft hast du schon ein existierendes Molekül und musst genau wissen, wie es mit einem biologischen Target interagiert. Das bringt uns zum Molecular Docking.
Molecular Docking sagt die Binding Pose voraus, um Binding Affinity und Specificity zu bewerten. In einem Diffusion Framework nehmen Modelle ein bekanntes Molekül und eine Target-Struktur als Inputs. Anstatt die chemische Identität zu generieren, operiert der Diffusion Process rein auf der räumlichen Orientierung des Moleküls. Das Modell startet mit dem Liganden in einer zufälligen, noisy 3D-Pose und denoised sie iterativ. Es verfeinert die räumlichen Koordinaten des Moleküls, bis es sich in der korrekten Binding Configuration innerhalb der Protein Pocket einpendelt.
Advanced Docking Models gehen hier noch einen Schritt weiter, indem sie das Target selbst als flexible Entität behandeln. Ein Modell namens Re-Dock nutzt eine Technik namens Diffusion Bridge, um die Binding Poses des Liganden vorherzusagen und gleichzeitig die Bewegung der Pocket Sidechains zu modellieren. Das erzeugt ein realistisches, flexibles Docking-Szenario, in dem sich sowohl der Ligand als auch das Target während der Prediction Phase aneinander anpassen.
Der entscheidende Shift hier ist, dass Diffusion Models das Structural Drug Design weg von starren, isolierten Approximationen bewegt haben. Indem sowohl der generierte Ligand als auch die biologische Pocket als kontinuierliches, anpassungsfähiges geometrisches System behandelt werden, outputtet das Modell nativ Moleküle und Poses, die physikalisch in der präzisen Realität der Target-Umgebung verankert sind.
Das war's für diese Folge. Danke fürs Zuhören, und keep building!
19
Die Size Trap in der generativen Evaluierung
4m 38s
Lerne, warum Standard-Benchmarks für generative Modelle zutiefst fehlerhaft sein können. Wir enthüllen den verzerrenden Effekt der generierten Bibliotheksgröße auf Metriken wie die Fréchet ChemNet Distance.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 19 von 22. Du evaluierst dein neues generatives Chemiemodell, indem du tausend Moleküle samplest, und die Metriken sehen furchtbar aus. Generierst du hunderttausend aus genau demselben Model, sieht es plötzlich erstklassig aus. Scale verändert alles. Dieses Phänomen wird als Size Trap in der Generative Evaluation bezeichnet.
Generative Drug Discovery Pipelines durchlaufen im Allgemeinen drei Phasen. Du trainierst, du generierst und du evaluierst. Wenn Anwender die Evaluierungsphase erreichen, stehen sie vor der grundlegenden Frage, wie viele De-novo-Designs sie fürs Benchmarking generieren sollen. Standardmäßig greift man oft auf kleine Batches zurück, typischerweise tausend oder zehntausend SMILES Strings. Teams jagen diese Batches dann durch Standard Distributional Metrics. Die gebräuchlichste ist die Fréchet ChemNet Distance, oder FCD. FCD misst, wie nah deine generierten Moleküle im chemischen und biologischen Space an deinem Training Set liegen. Ein niedriger FCD Score bedeutet, dass deine generierte Distribution eng mit deiner Target Distribution übereinstimmt. Eine weitere gängige Metrik ist die Fréchet Descriptor Distance, oder FDD, die die Distribution physikochemischer Eigenschaften wie Molekulargewicht und topologischer Oberfläche vergleicht. Teams messen routinemäßig auch die Uniqueness, also den Anteil der generierten Designs, die wirklich unterschiedlich sind.
Hier ist die entscheidende Erkenntnis. All diese Metriken hängen stark von der physischen Größe der generierten Library ab. Sie messen die absolute Modellqualität nicht im luftleeren Raum. Wenn du nur tausend Moleküle samplest, sind deine FCD und FDD Scores künstlich hoch. Das Model sieht so aus, als hätte es die Target Distribution nicht gelernt. Aber wenn du weiter aus genau demselben Model samplest und die Library Size auf über zehntausend, fünfzigtausend oder hunderttausend Moleküle pushst, sinkt der FCD Score deutlich. Er sinkt immer weiter, bis er schließlich ein Plateau erreicht.
Das passiert, weil generatives Moleküldesign das Sampling aus einer hochkomplexen, gelernten Wahrscheinlichkeitsverteilung beinhaltet. Ein winziges Sample von tausend Molekülen kann die gesamte Bandbreite dieses Model Outputs nicht adäquat repräsentieren. Die Fréchet Distance Algorithmen brauchen eine massive Anzahl an Samples, um die Form des generierten Space präzise zu erfassen und mit dem Fine-Tuning Space zu vergleichen.
Stell dir ein konkretes Szenario vor, in dem du ein Recurrent Neural Network mit einem Transformer vergleichst. Wenn du das Recurrent Network mit hunderttausend Designs evaluierst, den Transformer aber nur mit zehntausend, wird das Recurrent Network wahrscheinlich deutlich überlegene FCD und FDD Scores zeigen. Der Performance Gap hat nichts mit der Architektur zu tun. Er ist rein ein Artefakt der Sample Size. Die Metriken sind für die kleinere Library noch nicht konvergiert.
Diese Falle funktioniert genau umgekehrt, wenn du dir die interne Diversity ansiehst. Uniqueness verhält sich at Scale völlig anders. Bei tausend Molekülen ist fast jeder valide SMILES String, den dein Model generiert, vielleicht unique. Das Model wirkt extrem kreativ. Aber wenn du die Generation in Richtung hunderttausend pushst, fällt die Uniqueness stark ab. Das Model fängt an, sich zu wiederholen. Wenn du verschiedene generative Modelle basierend auf Uniqueness in kleinem Scale rankst, sehen die Unterschiede zwischen ihnen minimal aus. Pushst du den Scale höher, wird der Gap zwischen den Modellen dramatisch größer. Das relative Ranking deiner Modelle wird sich tatsächlich umkehren, abhängig von der Größe der Library, die du zum Messen verwendest.
Um das zu fixen, musst du die Library Size als strikte Kontrollvariable in deiner Pipeline behandeln. Du kannst FCD, FDD oder Uniqueness niemals zuverlässig über Libraries unterschiedlicher Größe hinweg vergleichen. Um ein robustes Assessment sicherzustellen, solltest du Libraries mit mindestens hunderttausend Designs evaluieren, damit die Distributional Metrics vollständig konvergieren. Wenn sich deine Evaluation Metrics nur deshalb ändern, weil du den Sampling Loop länger laufen lässt, misst du die Size des Samples und nicht die Intelligenz des Models. Das war's für diese Folge. Danke fürs Zuhören und keep building!
20
Navigieren durch De-Novo-Halluzinationen
4m 25s
Bewerte KI-generierte Moleküle intelligent. Wir untersuchen den Exploration-Exploitation-Tradeoff von Modellwahrscheinlichkeiten und wie man häufige, qualitativ minderwertige 'chemische Halluzinationen' herausfiltert.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 20 von 22. Nur weil eine generative AI ein bestimmtes Molekül zehntausendmal ausspuckt, heißt das nicht, dass es ein brauchbares Medikament ist. Du denkst vielleicht, die Generierungshäufigkeit steht für chemische Qualität oder Relevanz. Tut sie aber nicht. Diese extrem häufigen Outputs sind oft das chemische Äquivalent eines Large Language Models, das halluziniert. Der Mechanismus, um das zu lösen, besteht darin, De-novo-Halluzinationen mithilfe der Model Likelihood zu navigieren.
Wenn du eine riesige Library von einer Million SMILES Strings aus einem fine-getunten Chemical Language Model generierst, musst du entscheiden, welche Moleküle du für zukünftige Studien priorisierst. Ein fehlerhafter Standardansatz ist es, einfach die Designs auszuwählen, die das Model am häufigsten ausgibt. Das führt zu einer sogenannten Count Trap. Anstatt robuste Wirkstoffkandidaten zu entdecken, extrahierst du am Ende nur einfache, sich wiederholende Substrukturen wie isolierte Benzolringe, simple Amine und einfache Ether. Das sind wiederkehrende strukturelle Halluzinationen. Das Model generiert sie ständig – nicht, weil sie von hoher Qualität sind, sondern weil sie syntaktisch einfach zu konstruieren sind.
Um diese Halluzinationen aufzudecken und herauszufiltern, evaluierst du deine Library mithilfe der Model Likelihood. Likelihood ist eine Metrik, die erfasst, wie gut eine generierte Sequenz mit der Probability Distribution übereinstimmt, die das Model während des Trainings gelernt hat. Für ein autoregressives Model berechnest du das, indem du die Sampling Probability jedes einzelnen Tokens im generierten SMILES String multiplizierst. Zuerst berechnest du den Likelihood Score für alle eine Million generierten Designs. Als Nächstes sortierst du die gesamte Library basierend auf diesen Scores. Schließlich teilst du die sortierte Library in zehn gleich große Gruppen, also Dezile, auf – von der niedrigsten bis zur höchsten Likelihood.
Hier wird es interessant. Die Analyse dieser Dezile offenbart einen strikten Exploration-Exploitation-Trade-off. Das zehnte Dezil enthält die Generierungen mit der höchsten Likelihood. Diese Designs repräsentieren Exploitation. Sie haben eine extrem hohe chemische Validität, und ihre generischen Bemis-Murcko-Scaffolds stimmen stark mit den bekannten aktiven Molekülen aus deinen Trainingsdaten überein. Das Model nutzt massiv das aus, wovon es bereits weiß, dass es funktioniert. Der Nachteil ist, dass es diesen Top-Tier-Designs an Novelty fehlt. Sie enthalten nur sehr wenige neue Substrukturen, weil das Model auf Nummer sicher geht.
Wenn du zu den mittleren Dezilen runtergehst, triffst du auf eine Balance. Novelty und einzigartige Substrukturen erreichen in diesem mittleren Bereich ihren Höhepunkt, während die Validität akzeptabel bleibt. Aber wenn du zum ersten Dezil runtergehst – den zehn Prozent der Moleküle mit den absolut niedrigsten Likelihood Scores –, landest du in der Count Trap. Wenn du die Designs isolierst, die das Model im gesamten Run mit einer Million Molekülen mehr als zehnmal generiert hat, clustern diese fast alle in diesem untersten Dezil. Sie haben unglaublich niedrige Model Likelihoods, tauchen aber mit massiver Häufigkeit auf. Ihre strukturelle Ähnlichkeit zu deinem Training Set ist furchtbar, und ihre allgemeine chemische Validität bricht komplett ein.
Indem du deine Library auf diese Weise in Bins unterteilst, beweist du mathematisch, dass Häufigkeit ein falsches Signal für Qualität ist. Du kannst die Low-Likelihood-, High-Frequency-Bins systematisch verwerfen und dein Computational Screening auf die mittleren Dezile fokussieren, in denen echte chemische Exploration stattfindet. Die häufigsten Outputs eines generativen chemischen Models sind oft seine schlechtesten, aber wenn du deine Library nach Likelihood-Dezilen filterst, verwandelst du dieses Noise in eine präzise Karte, die zeigt, wo das Model exploriert und wo es nur halluziniert.
Das war's für diese Folge. Danke fürs Zuhören und keep building!
21
Einschränkungen beim Molecule Sampling
4m 52s
Verstehe, warum NLP-Techniken in der Chemie versagen. Wir vergleichen Temperature Sampling mit Top-k und Top-p und erklären, warum das eingeschränkte chemische Vokabular alles verändert.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 21 von 22. Beim Natural Language Processing erzeugt Top-p Sampling brillant kreative Texte. Aber wenn du genau dieselbe Logik auf die Generierung von Molekülen anwendest, wird deine AI einfach für immer identische Kohlenstoffringe ausgeben. Der Grund dafür liegt in den Molecule Sampling Constraints.
Wenn ein chemisches Language Model einen SMILES-String generiert, baut es das Molekül Token für Token auf. Das Modell sagt eine Wahrscheinlichkeitsverteilung für das nächste Token voraus, und du musst eine bestimmte Auswahl aus dieser Verteilung extrahieren. Bei der Textgenerierung verlassen sich Entwickler stark auf Top-k und Top-p Sampling, um diese Wahl zu treffen. Top-k beschränkt das Modell auf die absolut wahrscheinlichsten k Tokens. Top-p beschränkt die Auswahl auf die kleinste Gruppe von Tokens, deren kombinierte Wahrscheinlichkeiten einen Ziel-Prozentsatz p überschreiten.
Wenn du diese Methoden auf ein chemisches Language Model anwendest, schlagen sie katastrophal fehl. Wenn du Top-k Sampling mit k gleich 3 auf ein LSTM anwendest, das auf Drug Targets trainiert wurde, wird dein Modell einen schweren Mode Collapse erleben. Es wird chemisch gültige Moleküle ausgeben, aber sie werden komplett repetitiv sein.
Hier ist die entscheidende Erkenntnis. Das Scheitern liegt an der Größe des chemischen Vokabulars. Ein Textmodell wählt aus Hunderttausenden von Wörtern. Ein chemisches Language Model nutzt ein stark eingeschränktes Alphabet. Es hat nur eine Handvoll Elemente wie Kohlenstoff, Sauerstoff und Stickstoff, plus Syntax-Tokens für Verzweigungen und Ringschlüsse.
Weil das chemische Alphabet winzig ist und weil gültige Chemie strenge Syntaxregeln erfordert, wie das Schließen jedes offenen Rings, dominiert eine sehr kleine Teilmenge von Tokens die Wahrscheinlichkeitsverteilung absolut. Kohlenstoff und grundlegende Struktur-Tokens sind fast immer extrem wahrscheinlich. Wenn du Top-k oder Top-p Sampling anwendest, schneidest du den Long Tail der Wahrscheinlichkeitsverteilung ab. Das Modell wird gezwungen, ausschließlich aus diesem schmalen Band dominanter Tokens auszuwählen. Es verfängt sich in einer Filterfalle und wiederholt endlos exakt dieselben Basic Scaffolds.
Um dieser Falle zu entkommen, musst du Temperature Sampling verwenden. Anstatt Tokens herauszufiltern, wendet Temperature Sampling einen Smoothing-Parameter auf die rohen Neural Network Scores an, bevor die finalen Wahrscheinlichkeiten berechnet werden. Das verändert die Form der gesamten Verteilung.
Stell dir ein Szenario vor, in dem du ein fine-getuntes LSTM-Modell laufen lässt, um neue Drug Candidates zu generieren. Du passt den Temperature-Parameter T an, um den Trade-off zwischen Validität und Diversität einzustellen. Wenn du T niedrig ansetzt, so um die 0,5, bildet die Wahrscheinlichkeitsverteilung einen scharfen Peak. Das Modell nutzt die wahrscheinlichsten Tokens stark aus. Dein Output wird eine extrem hohe chemische Validität aufweisen, aber den Strukturen wird es an Neuartigkeit fehlen. Sie werden das Training Set stark imitieren.
Wenn du T auf 1,5 oder 2,0 erhöhst, flachst du die Wahrscheinlichkeitsverteilung ab. Jetzt haben die weniger wahrscheinlichen Tokens eine mathematische Chance, gesampelt zu werden. Dein Modell beginnt, neuen Chemical Space zu erkunden. Die Anzahl einzigartiger Substrukturen in deiner generierten Library schießt in die Höhe. Du findest extrem neuartige Moleküle. Der Trade-off ist, dass höhere Temperatures die Randomness erhöhen, was dazu führt, dass das Modell mehr Syntaxfehler macht, was den Gesamtprozentsatz an validen SMILES-Strings reduziert.
Du kannst Textgenerierungs-Strategien nicht blind ins Molecular Design portieren. Weil das chemische Vokabular von Natur aus eingeschränkt ist, bleibt Temperature Scaling der effektivste Hebel, um strenge chemische Validität mit der Exploration neuartiger Strukturen auszubalancieren.
Danke fürs Zuhören. Ich hoffe, du hast etwas Neues mitgenommen.
22
Bereitstellung von Cheminformatik in der Cloud
4m 10s
Bringe deine KI-Pipeline in die Produktion. Wir diskutieren das Verpacken von RDKit und Machine-Learning-Modellen in Docker-Container und die Skalierung von Workloads über eine Cloud-Infrastruktur.
Hallo, hier ist Alex von DEV STORIES DOT EU. Python Cheminformatics & AI, Folge 22 von 22. Du hast eine hochmoderne AI Drug Discovery Pipeline auf deinem Laptop gebaut, aber wie screenst du eine Milliarde Moleküle übers Wochenende? Die Antwort lautet: Cheminformatics in der Cloud deployen.
Ein Model von einer lokalen Umgebung in eine verteilte Cloud Architecture zu verschieben, scheitert meistens am Dependency Layer. RDKit ist keine reine Python Library. Es ist eine große C++ Codebase, die System-Level Dependencies erfordert, allen voran die Boost C++ Libraries. Wenn du generische Cloud Server provisionierst und Standard-Installationsskripte ausführst, stößt du oft auf Compiler-Fehler oder fehlende Shared Object Files. Die offizielle RDKit Documentation betont, dass ein Build from Source eine spezifische C++ Toolchain erfordert. Zwar gibt es pre-compiled pip Wheels, aber der robusteste Weg, um sicherzustellen, dass alle zugrundeliegenden Dependencies zusammenpassen, ist die Nutzung von Conda. Conda jedoch dynamisch auf Tausenden von temporären Cloud Workern zu installieren, kostet zu viel Zeit und bringt Netzwerkinstabilität beim Scale-up mit sich.
Hier ist die entscheidende Erkenntnis. Du umgehst das Dependency-Problem komplett, indem du deine Pipeline in einen Docker Container wrappst. Du schreibst ein Config File, das ein Base OS festlegt. In diesem Container installierst du ein leichtgewichtiges Conda Environment, pullst die kompilierten RDKit Binaries und fügst deine Machine Learning Frameworks wie PyTorch oder XGBoost hinzu. Zum Schluss kopierst du deine pre-trained Model Weights in das Image. Das Builden dieses Images friert den gesamten Stack in ein einziges, unveränderliches Artefakt ein. Der Cloud Provider muss nur wissen, wie man einen Standard Docker Container ausführt. Die komplexen C++ Dependencies sind sicher darin eingeschlossen.
Um Millionen von Molekülen zu verarbeiten, trennst du deinen Data Flow von deinen Compute Workern, indem du eine Cloud Message Queue nutzt. Du partitionierst deinen riesigen Dataset aus SMILES Strings in kleinere, handhabbare Chunks. Du legst diese Chunks in einem Cloud Object Storage ab und sendest eine Message mit der Chunk Location an die Queue.
Dann richtest du einen skalierbaren Cloud Compute Service auf diese Queue. Für schwere, GPU-beschleunigte Workloads deployst du deinen Container über einen Service wie AWS Batch. Für leichtere, CPU-basierte Inference übernehmen Serverless Container Plattformen wie Google Cloud Run oder AWS Lambda das perfekt. Du konfigurierst den Compute Service so, dass er basierend auf der Queue Depth automatisch skaliert. Wenn fünfzigtausend Messages warten, startet der Cloud Controller tausende identische Docker Container gleichzeitig.
Jeder Container verbindet sich mit der Queue und claimt eine Message. Er lädt den entsprechenden Chunk an SMILES Strings herunter. RDKit konvertiert die SMILES in Molecular Graphs, berechnet die benötigten Descriptors und übergibt sie an dein Machine Learning Model für die Inference. Der Container schreibt die Molecules mit dem höchsten Score direkt in eine Managed Cloud Database. Sobald der Chunk verarbeitet ist, löscht der Worker die Message aus der Queue und schnappt sich die nächste. Wenn die Queue leer ist, terminiert die Cloud Infrastructure die Container automatisch. Du zahlst nur für die exakten Compute Seconds, die dein Code tatsächlich verbraucht hat.
Beim Skalieren von Cheminformatics geht es selten darum, schnellere Loop Structures in Python zu schreiben; es geht darum, dein Environment zuverlässig zu packagen und eine decoupled Cloud Architecture zu nutzen, um Daten parallel zu verarbeiten. Das schließt unsere Serie über Python Cheminformatics und AI ab. Ich empfehle dir, die offizielle RDKit Documentation zur Installation zu lesen, das Containerisieren eines einfachen Scripts hands-on auszuprobieren oder devstories dot eu zu besuchen, um Themen für zukünftige Serien vorzuschlagen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
Tap to start playing
Browsers block autoplay
Share this episode
Episode
—
Copy this episode in another language:
Diese Website verwendet keine Cookies. Unser Hosting-Anbieter protokolliert möglicherweise deine IP-Adresse zu Analysezwecken. Mehr erfahren.