<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Tiny Lab BioML</title>
<link>https://tiny-lab-bioml.netlify.app/</link>
<atom:link href="https://tiny-lab-bioml.netlify.app/index.xml" rel="self" type="application/rss+xml"/>
<description>A blog about bioinformatics, machine learning, and drug discovery.</description>
<generator>quarto-1.8.26</generator>
<lastBuildDate>Fri, 24 Jul 2026 07:00:00 GMT</lastBuildDate>
<item>
  <title>From Fingerprints to Message Passing: Benchmarking Three Approaches to Molecular Toxicity Prediction on Tox21</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/</link>
  <description><![CDATA[ 





<section id="summary" class="level1">
<h1>Summary</h1>
<p>In this post, I compare three approaches to predicting chemical toxicity directly from molecular structure, using the Tox21 dataset (~7,800 compounds tested across 12 nuclear receptor and stress-response assays). The first is a Random Forest trained on molecular fingerprints, a standard cheminformatics baseline. The second is a Graph Neural Network (GINE) built from scratch that learns directly from atoms and bonds. The third is Chemprop, a widely-used graph neural network package, combined with RDKit 2D molecular descriptors. All three models are evaluated using a scaffold split, which keeps structurally similar molecules out of both the training and test sets for a more realistic test of generalization to new chemical structures. All three models achieve similar performance that aligns with previous literature benchmarks. I also walk through a real numerical pitfall with RDKit descriptors that can silently corrupt training, and use t-SNE to check whether the learned graph representations capture meaningful chemical structure.</p>
</section>
<section id="introduction" class="level1">
<h1>Introduction</h1>
<p>Tox21 is a multi-task binary classification dataset for predicting the toxicity of chemical compounds. The dataset contains 12 different toxicity tasks, each corresponding to a specific biological target or pathway. The goal is to predict whether a given compound is toxic or non-toxic for each of these tasks. Each compound is represented by its SMILES string (Chemprop additionally uses RDKit 2D descriptors as extra molecule-level features, described in Model 3). The dataset is highly imbalanced, with some tasks having very few positive examples (3-15% positive rates). There are also many missing labels. This provides a challenge for training machine learning models. We will tackle these problems by using specific metrics and loss function as described later.</p>
<p>Three models to train:</p>
<ol type="1">
<li><p><strong>Random Forest (RF) with ECFP2048 (Morgan fingerprints) as input features</strong>: this is considered as a baseline model with classical machine learning approach trained on molecular fingerprints. The RF model will be well-tuned with hyperparameter search and cross-validation.</p></li>
<li><p><strong>GINE (Graph Isomorphism Network with Edge features), trained directly on atom- and bond-level graph features</strong>: GIN or GINE is a type of Graph Neural Network (GNN) with message-passing similar to a Graph Convolution Network (GCN). Unlike GCN, which combines messages by averaging neighbors’ embeddings, GINE sums the neighboring messages instead, which better preserves information about the number of neighbors a node has. This allows for better differentiation of certain non-isomorphic graphs than GCN. For an introduction into GIN vs GCN, see the <a href="https://projects.volkamerlab.org/teachopencadd/talktorials/T035_graph_neural_networks.html#GIN">TeachOpenCADD GNN tutorial</a>. The GINE model will be built from scratch using PyG’s <code>GINEConv</code> - a variant of GIN that includes both node and edge features during the message-passing steps (a typical GIN only calculates node features). This allows for learning of molecular properties from both atom and bond features from the compounds. I will be using the PyTorch Geometric (PyG) library to build the GINE model from scratch.</p></li>
<li><p><strong>Chemprop (D-MPNN), trained on the molecular graph plus RDKit 2D (whole-molecule) descriptors as extra features</strong>: Chemprop is a high-level library for building and training D-MPNN (Directed Message Passing Neural Network) models to predict molecular properties. D-MPNN passes messages along directed bonds and explicitly excludes the reverse-direction message when aggregating each edge’s update, avoiding the “tottering” problem (a signal bouncing immediately back to the atom it came from). D-MPNN has been shown to perform well on larger industrial proprietary datasets. Chemprop combines D-MPNN with a feed-forward neural network (FFNN) that takes in additional molecular features, such as RDKit 2D features, to improve the model’s performance. Chemprop abstracts away the details of building and training D-MPNN models, making it easier to use. I will be using Chemprop’s Python-first API that is built on PyTorch Lightning to train the D-MPNN model.</p></li>
</ol>
<p>To prevent data leakage, a scaffold split will be performed on the Tox21 dataset, which ensures that structurally related molecules do not end up in different partitions (train/validation/test). This is important because if structurally similar molecules are present in both training and test sets, the model may perform well on the test set simply because it has seen similar molecules during training, rather than learning to generalize to unseen molecules.</p>
<p>The final performance of each model will be summarized using AUROC, AUPRC and binary cross-entropy (BCE) loss. It is important to note that the RF model will be well-tuned with hyperparameter search and cross-validation, while the GINE and Chemprop models will be trained once with pre-selected hyperparameters. The learned graph-level embeddings from the GINE and Chemprop models will be visualized using t-SNE to see if the embeddings capture any meaningful chemical and predictive properties in the data.</p>
</section>
<section id="data-processing" class="level1">
<h1>Data processing</h1>
<p>Loading required libraries and setting up the environment:</p>
<div id="f2395524" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb1-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.nn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> nn</span>
<span id="cb1-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.nn.functional <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> F</span>
<span id="cb1-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch_geometric.data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Data, Dataset</span>
<span id="cb1-10"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch_geometric.loader <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DataLoader <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> PyGDataLoader</span>
<span id="cb1-11"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch_geometric.nn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> GINEConv, global_mean_pool, global_max_pool</span>
<span id="cb1-12"></span>
<span id="cb1-13"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rdkit <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Chem</span>
<span id="cb1-14"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rdkit.Chem <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Descriptors, Crippen, rdMolDescriptors, rdFingerprintGenerator</span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.ensemble <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomForestClassifier</span>
<span id="cb1-17"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomizedSearchCV, StratifiedKFold</span>
<span id="cb1-18"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> roc_auc_score, average_precision_score, log_loss</span>
<span id="cb1-19"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.manifold <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> TSNE</span>
<span id="cb1-20"></span>
<span id="cb1-21"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> rdkit.Chem.Scaffolds <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> MurckoScaffold</span>
<span id="cb1-22"></span>
<span id="cb1-23"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> lightning <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pytorch <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pl</span>
<span id="cb1-24"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> lightning.pytorch.callbacks <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> EarlyStopping, ModelCheckpoint, LearningRateMonitor</span>
<span id="cb1-25"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> lightning.pytorch.loggers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CSVLogger</span>
<span id="cb1-26"></span>
<span id="cb1-27"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> chemprop <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> cp_data</span>
<span id="cb1-28"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> chemprop <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> featurizers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> cp_featurizers</span>
<span id="cb1-29"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> chemprop <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> models <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> cp_models</span>
<span id="cb1-30"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> chemprop <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> nn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> cp_nn</span>
<span id="cb1-31"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> chemprop <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> utils <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> cp_utils</span>
<span id="cb1-32"></span>
<span id="cb1-33">DEVICE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb1-34">SEED <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span></span>
<span id="cb1-35">np.random.seed(SEED)</span>
<span id="cb1-36">torch.manual_seed(SEED)</span></code></pre></div></div>
</details>
</div>
<section id="scaffold-split" class="level2">
<h2 class="anchored" data-anchor-id="scaffold-split">Scaffold split</h2>
<p>The following functions generate Bemis-Murcko scaffolds and perform the scaffold split on the Tox21 dataset:</p>
<div id="0d923b21" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> generate_scaffold(smiles, include_chirality<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>):</span>
<span id="cb2-2">    mol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chem.MolFromSmiles(smiles)</span>
<span id="cb2-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> MurckoScaffold.MurckoScaffoldSmiles(mol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>mol, includeChirality<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>include_chirality)</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> scaffold_split(smiles_list, frac_train<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, frac_valid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, frac_test<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SEED):</span>
<span id="cb2-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Bemis-Murcko scaffold split: group molecules by scaffold, assign whole groups to</span></span>
<span id="cb2-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    train/valid/test (largest groups first into train), so structurally related molecules</span></span>
<span id="cb2-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    never end up split across partitions. Equivalent to DeepChem's ScaffoldSplitter.</span></span>
<span id="cb2-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(frac_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> frac_valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> frac_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-6</span></span>
<span id="cb2-12">    rng <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.RandomState(seed)</span>
<span id="cb2-13"></span>
<span id="cb2-14">    scaffold_to_indices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb2-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> idx, smi <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(smiles_list):</span>
<span id="cb2-16">        scaffold <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> generate_scaffold(smi)</span>
<span id="cb2-17">        scaffold_to_indices.setdefault(scaffold, []).append(idx) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># e.g. {"c1ccccc1": [0, 2], "c1ccncc1": [1]}</span></span>
<span id="cb2-18"></span>
<span id="cb2-19">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Shuffle within same-size groups for reproducible tie-breaking, then sort by group</span></span>
<span id="cb2-20">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># size descending (largest scaffold groups placed first).</span></span>
<span id="cb2-21">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(scaffold_to_indices.values())</span>
<span id="cb2-22">    rng.shuffle(groups)</span>
<span id="cb2-23">    groups.sort(key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>, reverse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb2-24"></span>
<span id="cb2-25">    n_total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(smiles_list)</span>
<span id="cb2-26">    n_train_cutoff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> frac_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_total</span>
<span id="cb2-27">    n_valid_cutoff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (frac_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> frac_valid) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n_total</span>
<span id="cb2-28"></span>
<span id="cb2-29">    train_idx, valid_idx, test_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], [], []</span>
<span id="cb2-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> group <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups:</span>
<span id="cb2-31">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_idx) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(group) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_train_cutoff:</span>
<span id="cb2-32">            train_idx.extend(group)</span>
<span id="cb2-33">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_idx) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(valid_idx) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(group) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> n_valid_cutoff:</span>
<span id="cb2-34">            valid_idx.extend(group)</span>
<span id="cb2-35">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb2-36">            test_idx.extend(group)</span>
<span id="cb2-37"></span>
<span id="cb2-38">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(train_idx), np.array(valid_idx), np.array(test_idx)</span>
<span id="cb2-39"></span>
<span id="cb2-40">TOX21_TASKS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb2-41">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-AR'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-AR-LBD'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-AhR'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-Aromatase'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-ER'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-ER-LBD'</span>,</span>
<span id="cb2-42">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'NR-PPAR-gamma'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SR-ARE'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SR-ATAD5'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SR-HSE'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SR-MMP'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SR-p53'</span></span>
<span id="cb2-43">]</span>
<span id="cb2-44">N_TASKS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(TOX21_TASKS)</span>
<span id="cb2-45">TOX21_URL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://deepchemdata.s3-us-west-1.amazonaws.com/datasets/tox21.csv.gz"</span></span>
<span id="cb2-46"></span>
<span id="cb2-47">raw_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(TOX21_URL, compression<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gzip"</span>)</span>
<span id="cb2-48"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"raw rows:"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(raw_df))</span>
<span id="cb2-49"></span>
<span id="cb2-50"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Drop the small number of molecules RDKit can't parse (invalid valence etc.)</span></span>
<span id="cb2-51">parses_ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> raw_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smiles"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> s: Chem.MolFromSmiles(s) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span>
<span id="cb2-52"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">dropping </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>parses_ok)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> unparseable SMILES out of </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(raw_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb2-53">raw_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> raw_df[parses_ok].reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb2-54"></span>
<span id="cb2-55">all_smiles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> raw_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smiles"</span>].values</span>
<span id="cb2-56">y_all <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> raw_df[TOX21_TASKS].values.astype(np.float32)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NaN where missing</span></span>
<span id="cb2-57">w_all <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>np.isnan(y_all)).astype(np.float32)            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1 = present, 0 = missing</span></span>
<span id="cb2-58">y_all <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.nan_to_num(y_all, nan<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># garbage fill where w==0</span></span>
<span id="cb2-59"></span>
<span id="cb2-60">train_idx, val_idx, test_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scaffold_split(all_smiles, frac_train<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, frac_valid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, frac_test<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SEED)</span>
<span id="cb2-61"></span>
<span id="cb2-62"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> subset(idx):</span>
<span id="cb2-63">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> all_smiles[idx], y_all[idx], w_all[idx]</span>
<span id="cb2-64"></span>
<span id="cb2-65">train_smiles, y_train, w_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subset(train_idx)</span>
<span id="cb2-66">val_smiles,   y_val,   w_val   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subset(val_idx)</span>
<span id="cb2-67">test_smiles,  y_test,  w_test  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subset(test_idx)</span>
<span id="cb2-68"></span>
<span id="cb2-69"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">train / val / test molecules: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_smiles)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> / </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_smiles)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> / </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(test_smiles)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>dropping 8 unparseable SMILES out of 7831

train / val / test molecules: 6258 / 782 / 783</code></pre>
</section>
<section id="eda" class="level2">
<h2 class="anchored" data-anchor-id="eda">EDA</h2>
<p>To get a quick overview of the dataset, we can visualize the missing-label rate and positive-class rate for each task in the training set:</p>
<div id="d8f733e7" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Quick EDA: missing-label rate and positive-class rate per task (on non-missing labels)</span></span>
<span id="cb4-2">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb4-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(TOX21_TASKS):</span>
<span id="cb4-4">    mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> w_train[:, i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb4-5">    missing_rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mask.mean()</span>
<span id="cb4-6">    pos_rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_train[mask, i].mean() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> np.nan</span>
<span id="cb4-7">    rows.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"task"</span>: t, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"missing_rate_train"</span>: missing_rate, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"positive_rate_train"</span>: pos_rate})</span>
<span id="cb4-8">eda_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(rows).set_index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"task"</span>)</span>
<span id="cb4-9"></span>
<span id="cb4-10">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb4-11">eda_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"missing_rate_train"</span>].plot.barh(ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>)</span>
<span id="cb4-12">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Missing-label rate per task (train)"</span>)</span>
<span id="cb4-13">eda_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"positive_rate_train"</span>].plot.barh(ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"indianred"</span>)</span>
<span id="cb4-14">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Positive-class rate per task (train, non-missing only)"</span>)</span>
<span id="cb4-15">plt.tight_layout()</span>
<span id="cb4-16">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic1.png" class="img-fluid"> As we can see, the Tox21 dataset is highly imbalanced, with some tasks having very few positive examples. There are also many missing labels. We will deal with these problems by including metrics that are robust to class imbalance (AUPRC) and by using a loss function that ignores missing labels. To that end, both AUROC and AUPRC will be computed per task and then macro-averaged across tasks. The loss function will be a masked binary cross-entropy loss, which ignores missing labels during training.</p>
</section>
</section>
<section id="model-1-random-forest" class="level1">
<h1>Model 1: Random Forest</h1>
<section id="extracting-ecfp2048-features" class="level2">
<h2 class="anchored" data-anchor-id="extracting-ecfp2048-features">Extracting ECFP2048 features</h2>
<p>ECFP2048, which is also known as Morgan fingerprints with radius 2, is a widely used molecular fingerprint representation in cheminformatics. It captures the presence of substructures in molecules and is particularly useful for machine learning tasks involving chemical data. Here we will use the bit vector representation of ECFP2048 as input features for a Random Forest classifier. Since Tox21 is a multi-task dataset with missing labels for some tasks, we will train 12 independent Random Forest classifiers, one for each task. Each classifier will be trained only on the rows where that task’s label is present.</p>
<div id="5bc09693" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ecfp_features(smiles_list, radius<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, n_bits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2048</span>):</span>
<span id="cb5-2">    morgan_gen <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rdFingerprintGenerator.GetMorganGenerator(radius<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>radius, fpSize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_bits)</span>
<span id="cb5-3">    fps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros((<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(smiles_list), n_bits), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.float32) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (N, 2048)</span></span>
<span id="cb5-4">    valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.ones(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(smiles_list), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (N,) of True</span></span>
<span id="cb5-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, smi <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(smiles_list):</span>
<span id="cb5-6">        mol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chem.MolFromSmiles(smi)</span>
<span id="cb5-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> mol <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb5-8">            valid[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="cb5-9">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb5-10">        fps[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> morgan_gen.GetFingerprintAsNumPy(mol).astype(np.float32)</span>
<span id="cb5-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fps, valid</span>
<span id="cb5-12"></span>
<span id="cb5-13">X_train_ecfp, valid_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ecfp_features(train_smiles)</span>
<span id="cb5-14">X_val_ecfp,   valid_val   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ecfp_features(val_smiles)</span>
<span id="cb5-15">X_test_ecfp,  valid_test  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ecfp_features(test_smiles)</span>
<span id="cb5-16"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ECFP2048 feature matrices:"</span>, X_train_ecfp.shape, X_val_ecfp.shape, X_test_ecfp.shape)</span>
<span id="cb5-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Unparseable SMILES (train/val/test):"</span>, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>valid_train).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(), (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>valid_val).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(), (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>valid_test).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>())</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>ECFP2048 feature matrices: (6258, 2048) (782, 2048) (783, 2048)
Unparseable SMILES (train/val/test): 0 0 0</code></pre>
</section>
<section id="model-training-and-evaluation" class="level2">
<h2 class="anchored" data-anchor-id="model-training-and-evaluation">Model training and evaluation</h2>
<div id="8b0d8325" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> scipy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> stats</span>
<span id="cb7-2"></span>
<span id="cb7-3">RF_PARAM_DIST <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb7-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_estimators"</span>: stats.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>),</span>
<span id="cb7-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_depth"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>], <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep a depth cap in the mix — controls fit time, tree size, and overfitting</span></span>
<span id="cb7-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_features"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sqrt"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log2"</span>],</span>
<span id="cb7-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"class_weight"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"balanced"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>], <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># RF's class weight balancing for imbalanced target</span></span>
<span id="cb7-8">}</span>
<span id="cb7-9"></span>
<span id="cb7-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit_rf_for_task(X_tr, y_tr, mask_tr, n_iter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SEED, refit_metric<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"average_precision"</span>):</span>
<span id="cb7-11">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mask_tr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb7-12">    X, y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_tr[m], y_tr[m].astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb7-13">    cv_splitter <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StratifiedKFold(n_splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seed)</span>
<span id="cb7-14">    scoring <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"roc_auc"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"roc_auc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"average_precision"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"average_precision"</span>} <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># both AUROC and AUPRC due to imbalanced data</span></span>
<span id="cb7-15">    search <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RandomizedSearchCV(</span>
<span id="cb7-16">        RandomForestClassifier(random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seed, n_jobs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># single-threaded trees — avoids oversubscription (if -1 will be very slow)</span></span>
<span id="cb7-17">        param_distributions<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RF_PARAM_DIST,</span>
<span id="cb7-18">        n_iter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_iter, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_splitter, scoring<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>scoring,</span>
<span id="cb7-19">        refit<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>refit_metric, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seed, n_jobs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># parallelism lives here instead</span></span>
<span id="cb7-20">    )</span>
<span id="cb7-21">    search.fit(X, y)</span>
<span id="cb7-22">    best_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> search.best_index_</span>
<span id="cb7-23">    cv_auroc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> search.cv_results_[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_test_roc_auc"</span>][best_idx]</span>
<span id="cb7-24">    cv_auprc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> search.cv_results_[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_test_average_precision"</span>][best_idx]</span>
<span id="cb7-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> search.best_estimator_, search.best_params_, cv_auroc, cv_auprc</span>
<span id="cb7-26"></span>
<span id="cb7-27">rf_models, rf_best_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}, {}</span>
<span id="cb7-28"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, task <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(TOX21_TASKS):</span>
<span id="cb7-29">    model, params, cv_auroc, cv_auprc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf_for_task(X_train_ecfp, y_train[:, i], w_train[:, i])</span>
<span id="cb7-30">    rf_models[task] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model</span>
<span id="cb7-31">    rf_best_params[task] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> params</span>
<span id="cb7-32">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>task<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">] CV auroc=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_auroc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.3f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> auprc=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_auprc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.3f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | best params: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>params<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<div id="19f13798" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">rf_best_params_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(rf_best_params).T</span>
<span id="cb8-2">rf_best_params_df.index.name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tasks"</span></span>
<span id="cb8-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(rf_best_params_df)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>              class_weight max_depth max_features n_estimators
tasks                                                         
NR-AR                 None        20         log2          396
NR-AR-LBD         balanced        20         sqrt          333
NR-AhR                None        30         log2          231
NR-Aromatase          None        20         log2          396
NR-ER             balanced        20         sqrt          333
NR-ER-LBD         balanced        30         sqrt          228
NR-PPAR-gamma         None        30         log2          231
SR-ARE            balanced      None         sqrt          393
SR-ATAD5              None        20         log2          399
SR-HSE                None        30         sqrt          260
SR-MMP            balanced      None         sqrt          393
SR-p53                None        30         log2          231</code></pre>
<p>Now evaluate the Random Forest models on the validation and test sets, computing AUROC, AUPRC, and binary cross-entropy (BCE) per task, and then macro-averaging across tasks:</p>
<div id="ea77ba7c" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> masked_task_metrics(y_true_2d, y_prob_2d, w_2d, task_names):</span>
<span id="cb10-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb10-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Output metrics for multi-label binary classification.</span></span>
<span id="cb10-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    y_prob_2d: prediction probability (not logits)</span></span>
<span id="cb10-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    w_2d: 1=present, 0=missing</span></span>
<span id="cb10-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    task_names: list of task names</span></span>
<span id="cb10-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Returns: </span></span>
<span id="cb10-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      df: metrics per task</span></span>
<span id="cb10-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      macro: macro-averaged metrics</span></span>
<span id="cb10-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb10-11">    rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb10-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(task_names):</span>
<span id="cb10-13">        m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> w_2d[:, i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb10-14">        yt, yp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_true_2d[m, i], y_prob_2d[m, i]</span>
<span id="cb10-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> m.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(np.unique(yt)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb10-16">            rows.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"task"</span>: t, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_not_missing"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(m.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auroc"</span>: np.nan, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auprc"</span>: np.nan, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bce"</span>: np.nan})</span>
<span id="cb10-17">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb10-18">        eps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-7</span></span>
<span id="cb10-19">        yp_clip <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.clip(yp, eps, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> eps) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># clip to prevent log(0)</span></span>
<span id="cb10-20">        rows.append({</span>
<span id="cb10-21">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"task"</span>: t, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_not_missing"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(m.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()),</span>
<span id="cb10-22">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auroc"</span>: roc_auc_score(yt, yp),</span>
<span id="cb10-23">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auprc"</span>: average_precision_score(yt, yp),</span>
<span id="cb10-24">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bce"</span>: log_loss(yt, yp_clip, labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]),</span>
<span id="cb10-25">        })</span>
<span id="cb10-26">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(rows).set_index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"task"</span>)</span>
<span id="cb10-27">    macro <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auroc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auprc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bce"</span>]].mean(skipna<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb10-28">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df, macro</span>
<span id="cb10-29"></span>
<span id="cb10-30"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> rf_predict_proba_matrix(models, X, task_names):</span>
<span id="cb10-31">    P <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros((X.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(task_names)), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.float32)</span>
<span id="cb10-32">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(task_names):</span>
<span id="cb10-33">        P[:, i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> models[t].predict_proba(X)[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb10-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> P</span>
<span id="cb10-35"></span>
<span id="cb10-36">rf_val_proba  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rf_predict_proba_matrix(rf_models, X_val_ecfp,  TOX21_TASKS)</span>
<span id="cb10-37">rf_test_proba <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rf_predict_proba_matrix(rf_models, X_test_ecfp, TOX21_TASKS)</span>
<span id="cb10-38"></span>
<span id="cb10-39">rf_val_per_task,  rf_val_macro  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> masked_task_metrics(y_val,  rf_val_proba,  w_val,  TOX21_TASKS)</span>
<span id="cb10-40">rf_test_per_task, rf_test_macro <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> masked_task_metrics(y_test, rf_test_proba, w_test, TOX21_TASKS)</span>
<span id="cb10-41"></span>
<span id="cb10-42"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RF — validation macro:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, rf_val_macro, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb10-43"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RF — test macro:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, rf_test_macro)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>RF — validation macro:
 auroc    0.741988
auprc    0.392214
bce      0.290596
dtype: float64 

RF — test macro:
 auroc    0.732228
auprc    0.382328
bce      0.287920
dtype: float64</code></pre>
<div id="12ea6c29" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(rf_test_per_task)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>               n_not_missing     auroc     auprc       bce
task                                                      
NR-AR                    710  0.662598  0.444872  0.140264
NR-AR-LBD                625  0.825365  0.470748  0.175261
NR-AhR                   631  0.810336  0.480379  0.339632
NR-Aromatase             513  0.750583  0.413734  0.287437
NR-ER                    542  0.700920  0.434790  0.470501
NR-ER-LBD                654  0.749201  0.391579  0.186523
NR-PPAR-gamma            573  0.715393  0.230247  0.148016
SR-ARE                   461  0.728359  0.455434  0.532457
SR-ATAD5                 666  0.738581  0.198776  0.198404
SR-HSE                   564  0.562813  0.150229  0.281093
SR-MMP                   517  0.806099  0.589835  0.384019
SR-p53                   633  0.736491  0.327309  0.311428</code></pre>
</section>
</section>
<section id="model-2-gine" class="level1">
<h1>Model 2: GINE</h1>
<section id="extracting-atom-and-bond-features" class="level2">
<h2 class="anchored" data-anchor-id="extracting-atom-and-bond-features">Extracting atom and bond features</h2>
<p>Extracting atom and bond features from the SMILES strings using RDKit, and converting them into PyTorch Geometric Data objects:</p>
<div id="13745506" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">ATOM_LIST <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'C'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'N'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'O'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'F'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Si'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'P'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Cl'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Br'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Mg'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Na'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Ca'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Fe'</span>,</span>
<span id="cb14-2">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'As'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'I'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'B'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'V'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'K'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Tl'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Sn'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Sb'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Se'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Zn'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Other'</span>]</span>
<span id="cb14-3">HYBRIDIZATIONS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Chem.rdchem.HybridizationType.SP, Chem.rdchem.HybridizationType.SP2,</span>
<span id="cb14-4">                   Chem.rdchem.HybridizationType.SP3, Chem.rdchem.HybridizationType.SP3D,</span>
<span id="cb14-5">                   Chem.rdchem.HybridizationType.SP3D2, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Other'</span>]</span>
<span id="cb14-6">CHIRAL_TAGS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Chem.rdchem.ChiralType.CHI_UNSPECIFIED, Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CW,</span>
<span id="cb14-7">               Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CCW, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Other'</span>]</span>
<span id="cb14-8">BOND_TYPES <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Chem.rdchem.BondType.SINGLE, Chem.rdchem.BondType.DOUBLE,</span>
<span id="cb14-9">              Chem.rdchem.BondType.TRIPLE, Chem.rdchem.BondType.AROMATIC]</span>
<span id="cb14-10">STEREO_TYPES <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Chem.rdchem.BondStereo.STEREONONE, Chem.rdchem.BondStereo.STEREOZ,</span>
<span id="cb14-11">                 Chem.rdchem.BondStereo.STEREOE, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Other'</span>]</span>
<span id="cb14-12"></span>
<span id="cb14-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> one_hot(x, choices: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]:</span>
<span id="cb14-14">    v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(choices)</span>
<span id="cb14-15">    idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> choices.index(x) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> choices <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(choices) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb14-16">    v[idx] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb14-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> v</span>
<span id="cb14-18"></span>
<span id="cb14-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> atom_features(atom: Chem.rdchem.Atom) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> np.ndarray:</span>
<span id="cb14-20">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb14-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Returns a bit vector of atom features.</span></span>
<span id="cb14-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    atom: RDKit atom object (from Mol object)</span></span>
<span id="cb14-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    returns: 1D np.array of atom features with shape (52,)</span></span>
<span id="cb14-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb14-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(</span>
<span id="cb14-26">        one_hot(atom.GetSymbol(), ATOM_LIST) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-27">        one_hot(atom.GetTotalDegree(), [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-28">        one_hot(atom.GetFormalCharge(), [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-29">        one_hot(atom.GetHybridization(), HYBRIDIZATIONS) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-30">        one_hot(atom.GetTotalNumHs(), [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-31">        one_hot(atom.GetChiralTag(), CHIRAL_TAGS) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-32">        [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(atom.GetIsAromatic()), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(atom.IsInRing())],</span>
<span id="cb14-33">        dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.float32,</span>
<span id="cb14-34">    )</span>
<span id="cb14-35"></span>
<span id="cb14-36"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> bond_features(bond: Chem.rdchem.Bond) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> np.ndarray:</span>
<span id="cb14-37">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb14-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Returns a bit vector of bond features.</span></span>
<span id="cb14-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    bond: RDKit bond object (from BondList object)</span></span>
<span id="cb14-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    returns: 1D np.array of bond features with shape (10,)</span></span>
<span id="cb14-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb14-42">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(</span>
<span id="cb14-43">        one_hot(bond.GetBondType(), BOND_TYPES) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-44">        one_hot(bond.GetStereo(), STEREO_TYPES) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-45">        [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(bond.GetIsConjugated()), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(bond.IsInRing())],</span>
<span id="cb14-46">        dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.float32,</span>
<span id="cb14-47">    )</span>
<span id="cb14-48"></span>
<span id="cb14-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mol_to_pyg_data(smiles: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb14-50">                    y: np.ndarray <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb14-51">                    w: np.ndarray <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb14-52">                    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb14-53">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb14-54"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Converts a SMILES string into a PyTorch Geometric Data object.</span></span>
<span id="cb14-55"></span>
<span id="cb14-56"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Args:</span></span>
<span id="cb14-57"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      smiles: The SMILES string of the molecule.</span></span>
<span id="cb14-58"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      y: Optional target labels (e.g., toxicity values) for the molecule.</span></span>
<span id="cb14-59"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      w: Optional weights/mask for the target labels (1 for present, 0 for missing).</span></span>
<span id="cb14-60"></span>
<span id="cb14-61"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Returns:</span></span>
<span id="cb14-62"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      A PyTorch Geometric Data object representing the molecule, or None if the SMILES</span></span>
<span id="cb14-63"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">      string cannot be parsed or results in a molecule with no atoms.</span></span>
<span id="cb14-64"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb14-65">    mol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chem.MolFromSmiles(smiles)</span>
<span id="cb14-66">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> mol <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> mol.GetNumAtoms() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb14-67">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb14-68">    x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(np.stack([atom_features(a) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> a <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> mol.GetAtoms()]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>)</span>
<span id="cb14-69">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># x is node features of shape: (num_nodes_in_molecule, num_node_features)</span></span>
<span id="cb14-70"></span>
<span id="cb14-71">    edge_index, edge_attr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], []</span>
<span id="cb14-72">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> bond <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> mol.GetBonds():</span>
<span id="cb14-73">        i, j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()</span>
<span id="cb14-74">        bf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bond_features(bond)</span>
<span id="cb14-75">        edge_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> [[i, j], [j, i]]</span>
<span id="cb14-76">        edge_attr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> [bf, bf]</span>
<span id="cb14-77">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(edge_index) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># single-atom molecule edge case, no bonds (e.g. bare ions like [Na+])</span></span>
<span id="cb14-78">        edge_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.empty((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">long</span>)</span>
<span id="cb14-79">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># PyG expects shape (2, num_edges), so empty (2, 0) is start/end nodes with no edges</span></span>
<span id="cb14-80">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># torch.long gives int64</span></span>
<span id="cb14-81">        edge_attr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.empty((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, BOND_FEAT_DIM), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>)</span>
<span id="cb14-82">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Gives empty edge_attr shape (0, 10)</span></span>
<span id="cb14-83">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb14-84">        edge_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(edge_index, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">long</span>).t().contiguous()</span>
<span id="cb14-85">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># If a atom has N bonds -&gt; edge index will be: (2, 2 * N), which is:</span></span>
<span id="cb14-86">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (StartAtom/EndAtom, i:j/j:i * N bonds)</span></span>
<span id="cb14-87">        edge_attr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(np.stack(edge_attr), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>)</span>
<span id="cb14-88">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># edge_attr output: (2 * N bonds, 10)</span></span>
<span id="cb14-89"></span>
<span id="cb14-90">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb14-91"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Demo: </span></span>
<span id="cb14-92"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        edge_index = [[1, 2], [2, 1], [3, 4], [4, 3]]</span></span>
<span id="cb14-93"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        In [29]: torch.tensor(edge_index, dtype=torch.long)</span></span>
<span id="cb14-94"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Out[29]:</span></span>
<span id="cb14-95"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        tensor([[1, 2],</span></span>
<span id="cb14-96"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">                [2, 1],</span></span>
<span id="cb14-97"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">                [3, 4],</span></span>
<span id="cb14-98"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">                [4, 3]])</span></span>
<span id="cb14-99"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        In [30]: torch.tensor(edge_index, dtype=torch.long).t()</span></span>
<span id="cb14-100"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Out[30]:</span></span>
<span id="cb14-101"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        tensor([[1, 2, 3, 4],</span></span>
<span id="cb14-102"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">                [2, 1, 4, 3]])</span></span>
<span id="cb14-103"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb14-104"></span>
<span id="cb14-105">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># PyG Data object aggregates all the information for a single graph into one container</span></span>
<span id="cb14-106">    data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Data(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>x, edge_index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>edge_index, edge_attr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>edge_attr, smiles<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>smiles)</span>
<span id="cb14-107">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> y <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb14-108">        data.y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(y, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>).view(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb14-109">        data.mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(w, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>).view(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb14-110">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> data</span>
<span id="cb14-111"></span>
<span id="cb14-112">ATOM_FEAT_DIM <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(atom_features(Chem.MolFromSmiles(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCO"</span>).GetAtomWithIdx(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)))</span>
<span id="cb14-113">BOND_FEAT_DIM <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(bond_features(Chem.MolFromSmiles(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCO"</span>).GetBondWithIdx(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)))</span>
<span id="cb14-114"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"atom feature dim:"</span>, ATOM_FEAT_DIM, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"| bond feature dim:"</span>, BOND_FEAT_DIM)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>atom feature dim: 52 | bond feature dim: 10</code></pre>
</section>
<section id="building-pyg-data" class="level2">
<h2 class="anchored" data-anchor-id="building-pyg-data">Building PyG data</h2>
<p><strong>The PyG Data structure can be summarized as below, using ethanol as an example:</strong></p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic2.png" class="img-fluid"></p>
<div id="76cb6d3a" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_pyg_list(smiles_arr: np.ndarray,</span>
<span id="cb16-2">                   y_arr: np.ndarray,</span>
<span id="cb16-3">                   w_arr: np.ndarray</span>
<span id="cb16-4">                   ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[Data]:</span>
<span id="cb16-5">    out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb16-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> smi, y, w <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(smiles_arr, y_arr, w_arr):</span>
<span id="cb16-7">        d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mol_to_pyg_data(smi, y, w)</span>
<span id="cb16-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb16-9">            out.append(d)</span>
<span id="cb16-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> out</span>
<span id="cb16-11"></span>
<span id="cb16-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This generates a list of PyG Data objects</span></span>
<span id="cb16-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For larger datasets needing on-disk caching, the Dataset subclass is required</span></span>
<span id="cb16-14">train_graphs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_pyg_list(train_smiles, y_train, w_train)</span>
<span id="cb16-15">val_graphs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_pyg_list(val_smiles, y_val, w_val)</span>
<span id="cb16-16">test_graphs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_pyg_list(test_smiles, y_test, w_test)</span>
<span id="cb16-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"PyG graphs — train/val/test: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_graphs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_graphs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(test_graphs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb16-18"></span>
<span id="cb16-19">BATCH_SIZE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span></span>
<span id="cb16-20">train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PyGDataLoader(train_graphs, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb16-21">val_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PyGDataLoader(val_graphs, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb16-22">test_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PyGDataLoader(test_graphs, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>PyG graphs — train/val/test: 6258/782/783</code></pre>
</section>
<section id="message-passing-in-gine" class="level2">
<h2 class="anchored" data-anchor-id="message-passing-in-gine">Message passing in GINE</h2>
<p><strong>How is message-passing performed in GINE?</strong></p>
<p>The edge features (here 10 dim) get projected up to match the node features’ <em>working</em> dimension — the 128-dim hidden representation after <code>atom_proj</code>. Once projected to the same dimension, the node and edge features can be combined and passed through a ReLU activation function. This is done for each neighbor u of a given node v, then the messages from all neighbors are summed to get an aggregated message. Finally, this aggregated neighbor message is summed with the feature of node v at a defined proportion, and then passed through an MLP to get the updated node v feature. This can be depicted as follows:</p>
<pre><code>For each neighbor u of node v:
  message(u→v) = ReLU( h_u + Linear(e_uv) )    
Aggregate message:
  aggr(v) = sum over all neighbors u of message(u→v)
Update embed + MLP transformation: 
  h_v_new = MLP( (1 + eps) * h_v + aggr(v) )</code></pre>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic3.png" class="img-fluid"></p>
<p>This message-passing is done many times (here 4 layers) to transfer messages across the molecule. One danger of too many layers is “over-smoothing”, when the useful signals get washed out from extensive summing and pooling. A residual connection (h = h + h_new) is added to prevent this and to allow useful signals passing directly through the layers.</p>
<p>The model can be visualized as below:</p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic4.png" class="img-fluid"></p>
<p>At the pooling layer, the mean pooled and max pooled features are concatenated to form a graph-level embedding. The max pooled features allow for capturing the most prominent features in the molecule, while the mean pooled features capture the overall distribution of features. The concatenated graph-level embedding is then passed through a MLP to produce the final predictions for each task.</p>
</section>
<section id="constructing-model" class="level2">
<h2 class="anchored" data-anchor-id="constructing-model">Constructing model</h2>
<p>Now we build the model:</p>
<div id="fc553cef" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> GINEMultiTask(nn.Module):</span>
<span id="cb19-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb19-3">                 atom_feat_dim,</span>
<span id="cb19-4">                 bond_feat_dim,</span>
<span id="cb19-5">                 hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>,</span>
<span id="cb19-6">                 num_layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb19-7">                 n_tasks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> N_TASKS,</span>
<span id="cb19-8">                 dropout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>):</span>
<span id="cb19-9">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb19-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.atom_proj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(atom_feat_dim, hidden_dim)</span>
<span id="cb19-11">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.convs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.ModuleList()</span>
<span id="cb19-12">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.ModuleList()</span>
<span id="cb19-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(num_layers):</span>
<span id="cb19-14">            mlp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(</span>
<span id="cb19-15">                nn.Linear(hidden_dim, hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb19-16">                nn.ReLU(),</span>
<span id="cb19-17">                nn.Linear(hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, hidden_dim),</span>
<span id="cb19-18">            )</span>
<span id="cb19-19">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.convs.append(GINEConv(mlp, edge_dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bond_feat_dim))</span>
<span id="cb19-20">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bns.append(nn.BatchNorm1d(hidden_dim))</span>
<span id="cb19-21">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.dropout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dropout</span>
<span id="cb19-22">        pooled_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># mean + max concat</span></span>
<span id="cb19-23">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.head <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(</span>
<span id="cb19-24">            nn.Linear(pooled_dim, hidden_dim),</span>
<span id="cb19-25">            nn.ReLU(),</span>
<span id="cb19-26">            nn.Dropout(dropout),</span>
<span id="cb19-27">            nn.Linear(hidden_dim, n_tasks),</span>
<span id="cb19-28">        )</span>
<span id="cb19-29"></span>
<span id="cb19-30">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> embed(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x, edge_index, edge_attr, batch):</span>
<span id="cb19-31">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb19-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        embed as a separate module to call model.embed() to easily get graph-level</span></span>
<span id="cb19-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        embeddings for downstream tasks like t-SNE below.</span></span>
<span id="cb19-34"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        This is the actual message passing step.</span></span>
<span id="cb19-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb19-36">        h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.atom_proj(x)</span>
<span id="cb19-37">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> conv, bn <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.convs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bns):</span>
<span id="cb19-38">            h_new <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> conv(h, edge_index, edge_attr)</span>
<span id="cb19-39">            h_new <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bn(h_new)</span>
<span id="cb19-40">            h_new <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> F.relu(h_new) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># nn.F: for cleaner stateless ops within loop</span></span>
<span id="cb19-41">            h_new <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> F.dropout(h_new, p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.dropout, training<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.training) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># dropout will turn off when eval</span></span>
<span id="cb19-42">            h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> h_new  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># residual connection</span></span>
<span id="cb19-43">        h_mean <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> global_mean_pool(h, batch) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, hidden_dim)</span></span>
<span id="cb19-44">        h_max <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> global_max_pool(h, batch) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch: idx of which molecule each atom belongs to</span></span>
<span id="cb19-45">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.cat([h_mean, h_max], dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, hidden_dim * 2)</span></span>
<span id="cb19-46"></span>
<span id="cb19-47">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x, edge_index, edge_attr, batch):</span>
<span id="cb19-48">        embedding <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.embed(x, edge_index, edge_attr, batch)</span>
<span id="cb19-49">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.head(embedding)</span>
<span id="cb19-50"></span>
<span id="cb19-51"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> masked_bce_loss(logits, y, mask):</span>
<span id="cb19-52">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb19-53"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Computes the mean binary cross entropy loss for non-missing samples.</span></span>
<span id="cb19-54"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb19-55">    loss_mat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> F.binary_cross_entropy_with_logits(logits, y, reduction<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>)</span>
<span id="cb19-56">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># reduction="none" keeps the full (B, n_tasks) matrix of per-example-per-task losses instead of collapsing it</span></span>
<span id="cb19-57">    loss_mat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_mat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mask</span>
<span id="cb19-58">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> loss_mat.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>().clamp(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (summed loss / total sample n) = mean loss</span></span>
<span id="cb19-59"></span>
<span id="cb19-60"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb19-61"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">One subtlety worth flagging: this normalizes globally across the whole batch×task matrix,</span></span>
<span id="cb19-62"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">not per-task. So a task with a low missing-rate (e.g. NR-AhR) contributes more total</span></span>
<span id="cb19-63"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">loss mass per batch than a sparse one (e.g. NR-AR-LBD), simply because it has more</span></span>
<span id="cb19-64"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">valid entries — the loss doesn't explicitly rebalance for that. If we ever see the model</span></span>
<span id="cb19-65"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">doing noticeably worse on the sparsest tasks specifically, that's one place to look</span></span>
<span id="cb19-66"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(a per-task-then-averaged loss would be the fix).</span></span>
<span id="cb19-67"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span></code></pre></div></div>
</details>
</div>
<p>💡<em>A note for how PyG handles variable sized molecules with different atom and bond sizes:</em></p>
<p><em>The DataLoader actually concatenates everything in a batch into one big disjoint graph. It is the edge index that tells the model that atoms from different molecules do not connect and should not message-pass. At the end of message-passing, per-graph/molecule level feature is calculated by pooling all node features from the same molecule. So how does the model know which nodes belong to which molecule? It gets that information from the batch vector provided.</em></p>
<p><em>As an example: say a batch contains an ethanol example (3 atoms, 2 bonds → 4 directed edges) plus a second molecule, methanol (2 atoms, 1 bond → 2 directed edges). PyGDataLoader doesn’t pad anything — it concatenates everything into one big graph:</em></p>
<pre><code>- x: ethanol's 3 rows stacked on top of methanol's 2 rows  → (5, atom_feat_dim)
- edge_attr: ethanol's 4 rows stacked on top of methanol's 2 rows  → (6, bond_feat_dim))
- edge_index: ethanol's indices unchanged: [[0,1,1,2],[1,0,2,1]]
- methanol's indices shifted by +3 (ethanol's atom count): original methanol edges [[0,1],[1,0]] become [[3,4],[4,3]]
- concatenated: [[0,1,1,2,3,4],[1,0,2,1,4,3]] → shape (2, 6)
- batch: [0,0,0,1,1]   ← which molecule each of the 5 nodes belongs to.</code></pre>
</section>
<section id="model-training" class="level2">
<h2 class="anchored" data-anchor-id="model-training">Model training</h2>
<p>Next is to design the training loop. We will employ these mechanisms to counter over-fitting:</p>
<ul>
<li><strong>Dropout</strong> (0.2) inside every conv block and the FFN head.</li>
<li><strong>ReduceLROnPlateau</strong> scheduler on validation loss (halves LR after 5 stagnant epochs).</li>
<li><strong>Early stopping</strong> on validation loss (patience 15), restoring the best-val-loss weights at the end rather than using the final epoch’s weights.</li>
<li><strong>Weight decay</strong> (L2 regularization) in the optimizer.</li>
</ul>
<div id="e08912f0" class="cell" data-execution_count="12">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@torch.no_grad</span>()</span>
<span id="cb21-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> evaluate_gine(model, loader, task_names):</span>
<span id="cb21-3">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb21-4">    all_logits, all_y, all_mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], [], []</span>
<span id="cb21-5">    total_loss, total_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb21-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> batch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> loader:</span>
<span id="cb21-7">        batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.to(DEVICE)</span>
<span id="cb21-8">        logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(batch.x, batch.edge_index, batch.edge_attr, batch.batch)</span>
<span id="cb21-9">        y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.y.view(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(task_names)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, N_TASKS)</span></span>
<span id="cb21-10">        mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.mask.view(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(task_names))</span>
<span id="cb21-11">        loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> masked_bce_loss(logits, y, mask) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this gets avg loss per batch</span></span>
<span id="cb21-12">        total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> loss.item() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>().item() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># avg loss X total n</span></span>
<span id="cb21-13">        total_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>().item()</span>
<span id="cb21-14">        all_logits.append(logits.cpu())</span>
<span id="cb21-15">        all_y.append(y.cpu())</span>
<span id="cb21-16">        all_mask.append(mask.cpu())</span>
<span id="cb21-17">    logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(all_logits).numpy() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># concat list of batches[(B,), (B,), ...] -&gt; [N, ]</span></span>
<span id="cb21-18">    y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(all_y).numpy()</span>
<span id="cb21-19">    mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(all_mask).numpy()</span>
<span id="cb21-20">    proba <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> np.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>logits)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sigmoid function</span></span>
<span id="cb21-21">    per_task_metrics, macro_metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> masked_task_metrics(y, proba, mask, task_names)</span>
<span id="cb21-22">    avg_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(total_count, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb21-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> avg_loss, macro_metrics, per_task_metrics, proba</span>
<span id="cb21-24"></span>
<span id="cb21-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> train_gine(model,</span>
<span id="cb21-26">               train_loader,</span>
<span id="cb21-27">               val_loader,</span>
<span id="cb21-28">               task_names,</span>
<span id="cb21-29">               max_epochs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb21-30">               lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>,</span>
<span id="cb21-31">               weight_decay<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-3</span>,</span>
<span id="cb21-32">               patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>):</span>
<span id="cb21-33"></span>
<span id="cb21-34">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.to(DEVICE)</span>
<span id="cb21-35"></span>
<span id="cb21-36">    optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.AdamW(model.parameters(), lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>lr, weight_decay<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>weight_decay)</span>
<span id="cb21-37">    scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.lr_scheduler.ReduceLROnPlateau(</span>
<span id="cb21-38">        optimizer,</span>
<span id="cb21-39">        mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"min"</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># goal is min val loss</span></span>
<span id="cb21-40">        factor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,</span>
<span id="cb21-41">        patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb21-42">        min_lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-6</span></span>
<span id="cb21-43">    )</span>
<span id="cb21-44"></span>
<span id="cb21-45">    history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>: [],</span>
<span id="cb21-46">               <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>: [],</span>
<span id="cb21-47">               <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>: [],</span>
<span id="cb21-48">               <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>: [],</span>
<span id="cb21-49">               <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>: []</span>
<span id="cb21-50">               }</span>
<span id="cb21-51"></span>
<span id="cb21-52">    best_val_loss, best_state, epochs_no_improve <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inf"</span>), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb21-53"></span>
<span id="cb21-54">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, max_epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb21-55">        model.train()</span>
<span id="cb21-56">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> batch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_loader:</span>
<span id="cb21-57">            batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.to(DEVICE)</span>
<span id="cb21-58">            optimizer.zero_grad()</span>
<span id="cb21-59">            logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(batch.x, batch.edge_index, batch.edge_attr, batch.batch)</span>
<span id="cb21-60">            y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.y.view(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(task_names))</span>
<span id="cb21-61">            mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.mask.view(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(task_names))</span>
<span id="cb21-62">            loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> masked_bce_loss(logits, y, mask)</span>
<span id="cb21-63">            loss.backward()</span>
<span id="cb21-64">            optimizer.step()</span>
<span id="cb21-65"></span>
<span id="cb21-66">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Generate metrics</span></span>
<span id="cb21-67">        train_loss, train_macro, _, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate_gine(model, train_loader, task_names)</span>
<span id="cb21-68">        val_loss, val_macro, _, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate_gine(model, val_loader, task_names)</span>
<span id="cb21-69"></span>
<span id="cb21-70">        current_lr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> optimizer.param_groups[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>]</span>
<span id="cb21-71"></span>
<span id="cb21-72">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Log metrics</span></span>
<span id="cb21-73">        history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>].append(train_loss)</span>
<span id="cb21-74">        history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>].append(val_loss)</span>
<span id="cb21-75">        history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>].append(train_macro[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auroc"</span>])</span>
<span id="cb21-76">        history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>].append(val_macro[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auroc"</span>])</span>
<span id="cb21-77">        history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>].append(current_lr)</span>
<span id="cb21-78"></span>
<span id="cb21-79">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Lr scheduling and early stopping</span></span>
<span id="cb21-80">        scheduler.step(val_loss)</span>
<span id="cb21-81"></span>
<span id="cb21-82">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> val_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> best_val_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>:</span>
<span id="cb21-83">            best_val_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_loss</span>
<span id="cb21-84">            best_state <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {k: v.detach().cpu().clone() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.state_dict().items()}</span>
<span id="cb21-85">            epochs_no_improve <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb21-86">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb21-87">            epochs_no_improve <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb21-88"></span>
<span id="cb21-89">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> epoch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> epoch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="cb21-90">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"epoch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>epoch<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:3d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | train_loss </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>train_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | val_loss </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>val_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> "</span></span>
<span id="cb21-91">                  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"| train_auroc </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>train_macro[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'auroc'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | val_auroc </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>val_macro[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'auroc'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> "</span></span>
<span id="cb21-92">                  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"| lr </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>current_lr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2e}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb21-93"></span>
<span id="cb21-94">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> epochs_no_improve <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> patience:</span>
<span id="cb21-95">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Early stopping at epoch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>epoch<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> (no val_loss improvement for </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>patience<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> epochs)."</span>)</span>
<span id="cb21-96">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb21-97"></span>
<span id="cb21-98">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> best_state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb21-99">        model.load_state_dict(best_state)</span>
<span id="cb21-100">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> model, history</span>
<span id="cb21-101">  </span>
<span id="cb21-102"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Instantiate the model</span></span>
<span id="cb21-103">gine_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GINEMultiTask(ATOM_FEAT_DIM,</span>
<span id="cb21-104">                           BOND_FEAT_DIM,</span>
<span id="cb21-105">                           hidden_dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>,</span>
<span id="cb21-106">                           num_layers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb21-107">                           dropout<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)</span>
<span id="cb21-108"></span>
<span id="cb21-109"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Training</span></span>
<span id="cb21-110">gine_model, gine_history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_gine(gine_model,</span>
<span id="cb21-111">                                      train_loader,</span>
<span id="cb21-112">                                      val_loader,</span>
<span id="cb21-113">                                      TOX21_TASKS)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>epoch   1 | train_loss 0.2247 | val_loss 0.2883 | train_auroc 0.6957 | val_auroc 0.6603 | lr 1.00e-04
epoch   5 | train_loss 0.1922 | val_loss 0.2679 | train_auroc 0.8202 | val_auroc 0.7333 | lr 1.00e-04
epoch  10 | train_loss 0.1804 | val_loss 0.2611 | train_auroc 0.8648 | val_auroc 0.7581 | lr 1.00e-04
epoch  15 | train_loss 0.1673 | val_loss 0.2722 | train_auroc 0.8847 | val_auroc 0.7612 | lr 1.00e-04
epoch  20 | train_loss 0.1535 | val_loss 0.2558 | train_auroc 0.8947 | val_auroc 0.7666 | lr 5.00e-05
epoch  25 | train_loss 0.1486 | val_loss 0.2569 | train_auroc 0.9044 | val_auroc 0.7644 | lr 5.00e-05
epoch  30 | train_loss 0.1443 | val_loss 0.2532 | train_auroc 0.9090 | val_auroc 0.7701 | lr 2.50e-05
epoch  35 | train_loss 0.1419 | val_loss 0.2540 | train_auroc 0.9130 | val_auroc 0.7722 | lr 1.25e-05
Early stopping at epoch 37 (no val_loss improvement for 15 epochs).</code></pre>
</section>
<section id="evaluation" class="level2">
<h2 class="anchored" data-anchor-id="evaluation">Evaluation</h2>
<div id="0432326b" class="cell" data-execution_count="13">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_diagnostics(history, title):</span>
<span id="cb23-2">    epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb23-3">    fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb23-4"></span>
<span id="cb23-5">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].plot(epochs, history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span>)</span>
<span id="cb23-6">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].plot(epochs, history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val"</span>)</span>
<span id="cb23-7">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>title<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: BCE loss"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].legend()</span>
<span id="cb23-8"></span>
<span id="cb23-9">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].plot(epochs, history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span>)</span>
<span id="cb23-10">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].plot(epochs, history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val"</span>)</span>
<span id="cb23-11">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>title<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: macro AUROC"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].legend()</span>
<span id="cb23-12"></span>
<span id="cb23-13">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].plot(epochs, history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>], color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkgreen"</span>)</span>
<span id="cb23-14">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>title<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: learning rate"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].set_yscale(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log"</span>)</span>
<span id="cb23-15"></span>
<span id="cb23-16">    plt.tight_layout()</span>
<span id="cb23-17">    plt.show()</span>
<span id="cb23-18"></span>
<span id="cb23-19">plot_diagnostics(gine_history, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GINE"</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic5.png" class="img-fluid"></p>
<p>As we can see, there is a clear gap between the training and validation loss, indicating that the model is overfitting. In the future, a hyperparameter sweep can be performed to find the optimal model architecture and training parameters to reduce overfitting.</p>
<div id="e7245751" class="cell" data-execution_count="14">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Evaluate on test data</span></span>
<span id="cb24-2">gine_test_loss, gine_test_macro, gine_test_per_task, gine_test_proba <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate_gine(</span>
<span id="cb24-3">    gine_model, test_loader, TOX21_TASKS</span>
<span id="cb24-4">)</span>
<span id="cb24-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GINE — test macro:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, gine_test_macro)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>GINE — test macro:
 auroc    0.752415
auprc    0.367339
bce      0.268268
dtype: float64</code></pre>
<div id="d05322cb" class="cell" data-execution_count="15">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(gine_test_per_task)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>               n_not_missing     auroc     auprc       bce
task                                                      
NR-AR                    710  0.756275  0.410758  0.139618
NR-AR-LBD                625  0.784992  0.430528  0.121509
NR-AhR                   631  0.861561  0.611699  0.289744
NR-Aromatase             513  0.759482  0.408706  0.281288
NR-ER                    542  0.711959  0.429774  0.369044
NR-ER-LBD                654  0.722159  0.337079  0.155390
NR-PPAR-gamma            573  0.710114  0.096841  0.160126
SR-ARE                   461  0.737652  0.468324  0.535995
SR-ATAD5                 666  0.710179  0.204821  0.204716
SR-HSE                   564  0.735774  0.234789  0.255386
SR-MMP                   517  0.828037  0.547383  0.373727
SR-p53                   633  0.710802  0.227364  0.332671</code></pre>
</section>
</section>
<section id="model-3-chemprop" class="level1">
<h1>Model 3: Chemprop</h1>
<p>Chemprop data workflow:</p>
<ul>
<li>Create Mol objects and RDKit 2D features (x_d): <code>make_rdkit2d_features</code>.</li>
<li>Create MoleculeDatapoint objects: for each molecule, combine its Mol object, labels (y), and any extra features (x_d) into a <code>MoleculeDatapoint</code> instance (via <code>make_datapoints</code>).</li>
<li>Create MoleculeDataset objects: collect these <code>MoleculeDatapoint</code> instances into <code>MoleculeDataset</code>s for the train, validation, and test sets. Provide a graph featurizer to the dataset.</li>
<li>Create DataLoaders: pass these <code>MoleculeDataset</code> objects to <code>build_dataloader</code> to create iterable loaders that feed batches of graph data to the Chemprop model during training and evaluation.</li>
</ul>
<section id="extracting-features" class="level2">
<h2 class="anchored" data-anchor-id="extracting-features">Extracting features</h2>
<p>During my initial training, I noticed that the Chemprop model was producing astronomical loss values. Upon investigation, I found that some of the 2D features had extreme values (likely Ipc/Kappa3, similarly reported <a href="https://github.com/rdkit/rdkit/issues/1527">here</a>) that had corrupted the training steps. The short-term solution is to clip these values to <img src="https://latex.codecogs.com/png.latex?1e%5E6"> to prevent them from blowing up the scaling and downstream logits/loss to nonsensical magnitudes.</p>
<div id="ee5fa52b" class="cell" data-execution_count="16">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_rdkit2d_features(</span>
<span id="cb28-2">    smiles_list: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>],</span>
<span id="cb28-3">    clip_max: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e6</span>,</span>
<span id="cb28-4">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>, np.ndarray]:</span>
<span id="cb28-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb28-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Compute chemprop's RDKit 2D descriptors, guarding against known-pathological</span></span>
<span id="cb28-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    descriptors (notably Ipc, and occasionally Kappa3) that can return finite-but-</span></span>
<span id="cb28-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    astronomically-large values (documented up to ~1e162 for Ipc on real molecules,</span></span>
<span id="cb28-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    see rdkit/rdkit#1527) for some molecules. These pass straight through</span></span>
<span id="cb28-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    nan_to_num(posinf=...) since they aren't literally inf, but blow up scaling and</span></span>
<span id="cb28-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    downstream logits/loss to nonsensical magnitudes. Hard-clipping is a blunt but</span></span>
<span id="cb28-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    reliable guard against any similarly-behaved descriptor, not just Ipc specifically.</span></span>
<span id="cb28-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb28-14">    mol_featurizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_featurizers.MoleculeFeaturizerRegistry[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rdkit_2d"</span>]()</span>
<span id="cb28-15">    mols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [cp_utils.make_mol(smi, keep_h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, add_h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> smi <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> smiles_list]</span>
<span id="cb28-16">    X_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([mol_featurizer(m) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> mols], dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.float64)</span>
<span id="cb28-17">    X_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.nan_to_num(X_d, nan<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, posinf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, neginf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)</span>
<span id="cb28-18"></span>
<span id="cb28-19">    n_clipped <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(X_d) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> clip_max))</span>
<span id="cb28-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n_clipped:</span>
<span id="cb28-21">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"clipping </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_clipped<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> extreme RDKit 2D feature values (|x| &gt; </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>clip_max<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.0e}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">), likely Ipc/Kappa3"</span>)</span>
<span id="cb28-22">    X_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.clip(X_d, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>clip_max, clip_max).astype(np.float32)</span>
<span id="cb28-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> mols, X_d</span>
<span id="cb28-24"></span>
<span id="cb28-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_datapoints(</span>
<span id="cb28-26">    smiles_list: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>],</span>
<span id="cb28-27">    y_arr: np.ndarray,</span>
<span id="cb28-28">    w_arr: np.ndarray,</span>
<span id="cb28-29">    mols: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>,</span>
<span id="cb28-30">    X_d: np.ndarray,</span>
<span id="cb28-31">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>:</span>
<span id="cb28-32">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb28-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Build chemprop MoleculeDatapoints, masking missing labels as NaN.</span></span>
<span id="cb28-34"></span>
<span id="cb28-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Raises if any SMILES failed to parse via cp_utils.make_mol (mols contains None),</span></span>
<span id="cb28-36"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    since that would otherwise fail silently or misalign rows downstream.</span></span>
<span id="cb28-37"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb28-38">    none_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(mols) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]</span>
<span id="cb28-39">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> none_idx:</span>
<span id="cb28-40">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(none_idx)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> SMILES failed chemprop parsing, e.g. </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>smiles_list[none_idx[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!r}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb28-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(smiles_list) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(y_arr) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(w_arr) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(mols) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(X_d), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"length mismatch"</span></span>
<span id="cb28-42"></span>
<span id="cb28-43">    y_masked <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_arr.copy()</span>
<span id="cb28-44">    y_masked[w_arr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.nan</span>
<span id="cb28-45">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [</span>
<span id="cb28-46">        cp_data.MoleculeDatapoint(mol, y, x_d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>xd)</span>
<span id="cb28-47">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> mol, y, xd <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(mols, y_masked, X_d)</span>
<span id="cb28-48">    ]</span>
<span id="cb28-49"></span>
<span id="cb28-50">train_mols, X_d_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_rdkit2d_features(train_smiles)</span>
<span id="cb28-51">val_mols,   X_d_val   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_rdkit2d_features(val_smiles)</span>
<span id="cb28-52">test_mols,  X_d_test  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_rdkit2d_features(test_smiles)</span>
<span id="cb28-53"></span>
<span id="cb28-54">cp_train_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_datapoints(train_smiles, y_train, w_train, train_mols, X_d_train)</span>
<span id="cb28-55">cp_val_data   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_datapoints(val_smiles,   y_val,   w_val,   val_mols,   X_d_val)</span>
<span id="cb28-56">cp_test_data  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_datapoints(test_smiles,  y_test,  w_test,  test_mols,  X_d_test)</span>
<span id="cb28-57"></span>
<span id="cb28-58"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RDKit 2D feature dim:"</span>, X_d_train.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb28-59"></span>
<span id="cb28-60"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The featurizer convert Mol to graph attributes e.g. nodes, edges, attributes</span></span>
<span id="cb28-61">molgraph_featurizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_featurizers.SimpleMoleculeMolGraphFeaturizer()</span>
<span id="cb28-62"></span>
<span id="cb28-63">cp_train_dset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_data.MoleculeDataset(cp_train_data, molgraph_featurizer)</span>
<span id="cb28-64">cp_val_dset   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_data.MoleculeDataset(cp_val_data,   molgraph_featurizer)</span>
<span id="cb28-65">cp_test_dset  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_data.MoleculeDataset(cp_test_data,  molgraph_featurizer)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>WARNING:chemprop.featurizers.molecule:The RDKit 2D features can deviate signifcantly from a normal distribution. Consider manually scaling them using an appropriate scaler before creating datapoints, rather than using the scikit-learn `StandardScaler` (the default in Chemprop).

clipping 321 extreme RDKit 2D feature values (|x| &gt; 1e+06), likely Ipc/Kappa3

RDKit 2D feature dim: 217</code></pre>
<p>As we can see from the output, the RDKit 2D features can deviate significantly from a normal distribution. Therefore, we will use a robust scaler (median &amp; IQR scaling) to scale the features instead of the default StandardScaler in Chemprop.</p>
</section>
<section id="scaling-features" class="level2">
<h2 class="anchored" data-anchor-id="scaling-features">Scaling features</h2>
<div id="2017a23b" class="cell" data-execution_count="17">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Scale 2D descriptors with robust scaler (scale with median, IQR)</span></span>
<span id="cb30-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.preprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RobustScaler, StandardScaler</span>
<span id="cb30-3"></span>
<span id="cb30-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_robust_x_d_scaler(X_d_train: np.ndarray) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> StandardScaler:</span>
<span id="cb30-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb30-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Fit sklearn's RobustScaler (median/IQR) on raw extra features, then repackage</span></span>
<span id="cb30-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    its fitted stats into a StandardScaler-shaped object.</span></span>
<span id="cb30-8"></span>
<span id="cb30-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    chemprop's normalize_inputs() / ScaleTransform.from_standard_scaler() are typed</span></span>
<span id="cb30-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    specifically to StandardScaler and read its .mean_/.scale_ attributes at transform</span></span>
<span id="cb30-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    time — a raw RobustScaler (.center_/.scale_) isn't a drop-in replacement. Building</span></span>
<span id="cb30-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    a genuine StandardScaler instance and overwriting its fitted attributes keeps any</span></span>
<span id="cb30-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    isinstance checks happy while making .transform() behave like RobustScaler</span></span>
<span id="cb30-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    (median-centered, IQR-scaled) instead of mean/std-based scaling.</span></span>
<span id="cb30-15"></span>
<span id="cb30-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    RobustScaler is generally more appropriate here than StandardScaler, since RDKit 2D</span></span>
<span id="cb30-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    descriptors (MolWt, ring counts, etc.) are known to deviate significantly from a</span></span>
<span id="cb30-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    normal distribution and can have long-tailed outliers that StandardScaler is</span></span>
<span id="cb30-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    sensitive to but median/IQR scaling is not.</span></span>
<span id="cb30-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb30-21">    robust <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RobustScaler()</span>
<span id="cb30-22">    robust.fit(X_d_train)</span>
<span id="cb30-23"></span>
<span id="cb30-24">    x_d_scaler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StandardScaler()</span>
<span id="cb30-25">    x_d_scaler.mean_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> robust.center_                                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># median per feature</span></span>
<span id="cb30-26">    x_d_scaler.scale_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(robust.scale_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, robust.scale_)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IQR per feature, guarded against div-by-zero</span></span>
<span id="cb30-27">    x_d_scaler.var_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x_d_scaler.scale_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>                             <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># kept consistent in case anything reads var_</span></span>
<span id="cb30-28">    x_d_scaler.n_features_in_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_d_train.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb30-29">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x_d_scaler</span>
<span id="cb30-30"></span>
<span id="cb30-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fit once on train, apply (not re-fit) to all three splits — same pattern as the</span></span>
<span id="cb30-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># original StandardScaler-based code, just swap the fitting step:</span></span>
<span id="cb30-33">x_d_scaler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_robust_x_d_scaler(X_d_train)</span>
<span id="cb30-34"></span>
<span id="cb30-35">cp_train_dset.normalize_inputs(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"X_d"</span>, x_d_scaler)</span>
<span id="cb30-36">cp_val_dset.normalize_inputs(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"X_d"</span>, x_d_scaler)</span>
<span id="cb30-37">cp_test_dset.normalize_inputs(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"X_d"</span>, x_d_scaler)</span>
<span id="cb30-38"></span>
<span id="cb30-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cache processed graph representations to speed up subsequent epochs</span></span>
<span id="cb30-40">cp_train_dset.cache <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb30-41">cp_val_dset.cache <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb30-42"></span>
<span id="cb30-43">BATCH_SIZE_CP <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># matches the Chemprop v1/v2 literature default</span></span>
<span id="cb30-44">cp_train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_data.build_dataloader(cp_train_dset, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE_CP, num_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb30-45">cp_val_loader   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_data.build_dataloader(cp_val_dset,   batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE_CP, num_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb30-46">cp_test_loader  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_data.build_dataloader(cp_test_dset,  batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE_CP, num_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div></div>
</details>
</div>
</section>
<section id="chemprop-model" class="level2">
<h2 class="anchored" data-anchor-id="chemprop-model">Chemprop model</h2>
<p>Let’s build the Chemprop model. The Chemprop model consists of three main components: D-MPNN message-passing module, a graph-level aggregation module, and a feedforward neural network (FFN) for binary classification.</p>
<div id="4a77786a" class="cell" data-execution_count="18">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1">HIDDEN_DIM <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span></span>
<span id="cb31-2">DEPTH <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb31-3">DROPOUT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span></span>
<span id="cb31-4"></span>
<span id="cb31-5">mp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_nn.BondMessagePassing(</span>
<span id="cb31-6">    d_h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>HIDDEN_DIM, depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DEPTH, dropout<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DROPOUT,</span>
<span id="cb31-7">)</span>
<span id="cb31-8">agg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_nn.MeanAggregation()</span>
<span id="cb31-9"></span>
<span id="cb31-10">ffn_input_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mp.output_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> X_d_train.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb31-11">ffn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_nn.BinaryClassificationFFN(</span>
<span id="cb31-12">    n_tasks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>N_TASKS, input_dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ffn_input_dim, hidden_dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>HIDDEN_DIM,</span>
<span id="cb31-13">    n_layers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, dropout<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DROPOUT,</span>
<span id="cb31-14">)</span>
<span id="cb31-15"></span>
<span id="cb31-16">X_d_transform <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_nn.ScaleTransform.from_standard_scaler(x_d_scaler)</span>
<span id="cb31-17"></span>
<span id="cb31-18">metric_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [cp_nn.metrics.BinaryAUROC(), cp_nn.metrics.BinaryAUPRC()]</span>
<span id="cb31-19"></span>
<span id="cb31-20">chemprop_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cp_models.MPNN(</span>
<span id="cb31-21">    mp, agg, ffn, batch_norm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>metric_list,</span>
<span id="cb31-22">    X_d_transform<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>X_d_transform,</span>
<span id="cb31-23">    warmup_epochs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, init_lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>, max_lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-3</span>, final_lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-5</span>,</span>
<span id="cb31-24">)</span>
<span id="cb31-25"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(chemprop_model)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>MPNN(
  (message_passing): BondMessagePassing(
    (W_i): Linear(in_features=86, out_features=128, bias=False)
    (W_h): Linear(in_features=128, out_features=128, bias=False)
    (W_o): Linear(in_features=200, out_features=128, bias=True)
    (dropout): Dropout(p=0.2, inplace=False)
    (tau): ReLU()
    (V_d_transform): Identity()
    (graph_transform): Identity()
  )
  (agg): MeanAggregation()
  (bn): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (predictor): BinaryClassificationFFN(
    (ffn): MLP(
      (0): Sequential(
        (0): Linear(in_features=345, out_features=128, bias=True)
      )
      (1): Sequential(
        (0): ReLU()
        (1): Dropout(p=0.2, inplace=False)
        (2): Linear(in_features=128, out_features=128, bias=True)
      )
      (2): Sequential(
        (0): ReLU()
        (1): Dropout(p=0.2, inplace=False)
        (2): Linear(in_features=128, out_features=12, bias=True)
      )
    )
    (criterion): BCELoss(task_weights=[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]])
    (output_transform): Identity()
  )
  (X_d_transform): ScaleTransform()
  (metrics): ModuleList(
    (0): BinaryAUROC()
    (1): BinaryAUPRC()
    (2): BCELoss(task_weights=[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]])
  )
)</code></pre>
<p>Note that Chemprop uses its own internal atom/bond featurization via <code>SimpleMoleculeMolGraphFeaturizer</code> — separate from, and a different dimensionality than, the custom 52/10-dim atom/bond features hand-built for GINE above. This is visible in the model summary’s <code>W_i: Linear(in_features=86, ...)</code> layer, which reflects Chemprop’s own atom+bond feature concatenation width, not the 52/10 dims computed earlier for GINE.</p>
</section>
<section id="training" class="level2">
<h2 class="anchored" data-anchor-id="training">Training</h2>
<p>Similar to the GINE model, we will use early stopping and learning rate scheduling to prevent overfitting. The Chemprop model will be trained for a maximum of 60 epochs, with early stopping patience of 25 epochs. The best model will be saved to the <code>/chemprop</code> directory.</p>
<div id="5a0d188b" class="cell" data-execution_count="19">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> os</span>
<span id="cb33-2">save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/chemprop"</span></span>
<span id="cb33-3">os.makedirs(save_path, exist_ok<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb33-4">logger <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CSVLogger(save_path, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tox21_chemprop"</span>)</span>
<span id="cb33-5">checkpoint_cb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ModelCheckpoint(</span>
<span id="cb33-6">    save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"best-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{epoch}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{val_loss:.3f}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, monitor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>, mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"min"</span>, save_last<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb33-7">)</span>
<span id="cb33-8">early_stop_cb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EarlyStopping(monitor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>, mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"min"</span>, patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>)</span>
<span id="cb33-9">lr_monitor_cb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> LearningRateMonitor(logging_interval<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)</span>
<span id="cb33-10"></span>
<span id="cb33-11">trainer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pl.Trainer(</span>
<span id="cb33-12">    logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>logger,</span>
<span id="cb33-13">    enable_checkpointing<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb33-14">    enable_progress_bar<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb33-15">    accelerator<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auto"</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># auto select cpu or gpu</span></span>
<span id="cb33-16">    devices<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how many cores</span></span>
<span id="cb33-17">    max_epochs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>,</span>
<span id="cb33-18">    callbacks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[checkpoint_cb, early_stop_cb, lr_monitor_cb],</span>
<span id="cb33-19">)</span>
<span id="cb33-20"></span>
<span id="cb33-21">trainer.fit(chemprop_model, cp_train_loader, cp_val_loader)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>┏━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┓
┃   ┃ Name            ┃ Type                    ┃ Params ┃ Mode  ┃ FLOPs ┃
┡━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━┩
│ 0 │ message_passing │ BondMessagePassing      │ 53.1 K │ train │     0 │
│ 1 │ agg             │ MeanAggregation         │      0 │ train │     0 │
│ 2 │ bn              │ BatchNorm1d             │    256 │ train │     0 │
│ 3 │ predictor       │ BinaryClassificationFFN │ 62.3 K │ train │     0 │
│ 4 │ X_d_transform   │ ScaleTransform          │      0 │ train │     0 │
│ 5 │ metrics         │ ModuleList              │      0 │ train │     0 │
└───┴─────────────────┴─────────────────────────┴────────┴───────┴───────┘

Trainable params: 115 K                                                                                            
Non-trainable params: 0                                                                                            
Total params: 115 K                                                                                                
Total estimated model params size (MB): 0.463                                                                      
Modules in train mode: 27                                                                                          
Modules in eval mode: 0                                                                                            
Total FLOPs: 0                                                                                                     

Epoch 36/59 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 126/126 0:00:02 • 0:00:00 46.86it/s v_num: 2.000 train_loss_step:     
                                                                                 0.262 val_loss: 0.259             
                                                                                 train_loss_epoch: 0.121           </code></pre>
</section>
<section id="evaluation-1" class="level2">
<h2 class="anchored" data-anchor-id="evaluation-1">Evaluation</h2>
<div id="e1101d8f" class="cell" data-execution_count="20">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pull per-epoch metrics back out of the CSV logger for diagnostic plots</span></span>
<span id="cb35-2">metrics_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>logger<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>log_dir<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/metrics.csv"</span></span>
<span id="cb35-3">cp_metrics_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(metrics_path)</span>
<span id="cb35-4"></span>
<span id="cb35-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> epoch_series(df: pd.DataFrame, col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> pd.Series:</span>
<span id="cb35-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb35-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Extract a per-epoch series from chemprop's CSVLogger metrics.csv.</span></span>
<span id="cb35-8"></span>
<span id="cb35-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    LearningRateMonitor logs LR rows with a blank `epoch` (keyed by step instead),</span></span>
<span id="cb35-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    so back-fill epoch from the next non-null row before dropping NaNs, rather than</span></span>
<span id="cb35-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    dropping rows that only lack an epoch stamp but do have a valid value.</span></span>
<span id="cb35-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb35-13">    sub <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>, col]].copy()</span>
<span id="cb35-14">    sub[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sub[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>].bfill()</span>
<span id="cb35-15">    sub <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sub.dropna(subset<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[col])</span>
<span id="cb35-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sub.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)[col].mean()</span>
<span id="cb35-17"></span>
<span id="cb35-18">cp_history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb35-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>: epoch_series(cp_metrics_df, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss_epoch"</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss_epoch"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cp_metrics_df <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> epoch_series(cp_metrics_df, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>),</span>
<span id="cb35-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>: epoch_series(cp_metrics_df, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>),</span>
<span id="cb35-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>: epoch_series(cp_metrics_df, [c <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cp_metrics_df.columns <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> c.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr-"</span>)][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]),</span>
<span id="cb35-22">}</span>
<span id="cb35-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># AUROC column names in chemprop v2's metric logging follow "val/roc"-style keys; adjust if your version differs</span></span>
<span id="cb35-24">auroc_col_candidates <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [c <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cp_metrics_df.columns <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"roc"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> c.lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> c.lower()]</span>
<span id="cb35-25">train_auroc_candidates <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [c <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cp_metrics_df.columns <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"roc"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> c.lower() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> c.lower()]</span>
<span id="cb35-26"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> auroc_col_candidates:</span>
<span id="cb35-27">    cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> epoch_series(cp_metrics_df, auroc_col_candidates[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb35-28"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> train_auroc_candidates:</span>
<span id="cb35-29">    cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> epoch_series(cp_metrics_df, train_auroc_candidates[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span></code></pre></div></div>
</details>
</div>
<div id="4ee3293f" class="cell" data-execution_count="21">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb36-1">fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb36-2"></span>
<span id="cb36-3">axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].plot(cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>].index, cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_loss"</span>].values, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span>)</span>
<span id="cb36-4">axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].plot(cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>].index, cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>].values, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val"</span>)</span>
<span id="cb36-5">axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop: BCE loss"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].legend()</span>
<span id="cb36-6"></span>
<span id="cb36-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cp_history:</span>
<span id="cb36-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> cp_history:</span>
<span id="cb36-9">        axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].plot(cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>].index, cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>].values, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span>)</span>
<span id="cb36-10">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].plot(cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>].index, cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>].values, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val"</span>)</span>
<span id="cb36-11">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop: AUROC"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].legend()</span>
<span id="cb36-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb36-13">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AUROC column not found in metrics.csv — see printed columns above"</span>)</span>
<span id="cb36-14"></span>
<span id="cb36-15">axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].plot(cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>].index, cp_history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lr"</span>].values, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkgreen"</span>)</span>
<span id="cb36-16">axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop: learning rate (Noam schedule)"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"epoch"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>].set_yscale(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log"</span>)</span>
<span id="cb36-17"></span>
<span id="cb36-18">plt.tight_layout()</span>
<span id="cb36-19">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic6.png" class="img-fluid"></p>
<p>We can see here that the Chemprop model is overfitting, as the training loss continues to decrease while the validation loss stays flat. A few things to bring up:</p>
<ul>
<li><strong>The RDKit 2D feature clipping may not be the best fix.</strong> Clipping the <code>Ipc</code>/<code>Kappa3</code> descriptor values to ±1e6 stops the numerical blow-up, but the clipped values themselves are still a somewhat arbitrary cutoff rather than a well-scaled feature — a log-transform of <code>Ipc</code> specifically (or dropping it entirely) would probably be a good fix.</li>
<li><strong>The learning rate schedule likely hadn’t finished annealing when early stopping fired.</strong> Chemprop’s Noam scheduler decay length is computed from <code>trainer.max_epochs</code> (60 here), not from whichever epoch early stopping actually lands on — so the LR at the “best” checkpoint may still be well above the intended <code>final_lr</code>.</li>
<li><strong>Chemprop defaults to plain <code>Adam</code> with no weight decay option on the public API</strong> — unlike the GINE loop above, which explicitly sets <code>weight_decay</code> in <code>AdamW</code>. There are ways to incorporate wieght decay into the workflow but will not be discussed here.</li>
</ul>
<div id="5e0f7c61" class="cell" data-execution_count="22">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Per-task metrics, computed the same way as RF/GINE for a like-for-like comparison table</span></span>
<span id="cb37-2">chemprop_model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb37-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb37-4">    preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trainer.predict(chemprop_model, cp_test_loader, ckpt_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"best"</span>, weights_only<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb37-5">    cp_test_proba <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(preds, dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).numpy()</span>
<span id="cb37-6"></span>
<span id="cb37-7">cp_test_per_task, cp_test_macro <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> masked_task_metrics(y_test, cp_test_proba, w_test, TOX21_TASKS)</span>
<span id="cb37-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop — test macro:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, cp_test_macro)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Chemprop — test macro:
 auroc    0.714631
auprc    0.264956
bce      0.410267
dtype: float64</code></pre>
<div id="b622db23" class="cell" data-execution_count="23">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(cp_test_per_task)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>               n_not_missing     auroc     auprc       bce
task                                                      
NR-AR                    710  0.674216  0.290272  0.257757
NR-AR-LBD                625  0.834176  0.252088  0.157581
NR-AhR                   631  0.763444  0.405000  0.581689
NR-Aromatase             513  0.694687  0.229284  0.614416
NR-ER                    542  0.652002  0.276363  0.569813
NR-ER-LBD                654  0.747490  0.187147  0.185182
NR-PPAR-gamma            573  0.621597  0.076866  0.236523
SR-ARE                   461  0.711489  0.464259  0.628591
SR-ATAD5                 666  0.634082  0.105101  0.310851
SR-HSE                   564  0.738257  0.205279  0.278903
SR-MMP                   517  0.795859  0.441507  0.668769
SR-p53                   633  0.708277  0.246308  0.433123</code></pre>
</section>
</section>
<section id="model-comparison" class="level1">
<h1>Model comparison</h1>
<div id="3f548335" class="cell" data-execution_count="24">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb41" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1">comparison <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({</span>
<span id="cb41-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RF + ECFP2048"</span>: rf_test_macro,</span>
<span id="cb41-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GINE"</span>: gine_test_macro,</span>
<span id="cb41-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop (+ RDKit2D)"</span>: cp_test_macro,</span>
<span id="cb41-5">}).T</span>
<span id="cb41-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(comparison)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>                         auroc     auprc       bce
RF + ECFP2048         0.732228  0.382328  0.287920
GINE                  0.752415  0.367339  0.268268
Chemprop (+ RDKit2D)  0.714631  0.264956  0.410267</code></pre>
<div id="6b43e2c1" class="cell" data-execution_count="25">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb43" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb43-2">comparison[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auroc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"auprc"</span>]].plot.bar(ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax)</span>
<span id="cb43-3">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"macro score (test set)"</span>)</span>
<span id="cb43-4">ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test-set macro AUROC / AUPRC by model"</span>)</span>
<span id="cb43-5">ax.set_ylim(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb43-6">plt.xticks(rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>)</span>
<span id="cb43-7">plt.tight_layout()</span>
<span id="cb43-8">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic7.png" class="img-fluid"></p>
<p>As we can see from the comparison table and bar plot, RF and GINE have quite similar performance on the test set, with GINE having the best performance in terms of AUROC and BCE loss, while RF + ECFP2048 has the best AUPRC. Chemprop’s AUPRC (0.265) sits below both (0.37-0.38) — potentially due to the contributing factors discussed above. Again, the RF model is well-tuned while the GINE and Chemprop models are trained with pre-selected hyperparameters, so further fine-tuning can be performed to improve their performance. In addition, deep learning models typically require larger datasets (e.g.&nbsp;&gt;10k) to learn meaningful patterns from the data. The Tox21 data, with ~7,800 data points, is on the smaller side for a flexible GNN to fine-tune its parameters. Thus, in which case that the available dataset is small, a classical ML approach is likely the better choice for prediction.</p>
</section>
<section id="t-sne-of-the-learned-representations" class="level1">
<h1>t-SNE of the learned representations</h1>
<p>The question here is that: do the learned graph representations (embeddings) from GINE and Chemprop models capture some chemical information that can be visualized in a low-dimensional space? To answer that, we will use t-SNE to reduce the dimensionality of the learned embeddings to 2D and visualize them with different overlays (molecular properties such as molecular weight, LogP and TPSA, and 2 task labels).</p>
<p>Extracting the GINE learned graph representations (embeddings) from the test set:</p>
<div id="f1d7eb0e" class="cell" data-execution_count="26">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb44" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb44-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@torch.no_grad</span>()</span>
<span id="cb44-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> extract_gine_embeddings(model, loader):</span>
<span id="cb44-3">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb44-4">    embs, smiles_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], []</span>
<span id="cb44-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> batch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> loader:</span>
<span id="cb44-6">        batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> batch.to(DEVICE)</span>
<span id="cb44-7">        emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.embed(batch.x, batch.edge_index, batch.edge_attr, batch.batch)</span>
<span id="cb44-8">        embs.append(emb.cpu().numpy()) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [(B, 256), (B, 256), ...]</span></span>
<span id="cb44-9">        smiles_list.extend(batch.smiles)</span>
<span id="cb44-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.concatenate(embs, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), smiles_list <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># concat embs on rows: (N, 256)</span></span>
<span id="cb44-11"></span>
<span id="cb44-12">gine_test_embeddings, gine_test_smiles_order <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_gine_embeddings(gine_model, test_loader) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (N, 256)</span></span>
<span id="cb44-13"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GINE test embedding matrix:"</span>, gine_test_embeddings.shape)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>GINE test embedding matrix: (783, 256)</code></pre>
<p>Extracting the Chemprop learned graph representations (embeddings) from the test set:</p>
<div id="213206b9" class="cell" data-execution_count="27">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb46" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb46-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@torch.no_grad</span>()</span>
<span id="cb46-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> extract_chemprop_embeddings(model, loader):</span>
<span id="cb46-3">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb46-4">    embs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb46-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> batch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> loader:</span>
<span id="cb46-6">        emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.encoding(batch.bmg, batch.V_d, batch.X_d, i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb46-7">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch.bmg: BatchMolGraph - batch disjoint graph</span></span>
<span id="cb46-8">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch.V_d: atom features</span></span>
<span id="cb46-9">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># batch.X_d: 2D descriptors</span></span>
<span id="cb46-10">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># i=0: extract embed right before FFN</span></span>
<span id="cb46-11">        embs.append(emb.cpu().numpy())</span>
<span id="cb46-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.concatenate(embs, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (N, HIDDEN_DIM + X_d_train.shape[1])</span></span>
<span id="cb46-13"></span>
<span id="cb46-14">chemprop_test_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_chemprop_embeddings(chemprop_model, cp_test_loader)</span>
<span id="cb46-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop test embedding matrix:"</span>, chemprop_test_embeddings.shape)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Chemprop test embedding matrix: (783, 345)</code></pre>
<p>Computing some molecular properties and task labels for coloring the t-SNE plots. The properties are computed using RDKit’s Descriptors and Crippen modules, while the task labels are extracted from the test set labels and weights.</p>
<div id="4903e42a" class="cell" data-execution_count="28">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb48" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> compute_property(smiles_list, fn):</span>
<span id="cb48-2">    vals <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.full(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(smiles_list), np.nan)</span>
<span id="cb48-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, smi <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(smiles_list):</span>
<span id="cb48-4">        mol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chem.MolFromSmiles(smi)</span>
<span id="cb48-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> mol <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb48-6">            vals[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fn(mol)</span>
<span id="cb48-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> vals</span>
<span id="cb48-8"></span>
<span id="cb48-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># gine_test_smiles_order is the exact row order of gine_test_embeddings (PyG loader order,</span></span>
<span id="cb48-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># with unparseable SMILES already dropped) — properties/labels must be looked up in that order.</span></span>
<span id="cb48-11">mol_wt   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> compute_property(gine_test_smiles_order, Descriptors.MolWt)</span>
<span id="cb48-12">logp     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> compute_property(gine_test_smiles_order, Crippen.MolLogP)</span>
<span id="cb48-13">tpsa     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> compute_property(gine_test_smiles_order, Descriptors.TPSA)</span>
<span id="cb48-14"></span>
<span id="cb48-15">smi_to_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {s: i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, s <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(test_smiles)}</span>
<span id="cb48-16">order_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([smi_to_idx[s] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> s <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> gine_test_smiles_order])</span>
<span id="cb48-17">nr_ar  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(w_test[order_idx, TOX21_TASKS.index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NR-AR"</span>)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb48-18">                   y_test[order_idx, TOX21_TASKS.index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NR-AR"</span>)], np.nan)</span>
<span id="cb48-19">sr_mmp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(w_test[order_idx, TOX21_TASKS.index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SR-MMP"</span>)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb48-20">                   y_test[order_idx, TOX21_TASKS.index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SR-MMP"</span>)], np.nan)</span>
<span id="cb48-21">                   </span>
<span id="cb48-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tsne_embed(X, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SEED):</span>
<span id="cb48-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> TSNE(n_components<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, perplexity<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, init<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pca"</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seed).fit_transform(X)</span>
<span id="cb48-24"></span>
<span id="cb48-25">gine_tsne <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tsne_embed(gine_test_embeddings)</span>
<span id="cb48-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Chemprop's test loader order matches cp_test_data / test_smiles directly (no drops, since</span></span>
<span id="cb48-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># chemprop's utils.make_mol handles the same SMILES successfully parsed earlier by RDKit)</span></span>
<span id="cb48-28">chemprop_tsne <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tsne_embed(chemprop_test_embeddings)</span></code></pre></div></div>
</details>
</div>
<p>Plotting the t-SNE embeddings with different overlays (molecular properties and task labels) for both GINE and Chemprop models:</p>
<div id="8c596e8f" class="cell" data-execution_count="29">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb49" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_tsne_grid(tsne_xy, overlays, model_name):</span>
<span id="cb49-2">    fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(overlays), figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(overlays), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.5</span>))</span>
<span id="cb49-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> ax, (label, values, cmap, discrete) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(axes, overlays):</span>
<span id="cb49-4">        nan_mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.isnan(values)</span>
<span id="cb49-5">        ax.scatter(tsne_xy[nan_mask, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], tsne_xy[nan_mask, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>, s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"missing"</span>)</span>
<span id="cb49-6">        sc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.scatter(tsne_xy[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>nan_mask, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], tsne_xy[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>nan_mask, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb49-7">                         c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>values[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>nan_mask], cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cmap, s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>,</span>
<span id="cb49-8">                         vmin<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> discrete <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, vmax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> discrete <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span>
<span id="cb49-9">        plt.colorbar(sc, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax, fraction<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.046</span>)</span>
<span id="cb49-10">        ax.set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>model_name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: colored by </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb49-11">        ax.set_xticks([])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ax.set_yticks([])</span>
<span id="cb49-12">    plt.tight_layout()</span>
<span id="cb49-13">    plt.show()</span>
<span id="cb49-14"></span>
<span id="cb49-15">overlays <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb49-16">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MolWt"</span>, mol_wt, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"viridis"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>),</span>
<span id="cb49-17">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LogP"</span>, logp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"viridis"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>),</span>
<span id="cb49-18">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TPSA"</span>, tpsa, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"viridis"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>),</span>
<span id="cb49-19">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NR-AR (active=1)"</span>, nr_ar, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"coolwarm"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb49-20">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SR-MMP (active=1)"</span>, sr_mmp, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"coolwarm"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb49-21">]</span></code></pre></div></div>
</details>
</div>
<div id="345862a2" class="cell" data-execution_count="30">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb50" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb50-1">plot_tsne_grid(gine_tsne, overlays, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GINE"</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic8.png" class="img-fluid"></p>
<div id="e8111f76" class="cell" data-execution_count="31">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb51" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb51-1">plot_tsne_grid(chemprop_tsne, overlays, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chemprop"</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic9.png" class="img-fluid"></p>
<p>As we can see, the t-SNE embeddings from both GINE and Chemprop models show mild clustering patterns based on molecular properties and task labels, suggesting that the learned graph representations capture some chemical information. Further analysis and interpretation (e.g.&nbsp;tune t-SNE perplexity, or try UMAP) of these embeddings can be performed to understand the relationships between molecular structures and their properties.</p>
</section>
<section id="disclosures" class="level1">
<h1>Disclosures</h1>
<p>The code was written with the aid of Claude Sonnet 5, and the model training was performed on Google Colab Pro+ with a Tesla T4 GPU. The accuracy of the code was verified by the author.</p>
</section>
<section id="references" class="level1">
<h1>References</h1>
<ul>
<li>Yang, K. et al.&nbsp;“Analyzing Learned Molecular Representations for Property Prediction.” <em>J. Chem. Inf. Model.</em> 2019, 59, 8, 3370–3388.</li>
<li>Heid, E. et al.&nbsp;“Chemprop: A Machine Learning Package for Chemical Property Prediction.” <em>J. Chem. Inf. Model.</em> 2024, 64, 1, 9–17.</li>
<li>Xu, K. et al.&nbsp;“How Powerful are Graph Neural Networks?” ICLR 2019. (GIN)</li>
<li>Hu, W. et al.&nbsp;“Strategies for Pre-training Graph Neural Networks.” ICLR 2020. (GINE’s edge-feature extension)</li>
<li>Wu, Z. et al.&nbsp;“MoleculeNet: A Benchmark for Molecular Machine Learning.” <em>Chem. Sci.</em> 2018, 9, 513–530.</li>
<li>Bemis, G.W.; Murcko, M.A.&nbsp;“The Properties of Known Drugs. 1. Molecular Frameworks.” <em>J. Med. Chem.</em> 1996, 39, 15, 2887–2893. (Bemis-Murcko scaffolds)</li>
<li>Huang, R. et al.&nbsp;“Tox21 Challenge to Build Predictive Models of Nuclear Receptor and Stress Response Pathways as Mediated by Exposure to Environmental Chemicals and Drugs.” <em>Front. Environ. Sci.</em> 2016.</li>
<li><a href="https://projects.volkamerlab.org/teachopencadd/talktorials/T035_graph_neural_networks.html">TeachOpenCADD GNN tutorial (T035)</a></li>
<li><a href="https://github.com/rdkit/rdkit/issues/1527">RDKit <code>Ipc</code> descriptor overflow, GitHub issue #1527</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Deep Learning</category>
  <category>Graph Neural Network</category>
  <category>PyTorch</category>
  <category>Cheminformatics</category>
  <category>Machine Learning</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/</guid>
  <pubDate>Fri, 24 Jul 2026 07:00:00 GMT</pubDate>
  <media:content url="https://tiny-lab-bioml.netlify.app/posts/p11_tox21_gnn/images/pic3.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Querying ChEMBL for Target-Specific Bioactivity and Compound Data in Python</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/p10_chembl_query/</link>
  <description><![CDATA[ 





<section id="chembl-target-query" class="level1">
<h1>chEMBL target query</h1>
<p>Small, reusable Python utilities for pulling target-specific bioactivity and compound data from <a href="https://www.ebi.ac.uk/chembl/">ChEMBL</a> given a UniProt ID, and evaluating those compounds against Lipinski’s rule of five — adapted from <a href="https://projects.volkamerlab.org/teachopencadd/talktorials/T001_query_chembl.html">TeachOpenCADD T001: Compound data acquisition (ChEMBL)</a> and <a href="https://projects.volkamerlab.org/teachopencadd/talktorials/T002_compound_adme.html">T002: Molecular filtering (Ro5)</a>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p10_chembl_query/images/chembl_egfr_pic50_vs_mw.png" class="img-fluid figure-img"></p>
<figcaption>Synthetic data representing pIC50 vs.&nbsp;molecular weight for EGFR inhibitors</figcaption>
</figure>
</div>
<p>Given a UniProt accession (e.g.&nbsp;<code>P00533</code> for EGFR), it:</p>
<ol type="1">
<li>Looks up the matching ChEMBL target(s)</li>
<li>Fetches IC50 bioactivity data (human, exact measurements, binding assays)</li>
<li>Filters to nM units and deduplicates by compound</li>
<li>Fetches canonical SMILES for the resulting compounds</li>
<li>Merges bioactivity + compound data and computes pIC50</li>
<li>Optionally adds Lipinski’s rule of five (Ro5) property columns</li>
</ol>
<p>… and returns a tidy <code>pandas.DataFrame</code> with columns:</p>
<p><code>| molecule_chembl_id | IC50 | units | smiles | pIC50 |</code></p>
<p>Adding Ro5 properties appends: <code>molecular_weight</code>, <code>n_hba</code>, <code>n_hbd</code>, <code>logp</code>, <code>ro5_fulfilled</code>.</p>
<section id="installation" class="level2">
<h2 class="anchored" data-anchor-id="installation">Installation</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">git</span> clone https://github.com/jaychung10010/chembl-target-query.git</span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> chembl-target-query</span>
<span id="cb1-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-r</span> requirements.txt</span></code></pre></div></div>
</section>
<section id="usage" class="level2">
<h2 class="anchored" data-anchor-id="usage">Usage</h2>
<p>A UniProt accession can map to multiple ChEMBL target entries (single protein, protein family, chimeric construct, protein-protein interaction, etc.), so the workflow is split into two steps — inspect, then extract. This avoids blocking <code>input()</code> prompts, so it works in any environment (plain scripts, Jupyter, agent-driven IDEs like Antigravity/Cursor where stdin isn’t interactive).</p>
<div id="e8704e7e" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> get_chembl_bioactivity_data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> fetch_chembl_targets, get_chembl_bioactivity_data</span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 1: see what ChEMBL targets match this UniProt ID</span></span>
<span id="cb2-4">targets_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fetch_chembl_targets(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"P00533"</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># EGFR</span></span>
<span id="cb2-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(targets_df)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Found 17 ChEMBL target(s) matching 'P00533':

        organism                                                                             pref_name target_chembl_id                  target_type
0   Homo sapiens                                                      Epidermal growth factor receptor        CHEMBL203               SINGLE PROTEIN
1   Homo sapiens                                                      Epidermal growth factor receptor        CHEMBL203               SINGLE PROTEIN
2   Homo sapiens                            Epidermal growth factor receptor and ErbB2 (HER1 and HER2)    CHEMBL2111431               PROTEIN FAMILY
3   Homo sapiens                                                      Epidermal growth factor receptor    CHEMBL2363049               PROTEIN FAMILY
4   Homo sapiens                            MER intracellular domain/EGFR extracellular domain chimera    CHEMBL3137284             CHIMERIC PROTEIN
5   Homo sapiens                                     Protein cereblon/Epidermal growth factor receptor    CHEMBL4523680  PROTEIN-PROTEIN INTERACTION
6   Homo sapiens                                                                           EGFR/PPP1CA    CHEMBL4523747  PROTEIN-PROTEIN INTERACTION
7   Homo sapiens           von Hippel-Lindau disease tumor suppressor/Epidermal growth factor receptor    CHEMBL4523998  PROTEIN-PROTEIN INTERACTION
8   Homo sapiens          Baculoviral IAP repeat-containing protein 2/Epidermal growth factor receptor    CHEMBL4802031  PROTEIN-PROTEIN INTERACTION
9   Homo sapiens                                                                             CCN2-EGFR    CHEMBL5465557  PROTEIN-PROTEIN INTERACTION
10  Homo sapiens  Microtubule-associated protein 1 light chain 3 beta/Epidermal growth factor receptor    CHEMBL6066839  PROTEIN-PROTEIN INTERACTION
11  Homo sapiens        Glucose-induced degradation protein 4 homolog/Epidermal growth factor receptor    CHEMBL6066845  PROTEIN-PROTEIN INTERACTION
12  Homo sapiens                     E3 ubiquitin-protein ligase Mdm2/Epidermal growth factor receptor    CHEMBL6193792  PROTEIN-PROTEIN INTERACTION
13  Homo sapiens                                                  UBR/Epidermal growth factor receptor    CHEMBL6193830  PROTEIN-PROTEIN INTERACTION
14  Homo sapiens       Protein zyg-11 homolog B/Protein zer-1 homolog/Epidermal growth factor receptor    CHEMBL6193837  PROTEIN-PROTEIN INTERACTION
15  Mus musculus                                     Protein cereblon/Epidermal growth factor receptor    CHEMBL6193841  PROTEIN-PROTEIN INTERACTION
16  Homo sapiens                   E3 ubiquitin-protein ligase RNF149/Epidermal growth factor receptor    CHEMBL6195769  PROTEIN-PROTEIN INTERACTION

Inspect the table above, then call get_chembl_bioactivity_data('P00533', target_index=&lt;row&gt;) with your chosen row index.</code></pre>
<div id="1f1be6dd" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 2: extract bioactivity + compound data for the target you want</span></span>
<span id="cb4-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (inspect targets_df above, then pick its row index)</span></span>
<span id="cb4-3">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_chembl_bioactivity_data(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"P00533"</span>, target_index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb4-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(df.head())</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>molecule_chembl_id   IC50 units  \
0        CHEMBL63786  0.003    nM   
1        CHEMBL35820  0.006    nM   
2        CHEMBL53711  0.006    nM   
3        CHEMBL66031  0.008    nM   
4      CHEMBL5270693  0.008    nM   

                                              smiles      pIC50  
0                  Brc1cccc(Nc2ncnc3cc4ccccc4cc23)c1  11.522879  
1                CCOc1cc2ncnc(Nc3cccc(Br)c3)c2cc1OCC  11.221849  
2                 CN(C)c1cc2c(Nc3cccc(Br)c3)ncnc2cn1  11.221849  
3                Brc1cccc(Nc2ncnc3cc4[nH]cnc4cc23)c1  11.096910  
4  COc1cc(N2CCC(N(C)C)CC2)ccc1Nc1ncc(C(=O)Oc2cccc...  11.096910</code></pre>
<p><strong>Adding Lipinski’s rule of five (Ro5) properties:</strong></p>
<div id="d7558640" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> get_chembl_bioactivity_data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> add_ro5_properties</span>
<span id="cb6-2"></span>
<span id="cb6-3">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_ro5_properties(df)</span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># adds: molecular_weight, n_hba, n_hbd, logp, ro5_fulfilled</span></span>
<span id="cb6-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(df.head())</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>molecule_chembl_id   IC50 units  \
0        CHEMBL63786  0.003    nM   
1        CHEMBL35820  0.006    nM   
2        CHEMBL53711  0.006    nM   
3        CHEMBL66031  0.008    nM   
4      CHEMBL5270693  0.008    nM   

                                              smiles      pIC50  \
0                  Brc1cccc(Nc2ncnc3cc4ccccc4cc23)c1  11.522879   
1                CCOc1cc2ncnc(Nc3cccc(Br)c3)c2cc1OCC  11.221849   
2                 CN(C)c1cc2c(Nc3cccc(Br)c3)ncnc2cn1  11.221849   
3                Brc1cccc(Nc2ncnc3cc4[nH]cnc4cc23)c1  11.096910   
4  COc1cc(N2CCC(N(C)C)CC2)ccc1Nc1ncc(C(=O)Oc2cccc...  11.096910   

   molecular_weight  n_hba  n_hbd    logp  ro5_fulfilled  
0        349.021459      3      1  5.2891           True  
1        387.058239      5      1  4.9333           True  
2        343.043258      5      1  3.5969           True  
3        339.011957      4      2  4.0122           True  
4        562.269239      8      2  6.1267          False</code></pre>
<p><strong>Skipping <code>target_index</code></strong> falls back to auto-selecting the first <code>SINGLE PROTEIN</code> + <code>Homo sapiens</code> match (printing a warning if none exists) — useful for unattended/batch runs over many targets:</p>
<div id="a8126472" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">targets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"P00533"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Q00534"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"P07900"</span>]  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># example UniProt IDs</span></span>
<span id="cb8-2">results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {uid: get_chembl_bioactivity_data(uid) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> uid <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> targets}</span></code></pre></div></div>
</details>
</div>
</section>
<section id="api" class="level2">
<h2 class="anchored" data-anchor-id="api">API</h2>
<section id="fetch_chembl_targetsuniprot_id-str---pd.dataframe" class="level3">
<h3 class="anchored" data-anchor-id="fetch_chembl_targetsuniprot_id-str---pd.dataframe">fetch_chembl_targets(uniprot_id: str) -&gt; pd.DataFrame</h3>
<p>Queries and prints all ChEMBL targets matching a UniProt accession. Returns the DataFrame so you can inspect <code>target_type</code>, <code>organism</code>, and <code>pref_name</code> before choosing which row to extract.</p>
</section>
<section id="get_chembl_bioactivity_datauniprot_id-target_indexnone-show_progresstrue---pd.dataframe" class="level3">
<h3 class="anchored" data-anchor-id="get_chembl_bioactivity_datauniprot_id-target_indexnone-show_progresstrue---pd.dataframe">get_chembl_bioactivity_data(uniprot_id, target_index=None, show_progress=True) -&gt; pd.DataFrame</h3>
<p>Runs the full extraction pipeline for the selected target and returns the merged, filtered bioactivity + compound DataFrame with pIC50 values.</p>
</section>
<section id="convert_ic50_to_pic50ic50_value-float---float" class="level3">
<h3 class="anchored" data-anchor-id="convert_ic50_to_pic50ic50_value-float---float">convert_ic50_to_pic50(ic50_value: float) -&gt; float</h3>
<p>Converts an IC50 value in nM to pIC50 (<code>9 - log10(IC50)</code>).</p>
</section>
<section id="calculate_ro5_propertiessmiles-str---pd.series" class="level3">
<h3 class="anchored" data-anchor-id="calculate_ro5_propertiessmiles-str---pd.series">calculate_ro5_properties(smiles: str) -&gt; pd.Series</h3>
<p>Computes molecular weight, H-bond acceptor/donor counts, logP, and Lipinski’s rule of five compliance (<code>ro5_fulfilled</code>, True if no more than one of the four Ro5 conditions is violated) for a single SMILES string.</p>
</section>
<section id="add_ro5_propertiesdataframe-pd.dataframe-smiles_col-str-smiles---pd.dataframe" class="level3">
<h3 class="anchored" data-anchor-id="add_ro5_propertiesdataframe-pd.dataframe-smiles_col-str-smiles---pd.dataframe">add_ro5_properties(dataframe: pd.DataFrame, smiles_col: str = “smiles”) -&gt; pd.DataFrame</h3>
<p>Applies <code>calculate_ro5_properties</code> to every row of a DataFrame (e.g.&nbsp;the output of <code>get_chembl_bioactivity_data</code>) and returns a copy with the Ro5 columns appended.</p>
</section>
</section>
<section id="notes" class="level2">
<h2 class="anchored" data-anchor-id="notes">Notes</h2>
<ul>
<li>Query speed depends heavily on how much bioactivity data exists for the target (a target can take from several seconds up to ~20 minutes) and on EBI server load — there’s no documented SLA for the public ChEMBL API.</li>
<li>This follows the exact filtering logic from TeachOpenCADD T001: IC50 measurements only, exact relation (<code>=</code>), binding assays (<code>B</code>), nM units, first-seen compound kept on duplicates.</li>
</ul>
</section>
<section id="acknowledgments" class="level2">
<h2 class="anchored" data-anchor-id="acknowledgments">Acknowledgments</h2>
<p>Built on the <a href="https://github.com/chembl/chembl_webresource_client"><code>chembl_webresource_client</code></a> and adapted from the <a href="https://github.com/volkamerlab/teachopencadd">TeachOpenCADD</a> platform (Volkamer Lab, Charité/FU Berlin).</p>
</section>
<section id="license" class="level2">
<h2 class="anchored" data-anchor-id="license">License</h2>
<p>MIT — see <a href="https://github.com/jaychung10010/chembl-target-query?tab=MIT-1-ov-file">LICENSE</a>.</p>


</section>
</section>

 ]]></description>
  <category>Python</category>
  <category>ChEMBL</category>
  <category>Cheminformatics</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/p10_chembl_query/</guid>
  <pubDate>Sun, 05 Jul 2026 07:00:00 GMT</pubDate>
</item>
<item>
  <title>Diagnosing Overfitting in a PPI Transformer: Hyperparameter Search and What Actually Helped</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/</link>
  <description><![CDATA[ 





<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>A hyperparameter search was conducted to diagnose and mitigate overfitting in a transformer-based model for predicting Protein-Protein Interactions (PPIs). The search explored variations in dropout rates, latent dimensions, and weight decay. The results showed that increasing dropout and reducing model size mildly improved generalization, while weight decay had a less pronounced effect. The best configuration achieved an AUROC improvement of ~0.02 on the leakage-reduced test set compared to the baseline. These results suggest that while hyperparameter tuning can provide modest gains, the model may have reached a possible performance ceiling given the current architecture and mean-pooled ESM2 embeddings. Further improvements are likely to require architectural changes or data augmentation strategies.</p>
</section>
<section id="the-problem" class="level2">
<h2 class="anchored" data-anchor-id="the-problem">The problem</h2>
<p>In my <a href="https://tiny-lab-bioml.netlify.app/posts/p8_ppi_transformer_predictor/">previous post</a>, I built a transformer-based model to predict PPIs trained from the HuRI dataset. The model achieved an AUROC of 0.75 and accuracy of 0.67 on leakage-reduced test data, which is comparable to the performance of existing models in the literature (<a href="https://academic.oup.com/bioinformatics/article/41/Supplement_1/i590/8199378">Reim et al.&nbsp;2025</a>). However, looking at the training and validation AUROC curves, it was clear that the model was overfitting to the training data quite early on. The training AUROC quickly reached 0.9 within the first few epochs, while the validation AUROC plateaued around 0.74 and even started to decline after epoch 10. This indicated that the model was learning patterns specific to the training data that did not generalize well to unseen data.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/previous_auroc.png" class="img-fluid figure-img"></p>
<figcaption>Training and validation AUROC curves showing overfitting.</figcaption>
</figure>
</div>
</section>
<section id="hypothesis" class="level2">
<h2 class="anchored" data-anchor-id="hypothesis">Hypothesis</h2>
<p>I hypothesized that the overfitting was due to the model being too complex for the amount of training data available, and that tuning the hyperparameters could help mitigate this issue. Specifically, I wanted to investigate how different hyperparameters such as latent dimension (model size), dropout rate, and weight decay affected the model’s performance and generalization ability.</p>
</section>
<section id="experimental-design" class="level2">
<h2 class="anchored" data-anchor-id="experimental-design">Experimental design</h2>
<p>Let’s look at the model architecture again:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/light_img1.png" class="img-fluid figure-img"></p>
<figcaption>Model architecture diagram.</figcaption>
</figure>
</div>
<p>I defined 8 sets of hyperparameter configurations to test, including variations in dropout rates for the projection, attention, and MLP layers, as well as different latent dimensions and weight decay values. The configurations were designed to systematically explore the effects of increasing dropout, reducing model size, and applying stronger regularization through weight decay.</p>
<div id="f96656d1" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define hp space</span></span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Label, Dropout (proj, attn, mlp), latent dim, weight_decay</span></span>
<span id="cb1-3">CONFIGS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-4">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"baseline"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>),</span>
<span id="cb1-5">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"high_dropout"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>),</span>
<span id="cb1-6">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"small_model"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>),</span>
<span id="cb1-7">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"small+dropout"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>),</span>
<span id="cb1-8">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"small+wd"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>),</span>
<span id="cb1-9">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"small+all"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>),</span>
<span id="cb1-10">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tiny_model"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>),</span>
<span id="cb1-11">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tiny+dropout"</span>, (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>),</span>
<span id="cb1-12">]</span></code></pre></div></div>
</details>
</div>
<p>Many of the training utilities were already defined in <a href="https://tiny-lab-bioml.netlify.app/posts/p8_ppi_transformer_predictor/#model-architecture-1">the previous post</a> so will not be shown here, such as:<br>
</p>
<ul>
<li><code>PPIModel</code>, <code>train</code>, <code>evaluate</code>, <code>get_loss_fn</code>, <code>MetricHistory</code><br>
</li>
<li><code>train_loader</code>, <code>val_loader</code>, <code>test_loader</code><br>
</li>
<li><code>train_dataset</code>, <code>val_dataset</code>, <code>test_dataset</code><br>
</li>
</ul>
<p>Here are some of the new functions that I defined for this hyperparameter search:<br>
</p>
<ul>
<li><code>build_model_and_optimizer</code>: This function takes in the hyperparameters and builds the PPIModel, sets up the optimizer with appropriate weight decay, and defines a learning rate scheduler. It also counts the number of trainable parameters in the model for later analysis.<br>
</li>
<li><code>run_hyperparameter_search</code>: This function iterates through the defined CONFIGS, builds the model for each configuration, and runs the training loop. It records the training history, number of parameters, and checkpoint path for each configuration in a dictionary.<br>
</li>
<li><code>evaluate_all_on_test</code>: After training all models, this function loads each model from its checkpoint and evaluates it on the test set, recording various metrics such as AUROC, AUPRC, F1 score, MCC, and accuracy in a DataFrame for easy comparison.</li>
</ul>
<div id="ca342b50" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to instantiate model and utilities</span></span>
<span id="cb2-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_model_and_optimizer(</span>
<span id="cb2-3">    proj_drop, attn_drop, mlp_drop, latent_dim, weight_decay,</span>
<span id="cb2-4">    lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>,</span>
<span id="cb2-5">):</span>
<span id="cb2-6">    torch.manual_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb2-7">    device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb2-8">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Using device: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>device<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb2-9"></span>
<span id="cb2-10">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPIModel(</span>
<span id="cb2-11">        esm2_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>,</span>
<span id="cb2-12">        latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim,</span>
<span id="cb2-13">        num_heads <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>),  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># scale heads with latent_dim</span></span>
<span id="cb2-14">        num_layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb2-15">        ffn_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb2-16">        hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb2-17">        proj_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> proj_drop,</span>
<span id="cb2-18">        attn_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> attn_drop,</span>
<span id="cb2-19">        mlp_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mlp_drop,</span>
<span id="cb2-20">    ).to(device)</span>
<span id="cb2-21"></span>
<span id="cb2-22">    decay_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb2-23">    no_decay_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb2-24"></span>
<span id="cb2-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, param <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.named_parameters():</span>
<span id="cb2-26">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> param.requires_grad:</span>
<span id="cb2-27">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb2-28">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bias'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> param.dim() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="cb2-29">            no_decay_params.append(param)</span>
<span id="cb2-30">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb2-31">            decay_params.append(param)</span>
<span id="cb2-32"></span>
<span id="cb2-33">    optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.AdamW([</span>
<span id="cb2-34">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'params'</span>: decay_params, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'weight_decay'</span>: weight_decay},</span>
<span id="cb2-35">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'params'</span>: no_decay_params, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'weight_decay'</span>: <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>},</span>
<span id="cb2-36">    ], lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>)</span>
<span id="cb2-37"></span>
<span id="cb2-38">    scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.lr_scheduler.ReduceLROnPlateau(</span>
<span id="cb2-39">        optimizer, mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>, patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, factor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, min_lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-7</span></span>
<span id="cb2-40">    )</span>
<span id="cb2-41"></span>
<span id="cb2-42">    n_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(p.numel() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.parameters() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> p.requires_grad)</span>
<span id="cb2-43"></span>
<span id="cb2-44">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> model, optimizer, scheduler, device, n_params</span></code></pre></div></div>
</details>
</div>
<div id="b19ee062" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to run hp search</span></span>
<span id="cb3-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> run_hyperparameter_search(</span>
<span id="cb3-3">    configs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CONFIGS,</span>
<span id="cb3-4">    train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb3-5">    val_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb3-6">    loss_fn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb3-7">    save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb3-8">    n_epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb3-9">    early_stop_limit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>,</span>
<span id="cb3-10">):</span>
<span id="cb3-11">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Iterate through CONFIGS to build model and perform training.</span></span>
<span id="cb3-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Record metrics and hp information in a dictionary.</span></span>
<span id="cb3-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb3-15"></span>
<span id="cb3-16">    all_results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {} <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># record: history, n_params, config, checkpoint</span></span>
<span id="cb3-17"></span>
<span id="cb3-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, (label, dropout, latent_dim, weight_decay) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(configs):</span>
<span id="cb3-19"></span>
<span id="cb3-20">      proj_drop, attn_drop, mlp_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dropout</span>
<span id="cb3-21"></span>
<span id="cb3-22">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'═'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">65</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-23">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Config </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(configs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-24">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  dropout=(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>proj_drop<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>attn_drop<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mlp_drop<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)  "</span></span>
<span id="cb3-25">                <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"latent_dim=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>latent_dim<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  weight_decay=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>weight_decay<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-26">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'═'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">65</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-27"></span>
<span id="cb3-28">      model, optimizer, scheduler, device, n_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_model_and_optimizer(</span>
<span id="cb3-29">          proj_drop, attn_drop, mlp_drop, latent_dim, weight_decay</span>
<span id="cb3-30">      )</span>
<span id="cb3-31">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Parameters: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_params<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:,}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  (</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_loader.dataset)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.1f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> params/sample)"</span>)</span>
<span id="cb3-32"></span>
<span id="cb3-33">      history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train(</span>
<span id="cb3-34">          model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model,</span>
<span id="cb3-35">          train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_loader,</span>
<span id="cb3-36">          val_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_loader,</span>
<span id="cb3-37">          optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> optimizer,</span>
<span id="cb3-38">          scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scheduler,</span>
<span id="cb3-39">          loss_fn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_fn,</span>
<span id="cb3-40">          device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> device,</span>
<span id="cb3-41">          n_epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n_epochs,</span>
<span id="cb3-42">          early_stop_limit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> early_stop_limit,</span>
<span id="cb3-43">          checkpoint_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/hparam_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'+'</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">.pt"</span>,</span>
<span id="cb3-44">      )</span>
<span id="cb3-45"></span>
<span id="cb3-46">      all_results[label] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb3-47">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>: history,</span>
<span id="cb3-48">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_params"</span>: n_params,</span>
<span id="cb3-49">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"config"</span>: (dropout, latent_dim, weight_decay),</span>
<span id="cb3-50">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ckpt"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/hparam_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'+'</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">.pt"</span>,</span>
<span id="cb3-51">      }</span>
<span id="cb3-52"></span>
<span id="cb3-53">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"All hyperparameter searches completed."</span>)</span>
<span id="cb3-54">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> all_results</span></code></pre></div></div>
</details>
</div>
<div id="a2e1668c" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to evaluate on test data</span></span>
<span id="cb4-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> evaluate_all_on_test(all_results, test_loader, loss_fn):</span>
<span id="cb4-3">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Evaluate all models on test data.</span></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Build model -&gt; load checkpoint -&gt; evaluate -&gt; record metrics.</span></span>
<span id="cb4-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Return a pd.DataFrame with all metrics.</span></span>
<span id="cb4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb4-8">    device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb4-9">    rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb4-10"></span>
<span id="cb4-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> label, res <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_results.items():</span>
<span id="cb4-12">      dropout, latent_dim, weight_decay <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"config"</span>]</span>
<span id="cb4-13">      proj_drop, attn_drop, mlp_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dropout</span>
<span id="cb4-14"></span>
<span id="cb4-15">      model, _, _, _, n_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_model_and_optimizer(</span>
<span id="cb4-16">          proj_drop, attn_drop, mlp_drop, latent_dim, weight_decay</span>
<span id="cb4-17">      )</span>
<span id="cb4-18"></span>
<span id="cb4-19">      model.load_state_dict(torch.load(res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ckpt"</span>]))</span>
<span id="cb4-20">      model.to(device)</span>
<span id="cb4-21">      model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb4-22"></span>
<span id="cb4-23">      _, auroc, auprc, probs, labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate(</span>
<span id="cb4-24">          model, test_loader, loss_fn, device</span>
<span id="cb4-25">      )</span>
<span id="cb4-26"></span>
<span id="cb4-27">      preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb4-28"></span>
<span id="cb4-29">      rows.append({</span>
<span id="cb4-30">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"config"</span>: label,</span>
<span id="cb4-31">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_params"</span>: n_params,</span>
<span id="cb4-32">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"latent_dim"</span>: latent_dim,</span>
<span id="cb4-33">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dropout"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>proj_drop<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>attn_drop<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mlp_drop<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)"</span>,</span>
<span id="cb4-34">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"weight_decay"</span>: weight_decay,</span>
<span id="cb4-35">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_auroc"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(auroc, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-36">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_auprc"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(auprc, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-37">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f1"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(f1_score(labels, preds), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-38">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"precision"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(precision_score(labels, preds), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-39">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"recall"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(recall_score(labels, preds), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-40">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mcc"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(matthews_corrcoef(labels, preds), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-41">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"accuracy"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(accuracy_score(labels, preds), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-42">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Best val AUROC from training (for reference)</span></span>
<span id="cb4-43">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"best_val_auroc"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>].history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-44">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Train-val gap at best epoch</span></span>
<span id="cb4-45">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gap_at_best"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(</span>
<span id="cb4-46">                res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>].history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>][</span>
<span id="cb4-47">                    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.argmax(res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>].history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>]))</span>
<span id="cb4-48">                ] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>].history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>]), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb4-49">            ),</span>
<span id="cb4-50">        })</span>
<span id="cb4-51"></span>
<span id="cb4-52">      <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:20s}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  test_auroc=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>auroc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  test_auprc=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>auprc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  "</span></span>
<span id="cb4-53">              <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"mcc=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>rows[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mcc'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-54"></span>
<span id="cb4-55">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(rows).sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_auroc"</span>, ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb4-56">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># columns are metrics, rows are configs</span></span>
<span id="cb4-57">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df</span></code></pre></div></div>
</details>
</div>
</section>
<section id="results-discussions" class="level2">
<h2 class="anchored" data-anchor-id="results-discussions">Results &amp; discussions</h2>
<p>The different hyperparameter configurations had varying effects on the training dynamics and final performance. To visualize these differences, I created several plotting functions:<br>
</p>
<ul>
<li><code>plot_learning_curves_comparison</code>: This function plots the validation AUROC, AUPRC, validation loss, and the gap between training and validation AUROC for all configurations on the same axes. This allows for easy comparison of how each configuration affected the learning curves and overfitting behavior.<br>
</li>
<li><code>plot_train_val_curves_per_config</code>: This function creates a grid of plots, where each plot shows the training and validation AUROC curves for a single configuration. This is a more traditional way to diagnose overfitting for each model individually.<br>
</li>
<li><code>plot_test_metrics_comparison</code>: This function creates bar charts comparing the test AUROC, AUPRC, F1 score, and MCC across all configurations. The bars are annotated with the metric values and the best-performing configuration is highlighted.<br>
</li>
</ul>
<div id="118235ae" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_learning_curves_comparison(all_results, save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb5-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb5-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Plots val AUROC, val AUPRC, val Loss, and train/val AUROC gap</span></span>
<span id="cb5-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    for all configs on the same axes for easy comparison.</span></span>
<span id="cb5-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb5-6">    labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(all_results.keys())</span>
<span id="cb5-7">    colors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cm.tab10(np.linspace(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(labels)))</span>
<span id="cb5-8"></span>
<span id="cb5-9">    fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>))</span>
<span id="cb5-10">    fig.suptitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hyperparameter Comparison — Learning Curves"</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, fontweight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bold'</span>)</span>
<span id="cb5-11"></span>
<span id="cb5-12">    metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb5-13">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>,  axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Val AUROC"</span>,  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max"</span>, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>]),</span>
<span id="cb5-14">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auprc"</span>,  axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Val AUPRC"</span>,  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max"</span>, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>]),</span>
<span id="cb5-15">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_loss"</span>,   axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Val Loss"</span>,   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"min"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>),</span>
<span id="cb5-16">        (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,         axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Train−Val AUROC Gap"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"min"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>),  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># special</span></span>
<span id="cb5-17">    ]</span>
<span id="cb5-18"></span>
<span id="cb5-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> metric_key, ax, title, _, ylim <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> metrics:</span>
<span id="cb5-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> label, color <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(labels, colors):</span>
<span id="cb5-21">            h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> all_results[label][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>].history</span>
<span id="cb5-22">            epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb5-23"></span>
<span id="cb5-24">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> metric_key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb5-25">                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Gap plot</span></span>
<span id="cb5-26">                gap <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [tr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> vl <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tr, vl <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>], h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>])]</span>
<span id="cb5-27">                ax.plot(epochs, gap, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>label, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>color, linewidth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span>)</span>
<span id="cb5-28">                ax.axhline(y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gray'</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>)</span>
<span id="cb5-29">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb5-30">                ax.plot(epochs, h[metric_key], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>label, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>color, linewidth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span>)</span>
<span id="cb5-31"></span>
<span id="cb5-32">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Mark best val AUROC epoch with a dot</span></span>
<span id="cb5-33">            best_ep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.argmax(h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>])) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb5-34">            best_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>][best_ep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb5-35">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> metric_key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>:</span>
<span id="cb5-36">                ax.scatter(best_ep, best_val, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>color, s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>, zorder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb5-37"></span>
<span id="cb5-38">        ax.set_title(title, fontweight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bold'</span>)</span>
<span id="cb5-39">        ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>)</span>
<span id="cb5-40">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb5-41">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ylim:</span>
<span id="cb5-42">            ax.set_ylim(ylim)</span>
<span id="cb5-43">        ax.legend(fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, loc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'best'</span>)</span>
<span id="cb5-44"></span>
<span id="cb5-45">    plt.tight_layout()</span>
<span id="cb5-46">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> save_path:</span>
<span id="cb5-47">        out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/hparam_learning_curves.png"</span></span>
<span id="cb5-48">        plt.savefig(out, dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>, bbox_inches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tight'</span>)</span>
<span id="cb5-49">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Saved → </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>out<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb5-50">    plt.show()</span></code></pre></div></div>
</details>
</div>
<div id="9be93c4d" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_train_val_curves_per_config(all_results, save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb6-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    For each config, plots train vs val AUROC side by side —</span></span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    the standard overfitting diagnostic view.</span></span>
<span id="cb6-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb6-6">    n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_results)</span>
<span id="cb6-7">    ncols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb6-8">    nrows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.ceil(n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ncols))</span>
<span id="cb6-9">    fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(nrows, ncols, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ncols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.5</span>, nrows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.5</span>))</span>
<span id="cb6-10">    axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> axes.flatten()</span>
<span id="cb6-11"></span>
<span id="cb6-12">    fig.suptitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Train vs Val AUROC per Config"</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>, fontweight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bold'</span>)</span>
<span id="cb6-13"></span>
<span id="cb6-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, (label, res) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(all_results.items()):</span>
<span id="cb6-15">        h   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"history"</span>].history</span>
<span id="cb6-16">        ax  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> axes[i]</span>
<span id="cb6-17">        eps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb6-18">        best_ep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.argmax(h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>])) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb6-19"></span>
<span id="cb6-20">        ax.plot(eps, h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Train"</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span>)</span>
<span id="cb6-21">        ax.plot(eps, h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>],   label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Val"</span>,   color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"coral"</span>,     lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.8</span>)</span>
<span id="cb6-22">        ax.axvline(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>best_ep, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gray'</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>,</span>
<span id="cb6-23">                   label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Best ep </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>best_ep<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb6-24"></span>
<span id="cb6-25">        best_val  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"val_auroc"</span>])</span>
<span id="cb6-26">        gap       <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> h[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_auroc"</span>][best_ep<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> best_val</span>
<span id="cb6-27">        n_params  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> res[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_params"</span>]</span>
<span id="cb6-28">        ax.set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">Best val=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>best_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  gap=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>gap<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.3f}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_params<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:,}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> params"</span>,</span>
<span id="cb6-29">                     fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb6-30">        ax.set_ylim([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>])</span>
<span id="cb6-31">        ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb6-32">        ax.legend(fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>)</span>
<span id="cb6-33">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb6-34"></span>
<span id="cb6-35">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hide unused subplots</span></span>
<span id="cb6-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(axes)):</span>
<span id="cb6-37">        axes[j].set_visible(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb6-38"></span>
<span id="cb6-39">    plt.tight_layout()</span>
<span id="cb6-40">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> save_path:</span>
<span id="cb6-41">        out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/hparam_per_config_curves.png"</span></span>
<span id="cb6-42">        plt.savefig(out, dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>, bbox_inches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tight'</span>)</span>
<span id="cb6-43">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Saved → </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>out<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb6-44">    plt.show()</span></code></pre></div></div>
</details>
</div>
<div id="a6f0568a" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_test_metrics_comparison(results_df, save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb7-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Bar chart comparing test AUROC, AUPRC, F1, and MCC across all configs.</span></span>
<span id="cb7-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Configs sorted by test AUROC descending.</span></span>
<span id="cb7-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb7-6">    metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_auroc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_auprc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mcc"</span>]</span>
<span id="cb7-7">    titles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test AUROC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test AUPRC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"F1 Score"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MCC"</span>]</span>
<span id="cb7-8">    labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> results_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"config"</span>].tolist()</span>
<span id="cb7-9">    x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.arange(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(labels))</span>
<span id="cb7-10">    colors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cm.tab10(np.linspace(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(labels)))</span>
<span id="cb7-11"></span>
<span id="cb7-12">    fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>))</span>
<span id="cb7-13">    fig.suptitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test Set Performance by Hyperparameter Config"</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>, fontweight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bold'</span>)</span>
<span id="cb7-14"></span>
<span id="cb7-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> ax, metric, title <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(axes.flatten(), metrics, titles):</span>
<span id="cb7-16">        vals <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> results_df[metric].tolist()</span>
<span id="cb7-17">        bars <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.bar(x, vals, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>colors, edgecolor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'white'</span>, linewidth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb7-18"></span>
<span id="cb7-19">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Annotate bars</span></span>
<span id="cb7-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> bar, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(bars, vals):</span>
<span id="cb7-21">            ax.text(bar.get_x() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> bar.get_width() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, bar.get_height() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.005</span>,</span>
<span id="cb7-22">                    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>v<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.3f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'center'</span>, va<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bottom'</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>)</span>
<span id="cb7-23"></span>
<span id="cb7-24">        ax.set_title(title, fontweight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bold'</span>)</span>
<span id="cb7-25">        ax.set_xticks(x)</span>
<span id="cb7-26">        ax.set_xticklabels(labels, rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">35</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'right'</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb7-27">        ax.set_ylim([<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(vals) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(vals) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.08</span>)])</span>
<span id="cb7-28">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'y'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb7-29"></span>
<span id="cb7-30">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Highlight best</span></span>
<span id="cb7-31">        best_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.argmax(vals))</span>
<span id="cb7-32">        bars[best_idx].set_edgecolor(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'black'</span>)</span>
<span id="cb7-33">        bars[best_idx].set_linewidth(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>)</span>
<span id="cb7-34"></span>
<span id="cb7-35">    plt.tight_layout()</span>
<span id="cb7-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> save_path:</span>
<span id="cb7-37">        out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/hparam_test_metrics.png"</span></span>
<span id="cb7-38">        plt.savefig(out, dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>, bbox_inches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tight'</span>)</span>
<span id="cb7-39">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Saved → </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>out<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-40">    plt.show()</span></code></pre></div></div>
</details>
</div>
<p>Now let’s run everything and discuss the results as we go along.</p>
<div id="8241677e" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run hp search</span></span>
<span id="cb8-2">loss_fn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_loss_fn(label_smoothing<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, pos_weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span>
<span id="cb8-3"></span>
<span id="cb8-4">save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PPI_prediction"</span></span>
<span id="cb8-5"></span>
<span id="cb8-6">all_results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> run_hyperparameter_search(</span>
<span id="cb8-7">    configs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CONFIGS,</span>
<span id="cb8-8">    train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_loader,</span>
<span id="cb8-9">    val_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_loader,</span>
<span id="cb8-10">    loss_fn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_fn,</span>
<span id="cb8-11">    save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> save_path,</span>
<span id="cb8-12">    n_epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb8-13">    early_stop_limit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>,</span>
<span id="cb8-14">)</span></code></pre></div></div>
</details>
</div>
<div id="9b3b7ed7" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot learning curves: compare configs</span></span>
<span id="cb9-2">plot_learning_curves_comparison(all_results, save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>save_path)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_learning_curves_1.png" class="img-fluid"></p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_learning_curves_2.png" class="img-fluid"></p>
<ul>
<li>Looking at validation AUROC and AUPRC, the metrics appear to peak at around 0.74 no matter the model configuration, suggesting that this might be the performance plateau that the current data setting can reach - meaning that the bottleneck is likely not the model architecture, but the limitation of mean-pooled ESM2 embeddings and the size of the HuRI dataset to generalize to unseen PPIs.</li>
</ul>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_learning_curves_3.png" class="img-fluid"></p>
<ul>
<li>Looking at the train-val AUROC gap curve, it appears that reducing the model size or increasing regularization/dropouts did reduce the severity of overfitting, albeit not sufficient to significantly improve the best validation AUROC.</li>
</ul>
<p>Let’s look at the actual train vs val AUROC curves for each configuration to see how the overfitting dynamics differ:</p>
<div id="a883029e" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot learning curves: compare train vs. val per config</span></span>
<span id="cb10-2">plot_train_val_curves_per_config(all_results, save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>save_path)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_per_config_curves_1.png" class="img-fluid"></p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_per_config_curves_2.png" class="img-fluid"></p>
<ul>
<li>Looking at the per-config train-vs-val curves, the reduction in the train-val gap is driven primarily by a lower training AUROC at later epochs — not by a meaningful increase in validation AUROC.</li>
</ul>
<p>Now we will evaluate the best model checkpoint for each config on the leakage-reduced test set to see if there is any improvement in test performance:</p>
<div id="e4a70c2e" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">results_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate_all_on_test(all_results, test_loader, loss_fn)</span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results_df.to_string(index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>))</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>       config  n_params  latent_dim       dropout  weight_decay  test_auroc  test_auprc     f1  precision  recall    mcc  accuracy  best_val_auroc  gap_at_best
small+dropout   2666241         256 (0.2,0.2,0.4)           0.1      0.7690      0.7683 0.5110     0.8101  0.3732 0.3393    0.6429          0.7375       0.2000
     small+wd   2666241         256 (0.1,0.1,0.3)           0.3      0.7666      0.7451 0.5851     0.7854  0.4662 0.3709    0.6694          0.7356       0.1759
  small_model   2666241         256 (0.1,0.1,0.3)           0.1      0.7663      0.7448 0.5867     0.7848  0.4684 0.3715    0.6700          0.7363       0.1751
    small+all   2666241         256 (0.2,0.2,0.4)           0.3      0.7653      0.7693 0.5401     0.8180  0.4031 0.3636    0.6567          0.7443       0.1988
   tiny_model    833409         128 (0.1,0.1,0.3)           0.1      0.7636      0.7623 0.5513     0.7837  0.4252 0.3462    0.6539          0.7358       0.2144
 high_dropout   9330177         512 (0.3,0.3,0.5)           0.1      0.7619      0.7538 0.5873     0.7548  0.4806 0.3483    0.6622          0.7439       0.1814
 tiny+dropout    833409         128 (0.3,0.3,0.5)           0.2      0.7599      0.7469 0.5802     0.7770  0.4629 0.3608    0.6650          0.7343       0.1945
     baseline   9330177         512 (0.1,0.1,0.3)           0.1      0.7466      0.7470 0.6314     0.7195  0.5626 0.3518    0.6717          0.7390       0.1688</code></pre>
<div id="c8fed633" class="cell" data-execution_count="12">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot test metrics across configs</span></span>
<span id="cb13-2">plot_test_metrics_comparison(results_df, save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>save_path)</span></code></pre></div></div>
</details>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_test_metrics_1.png" class="img-fluid figure-img"></p>
<figcaption>Test AUROC ranked by AUROC</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/images/hparam_test_metrics_2.png" class="img-fluid figure-img"></p>
<figcaption>Test AUPRC ranked by AUROC</figcaption>
</figure>
</div>
<ul>
<li>Looking at the test metrics, which is the most important indication of how the model is performing, the smaller models with stronger dropouts/regularization generally improved the performance when compared with the baseline. Among these models, the “small+dropout” showed consistently higher AUROC and AUPRC, which both improved by ~0.02, suggesting that this model config is most adequate for the data.</li>
<li>Why is there a disconnect between some AUROCs vs AUPRCs? AUROC measures the model’s ability to rank positives above negatives across all classification thresholds, treating both classes symmetrically. AUPRC, by contrast, focuses on the precision-recall trade-off and is more sensitive to how well the model identifies true positives with high confidence. Even on balanced datasets, the two metrics can diverge when a model ranks most positives correctly (good AUROC) but with poor confidence separation at high-score ranges (lower AUPRC). This is worth keeping in mind when calling out the best-performing model — a configuration that wins on AUROC may not win on AUPRC, as we see here with <code>small+dropout</code> vs <code>small+all</code>.</li>
</ul>
</section>
<section id="future-directions" class="level2">
<h2 class="anchored" data-anchor-id="future-directions">Future directions</h2>
<p>Now that there is a better understanding of how hyperparameter tuning affects the performance of the PPI transformer model, perhaps there are other avenues to explore. In future posts, I’ll investigate whether per-token (non-mean-pooled) embeddings or isoform-based data augmentation — selecting multiple isoforms per protein within a defined similarity band — can push past this ceiling.</p>
</section>
<section id="disclosures" class="level2">
<h2 class="anchored" data-anchor-id="disclosures">Disclosures</h2>
<p>The code was written with the aid of Claude Sonnet 4.6, and the model training was performed on Google Colab Pro+ with a Tesla T4 GPU. The accuracy of the codes were verified by the author.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/40662806/">Reim T, Hartebrodt A, Blumenthal DB, Bernett J, List M. Deep learning models for unbiased sequence-based PPI prediction plateau at an accuracy of 0.65. Bioinformatics. 2025 Jul 1;41(Supplement_1):i590-i598. doi: 10.1093/bioinformatics/btaf192. PMID: 40662806; PMCID: PMC12261406.</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/36927031/">Lin Z, Akin H, Rao R, Hie B, Zhu Z, Lu W, Smetanin N, Verkuil R, Kabeli O, Shmueli Y, Dos Santos Costa A, Fazel-Zarandi M, Sercu T, Candido S, Rives A. Evolutionary-scale prediction of atomic-level protein structure with a language model. Science. 2023 Mar 17;379(6637):1123-1130. doi: 10.1126/science.ade2574. Epub 2023 Mar 16. PMID: 36927031.</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/32296183/">Luck K, Kim DK, Lambourne L, Spirohn K, Begg BE, Bian W, Brignall R, Cafarelli T, Campos-Laborie FJ, Charloteaux B, Choi D, Coté AG, Daley M, Deimling S, Desbuleux A, Dricot A, Gebbia M, Hardy MF, Kishore N, Knapp JJ, Kovács IA, Lemmens I, Mee MW, Mellor JC, Pollis C, Pons C, Richardson AD, Schlabach S, Teeking B, Yadav A, Babor M, Balcha D, Basha O, Bowman-Colin C, Chin SF, Choi SG, Colabella C, Coppin G, D’Amata C, De Ridder D, De Rouck S, Duran-Frigola M, Ennajdaoui H, Goebels F, Goehring L, Gopal A, Haddad G, Hatchi E, Helmy M, Jacob Y, Kassa Y, Landini S, Li R, van Lieshout N, MacWilliams A, Markey D, Paulson JN, Rangarajan S, Rasla J, Rayhan A, Rolland T, San-Miguel A, Shen Y, Sheykhkarimli D, Sheynkman GM, Simonovsky E, Taşan M, Tejeda A, Tropepe V, Twizere JC, Wang Y, Weatheritt RJ, Weile J, Xia Y, Yang X, Yeger-Lotem E, Zhong Q, Aloy P, Bader GD, De Las Rivas J, Gaudet S, Hao T, Rak J, Tavernier J, Hill DE, Vidal M, Roth FP, Calderwood MA. A reference map of the human binary protein interactome. Nature. 2020 Apr;580(7803):402-408. doi: 10.1038/s41586-020-2188-x. Epub 2020 Apr 8. PMID: 32296183; PMCID: PMC7169983.</a></li>
<li><a href="https://arxiv.org/abs/2102.09548">Therapeutics Data Commons: Machine Learning Datasets and Tasks for Drug Discovery and Development</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Deep Learning</category>
  <category>Transformer</category>
  <category>PyTorch</category>
  <category>ESM2</category>
  <category>Protein Language Models</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/p9_ppi_model_hp_tuning/</guid>
  <pubDate>Mon, 22 Jun 2026 07:00:00 GMT</pubDate>
</item>
<item>
  <title>Predicting Protein-Protein Interactions with ESM2 Embeddings and Transformer-based Interaction Model</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/</link>
  <description><![CDATA[ 





<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>Using the PyTorch framework, I built a transformer-based model to predict Protein-Protein Interactions (PPIs) trained from the HuRI dataset. The workflow takes a pair of protein sequences as input, extracts ESM2 embeddings, and predicts the probability of interaction. The model achieved an AUPRC of 0.75 and accuracy of 0.67 on leakage-reduced test data, which is comparable to the performance of existing models in the literature. The transformer model significantly outperformed a baseline random forest model, which achieved an AUPRC of 0.62 and accuracy of 0.59 on the same test set.</p>
</section>
<section id="research-impact" class="level2">
<h2 class="anchored" data-anchor-id="research-impact">Research Impact</h2>
<p>Why is it important to build a PPI predictor?</p>
<ol type="1">
<li><p><strong>Drug discovery and disease mechanism:</strong> PPI is fundamental to how proteins carry out their functions in the cell. Identifying interaction partners of a drug target can help us understand the target’s biological role and its involvement in disease pathways. Many diseases involve dysregulated PPIs, often by disrupting normal interactions or creating new ones through functional mutations. Predicting how these mutations affect PPIs can help us better understand disease mechanisms and identify potential therapeutic targets. In addition, a PPI predictor model can be used for off-target screening of protein biologics, which is crucial for drug safety and efficacy.</p></li>
<li><p><strong>Proteome-wide interaction networks:</strong> Current large-scale PPI screen like HuRI contains roughly ~9,000 proteins, while the human proteome contains ~20,000 proteins, many of which are understudied. A trained model can be used to explore these unknown PPIs, potentially expanding our knowledge of interactome without the costs and time of experimental screens. A generalized PPI prediction model can be applied to other species as well, or to cross-species interaction like virus-host protein interaction, helping us understand the biology of non-model organisms and infectious diseases.</p></li>
<li><p><strong>Contributing to the PPI deep learning field:</strong> By utilizing state-of-the-art models like ESM2 and transformer architectures, I aim to see if building a model with comparable performance to existing models is possible. This contributes to the broader question of how much interaction-relevant information is already encoded in ESM2 embeddings, and whether further optimization of the model architecture can lead to significant performance gains. I will also address the issue of data leakage in PPI prediction, which is a common pitfall that can lead to overestimated performance. By carefully designing the training and evaluation strategy to avoid data leakage, I hope to provide a more realistic assessment of the model’s predictive power.</p></li>
</ol>
</section>
<section id="background" class="level2">
<h2 class="anchored" data-anchor-id="background">Background</h2>
<p>Last year, a paper by <a href="https://academic.oup.com/bioinformatics/article/41/Supplement_1/i590/8199378">Reim et al.&nbsp;(2025)</a> compared various deep learning architectures for PPI prediction, including models with attention mechanisms and incorporation of <a href="https://www.science.org/doi/10.1126/science.ade2574">ESM2 protein language model</a>. They found that regardless of the model architecture or the hyperparameter space, all models seemed to plateau at an accuracy of 0.65. They concluded that any performance gains observed are attributable to the use of ESM2 embeddings, rather than the model architecture itself. The paper also provided some interesting observations about the ESM2 model usage; for example, models profited from smaller embeddings (t33), and that per-token embeddings (sequence information preserved) did not yield better performance than per-protein embeddings (mean embeddings across sequence).</p>
<p>Inspired by this paper, I want to see if I can build a model with comparable performance, albeit with a different model design. I decided to use the <a href="https://interactome-atlas.org/">HuRI PPI dataset</a> for training and evaluation, rather than the <a href="https://cbdm-01.zdv.uni-mainz.de/~mschaefer/hippie/">HIPPIE dataset</a> used in the paper. The HuRI dataset came from a Yeast-2-Hybrid (Y2H) screen that contains ~9,000 proteins and ~64,000 experimental validated interactions. The HIPPIE dataset is a literature-curated dataset that is much larger but may also bias toward more well-studied proteins. Due to the difference in dataset size and quality, my result may not be directly comparable to the <code>Reim et al.</code> paper, but I will compare the transformer performance with a baseline random forest model to see if the transformer architecture provides any performance gain over a simpler model.</p>
<p>Many papers in the PPI prediction field have pointed out the issue of data leakage, which is when the same or similar proteins appear in both training and test sets, leading to overestimated performance. To address this, I will implement a leakage-reduced splitting strategy that ensures that proteins in the test set are not similar or present in the training set. This will provide a more realistic assessment of the model’s generalization ability.</p>
</section>
<section id="model-architecture" class="level2">
<h2 class="anchored" data-anchor-id="model-architecture">Model architecture</h2>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/images/light_img1.png" class="img-fluid"></p>
<p>The model contains four main components:&nbsp;</p>
<ol type="1">
<li><strong>ESM2 mean embedding extractor:</strong> a pre-trained ESM2 model that takes amino acid sequences of two proteins and generates their per-protein mean embeddings (EmbA and EmbB). I will use the <code>t33_650M_UR50D</code> variant of ESM2, which has been shown to perform well for PPI prediction in the <em>Reim et al.</em> paper.<br>
</li>
<li><strong>Protein projector:</strong> a feedforward neural network that takes the embeddings and projects them to a lower-dimensional space. Both proteins pass through identical weight, which forces a common geometry before interaction modeling.<br>
</li>
<li><strong>Interaction transformer:</strong> a transformer encoder that takes the projected embeddings of the two proteins and models their interactions. Because the protein pair is only 2 tokens, self-attention can be considered as cross-attention, and each protein attends to the other and itself. The transformer will have multiple layers of self-attention and feedforward networks to capture complex interaction patterns between the two proteins.<br>
</li>
<li><strong>PPI classifier:</strong> the MLP concatenates the output of the interaction transformer with two symmetric features of <code>|EmbA - EmbB|</code> and <code>EmbA * EmbB</code> (absolute difference and products), which gave the model more flexibility to learn the interaction-relevant information. The MLP will output a probability score indicating the likelihood of interaction between the two proteins.</li>
</ol>
<p>One caveat for the HuRI data is that the Y2H experiment is prone to false positives, which might exacerbate the issue of overfitting, meaning that the model will predict well on training data but could not generalized to unseen test data. To deal with this, these features were added to the model design:<br>
</p>
<ol type="1">
<li>Model training features that deals with overfitting: dropouts, L2 regularization (AdamW + weight decay), adaptive learning rate, and early stopping.<br>
</li>
<li>Label smoothing function to make sure that the target label is not overly confident on positive or negative outcomes.<br>
</li>
<li>Symmetric augmentation function that switch protein pairs randomly before training.</li>
</ol>
<p>Another consideration is the size of the model vs.&nbsp;training sample size. With around 50k of HuRI training samples, this is on the lower side of training a 9.3 million parameters transformer model. 9.3M params / 50k samples = 180 params per sample. Normally it would be great to get this ratio to &lt; 100 to prevent overfitting, but given that the model is not learning everything from scratch - ESM2 did the initial heavy lifting - this setting might be acceptable.</p>
</section>
<section id="data-processing" class="level2">
<h2 class="anchored" data-anchor-id="data-processing">1. Data processing</h2>
<p>First, I will download the positive interactions HuRI data from <a href="https://tdcommons.ai/multi_pred_tasks/ppi/">TDC</a>, and then process and clean up the data. A protein similarity-aware split will be performed to obtain the train, validation and test data. HuRI data only contains positive interactions, so I will also perform negative sampling to generate negative interaction samples for each of the split. This is done after the splitting to avoid further data leakage, as the negative samples are generated based on the proteins present in each split.</p>
<section id="data-download" class="level3">
<h3 class="anchored" data-anchor-id="data-download">Data download</h3>
<div id="fc41becc" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> tdc.multi_pred <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PPI</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load the HuRI dataset</span></span>
<span id="cb1-4">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPI(name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'HuRI'</span>)</span>
<span id="cb1-5">ppi_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.get_data()</span>
<span id="cb1-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(ppi_data)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>           Protein1_ID                                           Protein1  \
0      ENSG00000000005  MAKNPPENCEDCHILNAEAFKSKKICKSLKICGLVFGILALTLIVL...   
1      ENSG00000000005  MAKNPPENCEDCHILNAEAFKSKKICKSLKICGLVFGILALTLIVL...   
2      ENSG00000000005  MAKNPPENCEDCHILNAEAFKSKKICKSLKICGLVFGILALTLIVL...   
3      ENSG00000000005  MAKNPPENCEDCHILNAEAFKSKKICKSLKICGLVFGILALTLIVL...   
4      ENSG00000000005  MAKNPPENCEDCHILNAEAFKSKKICKSLKICGLVFGILALTLIVL...   
...                ...                                                ...   
52364  ENSG00000273899  MGRNKKKKRDGDDRRPRLVLSFDEEKRREYLTGFHKRKVERKKAAI...   
52365  ENSG00000275302  MKLCVTVLSLLMLVAAFCSPALSAPMGSDPPTACCFSYTARKLPRN...   
52366  ENSG00000275774  MASNVTNKMDPHSVNSRVFIGNLNTLVVKKSDVEAIFSKYGKIAGC...   
52367  ENSG00000276070  MKLCVTVLSLLVLVAAFCSLALSAPMGSDPPTACCFSYTARKLPRN...   
52368  ENSG00000276076  MPVCPGDSHRPPKALPHLVCGRRGRQVRSDRDKFVIFLDVKHFSPE...   

           Protein2_ID                                           Protein2  Y  
0      ENSG00000061656  MRRSSRPGSASSSRKHTPNFFSENSSMSITSEDSKGLRSAEPGPGE...  1  
1      ENSG00000099968  MASSSTVPLGFHYETKYVVLSYLGLLSQEKLQEQHLSSPQGVQLDI...  1  
2      ENSG00000104765  MSSHLVEPPPPLHNNNNNCEENEQSLPPPAGLNSSWVELPMNSSNG...  1  
3      ENSG00000105383  MPLLLLLPLLWAGALAMDPNFWLQVQESVTVQEGLCVLVPCTFFHP...  1  
4      ENSG00000114455  MKAQTALSFFLILITSLSGSQGIFPLAFFIYVPMNEQIVIGRLDED...  1  
...                ...                                                ... ..  
52364  ENSG00000273899  MGRNKKKKRDGDDRRPRLVLSFDEEKRREYLTGFHKRKVERKKAAI...  1  
52365  ENSG00000278619  MEVMDVFSTDDLTGFLQTKAQQGWLVAGTVGCPSTEDPQSSEIPIM...  1  
52366  ENSG00000275774  MASNVTNKMDPHSVNSRVFIGNLNTLVVKKSDVEAIFSKYGKIAGC...  1  
52367  ENSG00000278619  MEVMDVFSTDDLTGFLQTKAQQGWLVAGTVGCPSTEDPQSSEIPIM...  1  
52368  ENSG00000276076  MPVCPGDSHRPPKALPHLVCGRRGRQVRSDRDKFVIFLDVKHFSPE...  1  

[52369 rows x 5 columns]</code></pre>
<p>There are 52,369 positive interactions in the HuRI dataset. The “Protein1_ID” and “Protein2_ID” columns contain the Ensembl gene IDs of the interacting proteins, while the “Protein1” and “Protein2” columns contain the corresponding amino acid sequences. The “Y” column indicates that these are positive interactions (Y=1).</p>
</section>
<section id="processing-protein-isoforms" class="level3">
<h3 class="anchored" data-anchor-id="processing-protein-isoforms">Processing protein isoforms</h3>
<p>In this dataset, some proteins have multiple sequences associated with them, which may represent different isoforms or variants. The sequences are separated by asterisks (*). For example, if a protein has two sequences, the “Protein1” column may contain “MSEQ1*MSEQ2”. To make sure I don’t exclude any sequence motifs, I will take the longest isoform for each gene name. This is a simplification, as negative samples may be confounded by the inclusion of interaction motifs that are actually not present in the experiment. But it is a necessary step to train the model. Here I will make a dictionary mapping each gene name to its longest isoform.</p>
<div id="37f53508" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> create_protein_sequence_dict(df):</span>
<span id="cb3-2">    protein_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb3-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index, row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> df.iterrows():</span>
<span id="cb3-4">        protein1_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein1_ID"</span>]</span>
<span id="cb3-5">        protein2_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein2_ID"</span>]</span>
<span id="cb3-6">        protein1_seq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein1"</span>]</span>
<span id="cb3-7">        protein2_seq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein2"</span>]</span>
<span id="cb3-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> protein1_id <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> protein_dict:</span>
<span id="cb3-9">            protein_dict[protein1_id] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(protein1_seq.split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*"</span>), key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Take the longest sequence if there are multiple</span></span>
<span id="cb3-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> protein2_id <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> protein_dict:</span>
<span id="cb3-11">            protein_dict[protein2_id] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(protein2_seq.split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*"</span>), key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>)  </span>
<span id="cb3-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> protein_dict</span>
<span id="cb3-13"></span>
<span id="cb3-14">protein_sequence_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_protein_sequence_dict(ppi_data)</span>
<span id="cb3-15"></span>
<span id="cb3-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save protein sequence dictionary locally</span></span>
<span id="cb3-17"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb3-18">save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/path_to_data"</span></span>
<span id="cb3-19">np.save(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/protein_sequence_dict.npy"</span>, protein_sequence_dict)</span></code></pre></div></div>
</details>
</div>
<div id="221fd69c" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sequence length statistics: max, min, mean, median</span></span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> statistics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> median</span>
<span id="cb4-3">sequence_lengths <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> protein_sequence_dict.values()]</span>
<span id="cb4-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Max protein sequence length: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(sequence_lengths)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Min protein sequence length: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(sequence_lengths)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Mean protein sequence length: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(sequence_lengths) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(sequence_lengths)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.0f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Median protein sequence length: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median(sequence_lengths)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Max protein sequence length: 6907
Min protein sequence length: 25
Mean protein sequence length: 522
Median protein sequence length: 420.0</code></pre>
<div id="1a5da402" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot the distribution of sequence lengths</span></span>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ESM2 has a maximum sequence length of 1022</span></span>
<span id="cb6-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb6-4">plt.hist(sequence_lengths, bins<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'blue'</span>, edgecolor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'black'</span>)</span>
<span id="cb6-5">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Distribution of Protein Sequence Lengths'</span>)</span>
<span id="cb6-6">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Sequence Length'</span>)</span>
<span id="cb6-7">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Frequency'</span>)</span>
<span id="cb6-8">plt.axvline(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1022</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'red'</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ESM2 max length: 1022'</span>)</span>
<span id="cb6-9">plt.legend()</span>
<span id="cb6-10">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/images/img1.png" class="img-fluid"></p>
<div id="9edbdb63" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Map cleaned protein dictionary to the PPI data</span></span>
<span id="cb7-2">ppi_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein1"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ppi_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein1_ID"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(protein_sequence_dict)</span>
<span id="cb7-3">ppi_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein2"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ppi_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein2_ID"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(protein_sequence_dict)</span>
<span id="cb7-4"></span>
<span id="cb7-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Check that the sequences look fine</span></span>
<span id="cb7-6">all_proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.unique(pd.concat([ppi_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>], ppi_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>]]))</span>
<span id="cb7-7"></span>
<span id="cb7-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Total unique proteins: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Empty sequences      : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>(pd.Series(all_proteins).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Contains '*'         : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Series(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>contains(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">*'</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Contains whitespace  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Series(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>contains(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">s'</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-12"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Min length           : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Series(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb7-13"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Max length           : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Series(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Total unique proteins: 8170
Empty sequences      : 0
Contains '*'         : 0
Contains whitespace  : 0
Min length           : 25
Max length           : 6907</code></pre>
<p>As we can see, some proteins are longer than what the ESM2 model can handle (max 1022 amino acids). To be on the conservative side, I will remove these proteins from the dataset.</p>
<div id="0d213771" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We have another problem now: some proteins are longer than 1022 amino acids, which is the maximum sequence length that ESM2 can handle.</span></span>
<span id="cb9-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> filter_long_proteins(df, protein_dict, max_length<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1022</span>):</span>
<span id="cb9-3">    filtered_rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb9-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index, row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> df.iterrows():</span>
<span id="cb9-5">        protein1_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein1_ID"</span>]</span>
<span id="cb9-6">        protein2_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Protein2_ID"</span>]</span>
<span id="cb9-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(protein_dict[protein1_id]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> max_length <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(protein_dict[protein2_id]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> max_length:</span>
<span id="cb9-8">            filtered_rows.append(row)</span>
<span id="cb9-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Removed </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(df) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(filtered_rows)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> protein pairs with sequences longer than </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>max_length<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> amino acids"</span>)</span>
<span id="cb9-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">Remaining protein pairs: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(filtered_rows)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> pd.DataFrame(filtered_rows)</span>
<span id="cb9-12"></span>
<span id="cb9-13">ppi_data_filtered <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> filter_long_proteins(ppi_data, protein_sequence_dict)</span>
<span id="cb9-14"></span>
<span id="cb9-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># If two genes both map to the same sequence after picking longest, will get duplicate (Protein1, Protein2) pairs - remove these</span></span>
<span id="cb9-16">before <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(ppi_data_filtered)</span>
<span id="cb9-17">ppi_data_filtered <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ppi_data_filtered.drop_duplicates(subset<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>])</span>
<span id="cb9-18"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Removed </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>before <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(ppi_data_filtered)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> duplicate pairs after isoform resolution"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Removed 7179 protein pairs with sequences longer than 1022 amino acids

Remaining protein pairs: 45190

Removed 689 duplicate pairs after isoform resolution</code></pre>
<div id="3b94bd02" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">total_pairs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(ppi_data_filtered)</span>
<span id="cb11-2">total_proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(ppi_data_filtered[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> ppi_data_filtered[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>].tolist()))</span>
<span id="cb11-3">pos_perct <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(ppi_data_filtered[ppi_data_filtered[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> total_pairs</span>
<span id="cb11-4">neg_perct <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(ppi_data_filtered[ppi_data_filtered[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> total_pairs</span>
<span id="cb11-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"total protein pairs: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>total_pairs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | total unique proteins: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>total_proteins<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | positive: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pos_perct<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.1%}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | negative: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>neg_perct<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.1%}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb11-6"></span>
<span id="cb11-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save processed data locally</span></span>
<span id="cb11-8">ppi_data_filtered.to_feather(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/ppi_data_filtered.feather"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>total protein pairs: 44501 | total unique proteins: 7357 | positive: 100.0% | negative: 0.0%</code></pre>
<p>I get 44,501 positive protein pairs after filtering out long sequences and resolving isoforms. There are 7,357 unique proteins in these pairs. The dataset is currently imbalanced with 100% positive samples, so I will need to perform negative sampling to generate negative interaction samples for training the model. I will do that after the train-val-test split to avoid data leakage.</p>
</section>
<section id="leakage-reduced-splitting" class="level3">
<h3 class="anchored" data-anchor-id="leakage-reduced-splitting">Leakage-reduced splitting</h3>
<p>Here I employed a similarity aware split with CD-HIT to ensure that proteins similar to the test set are not seen during training. This is a rigorous strategy that clusters proteins by sequence similarity before splitting, thus making sure that similar proteins do not show up across the train, validation and test set. A similarity split on HuRI data is estimated to result in ~40-50% of data loss.</p>
<div id="7433f446" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> similarity_aware_split(</span>
<span id="cb13-2">    df: pd.DataFrame,</span>
<span id="cb13-3">    protein_col_a: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>,</span>
<span id="cb13-4">    protein_col_b: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>,</span>
<span id="cb13-5">    similarity_thr: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>,    </span>
<span id="cb13-6">    train_frac: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.70</span>,</span>
<span id="cb13-7">    val_frac: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>,</span>
<span id="cb13-8">    test_frac: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.15</span>,</span>
<span id="cb13-9">    random_state: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>,</span>
<span id="cb13-10">    verbose: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb13-11">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[pd.DataFrame, pd.DataFrame, pd.DataFrame]:</span>
<span id="cb13-12"></span>
<span id="cb13-13">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> subprocess, tempfile, os</span>
<span id="cb13-14">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> Bio <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> SeqIO</span>
<span id="cb13-15">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> Bio.SeqRecord <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> SeqRecord</span>
<span id="cb13-16">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> Bio.Seq <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Seq</span>
<span id="cb13-17">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb13-18">    <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb13-19"></span>
<span id="cb13-20">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Guard against unsupported threshold</span></span>
<span id="cb13-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> similarity_thr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>:</span>
<span id="cb13-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(</span>
<span id="cb13-23">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"CD-HIT requires similarity_thr &gt;= 0.4. Got </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>similarity_thr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb13-24">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Use similarity_aware_split_nokmer() for thresholds below 0.4."</span></span>
<span id="cb13-25">        )</span>
<span id="cb13-26"></span>
<span id="cb13-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Correct word size per CD-HIT documentation</span></span>
<span id="cb13-28">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>   similarity_thr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>: word_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb13-29">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> similarity_thr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>: word_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb13-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> similarity_thr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>: word_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb13-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:                       word_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>   </span>
<span id="cb13-32"></span>
<span id="cb13-33">    all_proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.unique(</span>
<span id="cb13-34">        pd.concat([df[protein_col_a], df[protein_col_b]])</span>
<span id="cb13-35">    )</span>
<span id="cb13-36">    seq_to_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {seq: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"prot_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(all_proteins)}</span>
<span id="cb13-37">    id_to_seq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {v: k <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> seq_to_id.items()}</span>
<span id="cb13-38"></span>
<span id="cb13-39">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> verbose:</span>
<span id="cb13-40">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Running CD-HIT on </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> proteins "</span></span>
<span id="cb13-41">              <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"(similarity threshold: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>similarity_thr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.0%}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, "</span></span>
<span id="cb13-42">              <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"word size: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>word_size<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)..."</span>)</span>
<span id="cb13-43"></span>
<span id="cb13-44">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> tempfile.TemporaryDirectory() <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tmpdir:</span>
<span id="cb13-45">        fasta_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> os.path.join(tmpdir, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proteins.fasta"</span>)</span>
<span id="cb13-46">        output_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> os.path.join(tmpdir, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"clustered"</span>)</span>
<span id="cb13-47">        cluster_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> output_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".clstr"</span></span>
<span id="cb13-48"></span>
<span id="cb13-49">        records <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb13-50">            SeqRecord(Seq(seq), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seq_to_id[seq], description<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb13-51">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_proteins</span>
<span id="cb13-52">        ]</span>
<span id="cb13-53">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(fasta_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'w'</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> f:</span>
<span id="cb13-54">            SeqIO.write(records, f, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fasta"</span>)</span>
<span id="cb13-55"></span>
<span id="cb13-56">        cmd <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb13-57">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cd-hit"</span>,</span>
<span id="cb13-58">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-i"</span>, fasta_path,</span>
<span id="cb13-59">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-o"</span>, output_path,</span>
<span id="cb13-60">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-c"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(similarity_thr),</span>
<span id="cb13-61">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-n"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(word_size),</span>
<span id="cb13-62">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-T"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4"</span>,</span>
<span id="cb13-63">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-M"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"4000"</span>,</span>
<span id="cb13-64">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-d"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0"</span>,</span>
<span id="cb13-65">        ]</span>
<span id="cb13-66">        result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subprocess.run(cmd, capture_output<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, text<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-67"></span>
<span id="cb13-68">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> result.returncode <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb13-69">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">RuntimeError</span>(</span>
<span id="cb13-70">                <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"CD-HIT failed (return code </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>returncode<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">):</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb13-71">                <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"STDOUT: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>stdout[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb13-72">                <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"STDERR: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>result<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>stderr[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb13-73">            )</span>
<span id="cb13-74"></span>
<span id="cb13-75">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Parse cluster file</span></span>
<span id="cb13-76">        protein_to_cluster <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb13-77">        current_cluster <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb13-78">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(cluster_path) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> f:</span>
<span id="cb13-79">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> line <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> f:</span>
<span id="cb13-80">                line <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> line.strip()</span>
<span id="cb13-81">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> line.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&gt;Cluster'</span>):</span>
<span id="cb13-82">                    current_cluster <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(line.split()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb13-83">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> line:</span>
<span id="cb13-84">                    prot_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> line.split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&gt;'</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'...'</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb13-85">                    protein_to_cluster[prot_id] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> current_cluster</span>
<span id="cb13-86"></span>
<span id="cb13-87">    seq_to_cluster <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb13-88">        seq: protein_to_cluster[seq_to_id[seq]]</span>
<span id="cb13-89">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_proteins</span>
<span id="cb13-90">    }</span>
<span id="cb13-91"></span>
<span id="cb13-92">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save protein_to_cluster and seq_to_cluster locally as dataframe</span></span>
<span id="cb13-93">    protein_to_cluster_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame.from_dict(protein_to_cluster, orient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'index'</span>, columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Cluster'</span>])</span>
<span id="cb13-94">    protein_to_cluster_df.index.name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein_ID'</span></span>
<span id="cb13-95">    protein_to_cluster_df.reset_index(inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-96">    protein_to_cluster_df.to_feather(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/protein_to_cluster.feather"</span>)</span>
<span id="cb13-97">    seq_to_cluster_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame.from_dict(seq_to_cluster, orient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'index'</span>, columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Cluster'</span>])</span>
<span id="cb13-98">    seq_to_cluster_df.index.name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein_ID'</span></span>
<span id="cb13-99">    seq_to_cluster_df.reset_index(inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-100">    seq_to_cluster_df.to_feather(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/seq_to_cluster.feather"</span>)</span>
<span id="cb13-101"></span>
<span id="cb13-102">    all_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(seq_to_cluster.values()))</span>
<span id="cb13-103">    n_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_clusters)</span>
<span id="cb13-104"></span>
<span id="cb13-105">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> verbose:</span>
<span id="cb13-106">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> proteins → </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_clusters<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> clusters"</span>)</span>
<span id="cb13-107"></span>
<span id="cb13-108">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Split at cluster level</span></span>
<span id="cb13-109">    rng <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.default_rng(random_state)</span>
<span id="cb13-110">    rng.shuffle(all_clusters)</span>
<span id="cb13-111"></span>
<span id="cb13-112">    n_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> train_frac)</span>
<span id="cb13-113">    n_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(n_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> val_frac)</span>
<span id="cb13-114"></span>
<span id="cb13-115">    train_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(all_clusters[:n_train])</span>
<span id="cb13-116">    val_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(all_clusters[n_train : n_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> n_val])</span>
<span id="cb13-117">    test_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(all_clusters[n_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> n_val:])</span>
<span id="cb13-118"></span>
<span id="cb13-119">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> assign_split(row):</span>
<span id="cb13-120">        ca <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> seq_to_cluster[row[protein_col_a]]</span>
<span id="cb13-121">        cb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> seq_to_cluster[row[protein_col_b]]</span>
<span id="cb13-122">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ca <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_clusters <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> cb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_clusters: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span></span>
<span id="cb13-123">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ca <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> val_clusters   <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> cb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> val_clusters:   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val'</span></span>
<span id="cb13-124">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ca <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_clusters  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> cb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_clusters:  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span></span>
<span id="cb13-125">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'discard'</span></span>
<span id="cb13-126"></span>
<span id="cb13-127">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb13-128">    df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(assign_split, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb13-129"></span>
<span id="cb13-130">    train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>].drop(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-131">    val_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val'</span>].drop(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-132">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>].drop(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-133">    discarded <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_split'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'discard'</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb13-134"></span>
<span id="cb13-135">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> verbose:</span>
<span id="cb13-136">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">Pair split:"</span>)</span>
<span id="cb13-137">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train pairs    : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-138">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Val pairs      : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-139">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Test pairs     : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(test_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-140">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Discarded pairs: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>discarded<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb13-141"></span>
<span id="cb13-142">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> train_df, val_df, test_df</span>
<span id="cb13-143">  </span>
<span id="cb13-144">train_df, val_df, test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> similarity_aware_split(ppi_data, similarity_thr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Running CD-HIT on 7357 proteins (similarity threshold: 40%, word size: 2)...
  7357 proteins → 5967 clusters

Pair split:
  Train pairs    : 23653
  Val pairs      : 916
  Test pairs     : 903
  Discarded pairs: 19029</code></pre>
<p>A total of 19,029 pairs were discarded because they contained proteins that were similar across splits. This is a significant reduction in data size, but it is necessary to ensure that the model’s performance is not overestimated due to data leakage.</p>
<p>Let’s verify that there is no protein overlap between the splits:</p>
<div id="4ce4d069" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># A function to validate that no data leakage detected</span></span>
<span id="cb15-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> verify_no_leakage(</span>
<span id="cb15-3">    train_df: pd.DataFrame,</span>
<span id="cb15-4">    val_df: pd.DataFrame,</span>
<span id="cb15-5">    test_df: pd.DataFrame,</span>
<span id="cb15-6">    protein_col_a: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>,</span>
<span id="cb15-7">    protein_col_b: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>,</span>
<span id="cb15-8">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb15-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb15-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Asserts that no protein sequence appears in more than one split.</span></span>
<span id="cb15-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Raises AssertionError if leakage is detected.</span></span>
<span id="cb15-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb15-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_proteins(df):</span>
<span id="cb15-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(df[protein_col_a].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> df[protein_col_b].tolist())</span>
<span id="cb15-15"></span>
<span id="cb15-16">    train_proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_proteins(train_df)</span>
<span id="cb15-17">    val_proteins   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_proteins(val_df)</span>
<span id="cb15-18">    test_proteins  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_proteins(test_df)</span>
<span id="cb15-19"></span>
<span id="cb15-20">    train_val_overlap  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> val_proteins</span>
<span id="cb15-21">    train_test_overlap <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> test_proteins</span>
<span id="cb15-22">    val_test_overlap   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_proteins   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> test_proteins</span>
<span id="cb15-23"></span>
<span id="cb15-24">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">── Leakage Verification ──────────────────────────"</span>)</span>
<span id="cb15-25">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train proteins      : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-26">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Val proteins        : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-27">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Test proteins       : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(test_proteins)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-28">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train ∩ Val overlap : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_val_overlap)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-29">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train ∩ Test overlap: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_test_overlap)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-30">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Val ∩ Test overlap  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_test_overlap)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb15-31"></span>
<span id="cb15-32">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_val_overlap)  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-33">        <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"LEAKAGE: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_val_overlap)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> proteins in both train and val!"</span></span>
<span id="cb15-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_test_overlap) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-35">        <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"LEAKAGE: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_test_overlap)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> proteins in both train and test!"</span></span>
<span id="cb15-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_test_overlap)   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb15-37">        <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"LEAKAGE: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_test_overlap)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> proteins in both val and test!"</span></span>
<span id="cb15-38"></span>
<span id="cb15-39">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"  ✓ Zero protein overlap across all splits — no leakage detected"</span>)</span>
<span id="cb15-40">    </span>
<span id="cb15-41">verify_no_leakage(train_df, val_df, test_df)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>── Leakage Verification ──────────────────────────
  Train proteins      : 4763
  Val proteins        : 549
  Test proteins       : 536
  Train ∩ Val overlap : 0
  Train ∩ Test overlap: 0
  Val ∩ Test overlap  : 0
  ✓ Zero protein overlap across all splits — no leakage detected</code></pre>
</section>
<section id="negative-sampling" class="level3">
<h3 class="anchored" data-anchor-id="negative-sampling">Negative sampling</h3>
<p>A helper function to sample negative pairs within each split:</p>
<div id="ca366f42" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb17-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb17-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> itertools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> combinations</span>
<span id="cb17-4"></span>
<span id="cb17-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sample_negatives_within_split(</span>
<span id="cb17-6">    pos_df: pd.DataFrame,</span>
<span id="cb17-7">    protein_col_a: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1_ID'</span>,</span>
<span id="cb17-8">    protein_col_b: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2_ID'</span>,</span>
<span id="cb17-9">    frac: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>,</span>
<span id="cb17-10">    random_state: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>,</span>
<span id="cb17-11">    label_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>,</span>
<span id="cb17-12">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> pd.DataFrame:</span>
<span id="cb17-13">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb17-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Sample negative PPI pairs using ONLY proteins present in the given split.</span></span>
<span id="cb17-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb17-16"></span>
<span id="cb17-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Make sure the df is all positives</span></span>
<span id="cb17-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span>(pos_df[label_col] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Input dataframe contains negative samples"</span></span>
<span id="cb17-19"></span>
<span id="cb17-20">    rng <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.default_rng(random_state)</span>
<span id="cb17-21"></span>
<span id="cb17-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># All proteins present in this split</span></span>
<span id="cb17-23">    proteins <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(</span>
<span id="cb17-24">        pos_df[protein_col_a].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-25">        pos_df[protein_col_b].tolist()</span>
<span id="cb17-26">    ))</span>
<span id="cb17-27"></span>
<span id="cb17-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Build a set of known positives (both orderings) for fast lookup</span></span>
<span id="cb17-29">    pos_set <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>()</span>
<span id="cb17-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> pos_df.iterrows():</span>
<span id="cb17-31">        a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[protein_col_a], row[protein_col_b]</span>
<span id="cb17-32">        pos_set.add((a, b))</span>
<span id="cb17-33">        pos_set.add((b, a))  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># treat as symmetric</span></span>
<span id="cb17-34"></span>
<span id="cb17-35">    n_negatives <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pos_df) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> frac)</span>
<span id="cb17-36"></span>
<span id="cb17-37">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample candidate negative pairs</span></span>
<span id="cb17-38">    neg_pairs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb17-39">    max_attempts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n_negatives <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># safety cap to avoid infinite loop</span></span>
<span id="cb17-40">    attempts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb17-41"></span>
<span id="cb17-42">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(neg_pairs) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> n_negatives <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> attempts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> max_attempts:</span>
<span id="cb17-43">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample two different proteins at random</span></span>
<span id="cb17-44">        a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rng.choice(proteins, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, replace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb17-45"></span>
<span id="cb17-46">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip self-interactions and known positives</span></span>
<span id="cb17-47">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> b:</span>
<span id="cb17-48">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb17-49">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (a, b) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> pos_set:</span>
<span id="cb17-50">            attempts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb17-51">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb17-52"></span>
<span id="cb17-53">        neg_pairs.append({protein_col_a: a, protein_col_b: b, label_col: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>})</span>
<span id="cb17-54">        pos_set.add((a, b))   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># prevent duplicate negatives</span></span>
<span id="cb17-55">        pos_set.add((b, a))</span>
<span id="cb17-56"></span>
<span id="cb17-57">        attempts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb17-58"></span>
<span id="cb17-59">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(neg_pairs) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> n_negatives:</span>
<span id="cb17-60">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Warning: only sampled </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(neg_pairs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_negatives<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> negatives "</span></span>
<span id="cb17-61">              <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"(protein pool may be too small for requested frac=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>frac<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)"</span>)</span>
<span id="cb17-62"></span>
<span id="cb17-63">    neg_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(neg_pairs)</span>
<span id="cb17-64"></span>
<span id="cb17-65">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Carry over other columns from pos_df (Protein1, Protein2 sequences etc.)</span></span>
<span id="cb17-66">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># by joining on the ID columns if needed</span></span>
<span id="cb17-67">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> pos_df.columns:</span>
<span id="cb17-68">        seq_map <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(</span>
<span id="cb17-69">            pos_df[protein_col_a].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pos_df[protein_col_b].tolist(),</span>
<span id="cb17-70">            pos_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>].tolist()    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> pos_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>].tolist()</span>
<span id="cb17-71">        ))</span>
<span id="cb17-72">        neg_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> neg_df[protein_col_a].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(seq_map)</span>
<span id="cb17-73">        neg_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> neg_df[protein_col_b].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(seq_map)</span>
<span id="cb17-74"></span>
<span id="cb17-75">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Combine and shuffle</span></span>
<span id="cb17-76">    combined <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat(</span>
<span id="cb17-77">        [pos_df.assign(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>{label_col: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>}), neg_df],</span>
<span id="cb17-78">        ignore_index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb17-79">    ).sample(frac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>random_state).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb17-80"></span>
<span id="cb17-81">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> combined</span></code></pre></div></div>
</details>
</div>
<div id="8a697e3d" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_negatives_within_split(train_df, frac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb18-2">val_df   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_negatives_within_split(val_df, frac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">43</span>)</span>
<span id="cb18-3">test_df  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_negatives_within_split(test_df, frac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">44</span>)</span>
<span id="cb18-4"></span>
<span id="cb18-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Check to make sure that positive and negative samples are balanced in all sets</span></span>
<span id="cb18-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> df, name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>([train_df, val_df, test_df], [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"training"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"validation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test"</span>]):</span>
<span id="cb18-7">    positive_samples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Y"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb18-8">    negative_samples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Y"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb18-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Positive samples in </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(positive_samples)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, Negative samples in </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(negative_samples)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Positive samples in training set: 23653, Negative samples in training set: 23653
Positive samples in validation set: 916, Negative samples in validation set: 916
Positive samples in test set: 903, Negative samples in test set: 903</code></pre>
</section>
</section>
<section id="esm2-embedding-extraction" class="level2">
<h2 class="anchored" data-anchor-id="esm2-embedding-extraction">2. ESM2 embedding extraction</h2>
<p>I will now extract ESM2 embeddings from protein sequences:</p>
<ul>
<li>Proteins will first be sorted based on their sequence length. This is to save computational resources by grouping proteins of similar length together for minimizing padding waste.</li>
<li>The protein sequences will then be converted into ESM2 tokens, and then fed into the model to extract the final hidden state/dimension of 1280. I will apply a token mask to the sequence dimension of the embeddings to exclude the starting and end-of-sequence tokens in the calculation of the mean embeddings, so that the final mean embeddingsn will only include actual amino acid sequences.</li>
<li>The embedding for each protein will only be extracted once from the PPI protein dictionary constructed previously. Then it will be saved as a torch tensor dictionary.</li>
</ul>
<div id="c328a1ec" class="cell" data-execution_count="12">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load sequence dictionary</span></span>
<span id="cb20-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb20-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> transformers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AutoTokenizer, EsmModel</span>
<span id="cb20-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb20-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb20-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> tqdm <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tqdm</span>
<span id="cb20-7"></span>
<span id="cb20-8">protein_sequence_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.load(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/protein_sequence_dict.npy"</span>, allow_pickle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'TRUE'</span>).item()</span>
<span id="cb20-9"></span>
<span id="cb20-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load pre-trained ESM2 model and tokenizer</span></span>
<span id="cb20-11">model_checkpoint <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"facebook/esm2_t33_650M_UR50D"</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1280 dim</span></span>
<span id="cb20-12">tokenizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AutoTokenizer.from_pretrained(model_checkpoint)</span>
<span id="cb20-13">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EsmModel.from_pretrained(model_checkpoint)</span></code></pre></div></div>
</details>
</div>
<p>A helper function to extract ESM2 mean embeddings:</p>
<div id="9e92dfd7" class="cell" data-execution_count="13">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to extract mean ESM2 embeddings</span></span>
<span id="cb21-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> extract_mean_embedding(</span>
<span id="cb21-3">    sequence_dict : <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>],</span>
<span id="cb21-4">    tokenizer     : AutoTokenizer,</span>
<span id="cb21-5">    model         : EsmModel,</span>
<span id="cb21-6">    device        : torch.device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb21-7">    batch_size    : <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>,</span>
<span id="cb21-8">    max_len       : <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1022</span>,</span>
<span id="cb21-9">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, np.ndarray]:</span>
<span id="cb21-10"></span>
<span id="cb21-11">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb21-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Extract ESM2 last hidden layer embeddings for protein sequences.</span></span>
<span id="cb21-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Truncate sequences to max_len allowed for ESM2 input.</span></span>
<span id="cb21-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Remove special tokens that are not amino acids.</span></span>
<span id="cb21-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    For each input protein, calculate mean embeddings across amino acids.</span></span>
<span id="cb21-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb21-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> device <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb21-18">        device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb21-19"></span>
<span id="cb21-20">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.to(device)</span>
<span id="cb21-21">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb21-22"></span>
<span id="cb21-23">    sequence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(sequence_dict.values())</span>
<span id="cb21-24">    protein  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(sequence_dict.keys())</span>
<span id="cb21-25"></span>
<span id="cb21-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sort by length before batching to minimize padding waste</span></span>
<span id="cb21-27">    paired   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(sequence, protein), key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]), reverse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb21-28">    sequence, protein <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>paired) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># unzip</span></span>
<span id="cb21-29">    sequence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(sequence)</span>
<span id="cb21-30">    protein  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(protein)</span>
<span id="cb21-31"></span>
<span id="cb21-32">    n_batches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> math.ceil(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(sequence) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> batch_size)</span>
<span id="cb21-33">    all_batch_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb21-34"></span>
<span id="cb21-35">    steps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tqdm(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_batches))</span>
<span id="cb21-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> steps:</span>
<span id="cb21-37">        steps.set_description(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Processing batch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_batches<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb21-38">        start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> batch_size</span>
<span id="cb21-39">        end   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> batch_size</span>
<span id="cb21-40">        batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sequence[start:end]</span>
<span id="cb21-41"></span>
<span id="cb21-42">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Tokenize with padding and max length</span></span>
<span id="cb21-43">        inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokenizer(</span>
<span id="cb21-44">            batch,</span>
<span id="cb21-45">            return_tensors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pt"</span>,</span>
<span id="cb21-46">            padding        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb21-47">            truncation     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># longer than max_len will be truncated</span></span>
<span id="cb21-48">            max_length     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> max_len,</span>
<span id="cb21-49">        )</span>
<span id="cb21-50">        inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {name: tensor.to(device) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, tensor <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> inputs.items()}</span>
<span id="cb21-51"></span>
<span id="cb21-52">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb21-53">            outputs     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>inputs)</span>
<span id="cb21-54">            hidden      <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> outputs.last_hidden_state      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, seq_len, 1280)</span></span>
<span id="cb21-55">            attn_mask   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inputs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'attention_mask'</span>]       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, seq_len)</span></span>
<span id="cb21-56">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1: real token (including &lt;cls&gt; and &lt;eos&gt;), 0: padding token</span></span>
<span id="cb21-57"></span>
<span id="cb21-58">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Exclude &lt;cls&gt; (before start) and &lt;eos&gt; (end-of-sequence) from mean pool</span></span>
<span id="cb21-59">            token_mask          <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> attn_mask.clone()</span>
<span id="cb21-60">            token_mask[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove &lt;cls&gt;</span></span>
<span id="cb21-61">            eos_positions       <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> attn_mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb21-62">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> b, eos_pos <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(eos_positions):</span>
<span id="cb21-63">                token_mask[b, eos_pos] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove &lt;eos&gt;</span></span>
<span id="cb21-64"></span>
<span id="cb21-65">            mask_expanded <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> token_mask.unsqueeze(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, seq_len, 1)</span></span>
<span id="cb21-66">            sum_emb       <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (hidden <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> mask_expanded).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sum across seq_len</span></span>
<span id="cb21-67">            n_tokens      <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> token_mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span>
<span id="cb21-68">            mean_emb      <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (sum_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_tokens).detach().cpu().numpy()</span>
<span id="cb21-69"></span>
<span id="cb21-70">        all_batch_embeddings.append(mean_emb) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list of (B, 1280)</span></span>
<span id="cb21-71"></span>
<span id="cb21-72">    embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate(all_batch_embeddings, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stack along row: (all_prot, 1280)</span></span>
<span id="cb21-73"></span>
<span id="cb21-74">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return as dictionary {protein_id: embedding_vector}</span></span>
<span id="cb21-75">    embedding_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {prot: emb <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> prot, emb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(protein, embeddings)}</span>
<span id="cb21-76">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> embedding_dict</span>
<span id="cb21-77">  </span>
<span id="cb21-78"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extracting embeddings</span></span>
<span id="cb21-79">embedding_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_mean_embedding(protein_sequence_dict, tokenizer, model)</span>
<span id="cb21-80"></span>
<span id="cb21-81"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert to torch tensor dict and save</span></span>
<span id="cb21-82">embedding_tensor_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb21-83">    prot: torch.tensor(emb, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.float32)</span>
<span id="cb21-84">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> prot, emb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> embedding_dict.items()</span>
<span id="cb21-85">}</span>
<span id="cb21-86">torch.save(embedding_tensor_dict, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/esm2_t33_650M_UR50D_embeddings_all_proteins_for_ppi.pt"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Processing batch 129/129: 100%|██████████| 129/129 [30:16&lt;00:00, 14.08s/it]</code></pre>
<p>Let’s plot a t-SNE plot of the extracted ESM2 embeddings to see if there are any visible clusters:</p>
<div id="ba672cbb" class="cell" data-execution_count="14">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get protein embedding dataframe with dataset split information</span></span>
<span id="cb23-2">embedding_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame.from_dict(embedding_dict, orient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'index'</span>)</span>
<span id="cb23-3">embedding_df.index.name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein_ID'</span></span>
<span id="cb23-4">embedding_df.reset_index(inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb23-5"></span>
<span id="cb23-6">train_prot <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1_ID'</span>].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2_ID'</span>].tolist())</span>
<span id="cb23-7">valid_prot <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(valid_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1_ID'</span>].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> valid_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2_ID'</span>].tolist())</span>
<span id="cb23-8">test_prot  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1_ID'</span>].tolist() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2_ID'</span>].tolist())</span>
<span id="cb23-9"></span>
<span id="cb23-10">assign_split <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_prot <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> valid_prot <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span></span>
<span id="cb23-11">embedding_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Split'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein_ID'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(assign_split)</span>
<span id="cb23-12"></span>
<span id="cb23-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot t-SNE scatter plot from the protein embeddings df colored by dataset split type</span></span>
<span id="cb23-14"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb23-15"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb23-16"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.manifold <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> TSNE</span>
<span id="cb23-17"></span>
<span id="cb23-18">tsne <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> TSNE(n_components<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).fit_transform(embedding_df.iloc[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb23-19">tsne_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(tsne, columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tsne1'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tsne2'</span>])</span>
<span id="cb23-20">tsne_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Split"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Split"</span>]</span>
<span id="cb23-21"></span>
<span id="cb23-22">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb23-23">sns.scatterplot(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tsne_df, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tsne1'</span>, y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tsne2'</span>, hue<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Split'</span>, palette<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Set2'</span>,</span>
<span id="cb23-24">                alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span>
<span id="cb23-25">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'t-SNE Visualization of Protein Embeddings'</span>)</span>
<span id="cb23-26">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'t-SNE Dimension 1'</span>)</span>
<span id="cb23-27">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'t-SNE Dimension 2'</span>)</span>
<span id="cb23-28">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/images/img2.png" class="img-fluid"></p>
<p>We can see that from the t-SNE representation of ESM2 embeddings, there are a few major and smaller clusters, likely representing proteins of different properties (e.g.&nbsp;structural, biochemical, sequence properties). Most proteins reside in larger clusters, and it is difficult to differentiate them with mean embeddings and a simple out-of-the-box t-SNE. Hopefully there are subtle information encoded within the embeddings that could be learned by the transformer model below.</p>
</section>
<section id="prepare-datasets" class="level2">
<h2 class="anchored" data-anchor-id="prepare-datasets">3. Prepare datasets</h2>
<p>Using PyTorch’s Dataset and DataLoader for data loading, shuffling and batching:</p>
<ul>
<li>In the PPIDataset class, I only store the PPI dataframe and protein embedding dictionary, not the protein-pair embeddings. During training, the actual embedding for each protein gets look up during batch time by DataLoader through <code>__getitem__</code>. This saves RAM significantly by not repeated saving the same protein embedding in the dataset (e.g.&nbsp;some hub proteins like P53 might have many interactions and will appear many times in the PPI dataset).</li>
</ul>
<div id="66b4f519" class="cell" data-execution_count="15">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch.utils.data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Dataset, DataLoader</span>
<span id="cb24-2"></span>
<span id="cb24-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> PPIDataset(Dataset):</span>
<span id="cb24-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(</span>
<span id="cb24-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb24-6">        df: pd.DataFrame,</span>
<span id="cb24-7">        embedding_dict: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, torch.Tensor],</span>
<span id="cb24-8">        protein_a_id: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1_ID'</span>,</span>
<span id="cb24-9">        protein_b_id: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2_ID'</span>,</span>
<span id="cb24-10">        label_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>,</span>
<span id="cb24-11">    ):</span>
<span id="cb24-12">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.embedding_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict</span>
<span id="cb24-13">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.label_col      <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> label_col</span>
<span id="cb24-14"></span>
<span id="cb24-15">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Filter out rows where either protein has no embedding</span></span>
<span id="cb24-16">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (e.g. proteins that failed extraction or were filtered)</span></span>
<span id="cb24-17">        mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb24-18">            df[protein_a_id].isin(embedding_dict) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span></span>
<span id="cb24-19">            df[protein_b_id].isin(embedding_dict)</span>
<span id="cb24-20">        )</span>
<span id="cb24-21">        n_dropped <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>mask).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb24-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n_dropped <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb24-23">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Warning: dropped </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_dropped<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> pairs with missing embeddings"</span>)</span>
<span id="cb24-24"></span>
<span id="cb24-25">        df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[mask].reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb24-26"></span>
<span id="cb24-27">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Store only the protein IDs and labels — not the embeddings themselves</span></span>
<span id="cb24-28">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Embeddings are looked up at __getitem__ time from the shared dict</span></span>
<span id="cb24-29">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.protein_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[protein_a_id].tolist()</span>
<span id="cb24-30">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.protein_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[protein_b_id].tolist()</span>
<span id="cb24-31">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.labels    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(df[label_col].values, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.float32)</span>
<span id="cb24-32"></span>
<span id="cb24-33">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__len__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb24-34">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.labels)</span>
<span id="cb24-35"></span>
<span id="cb24-36">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, idx: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[torch.Tensor, torch.Tensor, torch.Tensor]:</span>
<span id="cb24-37">        emb_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.embedding_dict[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.protein_a[idx]]   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (1280,)</span></span>
<span id="cb24-38">        emb_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.embedding_dict[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.protein_b[idx]]   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (1280,)</span></span>
<span id="cb24-39">        label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.labels[idx]                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># model output is (B,) so this is ok</span></span>
<span id="cb24-40">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> emb_a, emb_b, label</span>
<span id="cb24-41">      </span>
<span id="cb24-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Build datasets for each split</span></span>
<span id="cb24-43">train_dataset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPIDataset(train_df, embedding_dict)</span>
<span id="cb24-44">val_dataset   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPIDataset(valid_df, embedding_dict)</span>
<span id="cb24-45">test_dataset  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPIDataset(test_df, embedding_dict)</span>
<span id="cb24-46"></span>
<span id="cb24-47"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Build DataLoaders</span></span>
<span id="cb24-48">train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(</span>
<span id="cb24-49">    train_dataset,</span>
<span id="cb24-50">    batch_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,</span>
<span id="cb24-51">    shuffle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># shuffle every epoch during training</span></span>
<span id="cb24-52">    num_workers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># parallel data loading</span></span>
<span id="cb24-53">    pin_memory <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># faster CPU→GPU transfer</span></span>
<span id="cb24-54">)</span>
<span id="cb24-55">val_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(</span>
<span id="cb24-56">    val_dataset,</span>
<span id="cb24-57">    batch_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,</span>
<span id="cb24-58">    shuffle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># no need to shuffle val/test</span></span>
<span id="cb24-59">    num_workers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb24-60">    pin_memory <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb24-61">)</span>
<span id="cb24-62">test_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(</span>
<span id="cb24-63">    test_dataset,</span>
<span id="cb24-64">    batch_size <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,</span>
<span id="cb24-65">    shuffle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb24-66">    num_workers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb24-67">    pin_memory <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb24-68">)</span>
<span id="cb24-69"></span>
<span id="cb24-70"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Verify shapes</span></span>
<span id="cb24-71">emb_a, emb_b, labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(train_loader))</span>
<span id="cb24-72"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(emb_a.shape)    </span>
<span id="cb24-73"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(emb_b.shape)    </span>
<span id="cb24-74"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(labels.shape)   </span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>torch.Size([512, 1280])
torch.Size([512, 1280])
torch.Size([512])</code></pre>
</section>
<section id="model-architecture-1" class="level2">
<h2 class="anchored" data-anchor-id="model-architecture-1">4. Model architecture</h2>
<p>Now I start building the model architecture. The model consists of three main components: <code>ProteinProjector</code>, <code>InteractionTransformer</code>, and <code>PPIClassifier</code>. I will build individual modules for each component, and then combine them into a full model.</p>
<section id="proteinprojector" class="level3">
<h3 class="anchored" data-anchor-id="proteinprojector">ProteinProjector</h3>
<div id="729c29dc" class="cell" data-execution_count="16">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb26-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.nn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> nn</span>
<span id="cb26-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.nn.functional <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> F</span>
<span id="cb26-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb26-5"></span>
<span id="cb26-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> ProteinProjector(nn.Module):</span>
<span id="cb26-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb26-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Projects a mean-pooled ESM2 embedding into a shared latent space.</span></span>
<span id="cb26-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Both proteins pass through the same projector (shared weights).</span></span>
<span id="cb26-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb26-11">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, esm2_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>, latent_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>, dropout: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>):</span>
<span id="cb26-12">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb26-13">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.net <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(</span>
<span id="cb26-14">            nn.Linear(esm2_dim, latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb26-15">            nn.LayerNorm(latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb26-16">            nn.GELU(),</span>
<span id="cb26-17">            nn.Dropout(dropout),</span>
<span id="cb26-18">            nn.Linear(latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, latent_dim),</span>
<span id="cb26-19">        )</span>
<span id="cb26-20"></span>
<span id="cb26-21">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x: torch.Tensor) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb26-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.net(x)</span></code></pre></div></div>
</details>
</div>
</section>
<section id="interactiontransformer" class="level3">
<h3 class="anchored" data-anchor-id="interactiontransformer">InteractionTransformer</h3>
<div id="dcf28b8a" class="cell" data-execution_count="17">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> InteractionTransformerLayer(nn.Module):</span>
<span id="cb27-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb27-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Single transformer layer operating on a pair (2-token sequence).</span></span>
<span id="cb27-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb27-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, latent_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, num_heads: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, ffn_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, dropout: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>):</span>
<span id="cb27-6">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb27-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> num_heads <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"latent_dim must be divisible by num_heads"</span></span>
<span id="cb27-8"></span>
<span id="cb27-9">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.norm1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.LayerNorm(latent_dim)</span>
<span id="cb27-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.attn  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.MultiheadAttention(</span>
<span id="cb27-11">            embed_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim,</span>
<span id="cb27-12">            num_heads <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> num_heads,</span>
<span id="cb27-13">            dropout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dropout,</span>
<span id="cb27-14">            batch_first <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, seq, dim) convention; defalut: (seq, B, dim)</span></span>
<span id="cb27-15">        )</span>
<span id="cb27-16">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.norm2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.LayerNorm(latent_dim)</span>
<span id="cb27-17">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ffn   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(</span>
<span id="cb27-18">            nn.Linear(latent_dim, ffn_dim),</span>
<span id="cb27-19">            nn.GELU(),</span>
<span id="cb27-20">            nn.Dropout(dropout),</span>
<span id="cb27-21">            nn.Linear(ffn_dim, latent_dim),</span>
<span id="cb27-22">            nn.Dropout(dropout),</span>
<span id="cb27-23">        )</span>
<span id="cb27-24"></span>
<span id="cb27-25">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x: torch.Tensor) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb27-26">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Self-attention with pre-norm (each token attends to both tokens)</span></span>
<span id="cb27-27">        x_norm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.norm1(x)</span>
<span id="cb27-28">        attn_out, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.attn(x_norm, x_norm, x_norm) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># attn_weight: (B, num_heads, 2, 2)</span></span>
<span id="cb27-29">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> attn_out</span>
<span id="cb27-30"></span>
<span id="cb27-31">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Feed-forward with pre-norm</span></span>
<span id="cb27-32">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ffn(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.norm2(x))</span>
<span id="cb27-33">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x</span></code></pre></div></div>
</details>
</div>
<div id="ce89afb3" class="cell" data-execution_count="18">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> InteractionTransformer(nn.Module):</span>
<span id="cb28-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb28-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Stack of InteractionTransformerLayers operating on the 2-token pair.</span></span>
<span id="cb28-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb28-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(</span>
<span id="cb28-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb28-7">        latent_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,</span>
<span id="cb28-8">        num_heads: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>,</span>
<span id="cb28-9">        num_layers: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb28-10">        ffn_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>,</span>
<span id="cb28-11">        dropout: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb28-12">    ):</span>
<span id="cb28-13">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb28-14">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.ModuleList([</span>
<span id="cb28-15">            InteractionTransformerLayer(latent_dim, num_heads, ffn_dim, dropout)</span>
<span id="cb28-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(num_layers)</span>
<span id="cb28-17">        ]) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ModuleList is iterable at forward</span></span>
<span id="cb28-18">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.norm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.LayerNorm(latent_dim)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># final layer norm</span></span>
<span id="cb28-19"></span>
<span id="cb28-20">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, emb_a: torch.Tensor, emb_b: torch.Tensor) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb28-21">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Stack into a 2-token sequence: (B, 2, latent_dim)</span></span>
<span id="cb28-22">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.stack([emb_a, emb_b], dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># stack at 1 position of shape</span></span>
<span id="cb28-23">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this is because attention layer takes: (B, seq, dim)</span></span>
<span id="cb28-24"></span>
<span id="cb28-25">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> layer <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers:</span>
<span id="cb28-26">            x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> layer(x)</span>
<span id="cb28-27"></span>
<span id="cb28-28">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.norm(x)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, 2, latent_dim)</span></span>
<span id="cb28-29"></span>
<span id="cb28-30">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Flatten the 2-token output into a single vector</span></span>
<span id="cb28-31">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Shape: (B, latent_dim * 2)</span></span>
<span id="cb28-32">        fused <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x.reshape(x.size(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb28-33">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fused</span></code></pre></div></div>
</details>
</div>
</section>
<section id="ppiclassifier" class="level3">
<h3 class="anchored" data-anchor-id="ppiclassifier">PPIClassifier</h3>
<div id="4477817b" class="cell" data-execution_count="19">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> PPIClassifier(nn.Module):</span>
<span id="cb29-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb29-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    MLP head that takes the fused transformer output + symmetric features</span></span>
<span id="cb29-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    and predicts PPI probability.</span></span>
<span id="cb29-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb29-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, latent_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>, hidden_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>, dropout: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>):</span>
<span id="cb29-7">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb29-8">        input_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># transformer(2×latent) + symmetric(2×latent)</span></span>
<span id="cb29-9"></span>
<span id="cb29-10">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.mlp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(</span>
<span id="cb29-11">            nn.Linear(input_dim, hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb29-12">            nn.LayerNorm(hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb29-13">            nn.GELU(),</span>
<span id="cb29-14">            nn.Dropout(dropout),</span>
<span id="cb29-15"></span>
<span id="cb29-16">            nn.Linear(hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, hidden_dim),</span>
<span id="cb29-17">            nn.LayerNorm(hidden_dim),</span>
<span id="cb29-18">            nn.GELU(),</span>
<span id="cb29-19">            nn.Dropout(dropout),</span>
<span id="cb29-20"></span>
<span id="cb29-21">            nn.Linear(hidden_dim, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),   </span>
<span id="cb29-22">        )</span>
<span id="cb29-23"></span>
<span id="cb29-24">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(</span>
<span id="cb29-25">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb29-26">        transformer_out: torch.Tensor,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim * 2)</span></span>
<span id="cb29-27">        emb_a: torch.Tensor,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim) — post-projection</span></span>
<span id="cb29-28">        emb_b: torch.Tensor,   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim)</span></span>
<span id="cb29-29">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb29-30">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Symmetric features: invariant to A↔B swap</span></span>
<span id="cb29-31">        diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(emb_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> emb_b)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim)</span></span>
<span id="cb29-32">        product <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> emb_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> emb_b              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim)</span></span>
<span id="cb29-33"></span>
<span id="cb29-34">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate all signals</span></span>
<span id="cb29-35">        combined <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat([transformer_out, diff, product], dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim*4)</span></span>
<span id="cb29-36">        logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.mlp(combined).squeeze(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B,)</span></span>
<span id="cb29-37">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> logits</span></code></pre></div></div>
</details>
</div>
</section>
<section id="full-model" class="level3">
<h3 class="anchored" data-anchor-id="full-model">Full model</h3>
<p>Now we can combine all the components into a full PPI prediction model:</p>
<div id="778b32b9" class="cell" data-execution_count="20">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> PPIModel(nn.Module):</span>
<span id="cb30-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb30-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Full PPI prediction model.</span></span>
<span id="cb30-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb30-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(</span>
<span id="cb30-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb30-7">        esm2_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>,</span>
<span id="cb30-8">        latent_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,</span>
<span id="cb30-9">        num_heads: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>,</span>
<span id="cb30-10">        num_layers: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb30-11">        ffn_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>,</span>
<span id="cb30-12">        hidden_dim: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>,</span>
<span id="cb30-13">        proj_drop: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb30-14">        attn_drop: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb30-15">        mlp_drop: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>,</span>
<span id="cb30-16">    ):</span>
<span id="cb30-17">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb30-18"></span>
<span id="cb30-19">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.projector <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ProteinProjector(</span>
<span id="cb30-20">            esm2_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> esm2_dim,</span>
<span id="cb30-21">            latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim,</span>
<span id="cb30-22">            dropout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> proj_drop,</span>
<span id="cb30-23">        )</span>
<span id="cb30-24">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.transformer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> InteractionTransformer(</span>
<span id="cb30-25">            latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim,</span>
<span id="cb30-26">            num_heads <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> num_heads,</span>
<span id="cb30-27">            num_layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> num_layers,</span>
<span id="cb30-28">            ffn_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ffn_dim,</span>
<span id="cb30-29">            dropout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> attn_drop,</span>
<span id="cb30-30">        )</span>
<span id="cb30-31">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.classifier <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPIClassifier(</span>
<span id="cb30-32">            latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> latent_dim,</span>
<span id="cb30-33">            hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> hidden_dim,</span>
<span id="cb30-34">            dropout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mlp_drop,</span>
<span id="cb30-35">        )</span>
<span id="cb30-36"></span>
<span id="cb30-37">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._init_weights()</span>
<span id="cb30-38"></span>
<span id="cb30-39">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _init_weights(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb30-40">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Xavier uniform (Glorot) for linear layers - better to stabilize gradient in deeper NN."""</span></span>
<span id="cb30-41">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> module <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.modules():</span>
<span id="cb30-42">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(module, nn.Linear):</span>
<span id="cb30-43">                nn.init.xavier_uniform_(module.weight)</span>
<span id="cb30-44">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> module.bias <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb30-45">                    nn.init.zeros_(module.bias)</span>
<span id="cb30-46"></span>
<span id="cb30-47">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(</span>
<span id="cb30-48">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>,</span>
<span id="cb30-49">        emb_a: torch.Tensor,</span>
<span id="cb30-50">        emb_b: torch.Tensor,</span>
<span id="cb30-51">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb30-52">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Project both proteins into shared latent space (shared weights)</span></span>
<span id="cb30-53">        proj_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.projector(emb_a)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim)</span></span>
<span id="cb30-54">        proj_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.projector(emb_b)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim)</span></span>
<span id="cb30-55"></span>
<span id="cb30-56">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Interaction transformer over the 2-token pair</span></span>
<span id="cb30-57">        fused <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.transformer(proj_a, proj_b)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B, latent_dim * 2)</span></span>
<span id="cb30-58"></span>
<span id="cb30-59">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. MLP classifier with symmetric features</span></span>
<span id="cb30-60">        logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.classifier(fused, proj_a, proj_b)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (B,)</span></span>
<span id="cb30-61">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> logits</span>
<span id="cb30-62"></span>
<span id="cb30-63">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@torch.no_grad</span>()</span>
<span id="cb30-64">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> predict_proba(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, emb_a: torch.Tensor, emb_b: torch.Tensor) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb30-65">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Convenience method: returns interaction probability in [0, 1]."""</span></span>
<span id="cb30-66">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.sigmoid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.forward(emb_a, emb_b))</span></code></pre></div></div>
</details>
</div>
</section>
<section id="training-utilities" class="level3">
<h3 class="anchored" data-anchor-id="training-utilities">Training utilities</h3>
<p>Now I’ll define the loss function and a data augmentation function that randomly swaps the order of the protein pairs during training to enforce symmetry:</p>
<div id="ad96deda" class="cell" data-execution_count="21">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_loss_fn(label_smoothing: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, pos_weight: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb31-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb31-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Returns BCEWithLogitsLoss with optional label smoothing and class weighting.</span></span>
<span id="cb31-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb31-5">    pw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor([pos_weight]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> pos_weight <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb31-6"></span>
<span id="cb31-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> loss_fn(logits: torch.Tensor, labels: torch.Tensor) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> torch.Tensor:</span>
<span id="cb31-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> label_smoothing <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb31-9">            labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> label_smoothing) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> label_smoothing</span>
<span id="cb31-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> nn.BCEWithLogitsLoss(pos_weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>pw)(logits, labels.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>())</span>
<span id="cb31-11"></span>
<span id="cb31-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> loss_fn</span>
<span id="cb31-13"></span>
<span id="cb31-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> symmetry_augment(emb_a: torch.Tensor,</span>
<span id="cb31-15">                     emb_b: torch.Tensor,</span>
<span id="cb31-16">                     labels: torch.Tensor):</span>
<span id="cb31-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb31-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Data augmentation: randomly swap A and B within a batch.</span></span>
<span id="cb31-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    PPI is symmetric, so (A,B) and (B,A) should predict the same label.</span></span>
<span id="cb31-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Call this during training before passing to the model.</span></span>
<span id="cb31-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb31-22">    swap_mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.rand(emb_a.size(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), device<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>emb_a.device) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span></span>
<span id="cb31-23">    emb_a_aug <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.where(swap_mask.unsqueeze(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), emb_b, emb_a)</span>
<span id="cb31-24">    emb_b_aug <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.where(swap_mask.unsqueeze(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), emb_a, emb_b)</span>
<span id="cb31-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> emb_a_aug, emb_b_aug, labels   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># labels unchanged (symmetric)</span></span></code></pre></div></div>
</details>
</div>
<p>How many parameters does the model have?</p>
<div id="b612247f" class="cell" data-execution_count="22">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Count parameters</span></span>
<span id="cb32-2">total_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(p.numel() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.parameters())</span>
<span id="cb32-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Model parameters: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>total_params<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:,}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  (</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>total_params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e6</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">M)"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Model parameters: 9,330,177  (9.33M)</code></pre>
</section>
</section>
<section id="model-training" class="level2">
<h2 class="anchored" data-anchor-id="model-training">5. Model training</h2>
<p>Instantiate the model, define the optimizer, scheduler, and loss function, and then run the training loop with validation at the end of each epoch.</p>
<section id="instantiate" class="level3">
<h3 class="anchored" data-anchor-id="instantiate">Instantiate</h3>
<div id="f2678da1" class="cell" data-execution_count="23">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1">torch.manual_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb34-2">device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb34-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Using device: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>device<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb34-4"></span>
<span id="cb34-5">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PPIModel(</span>
<span id="cb34-6">    esm2_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>,</span>
<span id="cb34-7">    latent_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,</span>
<span id="cb34-8">    num_heads <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>,</span>
<span id="cb34-9">    num_layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,</span>
<span id="cb34-10">    ffn_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>,</span>
<span id="cb34-11">    hidden_dim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>,</span>
<span id="cb34-12">    proj_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb34-13">    attn_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb34-14">    mlp_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>,</span>
<span id="cb34-15">).to(device)</span>
<span id="cb34-16"></span>
<span id="cb34-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(model)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Using device: cuda
PPIModel(
  (projector): ProteinProjector(
    (net): Sequential(
      (0): Linear(in_features=1280, out_features=1024, bias=True)
      (1): LayerNorm((1024,), eps=1e-05, elementwise_affine=True)
      (2): GELU(approximate='none')
      (3): Dropout(p=0.1, inplace=False)
      (4): Linear(in_features=1024, out_features=512, bias=True)
    )
  )
  (transformer): InteractionTransformer(
    (layers): ModuleList(
      (0-2): 3 x InteractionTransformerLayer(
        (norm1): LayerNorm((512,), eps=1e-05, elementwise_affine=True)
        (attn): MultiheadAttention(
          (out_proj): NonDynamicallyQuantizableLinear(in_features=512, out_features=512, bias=True)
        )
        (norm2): LayerNorm((512,), eps=1e-05, elementwise_affine=True)
        (ffn): Sequential(
          (0): Linear(in_features=512, out_features=1024, bias=True)
          (1): GELU(approximate='none')
          (2): Dropout(p=0.1, inplace=False)
          (3): Linear(in_features=1024, out_features=512, bias=True)
          (4): Dropout(p=0.1, inplace=False)
        )
      )
    )
    (norm): LayerNorm((512,), eps=1e-05, elementwise_affine=True)
  )
  (classifier): PPIClassifier(
    (mlp): Sequential(
      (0): Linear(in_features=2048, out_features=512, bias=True)
      (1): LayerNorm((512,), eps=1e-05, elementwise_affine=True)
      (2): GELU(approximate='none')
      (3): Dropout(p=0.3, inplace=False)
      (4): Linear(in_features=512, out_features=256, bias=True)
      (5): LayerNorm((256,), eps=1e-05, elementwise_affine=True)
      (6): GELU(approximate='none')
      (7): Dropout(p=0.3, inplace=False)
      (8): Linear(in_features=256, out_features=1, bias=True)
    )
  )
)</code></pre>
</section>
<section id="optimizer-scheduler-and-loss-function" class="level3">
<h3 class="anchored" data-anchor-id="optimizer-scheduler-and-loss-function">Optimizer, scheduler, and loss function</h3>
<p>I use AdamW with weight decay to effect L2 regularization on the training parameters to reduce overfitting. Weight decay should not be applied to LayerNorm and biases (1D tensors), so I separated them and only apply it to the linear weights (2D tensors).</p>
<div id="b75c045a" class="cell" data-execution_count="24">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb36-1">decay_params    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb36-2">no_decay_params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb36-3"></span>
<span id="cb36-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, param <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.named_parameters():</span>
<span id="cb36-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> param.requires_grad:</span>
<span id="cb36-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb36-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Exclude: explicit norm/bias names OR 1D parameters (LayerNorm scales)</span></span>
<span id="cb36-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bias'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> param.dim() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="cb36-9">        no_decay_params.append((name, param))</span>
<span id="cb36-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb36-11">        decay_params.append((name, param))</span>
<span id="cb36-12"></span>
<span id="cb36-13">optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.AdamW([</span>
<span id="cb36-14">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'params'</span>: [p <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> decay_params],    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'weight_decay'</span>: <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>},</span>
<span id="cb36-15">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'params'</span>: [p <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> no_decay_params], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'weight_decay'</span>: <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>},</span>
<span id="cb36-16">], lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>)</span>
<span id="cb36-17"></span>
<span id="cb36-18">scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.lr_scheduler.ReduceLROnPlateau(</span>
<span id="cb36-19">    optimizer,</span>
<span id="cb36-20">    mode <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>,     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># we want val AUROC to go UP</span></span>
<span id="cb36-21">    patience <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># wait 5 epochs before reducing</span></span>
<span id="cb36-22">    factor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># halve the lr each time</span></span>
<span id="cb36-23">    min_lr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-7</span>,      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># don't reduce below this</span></span>
<span id="cb36-24">)</span>
<span id="cb36-25"></span>
<span id="cb36-26">loss_fn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_loss_fn(label_smoothing<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, pos_weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span></code></pre></div></div>
</details>
</div>
</section>
<section id="training-loop" class="level3">
<h3 class="anchored" data-anchor-id="training-loop">Training loop</h3>
<p>A helper class <code>MetricHistory</code> is defined to store and plot the training and validation metrics across epochs, as well as the learning rate. It also has a method to print out the best epoch’s metrics for easy reference.</p>
<div id="f7932cf1" class="cell" data-execution_count="25">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb37-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.nn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> nn</span>
<span id="cb37-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb37-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb37-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> roc_auc_score, average_precision_score</span>
<span id="cb37-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> defaultdict</span>
<span id="cb37-7"></span>
<span id="cb37-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> MetricHistory:</span>
<span id="cb37-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb37-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Stores per-epoch train/val metrics and learning rate.</span></span>
<span id="cb37-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Provides plotting and easy access to best epoch stats.</span></span>
<span id="cb37-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb37-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb37-14">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> defaultdict(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>)</span>
<span id="cb37-15"></span>
<span id="cb37-16">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb37-17">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Record one epoch of metrics. Call once per epoch."""</span></span>
<span id="cb37-18">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> kwargs.items():</span>
<span id="cb37-19">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[key].append(value)</span>
<span id="cb37-20"></span>
<span id="cb37-21">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, save_path: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'learning_curves.png'</span>):</span>
<span id="cb37-22">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb37-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Plot train/val loss, AUROC, AUPRC, and learning rate</span></span>
<span id="cb37-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        on a single figure with 4 subplots.</span></span>
<span id="cb37-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb37-26">        epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_loss'</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb37-27"></span>
<span id="cb37-28">        fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb37-29">        fig.suptitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training Learning Curves'</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, fontweight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bold'</span>)</span>
<span id="cb37-30"></span>
<span id="cb37-31">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Loss ──────────────────────────────────────────</span></span>
<span id="cb37-32">        ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb37-33">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_loss'</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Train'</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'steelblue'</span>)</span>
<span id="cb37-34">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_loss'</span>],   label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Val'</span>,   color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coral'</span>)</span>
<span id="cb37-35">        ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss (BCEWithLogitsLoss)'</span>)</span>
<span id="cb37-36">        ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Epoch'</span>)</span>
<span id="cb37-37">        ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss'</span>)</span>
<span id="cb37-38">        ax.legend()</span>
<span id="cb37-39">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb37-40">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._mark_best_epoch(ax, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_loss'</span>], mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'min'</span>)</span>
<span id="cb37-41"></span>
<span id="cb37-42">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── AUROC ─────────────────────────────────────────</span></span>
<span id="cb37-43">        ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb37-44">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_auroc'</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Train'</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'steelblue'</span>)</span>
<span id="cb37-45">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auroc'</span>],   label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Val'</span>,   color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coral'</span>)</span>
<span id="cb37-46">        ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AUROC'</span>)</span>
<span id="cb37-47">        ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Epoch'</span>)</span>
<span id="cb37-48">        ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AUROC'</span>)</span>
<span id="cb37-49">        ax.set_ylim([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>])</span>
<span id="cb37-50">        ax.legend()</span>
<span id="cb37-51">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb37-52">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._mark_best_epoch(ax, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auroc'</span>], mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>)</span>
<span id="cb37-53"></span>
<span id="cb37-54">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── AUPRC ─────────────────────────────────────────</span></span>
<span id="cb37-55">        ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb37-56">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_auprc'</span>], label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Train'</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'steelblue'</span>)</span>
<span id="cb37-57">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auprc'</span>],   label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Val'</span>,   color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coral'</span>)</span>
<span id="cb37-58">        ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AUPRC'</span>)</span>
<span id="cb37-59">        ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Epoch'</span>)</span>
<span id="cb37-60">        ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AUPRC'</span>)</span>
<span id="cb37-61">        ax.set_ylim([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>])</span>
<span id="cb37-62">        ax.legend()</span>
<span id="cb37-63">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb37-64">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._mark_best_epoch(ax, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auprc'</span>], mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>)</span>
<span id="cb37-65"></span>
<span id="cb37-66">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Learning Rate ─────────────────────────────────</span></span>
<span id="cb37-67">        ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb37-68">        ax.plot(epochs, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lr'</span>], color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'forestgreen'</span>)</span>
<span id="cb37-69">        ax.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Learning Rate'</span>)</span>
<span id="cb37-70">        ax.set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Epoch'</span>)</span>
<span id="cb37-71">        ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'LR'</span>)</span>
<span id="cb37-72">        ax.set_yscale(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'log'</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log scale — LR drops are easier to see</span></span>
<span id="cb37-73">        ax.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>)</span>
<span id="cb37-74"></span>
<span id="cb37-75">        plt.tight_layout()</span>
<span id="cb37-76">        plt.savefig(save_path, dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">150</span>, bbox_inches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tight'</span>)</span>
<span id="cb37-77">        plt.show()</span>
<span id="cb37-78">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Learning curves saved to </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-79"></span>
<span id="cb37-80">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _mark_best_epoch(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, ax, values, mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>):</span>
<span id="cb37-81">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Mark the best epoch with a vertical dashed line."""</span></span>
<span id="cb37-82">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> values:</span>
<span id="cb37-83">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb37-84">        best_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.argmax(values) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> mode <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> np.argmin(values)</span>
<span id="cb37-85">        best_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> values[best_idx]</span>
<span id="cb37-86">        ax.axvline(</span>
<span id="cb37-87">            x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> best_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb37-88">            color <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gray'</span>,</span>
<span id="cb37-89">            linestyle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>,</span>
<span id="cb37-90">            alpha <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>,</span>
<span id="cb37-91">            label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Best epoch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>best_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> (</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>best_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">)'</span></span>
<span id="cb37-92">        )</span>
<span id="cb37-93">        ax.legend()</span>
<span id="cb37-94"></span>
<span id="cb37-95">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> print_best(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb37-96">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Print a summary of the best epoch by val AUROC."""</span></span>
<span id="cb37-97">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auroc'</span>]:</span>
<span id="cb37-98">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb37-99">        best_idx   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.argmax(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auroc'</span>]))</span>
<span id="cb37-100">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">── Best Epoch Summary ────────────────────────────────"</span>)</span>
<span id="cb37-101">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Epoch       : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>best_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-102">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train Loss  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_loss'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-103">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Val Loss    : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_loss'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-104">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train AUROC : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_auroc'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-105">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Val AUROC   : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auroc'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-106">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Train AUPRC : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_auprc'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-107">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Val AUPRC   : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_auprc'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb37-108">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  LR          : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>history[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lr'</span>][best_idx]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2e}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p>A helper function <code>evaluate</code> is defined to run the model in evaluation mode over a given DataLoader and compute the average loss, AUROC, AUPRC, and also return all predicted probabilities and labels for further analysis if needed.</p>
<div id="6601bdac" class="cell" data-execution_count="26">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> evaluate(model, loader, loss_fn, device):</span>
<span id="cb38-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb38-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Runs model in eval mode over loader.</span></span>
<span id="cb38-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Returns loss, AUROC, AUPRC.</span></span>
<span id="cb38-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb38-6">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb38-7">    all_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb38-8">    all_labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb38-9">    total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb38-10">    n_batches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb38-11"></span>
<span id="cb38-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb38-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> emb_a, emb_b, labels <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> loader:</span>
<span id="cb38-14">            emb_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> emb_a.to(device)</span>
<span id="cb38-15">            emb_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> emb_b.to(device)</span>
<span id="cb38-16">            labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> labels.to(device)</span>
<span id="cb38-17"></span>
<span id="cb38-18">            logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(emb_a, emb_b)</span>
<span id="cb38-19">            loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_fn(logits, labels)</span>
<span id="cb38-20"></span>
<span id="cb38-21">            total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> loss.item()</span>
<span id="cb38-22">            n_batches  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb38-23"></span>
<span id="cb38-24">            probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.sigmoid(logits)</span>
<span id="cb38-25">            all_probs.append(probs.cpu())</span>
<span id="cb38-26">            all_labels.append(labels.cpu())</span>
<span id="cb38-27"></span>
<span id="cb38-28">    all_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(all_probs).numpy()</span>
<span id="cb38-29">    all_labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(all_labels).numpy()</span>
<span id="cb38-30"></span>
<span id="cb38-31">    avg_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_batches</span>
<span id="cb38-32">    auroc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> roc_auc_score(all_labels, all_probs)</span>
<span id="cb38-33">    auprc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> average_precision_score(all_labels, all_probs)</span>
<span id="cb38-34"></span>
<span id="cb38-35">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> avg_loss, auroc, auprc, all_probs, all_labels</span></code></pre></div></div>
</details>
</div>
<p>Now define the full training loop that runs for a specified number of epochs, performs training and validation, updates the learning rate scheduler, records metrics in the history object, and implements early stopping based on validation AUROC. The best model checkpoint is saved to disk.</p>
<div id="e2b6b57a" class="cell" data-execution_count="27">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> train(</span>
<span id="cb39-2">    model,</span>
<span id="cb39-3">    train_loader,</span>
<span id="cb39-4">    val_loader,</span>
<span id="cb39-5">    optimizer,</span>
<span id="cb39-6">    scheduler,</span>
<span id="cb39-7">    loss_fn,</span>
<span id="cb39-8">    device: torch.device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb39-9">    n_epochs: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb39-10">    early_stop_limit: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>,</span>
<span id="cb39-11">    checkpoint_path: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'best_model.pt'</span>,</span>
<span id="cb39-12">):</span>
<span id="cb39-13">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb39-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Full training loop with metric history tracking.</span></span>
<span id="cb39-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb39-16"></span>
<span id="cb39-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> device <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb39-18">      device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb39-19"></span>
<span id="cb39-20">    history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> MetricHistory()</span>
<span id="cb39-21">    best_val_auroc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb39-22">    patience_counter <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb39-23"></span>
<span id="cb39-24">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_epochs):</span>
<span id="cb39-25"></span>
<span id="cb39-26">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Training pass ─────────────────────────────────</span></span>
<span id="cb39-27">        model.train()</span>
<span id="cb39-28">        train_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb39-29">        train_labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb39-30">        total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb39-31">        n_batches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb39-32"></span>
<span id="cb39-33">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> emb_a, emb_b, labels <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_loader:</span>
<span id="cb39-34">            emb_a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> emb_a.to(device)</span>
<span id="cb39-35">            emb_b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> emb_b.to(device)</span>
<span id="cb39-36">            labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> labels.to(device)</span>
<span id="cb39-37"></span>
<span id="cb39-38">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Symmetry augmentation — randomly swap A and B</span></span>
<span id="cb39-39">            emb_a, emb_b, labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> symmetry_augment(emb_a, emb_b, labels)</span>
<span id="cb39-40"></span>
<span id="cb39-41">            optimizer.zero_grad()</span>
<span id="cb39-42">            logits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(emb_a, emb_b)</span>
<span id="cb39-43">            loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_fn(logits, labels)</span>
<span id="cb39-44">            loss.backward()</span>
<span id="cb39-45">            optimizer.step()</span>
<span id="cb39-46"></span>
<span id="cb39-47">            total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> loss.item()</span>
<span id="cb39-48">            n_batches  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb39-49"></span>
<span id="cb39-50">            probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.sigmoid(logits).detach().cpu()</span>
<span id="cb39-51">            train_probs.append(probs)</span>
<span id="cb39-52">            train_labels.append(labels.cpu())</span>
<span id="cb39-53"></span>
<span id="cb39-54">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Train metrics</span></span>
<span id="cb39-55">        train_probs  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(train_probs).numpy()</span>
<span id="cb39-56">        train_labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.cat(train_labels).numpy()</span>
<span id="cb39-57">        train_loss   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> total_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n_batches</span>
<span id="cb39-58">        train_auroc  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> roc_auc_score(train_labels, train_probs)</span>
<span id="cb39-59">        train_auprc  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> average_precision_score(train_labels, train_probs)</span>
<span id="cb39-60"></span>
<span id="cb39-61">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Validation pass ───────────────────────────────</span></span>
<span id="cb39-62">        val_loss, val_auroc, val_auprc, _ap, _al <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate(</span>
<span id="cb39-63">            model, val_loader, loss_fn, device</span>
<span id="cb39-64">        )</span>
<span id="cb39-65"></span>
<span id="cb39-66">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Scheduler step ────────────────────────────────</span></span>
<span id="cb39-67">        scheduler.step(val_auroc)</span>
<span id="cb39-68">        current_lr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> optimizer.param_groups[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lr'</span>]</span>
<span id="cb39-69"></span>
<span id="cb39-70">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Record history ────────────────────────────────</span></span>
<span id="cb39-71">        history.update(</span>
<span id="cb39-72">            train_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_loss,</span>
<span id="cb39-73">            val_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_loss,</span>
<span id="cb39-74">            train_auroc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_auroc,</span>
<span id="cb39-75">            val_auroc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_auroc,</span>
<span id="cb39-76">            train_auprc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_auprc,</span>
<span id="cb39-77">            val_auprc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_auprc,</span>
<span id="cb39-78">            lr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> current_lr,</span>
<span id="cb39-79">        )</span>
<span id="cb39-80"></span>
<span id="cb39-81">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Print progress ────────────────────────────────</span></span>
<span id="cb39-82">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb39-83">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Epoch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>epoch<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:3d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_epochs<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | "</span></span>
<span id="cb39-84">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Train Loss: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>train_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  AUROC: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>train_auroc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  AUPRC: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>train_auprc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | "</span></span>
<span id="cb39-85">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Val Loss: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>val_loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  AUROC: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>val_auroc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  AUPRC: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>val_auprc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> | "</span></span>
<span id="cb39-86">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"LR: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>current_lr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2e}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb39-87">        )</span>
<span id="cb39-88"></span>
<span id="cb39-89">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ── Checkpoint + early stopping ───────────────────</span></span>
<span id="cb39-90">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> val_auroc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> best_val_auroc:</span>
<span id="cb39-91">            best_val_auroc   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_auroc</span>
<span id="cb39-92">            patience_counter <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb39-93">            torch.save(model.state_dict(), checkpoint_path)</span>
<span id="cb39-94">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb39-95">            patience_counter <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb39-96">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> patience_counter <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> early_stop_limit:</span>
<span id="cb39-97">                <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">Early stopping triggered at epoch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>epoch<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb39-98">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb39-99"></span>
<span id="cb39-100">    history.print_best()</span>
<span id="cb39-101">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> history</span></code></pre></div></div>
</details>
</div>
</section>
<section id="training" class="level3">
<h3 class="anchored" data-anchor-id="training">Training</h3>
<p>Finally, we can call the training function to start training the model. The model trained for less than 10 minutes on Colab Pro+ with Tesla T4 GPU.</p>
<div id="dc852448" class="cell" data-execution_count="28">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Training</span></span>
<span id="cb40-2">device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb40-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Using device: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>device<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb40-4"></span>
<span id="cb40-5">history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train(</span>
<span id="cb40-6">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model,</span>
<span id="cb40-7">    train_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_loader,</span>
<span id="cb40-8">    val_loader <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_loader,</span>
<span id="cb40-9">    optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> optimizer,</span>
<span id="cb40-10">    scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scheduler,</span>
<span id="cb40-11">    loss_fn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_fn,</span>
<span id="cb40-12">    device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> device,</span>
<span id="cb40-13">    n_epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb40-14">    early_stop_limit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>,</span>
<span id="cb40-15">    checkpoint_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/best_model.pt"</span>,</span>
<span id="cb40-16">)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Using device: cuda
Epoch   1/100 | Train Loss: 0.7000  AUROC: 0.5869  AUPRC: 0.5948 | Val Loss: 0.6855  AUROC: 0.5906  AUPRC: 0.5891 | LR: 1.00e-04
Epoch   2/100 | Train Loss: 0.6342  AUROC: 0.7057  AUPRC: 0.7244 | Val Loss: 0.6968  AUROC: 0.6557  AUPRC: 0.6538 | LR: 1.00e-04
Epoch   3/100 | Train Loss: 0.5709  AUROC: 0.8042  AUPRC: 0.8066 | Val Loss: 0.6929  AUROC: 0.7009  AUPRC: 0.6885 | LR: 1.00e-04
Epoch   4/100 | Train Loss: 0.5283  AUROC: 0.8494  AUPRC: 0.8503 | Val Loss: 0.6624  AUROC: 0.7292  AUPRC: 0.6994 | LR: 1.00e-04
Epoch   5/100 | Train Loss: 0.5028  AUROC: 0.8724  AUPRC: 0.8729 | Val Loss: 0.6865  AUROC: 0.7269  AUPRC: 0.6945 | LR: 1.00e-04
Epoch   6/100 | Train Loss: 0.4761  AUROC: 0.8938  AUPRC: 0.8941 | Val Loss: 0.7077  AUROC: 0.7232  AUPRC: 0.7033 | LR: 1.00e-04
Epoch   7/100 | Train Loss: 0.4566  AUROC: 0.9078  AUPRC: 0.9076 | Val Loss: 0.6812  AUROC: 0.7390  AUPRC: 0.7344 | LR: 1.00e-04
Epoch   8/100 | Train Loss: 0.4418  AUROC: 0.9176  AUPRC: 0.9167 | Val Loss: 0.7815  AUROC: 0.7353  AUPRC: 0.7401 | LR: 1.00e-04
Epoch   9/100 | Train Loss: 0.4236  AUROC: 0.9288  AUPRC: 0.9276 | Val Loss: 0.7170  AUROC: 0.7339  AUPRC: 0.7353 | LR: 1.00e-04
Epoch  10/100 | Train Loss: 0.4113  AUROC: 0.9359  AUPRC: 0.9345 | Val Loss: 0.7140  AUROC: 0.7233  AUPRC: 0.7255 | LR: 1.00e-04
Epoch  11/100 | Train Loss: 0.4009  AUROC: 0.9417  AUPRC: 0.9405 | Val Loss: 0.7713  AUROC: 0.7327  AUPRC: 0.7453 | LR: 1.00e-04
Epoch  12/100 | Train Loss: 0.3879  AUROC: 0.9480  AUPRC: 0.9472 | Val Loss: 0.8123  AUROC: 0.7127  AUPRC: 0.7251 | LR: 1.00e-04
Epoch  13/100 | Train Loss: 0.3740  AUROC: 0.9550  AUPRC: 0.9533 | Val Loss: 0.8318  AUROC: 0.7203  AUPRC: 0.7321 | LR: 5.00e-05
Epoch  14/100 | Train Loss: 0.3537  AUROC: 0.9638  AUPRC: 0.9622 | Val Loss: 0.8115  AUROC: 0.7301  AUPRC: 0.7426 | LR: 5.00e-05
Epoch  15/100 | Train Loss: 0.3459  AUROC: 0.9668  AUPRC: 0.9649 | Val Loss: 0.7772  AUROC: 0.7278  AUPRC: 0.7369 | LR: 5.00e-05
Epoch  16/100 | Train Loss: 0.3367  AUROC: 0.9704  AUPRC: 0.9689 | Val Loss: 0.8701  AUROC: 0.7194  AUPRC: 0.7340 | LR: 5.00e-05
Epoch  17/100 | Train Loss: 0.3315  AUROC: 0.9727  AUPRC: 0.9714 | Val Loss: 0.8339  AUROC: 0.7254  AUPRC: 0.7357 | LR: 5.00e-05
Epoch  18/100 | Train Loss: 0.3239  AUROC: 0.9751  AUPRC: 0.9740 | Val Loss: 0.8355  AUROC: 0.7255  AUPRC: 0.7430 | LR: 5.00e-05
Epoch  19/100 | Train Loss: 0.3194  AUROC: 0.9769  AUPRC: 0.9754 | Val Loss: 0.8642  AUROC: 0.7121  AUPRC: 0.7274 | LR: 2.50e-05
Epoch  20/100 | Train Loss: 0.3053  AUROC: 0.9811  AUPRC: 0.9796 | Val Loss: 0.8867  AUROC: 0.7024  AUPRC: 0.7154 | LR: 2.50e-05
Epoch  21/100 | Train Loss: 0.3003  AUROC: 0.9827  AUPRC: 0.9818 | Val Loss: 0.8992  AUROC: 0.7132  AUPRC: 0.7254 | LR: 2.50e-05
Epoch  22/100 | Train Loss: 0.2962  AUROC: 0.9836  AUPRC: 0.9821 | Val Loss: 0.9049  AUROC: 0.7100  AUPRC: 0.7245 | LR: 2.50e-05

Early stopping triggered at epoch 22

── Best Epoch Summary ────────────────────────────────
  Epoch       : 7
  Train Loss  : 0.4566
  Val Loss    : 0.6812
  Train AUROC : 0.9078
  Val AUROC   : 0.7390
  Train AUPRC : 0.9076
  Val AUPRC   : 0.7344
  LR          : 1.00e-04</code></pre>
<div id="ffcbbf0b" class="cell" data-execution_count="29">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb42" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb42-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot learning curves</span></span>
<span id="cb42-2">history.plot(save_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/learning_curves.png"</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/images/learning_curves.png" class="img-fluid"></p>
<p>As we can see here, the model achieves a peak validation AUROC of around 0.739 at epoch 7, after which it starts to overfit (training AUROC continues to improve while validation AUROC plateaus and then declines). The learning rate scheduler reduces the learning rate at epoch 13 when the validation AUROC plateaus, but the model still does not improve further, leading to early stopping at epoch 22.</p>
<p>I adjusted the training hyperparameters to mitigate overfitting, such as increasing dropout rates and weight decay, stronger label smoothing, reducing model size, and using a more aggressive learning rate scheduler. However, the model still shows signs of overfitting after a few epochs, which is probably due to the limitation of the data.</p>
</section>
</section>
<section id="model-evaluation" class="level2">
<h2 class="anchored" data-anchor-id="model-evaluation">6. Model evaluation</h2>
<p>Now that we have the best model checkpoint saved, we can load it and evaluate its performance on the held-out test set to see how well it generalizes to unseen data.</p>
<section id="evaluate-on-test-set" class="level3">
<h3 class="anchored" data-anchor-id="evaluate-on-test-set">Evaluate on test set</h3>
<div id="af50eff7" class="cell" data-execution_count="30">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb43" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1">model.load_state_dict(torch.load(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>save_path<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/data/best_model.pt"</span>))</span>
<span id="cb43-2">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.to(device)</span>
<span id="cb43-3">model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb43-4"></span>
<span id="cb43-5">_, test_auroc, test_auprc, test_probs, test_labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> evaluate(</span>
<span id="cb43-6">    model, test_loader, loss_fn, device</span>
<span id="cb43-7">)</span>
<span id="cb43-8"></span>
<span id="cb43-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> (</span>
<span id="cb43-10">    roc_auc_score,</span>
<span id="cb43-11">    average_precision_score,</span>
<span id="cb43-12">    accuracy_score,</span>
<span id="cb43-13">    matthews_corrcoef,</span>
<span id="cb43-14">    confusion_matrix,</span>
<span id="cb43-15">    PrecisionRecallDisplay,</span>
<span id="cb43-16">    RocCurveDisplay,</span>
<span id="cb43-17">    f1_score,</span>
<span id="cb43-18">    precision_score,</span>
<span id="cb43-19">    recall_score</span>
<span id="cb43-20">)</span>
<span id="cb43-21"></span>
<span id="cb43-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert probabilities to binary predictions at 0.5 threshold</span></span>
<span id="cb43-23">test_preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (test_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb43-24"></span>
<span id="cb43-25"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"AUROC     : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>roc_auc_score(test_labels, test_probs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-26"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"AUPRC     : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>average_precision_score(test_labels, test_probs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-27"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"F1 score  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>f1_score(test_labels, test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-28"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Precision : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>precision_score(test_labels, test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-29"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Recall    : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>recall_score(test_labels, test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-30"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Accuracy  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>accuracy_score(test_labels, test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-31"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"MCC       : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>matthews_corrcoef(test_labels, test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-32"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Confusion matrix:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>confusion_matrix(test_labels, test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>AUROC     : 0.7466
AUPRC     : 0.7470
F1 score  : 0.6314
Precision : 0.7195
Recall    : 0.5626
Accuracy  : 0.6717
MCC       : 0.3518
Confusion matrix:
[[705 198]
 [395 508]]</code></pre>
<p>The AUPRC is around 0.75, which is similar, if not slightly higher than the published models. But since the published data used HIPPIE data and this data is HuRI, and that the splitting method may not be exactly the same, it is difficult to determine if this is a real improvement to the models in the paper. However, the <em>Reim et al.</em> models were trained with over 163k training data, while here I only have 47k training data, so achieving similar performance with much less data is probably a good sign that the model architecture and training strategy are effective.</p>
<p>Also, at a decision probability threshold of 0.5, the precision is 0.72, while the recall is only 0.56. This indicates that the model is more accurate in calling true interactions, but the sensitivity of the model in identifying all positive interactions is not great. We can tune the decision threshold as below depending on our downstream requirements (e.g.&nbsp;catering for different wet lab validation strategies).</p>
<div id="3d10a7d2" class="cell" data-execution_count="31">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb45" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Try different thresholds and see how metrics change</span></span>
<span id="cb45-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> precision_recall_fscore_support, confusion_matrix</span>
<span id="cb45-3"></span>
<span id="cb45-4">thresholds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>]</span>
<span id="cb45-5"></span>
<span id="cb45-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Threshold'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Precision'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Recall'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'F1'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MCC'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb45-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">55</span>)</span>
<span id="cb45-8"></span>
<span id="cb45-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> thr <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> thresholds:</span>
<span id="cb45-10">    preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (test_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> thr).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb45-11">    p, r, f1, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> precision_recall_fscore_support(</span>
<span id="cb45-12">        test_labels, preds, average<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'binary'</span>, zero_division<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb45-13">    )</span>
<span id="cb45-14">    mcc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> matthews_corrcoef(test_labels, preds)</span>
<span id="cb45-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>thr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>r<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>f1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mcc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code> Threshold  Precision     Recall         F1        MCC
-------------------------------------------------------
      0.30     0.6599     0.7198     0.6886     0.3503
      0.40     0.6845     0.6224     0.6520     0.3369
      0.50     0.7195     0.5626     0.6314     0.3518
      0.60     0.7479     0.4994     0.5989     0.3511</code></pre>
<p>Plot the PR curve:</p>
<div id="7f505a05" class="cell" data-execution_count="32">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb47" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1">display <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PrecisionRecallDisplay.from_predictions(</span>
<span id="cb47-2">    test_preds, test_labels, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Precision Recall Curve"</span>, plot_chance_level<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, despine<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb47-3">)</span>
<span id="cb47-4">_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> display.ax_.set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2-class Precision-Recall curve"</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/images/pr_curve.png" class="img-fluid"></p>
</section>
<section id="compare-with-a-baseline-model" class="level3">
<h3 class="anchored" data-anchor-id="compare-with-a-baseline-model">Compare with a baseline model</h3>
<p>Now, I will compare the performance of the transformer-based model with a simpler Random Forest classifier, using the same embeddings as input features. This will help us understand how much the transformer architecture contributes to the performance compared to a more traditional machine learning model.</p>
<p>Prepare the data for training:</p>
<div id="05b0cb9a" class="cell" data-execution_count="33">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb48" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert embeddings to numpy</span></span>
<span id="cb48-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, values <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> embedding_dict.items():</span>
<span id="cb48-3">    embedding_dict[key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> values.numpy()</span>
<span id="cb48-4">    </span>
<span id="cb48-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> prepare_rf_data(df, embedding_dict):</span>
<span id="cb48-6">    X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb48-7">    y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb48-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _, row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> df.iterrows():</span>
<span id="cb48-9">        protein1_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict[row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein1_ID'</span>]]</span>
<span id="cb48-10">        protein2_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict[row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Protein2_ID'</span>]]</span>
<span id="cb48-11">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate embeddings to form feature vector</span></span>
<span id="cb48-12">        X.append(np.concatenate((protein1_emb, protein2_emb)))</span>
<span id="cb48-13">        y.append(row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>])</span>
<span id="cb48-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> np.array(X), np.array(y)</span>
<span id="cb48-15"></span>
<span id="cb48-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prepare data for all splits</span></span>
<span id="cb48-17">X_train, y_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prepare_rf_data(train_df, embedding_dict)</span>
<span id="cb48-18">X_val, y_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prepare_rf_data(valid_df, embedding_dict)</span>
<span id="cb48-19">X_test, y_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prepare_rf_data(test_df, embedding_dict)</span>
<span id="cb48-20"></span>
<span id="cb48-21"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Train data shape: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>X_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>y_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb48-22"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Validation data shape: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>X_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>y_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb48-23"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Test data shape: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>X_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>y_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Train data shape: (47306, 2560), (47306,)
Validation data shape: (1832, 2560), (1832,)
Test data shape: (1806, 2560), (1806,)</code></pre>
<p>I use <code>RandomizedSearchCV</code> to find the best hyperparameters for the Random Forest model. I will tune the number of trees (n_estimators) and the number of features to consider at each split (max_features).</p>
<div id="940bdf5c" class="cell" data-execution_count="34">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb50" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb50-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.ensemble <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomForestClassifier</span>
<span id="cb50-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomizedSearchCV</span>
<span id="cb50-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> scipy.stats <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> stats</span>
<span id="cb50-4"></span>
<span id="cb50-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the parameter distribution for RandomizedSearchCV</span></span>
<span id="cb50-6">param_dist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb50-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'n_estimators'</span>: stats.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>),         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of trees in the forest</span></span>
<span id="cb50-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max_features'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sqrt'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'log2'</span>],                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of features to consider at each split</span></span>
<span id="cb50-9">}</span>
<span id="cb50-10"></span>
<span id="cb50-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Initialize a RandomForestClassifier</span></span>
<span id="cb50-12">rf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RandomForestClassifier(random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>, n_jobs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># n_jobs=-1 uses all available cores</span></span>
<span id="cb50-13"></span>
<span id="cb50-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Initialize RandomizedSearchCV</span></span>
<span id="cb50-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The `scoring` parameter can be set to 'roc_auc' or 'average_precision' for PPI prediction.</span></span>
<span id="cb50-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 'average_precision' is often preferred for imbalanced datasets.</span></span>
<span id="cb50-17">random_search <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RandomizedSearchCV(</span>
<span id="cb50-18">    estimator<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>rf,</span>
<span id="cb50-19">    param_distributions<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>param_dist,</span>
<span id="cb50-20">    n_iter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of parameter settings that are sampled. More is better but takes longer.</span></span>
<span id="cb50-21">    cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of folds for cross-validation</span></span>
<span id="cb50-22">    scoring<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'roc_auc'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Evaluate using AUROC</span></span>
<span id="cb50-23">    random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>,</span>
<span id="cb50-24">    n_jobs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb50-25">    verbose<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb50-26">)</span>
<span id="cb50-27"></span>
<span id="cb50-28"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Starting RandomizedSearchCV..."</span>)</span>
<span id="cb50-29">random_search.fit(X_train, y_train)</span>
<span id="cb50-30"></span>
<span id="cb50-31"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RandomizedSearchCV completed."</span>)</span>
<span id="cb50-32"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Best parameters: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>random_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_params_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb50-33"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Best AUROC score on training data with cross-validation: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>random_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_score_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Starting RandomizedSearchCV...
Fitting 3 folds for each of 10 candidates, totalling 30 fits
[CV 1/3] END max_features=sqrt, n_estimators=320;, score=0.904 total time=10.2min
[CV 3/3] END max_features=sqrt, n_estimators=171;, score=0.900 total time= 5.3min
[CV 2/3] END max_features=sqrt, n_estimators=149;, score=0.904 total time= 4.6min
RandomizedSearchCV completed.
Best parameters: {'max_features': 'sqrt', 'n_estimators': 485}
Best AUROC score on training data with cross-validation: 0.9053</code></pre>
<p>Let’s see how the metrics change with different decision thresholds for the Random Forest model, and then evaluate the best model on the test set.</p>
<div id="02bfea73" class="cell" data-execution_count="35">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb52" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb52-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> (</span>
<span id="cb52-2">    roc_auc_score,</span>
<span id="cb52-3">    average_precision_score,</span>
<span id="cb52-4">    accuracy_score,</span>
<span id="cb52-5">    matthews_corrcoef,</span>
<span id="cb52-6">    confusion_matrix,</span>
<span id="cb52-7">    f1_score,</span>
<span id="cb52-8">    precision_score,</span>
<span id="cb52-9">    recall_score,</span>
<span id="cb52-10">    precision_recall_fscore_support</span>
<span id="cb52-11">)</span>
<span id="cb52-12"></span>
<span id="cb52-13">best_rf_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random_search.best_estimator_</span>
<span id="cb52-14"></span>
<span id="cb52-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predict probabilities on the test set</span></span>
<span id="cb52-16">rf_test_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> best_rf_model.predict_proba(X_test)[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb52-17"></span>
<span id="cb52-18">thresholds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>]</span>
<span id="cb52-19"></span>
<span id="cb52-20"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Threshold'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Precision'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Recall'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'F1'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MCC'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb52-21"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">55</span>)</span>
<span id="cb52-22"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> thr <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> thresholds:</span>
<span id="cb52-23">    preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (rf_test_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> thr).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb52-24">    p, r, f1, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> precision_recall_fscore_support(</span>
<span id="cb52-25">        y_test, preds, average<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'binary'</span>, zero_division<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb52-26">    )</span>
<span id="cb52-27">    mcc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> matthews_corrcoef(y_test, preds)</span>
<span id="cb52-28">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>thr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>p<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>r<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>f1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mcc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:&gt;10.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code> Threshold  Precision     Recall         F1        MCC
-------------------------------------------------------
      0.30     0.5298     0.8472     0.6519     0.1189
      0.40     0.6760     0.3488     0.4602     0.2075
      0.50     0.7273     0.0266     0.0513     0.0620
      0.60     0.5833     0.0078     0.0153     0.0136</code></pre>
<p>I’ll use the 0.4 threshold for the Random Forest model to calculate the final evaluation metrics on the test set, since it gives a better balance between precision and recall compared to the default 0.5 threshold.</p>
<div id="54aaab3c" class="cell" data-execution_count="36">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb54" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb54-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert probabilities to binary predictions at 0.4 threshold</span></span>
<span id="cb54-2">rf_test_preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (rf_test_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>).astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb54-3"></span>
<span id="cb54-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Random Forest Model Evaluation on Test Set:"</span>)</span>
<span id="cb54-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"AUROC     : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>roc_auc_score(y_test, rf_test_probs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"AUPRC     : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>average_precision_score(y_test, rf_test_probs)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"F1 score  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>f1_score(y_test, rf_test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Precision : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>precision_score(y_test, rf_test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Recall    : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>recall_score(y_test, rf_test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Accuracy  : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>accuracy_score(y_test, rf_test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"MCC       : </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>matthews_corrcoef(y_test, rf_test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb54-12"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Confusion matrix:</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>confusion_matrix(y_test, rf_test_preds)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Random Forest Model Evaluation on Test Set:
AUROC     : 0.6207
AUPRC     : 0.6200
F1 score  : 0.4602
Precision : 0.6760
Recall    : 0.3488
Accuracy  : 0.5908
MCC       : 0.2075
Confusion matrix:
[[752 151]
 [588 315]]</code></pre>
</section>
</section>
<section id="discussion" class="level2">
<h2 class="anchored" data-anchor-id="discussion">Discussion</h2>
<p>Although the model built here achieved similar performance to the published models, the accuracy is probably still not ideal for an actual <em>in silico</em> PPI screening campaign. The literature suggested that the performance boost of such model is mostly attributed to the use of pretrained language models like ESM2. Indeed, in this exercise, we can see that the performance gain from the transformer model vs.&nbsp;random forest is significant but not huge, and the model still shows signs of overfitting after a few epochs.&nbsp;</p>
<p>Here are a few potential next steps to further improve performance for PPI prediction:</p>
<ul>
<li>Explore per-token embeddings with 1D convolution neural network (CNN) to see if it can capture more fine-grained interaction motifs that are not captured by mean embeddings. The downside is that it will make the model larger, and without more data, it may again be more prone to overfitting.</li>
<li>Compare ESM2 with newer language models like <a href="https://biohub.ai/">ESM3 and ESMC</a> to see if the performance can be further improved with more sophisticated, larger pretrained models.</li>
<li>Including structural information/embeddings from <a href="https://alphafold.ebi.ac.uk/">AlphaFold</a> or <a href="https://biohub.ai/models/esmfold2">ESMFold2</a> to see if it can further improve the performance.</li>
</ul>
<p>Finally, it is important to note that the performance of the model is still limited by the quality and quantity of the training data. The current data mostly measure binary interactions, but in reality, the strength of interactions can vary widely. In the living cell, PPI is affected by many factors, including protein stoichiometry, subcellular localization, post-translational modifications, and the presence of other interacting partners. The availability of large-scale Y2H data like HuRI is a great step forward, but it still only captures a fraction of the complex interactome in the cell, and at a specific condition that may or may not be relevant to the biological targets of interest. Therefore, more high-throughput, physiologically relevant PPI data will be needed to further improve the performance of these models and make them more useful for real-world applications.</p>
</section>
<section id="disclosures" class="level2">
<h2 class="anchored" data-anchor-id="disclosures">Disclosures</h2>
<p>The codes were written with the aid of Claude Sonnet 4.6 and Gemini 2.5 Flash, and the model training was performed on Google Colab Pro+ with a Tesla T4 GPU. The accuracy of the codes were verified by the author.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/40662806/">Reim T, Hartebrodt A, Blumenthal DB, Bernett J, List M. Deep learning models for unbiased sequence-based PPI prediction plateau at an accuracy of 0.65. Bioinformatics. 2025 Jul 1;41(Supplement_1):i590-i598. doi: 10.1093/bioinformatics/btaf192. PMID: 40662806; PMCID: PMC12261406.</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/36927031/">Lin Z, Akin H, Rao R, Hie B, Zhu Z, Lu W, Smetanin N, Verkuil R, Kabeli O, Shmueli Y, Dos Santos Costa A, Fazel-Zarandi M, Sercu T, Candido S, Rives A. Evolutionary-scale prediction of atomic-level protein structure with a language model. Science. 2023 Mar 17;379(6637):1123-1130. doi: 10.1126/science.ade2574. Epub 2023 Mar 16. PMID: 36927031.</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/32296183/">Luck K, Kim DK, Lambourne L, Spirohn K, Begg BE, Bian W, Brignall R, Cafarelli T, Campos-Laborie FJ, Charloteaux B, Choi D, Coté AG, Daley M, Deimling S, Desbuleux A, Dricot A, Gebbia M, Hardy MF, Kishore N, Knapp JJ, Kovács IA, Lemmens I, Mee MW, Mellor JC, Pollis C, Pons C, Richardson AD, Schlabach S, Teeking B, Yadav A, Babor M, Balcha D, Basha O, Bowman-Colin C, Chin SF, Choi SG, Colabella C, Coppin G, D’Amata C, De Ridder D, De Rouck S, Duran-Frigola M, Ennajdaoui H, Goebels F, Goehring L, Gopal A, Haddad G, Hatchi E, Helmy M, Jacob Y, Kassa Y, Landini S, Li R, van Lieshout N, MacWilliams A, Markey D, Paulson JN, Rangarajan S, Rasla J, Rayhan A, Rolland T, San-Miguel A, Shen Y, Sheykhkarimli D, Sheynkman GM, Simonovsky E, Taşan M, Tejeda A, Tropepe V, Twizere JC, Wang Y, Weatheritt RJ, Weile J, Xia Y, Yang X, Yeger-Lotem E, Zhong Q, Aloy P, Bader GD, De Las Rivas J, Gaudet S, Hao T, Rak J, Tavernier J, Hill DE, Vidal M, Roth FP, Calderwood MA. A reference map of the human binary protein interactome. Nature. 2020 Apr;580(7803):402-408. doi: 10.1038/s41586-020-2188-x. Epub 2020 Apr 8. PMID: 32296183; PMCID: PMC7169983.</a></li>
<li><a href="https://arxiv.org/abs/2102.09548">Therapeutics Data Commons: Machine Learning Datasets and Tasks for Drug Discovery and Development</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Deep Learning</category>
  <category>Transformer</category>
  <category>PyTorch</category>
  <category>ESM2</category>
  <category>Protein Language Models</category>
  <category>Data Leakage</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/P8_ppi_transformer_predictor/</guid>
  <pubDate>Mon, 01 Jun 2026 07:00:00 GMT</pubDate>
</item>
<item>
  <title>Evaluating Data Leakage in Protein Binding Affinity Prediction</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/</link>
  <description><![CDATA[ 





<section id="research-impact" class="level2">
<h2 class="anchored" data-anchor-id="research-impact">Research Impact</h2>
<p>Data leakage is a critical issue in machine learning, especially in the context of protein-protein interaction (PPI) prediction. Data leakage occurs when information from the training data is inadvertently used in the testing phase, allowing the model to “remember” specific examples rather than learning generalizable patterns. To address this issue, this post compares two data splitting strategies, regular C3 split and strict C3 split, to evaluate the extent of data leakage when using pre-trained protein large language models (pLLMs) to predict peptide-MHC2 binding. The findings showed that while the neural network model generalized well on predicting binding peptides of seen MHC2 alleles, it struggled to generalize to unseen MHC2 alleles. This highlights the importance of using strict data splitting strategies to ensure that models are evaluated on truly unseen data, which is crucial for developing robust and generalizable models in protein binding affinity prediction.</p>
</section>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>I’ve recently come across <a href="https://www.biorxiv.org/content/10.1101/2025.04.21.649858v2">this paper</a> about data leakage in PPI prediction models using pLLMs, and it got me thinking about how data leakage might affect other types of protein interaction predictions, such as peptide-MHC2 binding. In this project, I decided to explore this issue by comparing two different data splitting strategies: a regular C3 split and a strict C3 split. The regular C3 split allows for some overlap between the training and testing sets, while the strict C3 split ensures that there is no overlap at all. By evaluating the performance of a neural network model trained on embeddings extracted from a pre-trained pLLM (ESM2) under these two splitting strategies, I aimed to understand the extent of data leakage and its impact on model generalization in the context of peptide-MHC2 binding prediction.</p>
</section>
<section id="key-steps" class="level2">
<h2 class="anchored" data-anchor-id="key-steps">Key Steps</h2>
<ol type="1">
<li><p><strong>Splitting Strategies</strong>: Peptide or MHC sequences were first clustered independently using two different approaches. In both cases, the goal was to ensure that similar protein sequences were not present in both the training and testing sets. Peptides were clustered based on a 3-gram sequence similarity approach, while MHC pseudo-sequences were clustered based on their BLOSUM62 amino acid similarity. After that, the cluster classes were split into training and testing sets using two different strategies largely based on the <a href="https://doi.org/10.1038/nmeth.2259">C3 approach</a>:</p>
<ul>
<li><p><strong>Regular C3 split</strong>: This split ensures that the test set contains pairs <img src="https://latex.codecogs.com/png.latex?(Peptide_%7Bnew%7D,%20MHC_%7Bany%7D)"> and <img src="https://latex.codecogs.com/png.latex?(Peptide_%7Bany%7D,%20MHC_%7Bnew%7D)">. This is a less strict C3 split, as it allows for some overlap in the individual components (peptides and MHCs) between the training and testing sets, but not in the interactions.</p></li>
<li><p><strong>Strict C3 split</strong>: This split ensures that for every pair <img src="https://latex.codecogs.com/png.latex?(Peptide,%20MHC)"> in the test set, both <img src="https://latex.codecogs.com/png.latex?Peptide"> and <img src="https://latex.codecogs.com/png.latex?MHC"> classes are entirely absent from the training set. This is the “Double-Cold” strategy, which is more stringent and ensures that the model is evaluated on completely unseen peptides and MHCs, thus providing a more accurate assessment of the model’s generalization capabilities. A down side of this split is that it results in a smaller training and testing set. To ensure a fair comparison between the two splits, the sample number from the “regular C3 split” was downsampled to match the sample number from the “strict C3 split”.</p></li>
</ul></li>
<li><p><strong>Embeddings Extraction and Model Training</strong>: Similar to <a href="https://jaychung10010.quarto.pub/all-things-bioinformatics/posts/P6_cnn_dnn_peptide_mhc/#references">my previous post</a>, we will extract ESM2 embeddings for both peptides and MHC2 pseudo-sequences. The embeddings will be extracted in a way that retains the 2D structure, which is crucial for applying convolutional layers in the model. After extracting the embeddings, we will concatenate the peptide and MHC2 embeddings along the sequence length dimension, retaining the sequence information and the 2D structure. We will then define a model architecture that includes two 1D convolutional layers followed by a self-attention layer and five dense layers. The model will be trained separately on the datasets generated from the regular C3 split and the strict C3 split, allowing us to compare the performance of the model under both splitting strategies.</p></li>
<li><p><strong>Comparing Regular vs.&nbsp;Strict C3 split</strong>: After training the model on both datasets, we will evaluate its performance using appropriate metrics such as <img src="https://latex.codecogs.com/png.latex?R%5E2"> score, root mean squared error (RMSE), and loss.</p></li>
</ol>
</section>
<section id="data-splitting-strategies" class="level2">
<h2 class="anchored" data-anchor-id="data-splitting-strategies">1. Data Splitting Strategies</h2>
<p>Loading required libraries:</p>
<div id="f295f940" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.cluster <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AgglomerativeClustering</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> GroupShuffleSplit</span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> Bio.Align <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> substitution_matrices</span>
<span id="cb1-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.feature_extraction.text <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CountVectorizer</span>
<span id="cb1-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics.pairwise <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> cosine_similarity</span>
<span id="cb1-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> train_test_split</span></code></pre></div></div>
</details>
</div>
<p>See <a href="https://jaychung10010.quarto.pub/all-things-bioinformatics/posts/2026-01-18_peptide_affinity_llm_nn/">my previous post</a> for source of data. First, let’s see what the input data looks like:</p>
<div id="c016792c" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">df.head()</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>   Peptide_ID           Peptide     MHC_ID  \
0      104653   VAPIEHIASMRRNYF  DRB1_1302   
1       37106   HDDKETSFIRNCARK  DRB1_0101   
2      118433   LIWVGINTRNMTMSM  DRB1_0101   
3       80770  GVTVIKNNMINNDLGP  DRB1_1501   
4       19888   PAPMLAAAAGWQTLS  DRB1_1101   

                                  MHC         Y  
0  QEFFIASGAAVDAIMESSFDYFDIDEATYHVGFT  0.501084  
1  QEFFIASGAAVDAIMWLFLECYDLQRATYHVGFT  0.441298  
2  QEFFIASGAAVDAIMWLFLECYDLQRATYHVGFT  0.217673  
3  QEFFIASGAAVDAIMWPRFDYFDIQAATYHVVFT  0.807811  
4  QEFFIASGAAVDAIMESSFDYFDFDRATYHVGFT  0.583271  </code></pre>
<p>Here we have the peptide sequences, MHC pseudo-sequences, and their corresponding binding affinity values (Y).</p>
<p>Let’s perfrom peptide clustering using a 3-gram approach to find overlapping peptides without source information. We will use the <code>CountVectorizer</code> from <code>sklearn</code> to create a matrix of 3-gram counts for each unique peptide, and then compute the cosine similarity between the peptides based on this matrix. Finally, we will use hierarchical clustering to group similar peptides together.</p>
<div id="af5a4842" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">vect <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CountVectorizer(analyzer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'char'</span>, ngram_range<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sequence of 3 a.a.</span></span>
<span id="cb4-2">pep_matrix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vect.fit_transform(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].unique()) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># row: unique peptides, col: unique 3 a.a.</span></span>
<span id="cb4-3">pep_sim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cosine_similarity(pep_matrix) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># peptide X peptide similarity matrix</span></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># use cosine dist when the orientation or pattern of the data is more important than the absolute scale</span></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># often used in text, genetic sequence</span></span>
<span id="cb4-6"></span>
<span id="cb4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cluster peptides that share many 3-mers (likely from the same protein)</span></span>
<span id="cb4-8">pep_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AgglomerativeClustering(</span>
<span id="cb4-9">    n_clusters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb4-10">    distance_threshold<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adjust: lower = more groups, stricter split</span></span>
<span id="cb4-11">    metric<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'precomputed'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># input is pre-computed dist</span></span>
<span id="cb4-12">    linkage<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'complete'</span></span>
<span id="cb4-13">).fit_predict(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> pep_sim)</span>
<span id="cb4-14"></span>
<span id="cb4-15">pep_map <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({</span>
<span id="cb4-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>: df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].unique(),</span>
<span id="cb4-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>: pep_clusters</span>
<span id="cb4-18">})</span>
<span id="cb4-19"></span>
<span id="cb4-20">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.merge(pep_map, on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>)</span></code></pre></div></div>
</details>
</div>
<div id="ad8a8776" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(pep_map.sort_values(by<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>).head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>))</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>                    Peptide  pep_group
1576         QYIKANAKFIGITE          0
702       YATFFIKANSKFIGITE          0
6842       MQYIKANSKFIGITEL          0
15556        QYQKANSKFIGITE          0
4185         QYIKANSKFIGITE          0
7940   SAMILAAYHPQQFIYAGSLS          1
16944  AAIGLSMAGSSAMILAAYHP          1
9611       RQIRMAKLLGRDPEQS          2
860        HGRQIRMAKLFGRDPE          2
6826       EGELHGRQIRMAKLLG          2
14166      HGRQIKMAKLLGRDPE          2
687         HGRQIRMAKLLGRDP          2
4640       HGRQIRMAKLLGRDPE          2
6532       HGRQIRMAKLLTRDPE          2
4614        QIRMAKLLGRDPEQS          2</code></pre>
<p>We can see that peptides that are likely from the same protein (e.g., “QYIKANAKFIGITE”, “YATFFIKANSKFIGITE”, “MQYIKANSKFIGITEL”) are clustered together in the same group (group 0). This indicates that our clustering approach is effectively grouping similar peptides together based on their 3-gram composition.</p>
<p>Next, we will cluster MHC pseudo-sequences based on their BLOSUM62 amino acid similarity. We will define a function to calculate the BLOSUM62 similarity between two sequences, and then create a similarity matrix for the MHC pseudo-sequences. Finally, we will use hierarchical clustering to group similar MHCs together.</p>
<div id="ca096edc" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to calculate BLOSUM62 similarity</span></span>
<span id="cb7-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> blosum62_similarity(seq1, seq2):</span>
<span id="cb7-3">    matrix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> substitution_matrices.load(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'BLOSUM62'</span>)</span>
<span id="cb7-4">    score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb7-5"></span>
<span id="cb7-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Align sequences by padding the shorter one (simple padding for score calculation)</span></span>
<span id="cb7-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Note: For rigorous alignment, a proper sequence alignment algorithm (e.g., Needleman-Wunsch) is needed.</span></span>
<span id="cb7-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This simplified approach assumes aligned positions are comparable.</span></span>
<span id="cb7-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq1), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq2))):</span>
<span id="cb7-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb7-11">            score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> matrix[seq1[i], seq2[i]]</span>
<span id="cb7-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">KeyError</span>: <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Handle cases where amino acid might not be in BLOSUM (e.g., 'X')</span></span>
<span id="cb7-13">            score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> </span>
<span id="cb7-14"></span>
<span id="cb7-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Normalize score (for simplicity, divide by max possible score)</span></span>
<span id="cb7-16">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># A more robust normalization might involve the self-similarity score.</span></span>
<span id="cb7-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Here a max possible similarity score for each aa is calculated and summed</span></span>
<span id="cb7-18">    max_score1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(matrix[aa, aa] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> aa <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> seq1 <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (aa, aa) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> matrix.keys())</span>
<span id="cb7-19">    max_score2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(matrix[aa, aa] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> aa <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> seq2 <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (aa, aa) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> matrix.keys())</span>
<span id="cb7-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> max_score1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> max_score2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>: <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Avoid division by zero</span></span>
<span id="cb7-21">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb7-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(max_score1, max_score2)</span>
<span id="cb7-23"></span>
<span id="cb7-24">mhc_sequences <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].unique()</span>
<span id="cb7-25"></span>
<span id="cb7-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create a similarity matrix for MHCs</span></span>
<span id="cb7-27">n_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(mhc_sequences)</span>
<span id="cb7-28">mhc_sim_matrix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.zeros((n_mhc, n_mhc))</span>
<span id="cb7-29"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_mhc):</span>
<span id="cb7-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(i, n_mhc):</span>
<span id="cb7-31">        sim <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> blosum62_similarity(mhc_sequences[i], mhc_sequences[j])</span>
<span id="cb7-32">        mhc_sim_matrix[i, j] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sim</span>
<span id="cb7-33">        mhc_sim_matrix[j, i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sim</span>
<span id="cb7-34"></span>
<span id="cb7-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cluster MHCs</span></span>
<span id="cb7-36">mhc_clusters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AgglomerativeClustering(</span>
<span id="cb7-37">    n_clusters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb7-38">    distance_threshold<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adjust: lower = more groups, stricter split for MHCs</span></span>
<span id="cb7-39">    metric<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'precomputed'</span>,</span>
<span id="cb7-40">    linkage<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'complete'</span></span>
<span id="cb7-41">).fit_predict(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mhc_sim_matrix)</span>
<span id="cb7-42"></span>
<span id="cb7-43">mhc_map <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({</span>
<span id="cb7-44">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>: mhc_sequences,</span>
<span id="cb7-45">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>: mhc_clusters</span>
<span id="cb7-46">})</span>
<span id="cb7-47"></span>
<span id="cb7-48">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.merge(mhc_map, on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>)</span></code></pre></div></div>
</details>
</div>
<div id="52f1bdc4" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(mhc_map.sort_values(by<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>))</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>                                   MHC  mhc_group
5   QEFFIASGAAVDAIMELSFEYYVLQKQNYHVVFT          0
15  QEFFIASGAAVDAIMERSYDYYVLQKRNYHVGFT          0
12  QEFFIASGAAVDAIMELSFEHYDLQKQNYHVGFT          0
8   QEFFIASGAAVDAIMESSYDYFDLQKRNYHVVFT          0
9   CNYHQGGGARVAHIMFFGLTYYDVGTETVHVAGI          1
..                                 ...        ...
64  YTYFLRRGGQTGHILHFPLIYYDYRTETVHKTPT         26
66  XXYHWTSGGQTGHGWALGSNYYDIRTETVHGVHT         27
70  QEFFIASGAAVDAIMESSFEYYDLQRATYHVGFT         28
62  QEFFIASGAAVDAIMESSFEYYDLQKRNYHVGFT         28
29  QEFFIASGAAVDAIMESGLEHFVIDRATYHAVFT         29

[75 rows x 2 columns]</code></pre>
<p>We can see that MHC pseudo-sequences that are similar based on their BLOSUM62 scores are clustered together in the same group (e.g., “QEFFIASGAAVDAIMELSFEYYVLQKQNYHVVFT”, “QEFFIASGAAVDAIMERSYDYYVLQKRNYHVGFT”, “QEFFIASGAAVDAIMELSFEHYDLQKQNYHVGFT” are all in group 0). This indicates that our clustering approach is effectively grouping similar MHC pseudo-sequences together based on their amino acid composition and similarity.</p>
<p>Next, we will perform the regular C3 split. To ensure total isolation between the training and testing sets, we will create a ‘SuperGroup’ that combines both the peptide and MHC groups. This way, we can ensure that no similar peptide-MHC pairs are present in both the training and testing sets, thus minimizing data leakage.</p>
<div id="30b059bc" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Perform the "Regular C3 split" first</span></span>
<span id="cb10-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We create a 'SuperGroup' that combines both to ensure total isolation</span></span>
<span id="cb10-3">df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'super_group'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>].astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>].astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>)</span>
<span id="cb10-4"></span>
<span id="cb10-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Split train vs temp_test</span></span>
<span id="cb10-6">gss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GroupShuffleSplit(n_splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, train_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb10-7">train_indices, temp_test_indices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(gss.split(df, groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'super_group'</span>]))</span>
<span id="cb10-8"></span>
<span id="cb10-9">train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[train_indices][[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]]</span>
<span id="cb10-10">temp_test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[temp_test_indices]</span>
<span id="cb10-11"></span>
<span id="cb10-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Split temp_text into test and valid</span></span>
<span id="cb10-13">gss1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GroupShuffleSplit(n_splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, train_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.66</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb10-14">test_indices, valid_indices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(gss1.split(temp_test_df, groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>temp_test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'super_group'</span>]))</span>
<span id="cb10-15"></span>
<span id="cb10-16">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[test_indices][[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]]</span>
<span id="cb10-17">valid_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[valid_indices][[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]]</span></code></pre></div></div>
</details>
</div>
<div id="cbc2c3a1" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(df)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>        Peptide_ID               Peptide                 MHC_ID  \
0            29993       MSGPMQQLTQPLQQV  HLA-DPA10201-DPB11401   
1            50950  CGKYLFNWAVRTKLKLTPIA              DRB1_1302   
2            58992       YKRQLMNILGAVYRY  HLA-DPA10201-DPB10101   
3             8140       FLGCLVKEIPPRLLY  HLA-DQA10501-DQB10201   
4           111514       KTQIDQVESTAGSLQ  HLA-DPA10201-DPB10501   
...            ...                   ...                    ...   
134276       15592       RFFLPIFSEFVLLAT              DRB1_0405   
134277       21667      EVFFQRLGIASGRARY              DRB1_1302   
134278       62271       YLFAKDKSGPLQPGV  HLA-DQA10102-DQB10602   
134279       79102       GELQIVDKIDADFKI              DRB1_1302   
134280      100096       SAAPLRTITADTFRK              DRB1_0701   

                                       MHC         Y  pep_group  mhc_group  \
0       YAFFQFSGGAILNTLHLQFEYFDLEKVRVHLDVT  0.216969       6334          6   
1       QEFFIASGAAVDAIMESSFDYFDIDEATYHVGFT  0.559077        205          3   
2       YAFFQFSGGAILNTLYGQFEYFAIEKVRVHLDVT  0.423504        457          6   
3       YNYHQRXFATVLHSLYFGLSSFAIRKARVHLETT  0.328660       1876         21   
4       YAFFQFSGGAILNTLFGQFEYFEIEKVRMHLDVT  0.000000       1157          6   
...                                    ...       ...        ...        ...   
134276  QEFFIASGAAVDAIMEVHFDYYSLQRATYHVGFT  0.721843       6951          4   
134277  QEFFIASGAAVDAIMESSFDYFDIDEATYHVGFT  0.257618       3632          3   
134278  CNYHQGGGARVAHIMFFGLTYYDVGTETVHVAGI  0.141380       2158          1   
134279  QEFFIASGAAVDAIMESSFDYFDIDEATYHVGFT  0.409599       3568          3   
134280  QEFFIASGAAVDAIMWGYFELYVIDRQTVHVGFT  0.242001       1440         17   

       super_group  
0           6334_6  
1            205_3  
2            457_6  
3          1876_21  
4           1157_6  
...            ...  
134276      6951_4  
134277      3632_3  
134278      2158_1  
134279      3568_3  
134280     1440_17  

[134281 rows x 8 columns]</code></pre>
<p>Now, let’s perform the strict C3 split. In this split, we will ensure that for every pair <img src="https://latex.codecogs.com/png.latex?(Peptide,%20MHC)"> in the test set, both the peptide and MHC classes are entirely absent from the training set. This means that we will first split the MHC groups and then split the peptide groups independently, ensuring that there is no overlap in either component between the training and testing sets.</p>
<div id="69e0f86c" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> strict_double_split(df, train_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>):</span>
<span id="cb13-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. First, split the MHC groups</span></span>
<span id="cb13-3">    gss_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GroupShuffleSplit(n_splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, train_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>train_size, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb13-4">    mhc_train_idx, mhc_test_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(gss_mhc.split(df, groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>]))</span>
<span id="cb13-5">    </span>
<span id="cb13-6">    mhc_train_alleles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[mhc_train_idx][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>].unique()</span>
<span id="cb13-7">    mhc_test_alleles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[mhc_test_idx][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>].unique()</span>
<span id="cb13-8">    </span>
<span id="cb13-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Second, split the Peptides groups</span></span>
<span id="cb13-10">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This prevents the model from seeing different fragments of the same protein</span></span>
<span id="cb13-11">    gss_pep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GroupShuffleSplit(n_splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, train_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>train_size, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb13-12">    pep_train_idx, pep_test_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(gss_pep.split(df, groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>]))</span>
<span id="cb13-13">    </span>
<span id="cb13-14">    pep_train_prots <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[pep_train_idx][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>].unique()</span>
<span id="cb13-15">    pep_test_prots <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.iloc[pep_test_idx][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>].unique()</span>
<span id="cb13-16">    </span>
<span id="cb13-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Create the "Strict" Test Set: </span></span>
<span id="cb13-18">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only interactions where BOTH the MHC is new AND the Protein is new.</span></span>
<span id="cb13-19">    train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>].isin(mhc_train_alleles) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>].isin(pep_train_prots)].copy()</span>
<span id="cb13-20">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_group'</span>].isin(mhc_test_alleles) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pep_group'</span>].isin(pep_test_prots)].copy()</span>
<span id="cb13-21">    </span>
<span id="cb13-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> train_df, test_df</span>
<span id="cb13-23"></span>
<span id="cb13-24">train_temp, test_strict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strict_double_split(df)</span>
<span id="cb13-25"></span>
<span id="cb13-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Random split of data into train or valid data</span></span>
<span id="cb13-27">train_strict, valid_strict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_test_split(train_temp, test_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.125</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb13-28"></span>
<span id="cb13-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save data to disc</span></span>
<span id="cb13-30"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> os</span>
<span id="cb13-31">save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/data'</span></span>
<span id="cb13-32">train_df.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_dat_cold.feather'</span>))</span>
<span id="cb13-33">valid_df.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_dat_cold.feather'</span>))</span>
<span id="cb13-34">test_df.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_dat_cold.feather'</span>))</span>
<span id="cb13-35">train_strict.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_dat_strict.feather'</span>))</span>
<span id="cb13-36">valid_strict.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_dat_strict.feather'</span>))</span>
<span id="cb13-37">test_strict.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_dat_strict.feather'</span>))</span></code></pre></div></div>
</details>
</div>
<div id="c55b4930" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">train_df.shape, test_df.shape, valid_df.shape</span>
<span id="cb14-2">train_strict.shape, test_strict.shape, valid_strict.shape</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Regular split shape:
((93392, 5), (26531, 5), (14358, 5))

Strict split shape:
((59757, 8), (9588, 8), (8537, 8))</code></pre>
<p>We can see that the regular C3 split results in a larger training and testing set compared to the strict C3 split. When we prepare the data for model training, we will need to downsample the regular C3 split to match the sample size of the strict C3 split to ensure a fair comparison between the two splitting strategies.</p>
</section>
<section id="embeddings-extraction-and-model-training" class="level2">
<h2 class="anchored" data-anchor-id="embeddings-extraction-and-model-training">2. Embeddings Extraction and Model Training</h2>
<p>Embedding extraction and model training procedures are similar to <a href="https://jaychung10010.quarto.pub/all-things-bioinformatics/posts/P6_cnn_dnn_peptide_mhc/">my previous post</a>, so I will not go through the code in detail here. Let’s load the data and downsample the regular C3 split to match the sample size of the strict C3 split:</p>
<div id="acb104e9" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">all_dat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb16-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>: pd.read_feather(os.path.join(load_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_dat_cold.feather'</span>)).sample(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">59757</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>), </span>
<span id="cb16-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid'</span>: pd.read_feather(os.path.join(load_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_dat_cold.feather'</span>)).sample(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8537</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb16-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>: pd.read_feather(os.path.join(load_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_dat_cold.feather'</span>)).sample(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9588</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb16-5">}</span>
<span id="cb16-6"></span>
<span id="cb16-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Shuffle samples</span></span>
<span id="cb16-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> keys, df <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_dat.items():</span>
<span id="cb16-9">  all_dat[keys] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.sample(frac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</details>
</div>
<p>For both data splits, we will extract ESM2 embeddings (<code>facebook/esm2_t30_150M_UR50D</code>) for the peptides and MHC pseudo-sequences, concatenate them, and then train a neural network model with convolutional layers. The model architecture and training procedure will be the same for both splits.</p>
<p>Here is the model architecture we will use:</p>
<div id="4d7867d2" class="cell" data-execution_count="12">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define 1D CNN + attention + MLP with multiple inputs using functional API</span></span>
<span id="cb17-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tensorflow <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tf</span>
<span id="cb17-3">tf.keras.backend.clear_session()</span>
<span id="cb17-4"></span>
<span id="cb17-5">tf.random.set_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb17-6"></span>
<span id="cb17-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_dense_block(n_neurons, dropout_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>):</span>
<span id="cb17-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tf.keras.Sequential([</span>
<span id="cb17-9">        tf.keras.layers.Dense(n_neurons, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>, kernel_initializer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'he_normal'</span>),</span>
<span id="cb17-10">        tf.keras.layers.BatchNormalization(),</span>
<span id="cb17-11">        tf.keras.layers.Dropout(dropout_rate)</span>
<span id="cb17-12">    ])</span>
<span id="cb17-13"></span>
<span id="cb17-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the input layers</span></span>
<span id="cb17-15">embedding_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>].shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:], name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'embedding_input'</span>)</span>
<span id="cb17-16">peptide_length_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'peptide_length_input'</span>)</span>
<span id="cb17-17">mhc_length_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_length_input'</span>)</span>
<span id="cb17-18"></span>
<span id="cb17-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CNN branch for embeddings</span></span>
<span id="cb17-20">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Conv1D(filters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, kernel_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, padding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'same'</span>, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>)(embedding_input)</span>
<span id="cb17-21">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.BatchNormalization()(x)</span>
<span id="cb17-22">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Dropout(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)(x)</span>
<span id="cb17-23">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Conv1D(filters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, kernel_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, padding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'same'</span>, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>)(x)</span>
<span id="cb17-24">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.BatchNormalization()(x)</span>
<span id="cb17-25">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Dropout(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)(x)</span>
<span id="cb17-26">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.AveragePooling1D(pool_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)(x)</span>
<span id="cb17-27"></span>
<span id="cb17-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Self-attention layer</span></span>
<span id="cb17-29">attention_output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Attention()([x, x])</span>
<span id="cb17-30">flat_attention <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Flatten()(attention_output)</span>
<span id="cb17-31"></span>
<span id="cb17-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate attention output with length inputs</span></span>
<span id="cb17-33">combined_features <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Concatenate()([flat_attention, peptide_length_input, mhc_length_input])</span>
<span id="cb17-34"></span>
<span id="cb17-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># MLP branch</span></span>
<span id="cb17-36">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(combined_features)</span>
<span id="cb17-37">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb17-38">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb17-39">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb17-40">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb17-41">output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Dense(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)(y)</span>
<span id="cb17-42"></span>
<span id="cb17-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create the functional model</span></span>
<span id="cb17-44">cnn_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.Model(inputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[embedding_input, peptide_length_input, mhc_length_input], outputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[output])</span>
<span id="cb17-45"></span>
<span id="cb17-46">cnn_model.summary()</span></code></pre></div></div>
</details>
</div>
<pre><code> Model: "functional_5"

┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Layer (type)        ┃ Output Shape      ┃    Param # ┃ Connected to      ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ embedding_input     │ (None, 71, 640)   │          0 │ -                 │
│ (InputLayer)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv1d (Conv1D)     │ (None, 71, 128)   │    409,728 │ embedding_input[… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ batch_normalization │ (None, 71, 128)   │        512 │ conv1d[0][0]      │
│ (BatchNormalizatio… │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dropout (Dropout)   │ (None, 71, 128)   │          0 │ batch_normalizat… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ conv1d_1 (Conv1D)   │ (None, 71, 64)    │     24,640 │ dropout[0][0]     │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ batch_normalizatio… │ (None, 71, 64)    │        256 │ conv1d_1[0][0]    │
│ (BatchNormalizatio… │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dropout_1 (Dropout) │ (None, 71, 64)    │          0 │ batch_normalizat… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ average_pooling1d   │ (None, 35, 64)    │          0 │ dropout_1[0][0]   │
│ (AveragePooling1D)  │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ attention           │ (None, 35, 64)    │          0 │ average_pooling1… │
│ (Attention)         │                   │            │ average_pooling1… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ flatten (Flatten)   │ (None, 2240)      │          0 │ attention[0][0]   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ peptide_length_inp… │ (None, 1)         │          0 │ -                 │
│ (InputLayer)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ mhc_length_input    │ (None, 1)         │          0 │ -                 │
│ (InputLayer)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ concatenate         │ (None, 2242)      │          0 │ flatten[0][0],    │
│ (Concatenate)       │                   │            │ peptide_length_i… │
│                     │                   │            │ mhc_length_input… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ sequential          │ (None, 128)       │    287,616 │ concatenate[0][0] │
│ (Sequential)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ sequential_1        │ (None, 128)       │     17,024 │ sequential[0][0]  │
│ (Sequential)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ sequential_2        │ (None, 128)       │     17,024 │ sequential_1[0][… │
│ (Sequential)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ sequential_3        │ (None, 128)       │     17,024 │ sequential_2[0][… │
│ (Sequential)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ sequential_4        │ (None, 128)       │     17,024 │ sequential_3[0][… │
│ (Sequential)        │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dense_5 (Dense)     │ (None, 1)         │        129 │ sequential_4[0][… │
└─────────────────────┴───────────────────┴────────────┴───────────────────┘

 Total params: 790,977 (3.02 MB)

 Trainable params: 789,313 (3.01 MB)

 Non-trainable params: 1,664 (6.50 KB)</code></pre>
<p>Training with max 100 epochs, with early stopping and performance scheduler callbacks:</p>
<div id="852571e2" class="cell" data-execution_count="13">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Performance scheduling of learning rate</span></span>
<span id="cb19-2">lr_scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.callbacks.ReduceLROnPlateau(factor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb19-3"></span>
<span id="cb19-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Early stopping</span></span>
<span id="cb19-5">early_stopping <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.callbacks.EarlyStopping(patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, restore_best_weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb19-6"></span>
<span id="cb19-7">optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.optimizers.Adam(learning_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>)</span>
<span id="cb19-8">cnn_model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">compile</span>(loss<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mse'</span>, optimizer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>optimizer, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RootMeanSquaredError'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2Score'</span>])</span>
<span id="cb19-9">fit_history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_model.fit(train_tfds, epochs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, validation_data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>valid_tfds,</span>
<span id="cb19-10">                            callbacks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[lr_scheduler, early_stopping])</span></code></pre></div></div>
</details>
</div>
<p>Regular C3 split training metrics: <img src="https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/images/r_train.png" class="img-fluid"></p>
<p>Strict C3 split training metrics: <img src="https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/images/s_train.png" class="img-fluid"></p>
</section>
<section id="comparing-regular-vs.-strict-c3-split" class="level2">
<h2 class="anchored" data-anchor-id="comparing-regular-vs.-strict-c3-split">3. Comparing Regular vs.&nbsp;Strict C3 split</h2>
<p>We will now compare the performance of the model trained on the regular C3 split and the strict C3 split using an independent test set. We will evaluate the models using metrics such as <img src="https://latex.codecogs.com/png.latex?R%5E2"> score, root mean squared error (RMSE), and loss.</p>
<div id="738c5f58" class="cell" data-execution_count="14">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1">cnn_model.evaluate(X_test_inputs, y_test)</span></code></pre></div></div>
</details>
</div>
<p><strong>Regular C3 split test metrics:</strong></p>
<pre><code>300/300 ━━━━━━━━━━━━━━━━━━━━ 4s 8ms/step - R2Score: 0.6597 - RootMeanSquaredError: 0.1524 - loss: 0.0232
[0.023598162457346916, 0.15361693501472473, 0.6540257930755615]</code></pre>
<p><strong>Strict C3 split test metrics:</strong></p>
<pre><code>300/300 ━━━━━━━━━━━━━━━━━━━━ 5s 13ms/step - R2Score: 0.1770 - RootMeanSquaredError: 0.2391 - loss: 0.0572
[0.05780040845274925, 0.24041715264320374, 0.18053573369979858]</code></pre>
<p>As we can see, the model trained on the regular C3 split performs significantly better on the test set compared to the model trained on the strict C3 split. The <img src="https://latex.codecogs.com/png.latex?R%5E2"> score is much higher and the RMSE is much lower for the regular C3 split. This suggests that although the model generalizes well on predicting binding peptides of seen MHC2 alleles, it struggles to generalize to unseen MHC2 alleles when using the strict C3 split.</p>
<p>Let’s take a look at the prediction plots:</p>
<p>Regular C3 split prediction plot for all MHC2: <img src="https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/images/r_pred.png" class="img-fluid"></p>
<p>Strict C3 split prediction plot for all MHC2: <img src="https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/images/s_pred.png" class="img-fluid"></p>
<p>Regular C3 split prediction plot separated by MHC2: <img src="https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/images/r_pred_sep.png" class="img-fluid"></p>
<p>Strict C3 split prediction plot separated by MHC2: <img src="https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/images/s_pred_sep.png" class="img-fluid"></p>
<p>As we can see, while the regular C3 split shows good performance across multiple MHC2 alleles, with some achieving an <img src="https://latex.codecogs.com/png.latex?R%5E2"> score &gt; 0.8, the strict C3 split shows max <img src="https://latex.codecogs.com/png.latex?R%5E2"> score of around 0.2 for the best performing MHC2 allele.</p>
<p>Notably, although the total test sample numbers are the same between the two split, due to the strict nature of the strict C3 split, the variety of MHC2 alleles in the test set is much smaller compared to the regular C3 split. Thus, we are perhaps being a little “strict” in our evaluation, since the strict C3 split has not been evaluated on many MHC2 alleles.</p>
<p>This result suggests important limitations for this model: it predicts well on MHC2 alleles that are present in the training data, but it does not perform well on unseen or novel MHC2 alleles. Perhaps the model is very good at memorizing specific interactions between peptides and MHC2 alleles, but did not learn well the general rules of protein-protein interaction, which is also a significant challenge for many PPI prediction models utilizing pLLMs. Some potential solutions to this issue could include:</p>
<ul>
<li>Increasing the diversity of the training data to include a wider range of MHC2 alleles, which may help the model learn more generalizable patterns.</li>
<li>Incorporating additional features or using more complex model architectures that can capture the underlying biology of peptide binding to MHC2 molecules, rather than relying solely on the embeddings from the pre-trained pLLM.</li>
<li>Re-train a pLLM on strict data with held out samples, so that the embeddings themselves are less prone to data leakage and more generalizable to unseen data.</li>
</ul>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>In this project, I explored the issue of data leakage in peptide-MHC2 binding prediction models using pre-trained protein language models (pLLMs). I compared two data splitting strategies, a regular C3 split and a strict C3 split, to evaluate the extent of data leakage and its impact on model performance. My findings showed that while the model trained on the regular C3 split performed well on the test set, it struggled to generalize to unseen MHC2 alleles when evaluated using the strict C3 split. This highlights the importance of using stringent data splitting strategies to ensure that models are evaluated on truly unseen data, which is crucial for developing robust and generalizable models in protein binding affinity prediction.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://doi.org/10.1038/nmeth.2259">Park, Y., Marcotte, E. Flaws in evaluation schemes for pair-input computational predictions. Nat Methods 9, 1134–1136 (2012).</a></li>
<li><a href="https://www.biorxiv.org/content/10.1101/2025.04.21.649858v2">Szymborski, Joseph, and Amin Emad. “Data for”A Flaw in Using Pre-trained pLMs in Protein-protein Interaction Inference Models””. bioRxiv, December 5, 2025.</a></li>
<li><a href="https://www.science.org/doi/10.1126/science.ade2574">Lin Z, Akin H, Rao R, Hie B, Zhu Z, Lu W, Smetanin N, Verkuil R, Kabeli O, Shmueli Y, Dos Santos Costa A, Fazel-Zarandi M, Sercu T, Candido S, Rives A. Evolutionary-scale prediction of atomic-level protein structure with a language model. Science. 2023 Mar 17;379(6637):1123-1130. doi: 10.1126/science.ade2574. Epub 2023 Mar 16. PMID: 36927031.</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Deep Learning</category>
  <category>Convolutional Neural Networks</category>
  <category>Self-Attention</category>
  <category>Keras</category>
  <category>ESM2</category>
  <category>Protein Language Models</category>
  <category>Data Leakage</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/P7_data_leakage_peptide_mhc/</guid>
  <pubDate>Wed, 25 Feb 2026 08:00:00 GMT</pubDate>
</item>
<item>
  <title>Peptide-MHCII Binding Affinity Prediction with Convolutional Neural Networks and Protein Large Language Model</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/</link>
  <description><![CDATA[ 





<section id="research-impact" class="level2">
<h2 class="anchored" data-anchor-id="research-impact">Research Impact</h2>
<p>To accurately predict peptide-MHCII binding affinity, I developed a 1D Convolutional Neural Network (CNN) combined with Multi-Layer Perceptron (MLP) model using protein embeddings from the ESM2 large language model.</p>
<p>Comparing with a simpler MLP-only model, the CNN + MLP model demonstrated over 12% improvement in peptide-MHCII binding prediction accuracy, achieving an <img src="https://latex.codecogs.com/png.latex?R%5E2"> score of 0.62 for all MHC alleles, and close to 0.8 for specific alleles. Saliency Map and In Silico Mutagenesis analyses revealed key amino acid positions that significantly influence binding affinity predictions, providing insights into the underlying biological interactions.</p>
<p>This exercise showcases the potential of combining Large Language Models with machine learning to tackle complex biological challenges. These could range from predicting protein-protein interactions and drug-target binding to forecasting drug responses from gene expression data.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/summary_figure.jpeg" class="img-fluid figure-img"></p>
<figcaption>Schematic overview of the CNN + MLP pipeline for predicting peptide-MHC binding affinity (figure generated with the assistance of Gemini).</figcaption>
</figure>
</div>
</section>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>In <a href="https://jaychung10010.quarto.pub/all-things-bioinformatics/posts/2026-01-18_peptide_affinity_llm_nn/">my last post</a>, I explored the use of protein large language model (LLM) embeddings from ESM2 for predicting peptide-MHCII binding affinity using a Multi-Layer Perceptron (MLP). While the MLP performed reasonably well, I believe that incorporating Convolutional Neural Networks (CNNs) could further enhance the model’s ability to capture local sequence patterns in the protein embeddings.</p>
<p>The protein sequence embeddings generated by ESM2 are typically 2-dimensional arrays, where one dimension represents the amino acid sequence and the other represents the embedding features. In my previous approach, I flattened these embeddings into 1-dimensional vectors by taking the mean before feeding them into the MLP. However, this flattening process may lead to the loss of important spatial relationships between amino acids in the sequence.</p>
<p>In this post, I will implement a 1D CNN to process the full embeddings from ESM2 without pre-flattening. I will apply 2 layers of 1D convolution followed by average pooling to capture local patterns in the sequence embeddings. After the CNN layers, I will add fully connected MLP layers to perform the final prediction task. I will compare the performance of this CNN + MLP model with a similar MLP-only model to evaluate the impact of incorporating convolutional layers.</p>
<p>Finally, to understand which amino acid positions contribute most to the binding affinity predictions, I will perform Saliency Map analysis on both the peptide and MHCII sequences, using gradients calculated from the model outputs with respect to the input embeddings. I will also perform an In Silico Mutagenesis (ISM) analysis to see how disruptive single amino acid changes affect the predicted binding affinity.</p>
</section>
<section id="key-steps" class="level2">
<h2 class="anchored" data-anchor-id="key-steps">Key Steps</h2>
<p>I will not go through all the steps in detail, as they are similar to my previous post. Instead, I will highlight the key steps involved in this approach:</p>
<ol type="1">
<li><p><strong>Embeddings Extraction</strong>: We will have to modify the embeddings extraction code to retain the 2D structure of the embeddings. We need to input the max sequence length to ensure consistent input sizes for the model. After that, we will concatenate the peptide and MHC2 embeddings along the sequence length dimension, retaining the sequence information and the 2D structure. This allows for the saliency map analysis later on.</p></li>
<li><p><strong>Model Architecture</strong>: We will define a new model architecture that includes 1D convolutional layers followed by dense layers. Using the functional API in TensorFlow/Keras, we will create a model that takes the 2D embeddings and peptide/MHC sequence lengths as inputs, applies convolutional layers, and then concatenates them to pass it through dense layers to make the final prediction.</p></li>
<li><p><strong>Training and Evaluation</strong>: We will train the new model and evaluate its performance against a similar MLP-only model, to see if the CNN layers improve binding affinity prediction.</p></li>
<li><p><strong>Saliency Map and In Silico Mutagenesis Analysis</strong>: We will compute saliency maps to identify important amino acid positions in the peptide and MHC2 sequences that influence binding affinity predictions. We will also perform ISM to assess the impact of single amino acid mutations on the predicted affinity.</p></li>
</ol>
</section>
<section id="embeddings-extraction" class="level2">
<h2 class="anchored" data-anchor-id="embeddings-extraction">1. Embeddings Extraction</h2>
<p>First, let’s see what the input data looks like:</p>
<div id="d3e8eebb" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1">all_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>].head()</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>   Peptide_ID           Peptide     MHC_ID  \
0      104653   VAPIEHIASMRRNYF  DRB1_1302   
1       37106   HDDKETSFIRNCARK  DRB1_0101   
2      118433   LIWVGINTRNMTMSM  DRB1_0101   
3       80770  GVTVIKNNMINNDLGP  DRB1_1501   
4       19888   PAPMLAAAAGWQTLS  DRB1_1101   

                                  MHC         Y  
0  QEFFIASGAAVDAIMESSFDYFDIDEATYHVGFT  0.501084  
1  QEFFIASGAAVDAIMWLFLECYDLQRATYHVGFT  0.441298  
2  QEFFIASGAAVDAIMWLFLECYDLQRATYHVGFT  0.217673  
3  QEFFIASGAAVDAIMWPRFDYFDIQAATYHVVFT  0.807811  
4  QEFFIASGAAVDAIMESSFDYFDFDRATYHVGFT  0.583271  </code></pre>
<p><code>all_dat</code> is a dictionary containing the training, validation, and test datasets as dataframes, each with peptide and MHC2 sequences, and binding affinity Y.</p>
<p>The embeddings extraction code to retain the 2D structure of the embeddings:</p>
<div id="7f3d8d49" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> transformers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AutoTokenizer, EsmModel</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb3-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb3-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> tqdm <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tqdm</span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load pre-trained ESM2 model and tokenizer</span></span>
<span id="cb3-8">model_checkpoint <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"facebook/esm2_t30_150M_UR50D"</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 640 dim</span></span>
<span id="cb3-9">tokenizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AutoTokenizer.from_pretrained(model_checkpoint)</span>
<span id="cb3-10">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EsmModel.from_pretrained(model_checkpoint)</span>
<span id="cb3-11"></span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to get embeddings</span></span>
<span id="cb3-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> extract_full_embedding(</span>
<span id="cb3-14">    sequence: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>],</span>
<span id="cb3-15">    tokenizer: AutoTokenizer,</span>
<span id="cb3-16">    model: EsmModel,</span>
<span id="cb3-17">    device: torch.device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb3-18">    batch_size: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>,</span>
<span id="cb3-19">    max_len: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="cb3-20">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> np.ndarray:</span>
<span id="cb3-21"></span>
<span id="cb3-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Extract full embeddings for peptide sequences from an LLM model.</span></span>
<span id="cb3-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">       Batch iteration is required as this is memory intensive."""</span></span>
<span id="cb3-24"></span>
<span id="cb3-25">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Use GPU when available</span></span>
<span id="cb3-26">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> device:</span>
<span id="cb3-27">        device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb3-28"></span>
<span id="cb3-29">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Separate sequence list into batches</span></span>
<span id="cb3-30">    n_batches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> math.ceil(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(sequence) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> batch_size)</span>
<span id="cb3-31">    all_batch_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb3-32"></span>
<span id="cb3-33">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.to(device) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Move model to the target device</span></span>
<span id="cb3-34">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Set model to evaluation mode</span></span>
<span id="cb3-35"></span>
<span id="cb3-36">    steps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tqdm(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_batches))</span>
<span id="cb3-37"></span>
<span id="cb3-38">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> steps:</span>
<span id="cb3-39">        steps.set_description(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Processing batch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_batches<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-40">        start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> batch_size</span>
<span id="cb3-41">        end <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> batch_size</span>
<span id="cb3-42">        batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sequence[start:end]</span>
<span id="cb3-43"></span>
<span id="cb3-44">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Tokenize peptide sequence and pad to max length</span></span>
<span id="cb3-45">        inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokenizer(batch, return_tensors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pt"</span>, padding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max_length'</span>, truncation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, max_length<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len)</span>
<span id="cb3-46"></span>
<span id="cb3-47">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Move input to the target device</span></span>
<span id="cb3-48">        inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {name: tensor.to(device) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, tensor <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> inputs.items()}</span>
<span id="cb3-49"></span>
<span id="cb3-50">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Forward pass through the model without gradient tracking to get embeddings</span></span>
<span id="cb3-51">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb3-52">          batch_mean_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>inputs).last_hidden_state.detach().cpu().numpy()</span>
<span id="cb3-53">        all_batch_embeddings.append(batch_mean_embeddings)</span>
<span id="cb3-54"></span>
<span id="cb3-55">    embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate(all_batch_embeddings, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-56">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This will return a (N_samples, max_len, n_dim) array</span></span>
<span id="cb3-57">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> embeddings</span></code></pre></div></div>
</details>
</div>
<p>Since each peptide and MHC2 sequence can have different lengths, we need to pad them to a consistent length during the embedding extraction so that they can be concatenated later. Let’s get the max sequence lengths for peptides or MHC2 sequences so we can pad the embeddings accordingly.</p>
<div id="1f22821b" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">length_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb4-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> df <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_dat.values():</span>
<span id="cb4-3">  length_pt.append(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>())</span>
<span id="cb4-4">max_len_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(length_pt)</span>
<span id="cb4-5"></span>
<span id="cb4-6">length_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb4-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> df <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_dat.values():</span>
<span id="cb4-8">  length_mhc.append(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>())</span>
<span id="cb4-9">max_len_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(length_mhc)</span>
<span id="cb4-10"></span>
<span id="cb4-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(max_len_pt, max_len_mhc)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>37 34</code></pre>
<p>The maximum peptide length is 37, and the maximum MHC2 length is 34.</p>
<p>Now we can extract the full embeddings for both peptides and MHC2 sequences, and pad them each to their respective max lengths.</p>
<div id="d420e238" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">embedding_dict_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb6-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> data, sequence <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence_dict_pt.items():</span>
<span id="cb6-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Extracting embeddings for </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">..."</span>)</span>
<span id="cb6-4">    embedding_dict_pt[data] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_full_embedding(sequence, tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>, max_len<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len_pt)</span>
<span id="cb6-5">    </span>
<span id="cb6-6">embedding_dict_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb6-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> data, sequence <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence_dict_mhc.items():</span>
<span id="cb6-8">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Extracting embeddings for </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">..."</span>)</span>
<span id="cb6-9">    embedding_dict_mhc[data] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_full_embedding(sequence, tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>, max_len<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len_mhc)</span></code></pre></div></div>
</details>
</div>
<p>Concatenate the peptide and MHC2 embeddings along the sequence dimension (axis=1) to create the final input embeddings for our model.</p>
<div id="3cda9488" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">embedding_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb7-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> data_type <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>]:</span>
<span id="cb7-3">  pt_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict_pt[<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data_type<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">_pt'</span>]</span>
<span id="cb7-4">  mhc_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict_mhc[<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data_type<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">_mhc'</span>]</span>
<span id="cb7-5">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate along the sequence length axis</span></span>
<span id="cb7-6">  embedding_dict[data_type] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate([pt_embeddings, mhc_embeddings], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb7-7"></span>
<span id="cb7-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Print shapes to verify</span></span>
<span id="cb7-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, value <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> embedding_dict.items():</span>
<span id="cb7-10">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Shape of </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>key<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> combined embeddings: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>value<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Shape of train combined embeddings: (82388, 71, 640)
Shape of valid combined embeddings: (11702, 71, 640)
Shape of test combined embeddings: (23410, 71, 640)</code></pre>
<p>The output here is: (sample size, sequence_length, embedding_dimension).</p>
<p>Finally, we need to determine the actual lengths of each peptide and MHC2 sequence (before padding) to provide as additional inputs to the model:</p>
<div id="cb3cdb7e" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Determine each peptide or MHC sequence length to add into the embeddings for training input</span></span>
<span id="cb9-2">seq_length_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb9-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, sequence <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence_dict_pt.items():</span>
<span id="cb9-4">    seq_length_pt[key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence]</span>
<span id="cb9-5"></span>
<span id="cb9-6">seq_length_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb9-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, sequence <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence_dict_mhc.items():</span>
<span id="cb9-8">    seq_length_mhc[key] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(seq) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence]</span></code></pre></div></div>
</details>
</div>
</section>
<section id="model-architecture" class="level2">
<h2 class="anchored" data-anchor-id="model-architecture">2. Model Architecture</h2>
<p>Make the TensorFlow datasets from these 2D embeddings.</p>
<div id="17a28dfd" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert data to Tensorflow dataset</span></span>
<span id="cb10-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tensorflow <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tf</span>
<span id="cb10-3"></span>
<span id="cb10-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Embeddings (already concatenated along sequence length axis)</span></span>
<span id="cb10-5">X_train_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>]</span>
<span id="cb10-6">X_valid_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid'</span>]</span>
<span id="cb10-7">X_test_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>]</span>
<span id="cb10-8"></span>
<span id="cb10-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Target variable</span></span>
<span id="cb10-10">y_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> all_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>].values</span>
<span id="cb10-11">y_valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> all_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>].values</span>
<span id="cb10-12">y_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> all_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>].values</span>
<span id="cb10-13"></span>
<span id="cb10-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sequence lengths (converting lists to numpy arrays and then to tf tensors)</span></span>
<span id="cb10-15">X_train_pt_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(np.array(seq_length_pt[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_pt'</span>]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb10-16">X_train_mhc_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(np.array(seq_length_mhc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_mhc'</span>]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb10-17">X_valid_pt_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(np.array(seq_length_pt[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_pt'</span>]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb10-18">X_valid_mhc_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(np.array(seq_length_mhc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_mhc'</span>]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb10-19">X_test_pt_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(np.array(seq_length_pt[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_pt'</span>]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb10-20">X_test_mhc_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(np.array(seq_length_mhc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_mhc'</span>]), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb10-21"></span>
<span id="cb10-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create tf.data.Dataset with multiple inputs</span></span>
<span id="cb10-23">train_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.data.Dataset.from_tensor_slices(((X_train_emb, X_train_pt_len, X_train_mhc_len), y_train))</span>
<span id="cb10-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Shuffle, batch and prefetch the train tfds</span></span>
<span id="cb10-25">train_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_tfds.shuffle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).batch(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>).prefetch(tf.data.AUTOTUNE)</span>
<span id="cb10-26"></span>
<span id="cb10-27">valid_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.data.Dataset.from_tensor_slices(((X_valid_emb, X_valid_pt_len, X_valid_mhc_len), y_valid))</span>
<span id="cb10-28">valid_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_tfds.batch(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>).prefetch(tf.data.AUTOTUNE)</span>
<span id="cb10-29"></span>
<span id="cb10-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For evaluation on X_test, we will need to ensure it's a tuple of tensors</span></span>
<span id="cb10-31">X_test_inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (X_test_emb, X_test_pt_len, X_test_mhc_len)</span>
<span id="cb10-32"></span>
<span id="cb10-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For X_train_inputs, we will need to ensure it's a tuple of tensors for R2 evaluation</span></span>
<span id="cb10-34">X_train_inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (X_train_emb, X_train_pt_len, X_train_mhc_len)</span></code></pre></div></div>
</details>
</div>
<p>Define the CNN + MLP model architecture. I’m using average pooling rather than max pooling as I find it tends to work better for this task, likely because it captures the overall presence of features rather than just the strongest activation.</p>
<div id="ee0af507" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define 1D CNN + MLP with multiple inputs using functional API</span></span>
<span id="cb11-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tensorflow <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tf</span>
<span id="cb11-3">tf.keras.backend.clear_session()</span>
<span id="cb11-4"></span>
<span id="cb11-5">tf.random.set_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb11-6"></span>
<span id="cb11-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_dense_block(n_neurons, dropout_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>):</span>
<span id="cb11-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tf.keras.Sequential([</span>
<span id="cb11-9">        tf.keras.layers.Dense(n_neurons, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>, kernel_initializer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'he_normal'</span>),</span>
<span id="cb11-10">        tf.keras.layers.BatchNormalization(),</span>
<span id="cb11-11">        tf.keras.layers.Dropout(dropout_rate)</span>
<span id="cb11-12">    ])</span>
<span id="cb11-13"></span>
<span id="cb11-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the input layers</span></span>
<span id="cb11-15">embedding_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>].shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:], name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'embedding_input'</span>)</span>
<span id="cb11-16">peptide_length_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'peptide_length_input'</span>)</span>
<span id="cb11-17">mhc_length_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mhc_length_input'</span>)</span>
<span id="cb11-18"></span>
<span id="cb11-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CNN branch for embeddings</span></span>
<span id="cb11-20">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Conv1D(filters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, kernel_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, padding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'same'</span>, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>)(embedding_input)</span>
<span id="cb11-21">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.BatchNormalization()(x)</span>
<span id="cb11-22">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Dropout(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)(x)</span>
<span id="cb11-23">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Conv1D(filters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, kernel_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, padding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'same'</span>, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>)(x)</span>
<span id="cb11-24">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.BatchNormalization()(x)</span>
<span id="cb11-25">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Dropout(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)(x)</span>
<span id="cb11-26">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.AveragePooling1D(pool_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)(x)</span>
<span id="cb11-27">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Flatten()(x)</span>
<span id="cb11-28"></span>
<span id="cb11-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate CNN output with length inputs</span></span>
<span id="cb11-30">combined_features <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Concatenate()([x, peptide_length_input, mhc_length_input])</span>
<span id="cb11-31"></span>
<span id="cb11-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># MLP branch</span></span>
<span id="cb11-33">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(combined_features)</span>
<span id="cb11-34">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb11-35">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb11-36">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb11-37">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)(y)</span>
<span id="cb11-38">output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Dense(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)(y)</span>
<span id="cb11-39"></span>
<span id="cb11-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create the functional model</span></span>
<span id="cb11-41">cnn_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.Model(inputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[embedding_input, peptide_length_input, mhc_length_input], outputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[output])</span>
<span id="cb11-42"></span>
<span id="cb11-43">cnn_model.summary()</span></code></pre></div></div>
</details>
</div>
<p>As we can see below, under the CNN architecture, the filter effectively compresses the embedding dimension from 640 down to 128, and then to 64. We set the padding to ‘same’ to retain the original sequence length of 71 after convolution. But if set to ‘valid’, the sequence length would reduce after each convolution layer, depending on the kernel size. The average pooling layer then reduces the sequence length dimension according to the pool size of 2 (basically halves it), and finally, we flatten the CNN output before concatenating it with the peptide and MHC2 lengths. This results in a feature vector of size 64 * 35 = 2240 from the CNN branch, which is then concatenated with the two length inputs, giving a total of 2242 features fed into the dense layers. Ultimately, the pooling layers help to prevent overfitting and save computational resources by reducing the dimensionality of the feature maps.</p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/cnn_model_summary.png" class="img-fluid"></p>
<p>Compare this with the MLP-only model architecture that we will compare against:</p>
<div id="4e561b06" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define MLP layers</span></span>
<span id="cb12-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define a helper function for the repetitive dense -&gt; batch norm -&gt; dropout block</span></span>
<span id="cb12-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_dense_block(n_neurons, dropout_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>):</span>
<span id="cb12-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tf.keras.Sequential([</span>
<span id="cb12-5">        tf.keras.layers.Dense(n_neurons, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>, kernel_initializer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'he_normal'</span>),</span>
<span id="cb12-6">        tf.keras.layers.BatchNormalization(),</span>
<span id="cb12-7">        tf.keras.layers.Dropout(dropout_rate)</span>
<span id="cb12-8">    ])</span>
<span id="cb12-9"></span>
<span id="cb12-10">tf.random.set_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb12-11"></span>
<span id="cb12-12">dnn_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.Sequential([</span>
<span id="cb12-13">    tf.keras.layers.Input(shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>X_train.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:]),</span>
<span id="cb12-14">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>),</span>
<span id="cb12-15">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>),</span>
<span id="cb12-16">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>),</span>
<span id="cb12-17">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>),</span>
<span id="cb12-18">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>),</span>
<span id="cb12-19">    tf.keras.layers.Dense(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-20">])</span></code></pre></div></div>
</details>
</div>
</section>
<section id="training-and-evaluation" class="level2">
<h2 class="anchored" data-anchor-id="training-and-evaluation">3. Training and Evaluation</h2>
<p>Set performance scheduling, early stopping, optimizer, compile model, and train the CNN + MLP model. The MLP-only model is trained with the same settings for comparison.</p>
<div id="172d7145" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Performance scheduling of learning rate</span></span>
<span id="cb13-2">lr_scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.callbacks.ReduceLROnPlateau(factor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb13-3"></span>
<span id="cb13-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Early stopping</span></span>
<span id="cb13-5">early_stopping <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.callbacks.EarlyStopping(patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, restore_best_weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-6"></span>
<span id="cb13-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define optimizer</span></span>
<span id="cb13-8">optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.optimizers.Adam(learning_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>)</span>
<span id="cb13-9"></span>
<span id="cb13-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compile and train the model</span></span>
<span id="cb13-11">cnn_model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">compile</span>(loss<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mse'</span>, optimizer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>optimizer, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RootMeanSquaredError'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2Score'</span>])</span>
<span id="cb13-12">fit_history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_model.fit(train_tfds, epochs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, validation_data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>valid_tfds,</span>
<span id="cb13-13">                            callbacks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[lr_scheduler, early_stopping])</span></code></pre></div></div>
</details>
</div>
<p>Training CNN models is quite memory intensive. This specific data and model architecture required around 30-40 GB of GPU memory and 80-90 GB of system memory. With sufficient resources, the training completed in about 20 minutes per run on an NVIDIA A100 GPU.</p>
<p>Plot training metrics:</p>
<div id="68303194" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot train and validation loss and RMSE across epochs</span></span>
<span id="cb14-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb14-3"></span>
<span id="cb14-4">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(nrows<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, ncols<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb14-5"></span>
<span id="cb14-6">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'loss'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_loss'</span>]].plot(</span>
<span id="cb14-7">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb14-8">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r--"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b-"</span>])</span>
<span id="cb14-9"></span>
<span id="cb14-10">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RootMeanSquaredError'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_RootMeanSquaredError'</span>]].plot(</span>
<span id="cb14-11">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb14-12">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r--"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b-"</span>])</span>
<span id="cb14-13"></span>
<span id="cb14-14">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2Score'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_R2Score'</span>]].plot(</span>
<span id="cb14-15">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb14-16">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r--"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b-"</span>])</span>
<span id="cb14-17"></span>
<span id="cb14-18">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'learning_rate'</span>]].plot(</span>
<span id="cb14-19">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb14-20">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"g-"</span>])</span>
<span id="cb14-21"></span>
<span id="cb14-22">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss'</span>)</span>
<span id="cb14-23">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss Over Epochs'</span>)</span>
<span id="cb14-24">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].legend([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training Loss'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Validation Loss'</span>])</span>
<span id="cb14-25"></span>
<span id="cb14-26">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RMSE'</span>)</span>
<span id="cb14-27">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RMSE Over Epochs'</span>)</span>
<span id="cb14-28">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].legend([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training RMSE'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Validation RMSE'</span>])</span>
<span id="cb14-29"></span>
<span id="cb14-30">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2'</span>)</span>
<span id="cb14-31">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2 Over Epochs'</span>)</span>
<span id="cb14-32">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].legend([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training R2'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Validation R2'</span>])</span>
<span id="cb14-33"></span>
<span id="cb14-34">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Learning Rate'</span>)</span>
<span id="cb14-35">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Learning Rate Over Epochs'</span>)</span>
<span id="cb14-36"></span>
<span id="cb14-37">plt.tight_layout()</span>
<span id="cb14-38">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/download (14).png" class="img-fluid"></p>
<p>The CNN + MLP model trained for the full 100 epochs, while the MLP-only model stopped early at epoch 80. Both models showed good convergence without overfitting.</p>
<p>Evaluate the model on the test set:</p>
<div id="7f3efdd6" class="cell" data-execution_count="12">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1">cnn_model.evaluate(X_test_inputs, y_test)</span></code></pre></div></div>
</details>
</div>
<p><strong>Test Results:</strong><br>
- R2Score: 0.6219<br>
- RootMeanSquaredError: 0.1606<br>
- loss: 0.0258<br>
</p>
<p>For comparison, the MLP-only model achieved the following test results:<br>
- R2Score: 0.5452<br>
- RootMeanSquaredError: 0.1775<br>
- loss: 0.0315<br>
</p>
<p>This indicates that, in this specific setting, incorporating CNN layers improved the model’s performance in predicting protein binding affinity.</p>
<p>Let’s plot a comparison of MLP-only vs CNN + MLP prediction accuracy on the test set, stratified by MHC2 alleles. Higher R2Score indicates better prediction performance.</p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/download1.png" class="img-fluid"></p>
<p>From the comparison plot, we can see that the CNN + MLP model generally provides better predictions across various MHC2 alleles compared to the MLP-only model.</p>
<p>Let’s look at one allele example on how well the CNN + MLP model predicts the affinity of <strong>HLA-DPA10201-DPB10101</strong>:</p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/download2.png" class="img-fluid"></p>
<p>As we can see, the <img src="https://latex.codecogs.com/png.latex?R%5E2"> = 0.8, which is an improvement over the MLP-only model of 0.72.</p>
<p>It is interesting to note that the MHC allele sample number does not correlate with the prediction performance, indicating that the model has learned meaningful patterns rather than just memorizing frequent alleles.</p>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/download3.png" class="img-fluid"></p>
</section>
<section id="saliency-map-and-in-silico-mutagenesis-analysis" class="level2">
<h2 class="anchored" data-anchor-id="saliency-map-and-in-silico-mutagenesis-analysis">4. Saliency Map and In Silico Mutagenesis Analysis</h2>
<p>To compute the saliency maps, we will calculate the gradients of the model output with respect to the input embeddings. This will help us identify which amino acid positions in the peptide and MHC2 sequences are most influential for the binding affinity predictions.</p>
<p>We will first randomly select 5 high-affinity samples from the test set for saliency analysis:</p>
<div id="f2363482" class="cell" data-execution_count="13">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Select 5 samples from the test data where Y &gt; 0.9</span></span>
<span id="cb16-2">high_affinity_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> all_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>][all_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>].sample(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb16-3"></span>
<span id="cb16-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get the indices of these samples</span></span>
<span id="cb16-5">sample_indices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data.index.values</span>
<span id="cb16-6"></span>
<span id="cb16-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Selected </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(high_affinity_data)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> samples with Y &gt; 0.9 for saliency analysis."</span>)</span>
<span id="cb16-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(high_affinity_data[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]])</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Selected 5 samples with Y &gt; 0.9 for saliency analysis.
               Peptide                 MHC_ID  \
21199  EKKYYAATQFEPLAA  HLA-DPA10301-DPB10402   
5997   AFLIGANYLGKPKEQ              DRB1_0101   
22257  DKRLAAYLMLMRSPS              DRB1_1501   
8396   SQVNPITLTAALLLL              DRB1_0701   
17575  NDKFTVFEGAFNKAI              DRB5_0101   

                                      MHC         Y  
21199  YMFFMFSGGAISNTLFGQFEYFDIEKVRMHLGMT  0.915458  
5997   QEFFIASGAAVDAIMWLFLECYDLQRATYHVGFT  1.000000  
22257  QEFFIASGAAVDAIMWPRFDYFDIQAATYHVVFT  1.000000  
8396   QEFFIASGAAVDAIMWGYFELYVIDRQTVHVGFT  0.956843  
17575  QEFFIASGAAVDAIMQDYFHDYDFDRATYHVGFT  1.000000  </code></pre>
<p>Now, we will extract the embeddings for these high-affinity samples:</p>
<div id="145a8e4a" class="cell" data-execution_count="14">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get embeddings for these high affinity data</span></span>
<span id="cb18-2">high_affinity_peptide <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].tolist()</span>
<span id="cb18-3">high_affinity_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].tolist()</span>
<span id="cb18-4"></span>
<span id="cb18-5">max_len_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">37</span></span>
<span id="cb18-6">max_len_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">34</span></span>
<span id="cb18-7"></span>
<span id="cb18-8">peptide_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_full_embedding(high_affinity_peptide, tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>, max_len<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len_pt)</span>
<span id="cb18-9">mhc_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_full_embedding(high_affinity_mhc, tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1280</span>, max_len<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len_mhc)</span>
<span id="cb18-10"></span>
<span id="cb18-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate the embeddings</span></span>
<span id="cb18-12">X_high_affinity_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate([peptide_embeddings, mhc_embeddings], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb18-13"></span>
<span id="cb18-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract corresponding sequence lengths</span></span>
<span id="cb18-15">X_high_affinity_pt_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>).values</span>
<span id="cb18-16">X_high_affinity_mhc_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>).values</span></code></pre></div></div>
</details>
</div>
<p>Define a helper function to compute saliency maps:</p>
<div id="c8f73e55" class="cell" data-execution_count="15">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tensorflow <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tf</span>
<span id="cb19-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb19-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb19-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb19-5"></span>
<span id="cb19-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> calculate_saliency_map(model: tf.keras.Model,</span>
<span id="cb19-7">                           embedding_data: np.ndarray,</span>
<span id="cb19-8">                           peptide_len_data: np.ndarray,</span>
<span id="cb19-9">                           mhc_len_data: np.ndarray,</span>
<span id="cb19-10">                           target_idx: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> np.ndarray:</span>
<span id="cb19-11"></span>
<span id="cb19-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculates saliency map for a given input using the trained model."""</span></span>
<span id="cb19-13"></span>
<span id="cb19-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert numpy arrays to TensorFlow tensors and ensure float32</span></span>
<span id="cb19-15">    input_embeddings_tensor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(embedding_data, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb19-16">    peptide_len_tensor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(peptide_len_data, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb19-17">    mhc_len_tensor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.convert_to_tensor(mhc_len_data, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb19-18"></span>
<span id="cb19-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> tf.GradientTape() <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tape:</span>
<span id="cb19-20">        tape.watch(input_embeddings_tensor) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Watch only the embeddings for saliency</span></span>
<span id="cb19-21">        </span>
<span id="cb19-22">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pass all inputs to the model for prediction of Y</span></span>
<span id="cb19-23">        predictions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model((input_embeddings_tensor, peptide_len_tensor, mhc_len_tensor))</span>
<span id="cb19-24">        </span>
<span id="cb19-25">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Select the target output if there are multiple outputs or a specific class</span></span>
<span id="cb19-26">        target_output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> predictions[:, target_idx]</span>
<span id="cb19-27"></span>
<span id="cb19-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate gradients of the target output with respect to the input embeddings</span></span>
<span id="cb19-29">    gradients <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tape.gradient(target_output, input_embeddings_tensor)</span>
<span id="cb19-30"></span>
<span id="cb19-31">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Take the mean across the embedding dimension to get a single saliency score per amino acid position</span></span>
<span id="cb19-32">    saliency <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.reduce_mean(gradients, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Take mean along last axis: embedding_dim</span></span>
<span id="cb19-33"></span>
<span id="cb19-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> saliency.numpy().flatten()</span></code></pre></div></div>
</details>
</div>
<div id="56b37520" class="cell" data-execution_count="16">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Package inputs for the model's predict method</span></span>
<span id="cb20-2">X_high_affinity_inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (X_high_affinity_embeddings, X_high_affinity_pt_len, X_high_affinity_mhc_len)</span>
<span id="cb20-3"></span>
<span id="cb20-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predictions for selected samples</span></span>
<span id="cb20-5">y_pred_high_affinity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_model.predict(X_high_affinity_inputs)</span></code></pre></div></div>
</details>
</div>
<p>Compute and plot the saliency maps for each selected high-affinity sample:</p>
<div id="b1224140" class="cell" data-execution_count="17">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1">fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(nrows<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(high_affinity_data), ncols<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(high_affinity_data) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb21-2">fig.suptitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency Maps for High Affinity Peptide-MHC Pairs (Y &gt; 0.9)'</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>)</span>
<span id="cb21-3"></span>
<span id="cb21-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ensure axes is always 2D even for a single row</span></span>
<span id="cb21-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(high_affinity_data) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:</span>
<span id="cb21-6">    axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([axes])</span>
<span id="cb21-7"></span>
<span id="cb21-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(high_affinity_data)):</span>
<span id="cb21-9">    sample_info <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data.iloc[i]</span>
<span id="cb21-10">    peptide_sequence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_info[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>]</span>
<span id="cb21-11">    mhc_sequence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_info[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>]</span>
<span id="cb21-12">    mhc_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_info[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>]</span>
<span id="cb21-13">    y_true_sample <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_info[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]</span>
<span id="cb21-14">    y_pred_sample <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_pred_high_affinity[i][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Access pre-calculated prediction</span></span>
<span id="cb21-15"></span>
<span id="cb21-16">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get one sample's embeddings and lengths at a time</span></span>
<span id="cb21-17">    current_embedding_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_high_affinity_embeddings[i:i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb21-18">    current_peptide_len_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_high_affinity_pt_len[i:i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb21-19">    current_mhc_len_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_high_affinity_mhc_len[i:i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb21-20"></span>
<span id="cb21-21">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate saliency map using the updated function signature</span></span>
<span id="cb21-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Normalize with a constant to enhance visualization</span></span>
<span id="cb21-23">    beta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e5</span></span>
<span id="cb21-24">    saliency_scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> calculate_saliency_map(cnn_model, </span>
<span id="cb21-25">                                             current_embedding_data, </span>
<span id="cb21-26">                                             current_peptide_len_data, </span>
<span id="cb21-27">                                             current_mhc_len_data) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> beta</span>
<span id="cb21-28"></span>
<span id="cb21-29">    peptide_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(peptide_sequence)</span>
<span id="cb21-30">    mhc_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(mhc_sequence)</span>
<span id="cb21-31"></span>
<span id="cb21-32">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Correctly slice saliency scores based on actual sequence lengths</span></span>
<span id="cb21-33">    peptide_saliency <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> saliency_scores[:peptide_len]</span>
<span id="cb21-34">    mhc_saliency <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> saliency_scores[max_len_pt : max_len_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> mhc_len]</span>
<span id="cb21-35"></span>
<span id="cb21-36">    annot_settings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rotation"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">90</span>}</span>
<span id="cb21-37"></span>
<span id="cb21-38">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot for Peptide Saliency</span></span>
<span id="cb21-39">    sns.heatmap(</span>
<span id="cb21-40">        [peptide_saliency],</span>
<span id="cb21-41">        cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coolwarm'</span>, </span>
<span id="cb21-42">        annot<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb21-43">        annot_kws<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>annot_settings,</span>
<span id="cb21-44">        fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".2f"</span>,</span>
<span id="cb21-45">        xticklabels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(peptide_sequence),</span>
<span id="cb21-46">        yticklabels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>],</span>
<span id="cb21-47">        cbar_kws<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency Score'</span>},</span>
<span id="cb21-48">        ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>axes[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb21-49">    )</span>
<span id="cb21-50">    axes[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Sample </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> - Peptide: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>peptide_sequence<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">True Y: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>y_true_sample<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, Pred Y: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>y_pred_sample<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb21-51">    axes[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].tick_params(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x'</span>, rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb21-52"></span>
<span id="cb21-53">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot for MHC Saliency</span></span>
<span id="cb21-54">    sns.heatmap(</span>
<span id="cb21-55">        [mhc_saliency],</span>
<span id="cb21-56">        cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coolwarm'</span>, </span>
<span id="cb21-57">        annot<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb21-58">        annot_kws<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>annot_settings,</span>
<span id="cb21-59">        fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".2f"</span>,</span>
<span id="cb21-60">        xticklabels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(mhc_sequence),</span>
<span id="cb21-61">        yticklabels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>],</span>
<span id="cb21-62">        cbar_kws<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency Score'</span>},</span>
<span id="cb21-63">        ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>axes[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb21-64">    )</span>
<span id="cb21-65">    axes[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Sample </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> - MHC: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mhc_sequence<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">MHC ID: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>mhc_id<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb21-66">    axes[i, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].tick_params(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x'</span>, rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb21-67"></span>
<span id="cb21-68">plt.tight_layout(rect<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.03</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>]) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adjust layout to make space for suptitle</span></span>
<span id="cb21-69">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/s_map.png" class="img-fluid"></p>
<p>Positive saliency scores (red) indicate that the amino acids are positively correlated with a higher binding affinity, while negative scores (blue) suggest that those amino acids contribute to lower binding affinity.</p>
<p>Next, let’s perform In Silico Mutagenesis (ISM) analysis to see how single amino acid mutations affect the predicted binding affinity. Instead of mutating every position, which will be computationally expensive, we will focus on mutating only the most salient positions (highest saliency score) in the peptide sequences for each sample.</p>
<p>First, generate a dictionary of the most disruptive mutations for each amino acid:</p>
<div id="db854816" class="cell" data-execution_count="18">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># A dictionary that suggests the most disruptive mutagenesis for each a.a.</span></span>
<span id="cb22-2">disruptive_mutations <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb22-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'W'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Small nonpolar -&gt; Bulkiest nonpolar/aromatic</span></span>
<span id="cb22-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'D'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Positively charged -&gt; Negatively charged</span></span>
<span id="cb22-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'N'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'F'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Polar uncharged -&gt; Hydrophobic aromatic</span></span>
<span id="cb22-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'D'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Negatively charged -&gt; Positively charged</span></span>
<span id="cb22-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'C'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Disulfide bond former -&gt; Similar size but non-disulfide/polar</span></span>
<span id="cb22-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'E'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'K'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Negatively charged -&gt; Positively charged</span></span>
<span id="cb22-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Q'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'W'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Polar uncharged -&gt; Bulkiest nonpolar/aromatic</span></span>
<span id="cb22-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'G'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'P'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Flexible -&gt; Conformational constraint</span></span>
<span id="cb22-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'H'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'D'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Positively charged -&gt; Negatively charged (pH depending)</span></span>
<span id="cb22-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'I'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'E'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hydrophobic -&gt; Negatively charged hydrophilic</span></span>
<span id="cb22-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'L'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'K'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hydrophobic -&gt; Positively charged hydrophilic</span></span>
<span id="cb22-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'K'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'D'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Positively charged -&gt; Negatively charged</span></span>
<span id="cb22-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'M'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'E'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Nonpolar/sulfur -&gt; Negatively charged hydrophilic</span></span>
<span id="cb22-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'F'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'E'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hydrophobic aromatic -&gt; Negatively charged hydrophilic</span></span>
<span id="cb22-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'P'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'G'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Conformational constraint -&gt; Flexible</span></span>
<span id="cb22-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'L'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Polar uncharged -&gt; Hydrophobic</span></span>
<span id="cb22-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'T'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'I'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Polar uncharged -&gt; Hydrophobic</span></span>
<span id="cb22-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'W'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Bulkiest nonpolar -&gt; Smallest nonpolar</span></span>
<span id="cb22-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'D'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Aromatic/polar -&gt; Negatively charged</span></span>
<span id="cb22-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'V'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'E'</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hydrophobic -&gt; Negatively charged hydrophilic</span></span>
<span id="cb22-23">}</span></code></pre></div></div>
</details>
</div>
<p>Perform ISM on the top salient positions in the peptide sequences:</p>
<div id="32e1509f" class="cell" data-execution_count="19">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Find aa with the highest saliency score across all samples</span></span>
<span id="cb23-2">max_scores_aa_pos_pt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb23-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(high_affinity_data)):</span>
<span id="cb23-4">  sample_info <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data.iloc[i]</span>
<span id="cb23-5">  peptide_sequence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_info[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>]</span>
<span id="cb23-6">  current_embedding_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_high_affinity_embeddings[i:i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb23-7">  current_peptide_len_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_high_affinity_pt_len[i:i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb23-8">  current_mhc_len_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X_high_affinity_mhc_len[i:i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb23-9">  saliency <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> calculate_saliency_map(cnn_model, current_embedding_data, current_peptide_len_data, current_mhc_len_data)</span>
<span id="cb23-10">  max_score_pos <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> saliency[:current_peptide_len_data[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]].argmax().tolist()</span>
<span id="cb23-11">  max_score_aa <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> peptide_sequence[max_score_pos]</span>
<span id="cb23-12">  max_scores_aa_pos_pt[sample_info[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>].tolist()] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {max_score_aa: max_score_pos}</span>
<span id="cb23-13"></span>
<span id="cb23-14"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Identified highest saliency amino acids and their positions:"</span>)</span>
<span id="cb23-15">display(max_scores_aa_pos_pt)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Identified highest saliency amino acids and their positions:
{60550: {'L': 12},
 117646: {'L': 2},
 51178: {'P': 13},
 73939: {'A': 10},
 26350: {'F': 3}}</code></pre>
<div id="75f88de0" class="cell" data-execution_count="20">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1">mutated_peptide_predictions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb25-2"></span>
<span id="cb25-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, (peptide_id, saliency_info) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(max_scores_aa_pos_pt.items()):</span>
<span id="cb25-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get original sample info</span></span>
<span id="cb25-5">    sample_row <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> high_affinity_data[high_affinity_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peptide_id].iloc[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb25-6">    original_peptide <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>]</span>
<span id="cb25-7">    original_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>]</span>
<span id="cb25-8">    original_y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_pred_high_affinity[high_affinity_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peptide_id].flatten()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb25-9"></span>
<span id="cb25-10">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get the AA with highest saliency and its position</span></span>
<span id="cb25-11">    saliency_aa <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(saliency_info.keys())[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb25-12">    saliency_pos <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(saliency_info.values())[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb25-13"></span>
<span id="cb25-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Determine the disruptive mutation</span></span>
<span id="cb25-15">    disruptive_aa <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> disruptive_mutations.get(saliency_aa, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A'</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Default to Alanine if not in dict</span></span>
<span id="cb25-16"></span>
<span id="cb25-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create mutated peptide sequence</span></span>
<span id="cb25-18">    mutated_peptide_sequence_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(original_peptide)</span>
<span id="cb25-19">    mutated_peptide_sequence_list[saliency_pos] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> disruptive_aa</span>
<span id="cb25-20">    mutated_peptide <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(mutated_peptide_sequence_list)</span>
<span id="cb25-21"></span>
<span id="cb25-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># --- Extract embeddings for the mutated peptide ---</span></span>
<span id="cb25-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ensure original MHC embeddings are reused to isolate peptide effect</span></span>
<span id="cb25-24">    original_mhc_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_full_embedding([original_mhc], tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, max_len<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len_mhc)</span>
<span id="cb25-25"></span>
<span id="cb25-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract embeddings for the mutated peptide</span></span>
<span id="cb25-27">    mutated_peptide_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_full_embedding([mutated_peptide], tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, max_len<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_len_pt)</span>
<span id="cb25-28"></span>
<span id="cb25-29">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate mutated peptide embeddings with original MHC embeddings</span></span>
<span id="cb25-30">    X_mutated_combined_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate([mutated_peptide_embeddings, original_mhc_embeddings], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb25-31"></span>
<span id="cb25-32">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get sequence lengths for mutated peptide and original MHC</span></span>
<span id="cb25-33">    mutated_peptide_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(mutated_peptide)])</span>
<span id="cb25-34">    original_mhc_len <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(original_mhc)])</span>
<span id="cb25-35"></span>
<span id="cb25-36">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Package inputs for prediction</span></span>
<span id="cb25-37">    X_mutated_inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb25-38">        X_mutated_combined_embeddings,</span>
<span id="cb25-39">        tf.convert_to_tensor(mutated_peptide_len, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32),</span>
<span id="cb25-40">        tf.convert_to_tensor(original_mhc_len, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tf.float32)</span>
<span id="cb25-41">    )</span>
<span id="cb25-42"></span>
<span id="cb25-43">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predict binding affinity for the mutated peptide</span></span>
<span id="cb25-44">    mutated_y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_model.predict(X_mutated_inputs).flatten()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb25-45"></span>
<span id="cb25-46">    mutated_peptide_predictions.append({</span>
<span id="cb25-47">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide_ID'</span>: peptide_id,</span>
<span id="cb25-48">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Original_Peptide'</span>: original_peptide,</span>
<span id="cb25-49">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Mutated_Peptide'</span>: mutated_peptide,</span>
<span id="cb25-50">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency_AA'</span>: saliency_aa,</span>
<span id="cb25-51">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency_Pos'</span>: saliency_pos <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb25-52">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Disruptive_AA'</span>: disruptive_aa,</span>
<span id="cb25-53">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Original_Pred_Y'</span>: original_y_pred,</span>
<span id="cb25-54">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Mutated_Pred_Y'</span>: mutated_y_pred,</span>
<span id="cb25-55">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Change_in_Y'</span>: mutated_y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> original_y_pred</span>
<span id="cb25-56">    })</span>
<span id="cb25-57"></span>
<span id="cb25-58">mutated_predictions_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(mutated_peptide_predictions)</span>
<span id="cb25-59"></span>
<span id="cb25-60"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(mutated_predictions_df)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>   Peptide_ID Original_Peptide  Mutated_Peptide Saliency_AA  Saliency_Pos  \
0       60550  EKKYYAATQFEPLAA  EKKYYAATQFEPKAA           L            13   
1      117646  AFLIGANYLGKPKEQ  AFKIGANYLGKPKEQ           L             3   
2       51178  DKRLAAYLMLMRSPS  DKRLAAYLMLMRSGS           P            14   
3       73939  SQVNPITLTAALLLL  SQVNPITLTAWLLLL           A            11   
4       26350  NDKFTVFEGAFNKAI  NDKETVFEGAFNKAI           F             4   

  Disruptive_AA  Original_Pred_Y  Mutated_Pred_Y  Change_in_Y  
0             K         0.879057        0.721061    -0.157996  
1             K         0.782684        0.729118    -0.053567  
2             G         0.652823        0.643233    -0.009590  
3             W         0.665965        0.581599    -0.084366  
4             E         0.678189        0.355576    -0.322613  </code></pre>
<p>Plot the changes in predicted binding affinity due to the mutations:</p>
<div id="c8ef1f07" class="cell" data-execution_count="21">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb27-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb27-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> adjustText <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> adjust_text</span>
<span id="cb27-4"></span>
<span id="cb27-5">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb27-6">sns.scatterplot(</span>
<span id="cb27-7">    data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>mutated_predictions_df,</span>
<span id="cb27-8">    x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Original_Pred_Y'</span>,</span>
<span id="cb27-9">    y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Mutated_Pred_Y'</span>,</span>
<span id="cb27-10">    hue<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Change_in_Y'</span>, </span>
<span id="cb27-11">    s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>,</span>
<span id="cb27-12">    palette<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coolwarm'</span>, </span>
<span id="cb27-13">    legend<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'full'</span></span>
<span id="cb27-14">)</span>
<span id="cb27-15"></span>
<span id="cb27-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add a diagonal line for reference (where Y_original == Y_mutated)</span></span>
<span id="cb27-17">plt.plot([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'k--'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No Change'</span>)</span>
<span id="cb27-18"></span>
<span id="cb27-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Annotate points with Peptide_ID or a combination of info</span></span>
<span id="cb27-20">texts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb27-21"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> idx, row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> mutated_predictions_df.iterrows():</span>
<span id="cb27-22">    label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Original_Peptide'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency_AA'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span>row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Saliency_Pos'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">-&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Disruptive_AA'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb27-23">    texts.append(plt.text(row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Original_Pred_Y'</span>], row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Mutated_Pred_Y'</span>], label, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>))</span>
<span id="cb27-24"></span>
<span id="cb27-25">adjust_text(texts, arrowprops<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(arrowstyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gray'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb27-26"></span>
<span id="cb27-27">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Predicted Binding Affinity: Original vs. Mutated Peptides'</span>)</span>
<span id="cb27-28">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Original Predicted Y'</span>)</span>
<span id="cb27-29">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Mutated Predicted Y'</span>)</span>
<span id="cb27-30">plt.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>)</span>
<span id="cb27-31">plt.xlim(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb27-32">plt.ylim(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb27-33">plt.axhline(y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gray'</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">':'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span>
<span id="cb27-34">plt.axvline(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gray'</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">':'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span>
<span id="cb27-35">plt.legend(title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Change in Y'</span>)</span>
<span id="cb27-36">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/images/ism_scatter.png" class="img-fluid"></p>
<p>As we can see from the ISM analysis, mutating the most salient amino acid positions in the peptide sequences generally leads to a decrease in predicted binding affinity, as indicated by the points falling below the diagonal line. Some mutations result in significant drops in predicted affinity, while others are less impactful. However, we are only mutating a single position here, and multiple mutations may have a more pronounced effect. This analysis provides a hypothesis for experimental validation of key residues involved in peptide-MHC binding.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Incorporating convolutional neural networks (CNNs) into the protein binding prediction model improved performance compared to a MLP-only approach. By retaining the 2D structure of the ESM2 embeddings and applying 1D convolutional layers, the model was able to capture local sequence patterns that are important for binding affinity prediction. The CNN + MLP model achieved higher R2 scores and lower RMSE on the test set, demonstrating its effectiveness.</p>
<p>It is important to note that further hyperparameter tuning for either model could yield different results. Additionally, exploring other architectures, such as attention mechanisms, could provide additional insights into modeling protein binding affinity.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://github.com/facebookresearch/esm">ESM2</a></li>
<li><a href="https://www.oreilly.com/library/view/hands-on-machine-learning/9781492032632/">Hands-on Machine Learning with Scikit-Learn, Keras, and TensorFlow</a></li>
<li><a href="https://github.com/deep-learning-for-biology">Deep Learning for Biology</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Deep Learning</category>
  <category>Convolutional Neural Networks</category>
  <category>Keras</category>
  <category>ESM2</category>
  <category>Protein Language Models</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/P6_cnn_dnn_peptide_mhc/</guid>
  <pubDate>Tue, 03 Feb 2026 08:00:00 GMT</pubDate>
</item>
<item>
  <title>Predicting Peptide-MHC Class II Binding with ESM2 and Neural Networks</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/</link>
  <description><![CDATA[ 





<p>In this post, I will build a neural network to predict the binding affinity between peptides and MHC Class II alleles, utilizing embeddings extracted from the Evolutionary Scale Modeling 2 (ESM2) protein large language model (LLM).</p>
<section id="background" class="level2">
<h2 class="anchored" data-anchor-id="background">Background</h2>
<p><strong>Why is this important?</strong></p>
<ul>
<li><strong>Understanding Immune Response</strong>: MHC Class II molecules present peptide fragments to CD4+ T helper cells, which are crucial for initiating and regulating adaptive immune responses. Understanding which peptides bind strongly to MHC II allows researchers to identify potential T cell epitopes.</li>
<li><strong>Vaccine Design</strong>: Accurate prediction of MHC II-binding peptides can guide the design of subunit vaccines. By selecting peptides likely to bind to a broad range of MHC II alleles (covering genetic diversity in a population), vaccines can be designed to elicit robust T cell responses.</li>
<li><strong>Autoimmune Diseases</strong>: Inappropriate presentation of self-peptides by MHC II molecules can contribute to autoimmune diseases. Predicting these interactions helps in understanding disease mechanisms and developing therapeutic interventions.</li>
<li><strong>Allergy Research</strong>: Similarly, understanding how allergens bind to MHC II can shed light on allergic reactions and aid in treatment development.</li>
<li><strong>Personalized Medicine</strong>: With advancements in sequencing, predicting an individual’s MHC II genotype and the peptides they present could lead to personalized immunotherapies.</li>
</ul>
</section>
<section id="analysis-plan" class="level2">
<h2 class="anchored" data-anchor-id="analysis-plan">Analysis Plan</h2>
<ol type="1">
<li>Download and split the TDC MHC2_IEDB-Jensen dataset.</li>
<li>Perform exploratory data analysis (EDA).</li>
<li>Extract and merge LLM embeddings for peptides and MHC sequences.</li>
<li>Setup TensorFlow datasets, build a Multilayer Perceptron (MLP) model, with defined loss function and optimizer.</li>
<li>Train the model and evaluate metrics.</li>
<li>Assess prediction accuracy on test data.</li>
</ol>
</section>
<section id="summary-figure" class="level2">
<h2 class="anchored" data-anchor-id="summary-figure">Summary Figure</h2>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/summary_figure.png" class="img-fluid figure-img"></p>
<figcaption>Schematic overview of the Deep Neural Network pipeline for predicting peptide-MHC binding affinity (Figure generated with the assistance of Gemini).</figcaption>
</figure>
</div>
</section>
<section id="data-selection-and-splitting" class="level2">
<h2 class="anchored" data-anchor-id="data-selection-and-splitting">1. Data Selection and Splitting</h2>
<p>We will use datasets from <strong>Therapeutics Data Commons (TDC)</strong>, a large-scale data repository for machine learning projects.</p>
<div id="4f38659f" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Access the MHC2_IEDB_Jensen data from TDC API and obtain splitted data</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> tdc.multi_pred <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PeptideMHC</span>
<span id="cb1-3"></span>
<span id="cb1-4">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PeptideMHC(name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MHC2_IEDB_Jensen"</span>)</span>
<span id="cb1-5">split <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.get_split(method <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"random"</span>, seed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span>, frac <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>])</span>
<span id="cb1-6">train_df, valid_df, test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> split[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>], split[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid'</span>], split[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>]</span></code></pre></div></div>
</details>
</div>
<div id="a35b133b" class="cell" data-execution_count="2">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save the files to drive</span></span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> os</span>
<span id="cb2-3">save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'./data'</span></span>
<span id="cb2-4">os.makedirs(save_path, exist_ok<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb2-5"></span>
<span id="cb2-6">train_df.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_dat.feather'</span>))</span>
<span id="cb2-7">valid_df.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_dat.feather'</span>))</span>
<span id="cb2-8">test_df.to_feather(os.path.join(save_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_dat.feather'</span>))</span></code></pre></div></div>
</details>
</div>
</section>
<section id="exploratory-data-analysis" class="level2">
<h2 class="anchored" data-anchor-id="exploratory-data-analysis">2. Exploratory Data Analysis</h2>
<p>Let’s examine the structure and distribution of our data.</p>
<div id="8fc79174" class="cell" data-execution_count="3">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how many data points in each data set</span></span>
<span id="cb3-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Number of data points in the training set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Number of data points in the validation set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(valid_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Number of data points in the test set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(test_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Number of data points in the training set: 93997
Number of data points in the validation set: 13428
Number of data points in the test set: 26856</code></pre>
<p>A quick look at the training data reveals the structure: <code>Peptide</code> sequence, <code>MHC</code> sequence (pseudo-sequence), and the binding affinity <code>Y</code>.</p>
<div id="7a2fc3c0" class="cell" data-execution_count="4">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># quick look at the train data structure</span></span>
<span id="cb5-2">train_df.head()</span></code></pre></div></div>
</details>
</div>
<div class="scrolling-table">
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: right;"></th>
<th style="text-align: left;">Peptide</th>
<th style="text-align: left;">MHC</th>
<th style="text-align: right;">Y</th>
<th style="text-align: left;">MHC_ID</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: right;">0</td>
<td style="text-align: left;">PKYVKQNTLKLAT</td>
<td style="text-align: left;">YAFFMF…</td>
<td style="text-align: right;">0.000000</td>
<td style="text-align: left;">HLA-DPA10103-DPB10201</td>
</tr>
<tr class="even">
<td style="text-align: right;">1</td>
<td style="text-align: left;">AAAAGWQTLSAALDA</td>
<td style="text-align: left;">YAFFMF…</td>
<td style="text-align: right;">0.238910</td>
<td style="text-align: left;">HLA-DPA10103-DPB10201</td>
</tr>
<tr class="odd">
<td style="text-align: right;">2</td>
<td style="text-align: left;">AALDAQAVELTARLN</td>
<td style="text-align: left;">YAFFMF…</td>
<td style="text-align: right;">0.357937</td>
<td style="text-align: left;">HLA-DPA10103-DPB10201</td>
</tr>
<tr class="even">
<td style="text-align: right;">3</td>
<td style="text-align: left;">ADLGYGPATPAAPAA</td>
<td style="text-align: left;">YAFFMF…</td>
<td style="text-align: right;">0.285795</td>
<td style="text-align: left;">HLA-DPA10103-DPB10201</td>
</tr>
<tr class="odd">
<td style="text-align: right;">4</td>
<td style="text-align: left;">AGSYAADLGYGPATP</td>
<td style="text-align: left;">YAFFMF…</td>
<td style="text-align: right;">0.108843</td>
<td style="text-align: left;">HLA-DPA10103-DPB10201</td>
</tr>
</tbody>
</table>
</div>
<section id="distribution-of-binding-affinity" class="level3">
<h3 class="anchored" data-anchor-id="distribution-of-binding-affinity">Distribution of Binding Affinity</h3>
<p>We can visualize the distribution of the target variable <code>Y</code> (binding affinity) in the training set.</p>
<div id="8068a933" class="cell" data-execution_count="5">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># look at the distribution of Y in training data</span></span>
<span id="cb6-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb6-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb6-4"></span>
<span id="cb6-5">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb6-6">sns.histplot(train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>], bins<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, kde<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb6-7">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Distribution of Y (Binding Affinity) in Training Data'</span>)</span>
<span id="cb6-8">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Binding Affinity (Y)'</span>)</span>
<span id="cb6-9">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Frequency'</span>)</span>
<span id="cb6-10">plt.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span>
<span id="cb6-11">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_10_output.png" class="img-fluid"></p>
<p>The Y values represent normalized binding affinity between the peptides and the MHC II, with higher values representing higher affinities. We can see from the distribution that many pairs have no affinity (Y = 0), while others have variable levels of affinity.</p>
</section>
<section id="peptide-and-mhc-occurrences" class="level3">
<h3 class="anchored" data-anchor-id="peptide-and-mhc-occurrences">Peptide and MHC Occurrences</h3>
<div id="f4bb3b9c" class="cell" data-execution_count="6">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># How many unique MHC_ID and peptides are there?</span></span>
<span id="cb7-2">unique_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>].nunique()</span>
<span id="cb7-3">unique_peptides <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].nunique()</span>
<span id="cb7-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Number of unique MHC_IDs in training set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>unique_mhc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb7-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Number of unique peptides in training set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>unique_peptides<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Number of unique MHC_IDs in training set: 79
Number of unique peptides in training set: 14597</code></pre>
</section>
<section id="mhc-type-distribution" class="level3">
<h3 class="anchored" data-anchor-id="mhc-type-distribution">MHC Type Distribution</h3>
<p>We can also look at the distribution of MHC types in our training data.</p>
<div id="428982f6" class="cell" data-execution_count="7">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># plot barplot of instances per MHC2 molecule</span></span>
<span id="cb9-2">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb9-3">train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MHC_ID"</span>].value_counts().sort_values(ascending <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>).plot(kind <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bar'</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_14_output.png" class="img-fluid"></p>
<p>Some MHCs have many peptide binding data points, while others have only a few. In the next session, we will remove low instance MHC data so that the prediction model has sufficient training data.</p>
</section>
</section>
<section id="extract-and-merge-llm-embeddings" class="level2">
<h2 class="anchored" data-anchor-id="extract-and-merge-llm-embeddings">3. Extract and Merge LLM Embeddings</h2>
<p>To represent the protein sequences for our neural network, we will use <strong>ESM-2 (Evolutionary Scale Modeling)</strong>, a state-of-the-art protein language model. We’ll use the 150M parameter version (<code>esm2_t30_150M_UR50D</code>), which has 640 embedding dimensions.</p>
<div id="9c9bc837" class="cell" data-execution_count="8">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only keep MHC_ID that has &gt;= 1000 instances in train data, so that the model has sufficient training data</span></span>
<span id="cb10-2">n_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MHC_ID"</span>].value_counts()</span>
<span id="cb10-3">keep_mhc_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n_data[n_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>].index.tolist()</span>
<span id="cb10-4">train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_df[train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MHC_ID"</span>].isin(keep_mhc_id)].reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb10-5">valid_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_df[valid_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MHC_ID"</span>].isin(keep_mhc_id)].reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb10-6">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df[test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MHC_ID"</span>].isin(keep_mhc_id)].reset_index(drop<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</details>
</div>
<div id="9a90f0bb" class="cell" data-execution_count="9">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># How many data points in each data set</span></span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Number of data points in the training set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb11-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Number of data points in the validation set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(valid_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb11-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Number of data points in the test set: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(test_df)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</details>
</div>
<p><strong>Output:</strong></p>
<pre><code>Number of data points in the training set: 82388
Number of data points in the validation set: 11702
Number of data points in the test set: 23410</code></pre>
<div id="cd0d8ed1" class="cell" data-execution_count="10">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> transformers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AutoTokenizer, EsmModel</span>
<span id="cb13-2"></span>
<span id="cb13-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># model checkpoints can be seen here: https://github.com/facebookresearch/esm#available-models-and-datasets-</span></span>
<span id="cb13-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the one we use has medium complexity and has 640 dimensions</span></span>
<span id="cb13-5"></span>
<span id="cb13-6">model_checkpoint <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"facebook/esm2_t30_150M_UR50D"</span></span>
<span id="cb13-7">tokenizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AutoTokenizer.from_pretrained(model_checkpoint)</span>
<span id="cb13-8">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> EsmModel.from_pretrained(model_checkpoint)</span></code></pre></div></div>
</details>
</div>
<p>A note to LLM model selection for this specific task: I’ve tried larger ESM2 model with 1280 or 2560 embedding dimensions, and they did not improve the accuracy of binding prediction. As peptides and MHC lengths are quite short, it is possible that the 640 dimension model has already saturated learnable information for this task.</p>
<div id="43c341db" class="cell" data-execution_count="11">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Write a function to extract mean embeddings for protein sequences</span></span>
<span id="cb14-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GPU will significantly speed up the process</span></span>
<span id="cb14-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This is memory intensive, so we will batch the iteration</span></span>
<span id="cb14-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb14-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> transformers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AutoTokenizer, EsmModel</span>
<span id="cb14-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb14-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb14-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> tqdm <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tqdm</span>
<span id="cb14-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb14-10"></span>
<span id="cb14-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> extract_mean_embedding(</span>
<span id="cb14-12">    sequence: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>],</span>
<span id="cb14-13">    tokenizer: AutoTokenizer,</span>
<span id="cb14-14">    model: EsmModel,</span>
<span id="cb14-15">    device: torch.device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb14-16">    batch_size: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span></span>
<span id="cb14-17">    ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> pd.DataFrame:</span>
<span id="cb14-18"></span>
<span id="cb14-19">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Extract mean embeddings for peptide sequences from a LLM model."""</span></span>
<span id="cb14-20"></span>
<span id="cb14-21">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Use GPU when available</span></span>
<span id="cb14-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> device:</span>
<span id="cb14-23">        device <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuda"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> torch.cuda.is_available() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cpu"</span>)</span>
<span id="cb14-24"></span>
<span id="cb14-25">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Separate sequence list into batches</span></span>
<span id="cb14-26">    n_batches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> math.ceil(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(sequence) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> batch_size)</span>
<span id="cb14-27">    all_batch_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb14-28"></span>
<span id="cb14-29">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.to(device) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Move model to the target device</span></span>
<span id="cb14-30">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Set model to evaluation mode</span></span>
<span id="cb14-31"></span>
<span id="cb14-32">    steps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tqdm(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_batches))</span>
<span id="cb14-33"></span>
<span id="cb14-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> steps:</span>
<span id="cb14-35">        steps.set_description(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Processing batch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_batches<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb14-36">        start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> batch_size</span>
<span id="cb14-37">        end <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> batch_size</span>
<span id="cb14-38">        batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sequence[start:end]</span>
<span id="cb14-39"></span>
<span id="cb14-40">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Tokenize peptide sequence and pad to equal length</span></span>
<span id="cb14-41">        inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokenizer(batch, return_tensors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pt"</span>, padding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb14-42"></span>
<span id="cb14-43">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Move input to the target device</span></span>
<span id="cb14-44">        inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {name: tensor.to(device) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, tensor <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> inputs.items()}</span>
<span id="cb14-45"></span>
<span id="cb14-46">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Forward pass through the model without gradient tracking to get mean embeddings</span></span>
<span id="cb14-47">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb14-48">          batch_mean_embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>inputs).last_hidden_state.mean(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).detach().cpu().numpy()</span>
<span id="cb14-49">        all_batch_embeddings.append(batch_mean_embeddings)</span>
<span id="cb14-50"></span>
<span id="cb14-51">    embeddings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(np.vstack(all_batch_embeddings))</span>
<span id="cb14-52">    embeddings.columns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"me_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(embeddings.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])]</span>
<span id="cb14-53">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> embeddings</span></code></pre></div></div>
</details>
</div>
<p>The ESM2 model returns a sequence of embeddings for each token in the input sequence. We take the mean of these embeddings to get a single embedding for the entire sequence. It is also possible to keep the sequence of embeddings for each token, and use other methods to aggregate the embeddings, such as max pooling or attention pooling, or train a 1D Convolutional Neural Network (CNN) to learn the optimal way to aggregate the embeddings. In this case, we will keep the mean embeddings for each sequence.</p>
<div id="19bf016b" class="cell" data-execution_count="12">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Put all peptide/MHC data into a dictionary</span></span>
<span id="cb15-2">sequence_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb15-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_pt"</span>: train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].tolist(),</span>
<span id="cb15-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"valid_pt"</span>: valid_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].tolist(),</span>
<span id="cb15-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_pt"</span>: test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>].tolist(),</span>
<span id="cb15-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train_mhc"</span>: train_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].tolist(),</span>
<span id="cb15-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"valid_mhc"</span>: valid_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].tolist(),</span>
<span id="cb15-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test_mhc"</span>: test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC'</span>].tolist()</span>
<span id="cb15-9">}</span>
<span id="cb15-10"></span>
<span id="cb15-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract embeddings for all peptide/MHC data</span></span>
<span id="cb15-12">embedding_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb15-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> data, sequence <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sequence_dict.items():</span>
<span id="cb15-14">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Extracting embeddings for </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>data<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">..."</span>)</span>
<span id="cb15-15">    embedding_dict[data] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> extract_mean_embedding(sequence, tokenizer, model, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2560</span>)</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/embeddings.png" class="img-fluid"></p>
<p>There are other, more complex ways to combine embeddings from two interacting entities, but for this task, we will use the simple approach of concatenating the embeddings.</p>
<div id="80191143" class="cell" data-execution_count="13">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Modify column names to add peptide/MHC prefix</span></span>
<span id="cb16-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> key, me <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> embedding_dict.items():</span>
<span id="cb16-3">  me.columns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>key<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>col<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> me.columns]</span>
<span id="cb16-4"></span>
<span id="cb16-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Concatenate peptide and MHC mean embeddings and name columns</span></span>
<span id="cb16-6">train_me <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([train_df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]],</span>
<span id="cb16-7">                      embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_pt'</span>],</span>
<span id="cb16-8">                      embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_mhc'</span>]], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb16-9">valid_me <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([valid_df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]],</span>
<span id="cb16-10">                      embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_pt'</span>],</span>
<span id="cb16-11">                      embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_mhc'</span>]], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb16-12">test_me <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([test_df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Peptide'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>]],</span>
<span id="cb16-13">                     embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_pt'</span>],</span>
<span id="cb16-14">                     embedding_dict[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_mhc'</span>]], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb16-15"></span>
<span id="cb16-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save data as feather files</span></span>
<span id="cb16-17">model_cp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(model.name_or_path).replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span>)</span>
<span id="cb16-18">df_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [(train_me, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train_me'</span>), (valid_me, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'valid_me'</span>), (test_me, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test_me'</span>)]</span>
<span id="cb16-19">save_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'./data'</span></span>
<span id="cb16-20"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> df, df_name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> df_list:</span>
<span id="cb16-21">  df.to_feather(os.path.join(save_path, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>model_cp<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>df_name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">.feather'</span>))</span></code></pre></div></div>
</details>
</div>
<p>Let’s visualize the embeddings using t-SNE to see if there are any patterns in the data.</p>
<div id="8921a256" class="cell" data-execution_count="14">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot t-SNE of sampled peptide-MHC mean embeddings</span></span>
<span id="cb17-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb17-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb17-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.manifold <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> TSNE</span>
<span id="cb17-5"></span>
<span id="cb17-6">sampled_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_me.sample(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).index <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sample 5000 data points for visualization</span></span>
<span id="cb17-7">X_embedded <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> TSNE(n_components<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, learning_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'auto'</span>,</span>
<span id="cb17-8">                  init<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'random'</span>, perplexity<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>).fit_transform(train_me.loc[sampled_index])</span>
<span id="cb17-9"></span>
<span id="cb17-10">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb17-11">plt.scatter(X_embedded[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], X_embedded[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb17-12">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'t-SNE of Peptide-MHC Embeddings'</span>)</span>
<span id="cb17-13">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_29_output.png" class="img-fluid"></p>
<p>In the above t-SNE plot, we can see some cluster structures correlating with higher Y, indicating that the embeddings encode information relating to peptide-MHC affinity.</p>
</section>
<section id="neural-network-training" class="level2">
<h2 class="anchored" data-anchor-id="neural-network-training">4. Neural Network Training</h2>
<p>We will build a MLP that takes the concatenated peptide and MHC embeddings as input, and outputs the predicted affinity.</p>
<section id="dataset-preparation" class="level3">
<h3 class="anchored" data-anchor-id="dataset-preparation">Dataset Preparation</h3>
<p>We convert our extracted embeddings and labels into TensorFlow datasets.</p>
<div id="21489bc9" class="cell" data-execution_count="15">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert data to Tensorflow dataset</span></span>
<span id="cb18-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tensorflow <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tf</span>
<span id="cb18-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb18-4"></span>
<span id="cb18-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compile all feature columns (peptide and MHC embeddings) into a single NumPy array for each dataset</span></span>
<span id="cb18-6">X_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_me.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(regex<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"^pt|^mhc"</span>).values</span>
<span id="cb18-7">y_train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_me[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>].values</span>
<span id="cb18-8"></span>
<span id="cb18-9">X_valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_me.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(regex<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"^pt|^mhc"</span>).values</span>
<span id="cb18-10">y_valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_me[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>].values</span>
<span id="cb18-11"></span>
<span id="cb18-12">X_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_me.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(regex<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"^pt|^mhc"</span>).values</span>
<span id="cb18-13">y_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_me[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>].values</span>
<span id="cb18-14"></span>
<span id="cb18-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create tf.data.Dataset from these concatenated arrays</span></span>
<span id="cb18-16">train_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.data.Dataset.from_tensor_slices((X_train, y_train))</span>
<span id="cb18-17"></span>
<span id="cb18-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Shuffle, batch and prefetch the tfds</span></span>
<span id="cb18-19">train_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_tfds.shuffle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).batch(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>).prefetch(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb18-20"></span>
<span id="cb18-21">valid_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.data.Dataset.from_tensor_slices((X_valid, y_valid))</span>
<span id="cb18-22">valid_tfds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_tfds.batch(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>).prefetch(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</details>
</div>
</section>
<section id="model-architecture" class="level3">
<h3 class="anchored" data-anchor-id="model-architecture">Model Architecture</h3>
<p>The model consists of dense layers with varying dropout rates to prevent overfitting.</p>
<div id="94725e70" class="cell" data-execution_count="16">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define MLP layers</span></span>
<span id="cb19-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define a helper function for the repetitive dense -&gt; batch norm -&gt; dropout block</span></span>
<span id="cb19-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_dense_block(n_neurons, dropout_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>):</span>
<span id="cb19-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tf.keras.Sequential([</span>
<span id="cb19-5">        tf.keras.layers.Dense(n_neurons, activation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'relu'</span>, kernel_initializer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'he_normal'</span>),</span>
<span id="cb19-6">        tf.keras.layers.BatchNormalization(),</span>
<span id="cb19-7">        tf.keras.layers.Dropout(dropout_rate)</span>
<span id="cb19-8">    ])</span>
<span id="cb19-9"></span>
<span id="cb19-10">tf.random.set_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb19-11">norm_layer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.layers.Normalization(input_shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>X_train.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:])</span>
<span id="cb19-12"></span>
<span id="cb19-13">dnn_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.Sequential([</span>
<span id="cb19-14">    norm_layer,</span>
<span id="cb19-15">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>),</span>
<span id="cb19-16">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>),</span>
<span id="cb19-17">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>),</span>
<span id="cb19-18">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>),</span>
<span id="cb19-19">    make_dense_block(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>),</span>
<span id="cb19-20">    tf.keras.layers.Dense(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb19-21">])</span>
<span id="cb19-22">dnn_model.summary()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/model.png" class="img-fluid"></p>
<p>Here I am using a MLP of 5 layers, with batch normalization and dropout after each layer to control for overfitting.</p>
</section>
<section id="training" class="level3">
<h3 class="anchored" data-anchor-id="training">Training</h3>
<p>I used performance scheduling to make sure that the model converges to a good solution. I also used early stopping to further prevent overfitting.</p>
<div id="cba67445" class="cell" data-execution_count="17">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Performance scheduling of learning rate</span></span>
<span id="cb20-2">lr_scheduler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.callbacks.ReduceLROnPlateau(factor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb20-3"></span>
<span id="cb20-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Early stopping</span></span>
<span id="cb20-5">early_stopping <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.callbacks.EarlyStopping(patience<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, restore_best_weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</details>
</div>
<div id="8bd3d696" class="cell" data-execution_count="18">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1">optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tf.keras.optimizers.Adam(learning_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>)</span>
<span id="cb21-2">dnn_model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">compile</span>(loss<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mse'</span>, optimizer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>optimizer, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RootMeanSquaredError'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2Score'</span>])</span>
<span id="cb21-3"></span>
<span id="cb21-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adapt the normalization layer using only the feature tensors from the dataset</span></span>
<span id="cb21-5">norm_layer.adapt(train_tfds.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x, y: x))</span>
<span id="cb21-6">tf.random.set_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb21-7">fit_history <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnn_model.fit(train_tfds, epochs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, validation_data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>valid_tfds,</span>
<span id="cb21-8">                            callbacks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[lr_scheduler, early_stopping])</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/train1.png" class="img-fluid"></p>
</section>
<section id="training-history" class="level3">
<h3 class="anchored" data-anchor-id="training-history">Training History</h3>
<p>Let’s analyze the training performance over epochs.</p>
<div id="5ccbcc60" class="cell" data-execution_count="19">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot train and validation loss and RMSE across epochs</span></span>
<span id="cb22-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb22-3"></span>
<span id="cb22-4">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(nrows<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, ncols<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb22-5"></span>
<span id="cb22-6">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'loss'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_loss'</span>]].plot(</span>
<span id="cb22-7">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb22-8">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r--"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b-"</span>])</span>
<span id="cb22-9"></span>
<span id="cb22-10">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RootMeanSquaredError'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_RootMeanSquaredError'</span>]].plot(</span>
<span id="cb22-11">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb22-12">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r--"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b-"</span>])</span>
<span id="cb22-13"></span>
<span id="cb22-14">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2Score'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val_R2Score'</span>]].plot(</span>
<span id="cb22-15">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb22-16">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r--"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"b-"</span>])</span>
<span id="cb22-17"></span>
<span id="cb22-18">pd.DataFrame(fit_history.history)[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'learning_rate'</span>]].plot(</span>
<span id="cb22-19">    grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Epoch"</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb22-20">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"g-"</span>])</span>
<span id="cb22-21"></span>
<span id="cb22-22">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss'</span>)</span>
<span id="cb22-23">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss Over Epochs'</span>)</span>
<span id="cb22-24">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].legend([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training Loss'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Validation Loss'</span>])</span>
<span id="cb22-25"></span>
<span id="cb22-26">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RMSE'</span>)</span>
<span id="cb22-27">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RMSE Over Epochs'</span>)</span>
<span id="cb22-28">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].legend([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training RMSE'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Validation RMSE'</span>])</span>
<span id="cb22-29"></span>
<span id="cb22-30">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2'</span>)</span>
<span id="cb22-31">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R2 Over Epochs'</span>)</span>
<span id="cb22-32">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].legend([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Training R2'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Validation R2'</span>])</span>
<span id="cb22-33"></span>
<span id="cb22-34">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Learning Rate'</span>)</span>
<span id="cb22-35">ax[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Learning Rate Over Epochs'</span>)</span>
<span id="cb22-36"></span>
<span id="cb22-37">plt.tight_layout()</span>
<span id="cb22-38">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_40_output.png" class="img-fluid"></p>
<p>As we can see, validation loss and errors have been kept very close to that of training, and they eventually dropped down to very similar levels, suggesting that the model did not overfit.</p>
</section>
</section>
<section id="model-evaluation" class="level2">
<h2 class="anchored" data-anchor-id="model-evaluation">5. Model Evaluation</h2>
<p>Finally, we evaluate the model on the training and test set.</p>
<section id="training-set" class="level3">
<h3 class="anchored" data-anchor-id="training-set">Training Set</h3>
<div id="c0f5b12c" class="cell" data-execution_count="20">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Evaluate R-squared of predicted vs actual binding affinity for each MHC type</span></span>
<span id="cb23-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> r2_score</span>
<span id="cb23-3"></span>
<span id="cb23-4">y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnn_model.predict(X_train)</span>
<span id="cb23-5">y_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_train</span>
<span id="cb23-6"></span>
<span id="cb23-7">mhc_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_me[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>].values</span>
<span id="cb23-8">r2_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>: mhc_id, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>: y_true, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y_pred'</span>: y_pred.flatten()})</span>
<span id="cb23-9"></span>
<span id="cb23-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove MHC_ID &lt;= 10 instances</span></span>
<span id="cb23-11">r2_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_df.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb23-12"></span>
<span id="cb23-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate R2 and MHC instances</span></span>
<span id="cb23-14">mhc_n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>].value_counts()</span>
<span id="cb23-15">r2_by_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_df.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: r2_score(x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y'</span>], x[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Y_pred'</span>]))</span>
<span id="cb23-16"></span>
<span id="cb23-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Join statistics by MHC_ID</span></span>
<span id="cb23-18">r2_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([mhc_n, r2_by_mhc], axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb23-19">r2_df.columns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'n'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r2'</span>]</span>
<span id="cb23-20">r2_df.sort_values(by<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r2'</span>, ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</details>
</div>
<div id="4f380c84" class="cell" data-execution_count="21">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot MHC instance vs prediction accuracy scatter plot</span></span>
<span id="cb24-2">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb24-3">plt.scatter(r2_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'n'</span>], r2_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r2'</span>], alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb24-4"></span>
<span id="cb24-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> adjustText <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> adjust_text</span>
<span id="cb24-6">texts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [plt.text(r2_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'n'</span>].iloc[i], r2_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r2'</span>].iloc[i], r2_df.index[i]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(r2_df))]</span>
<span id="cb24-7">adjust_text(</span>
<span id="cb24-8">  texts, expand<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.1</span>), arrowprops<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(arrowstyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-&gt;"</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey"</span>)</span>
<span id="cb24-9">)</span>
<span id="cb24-10"></span>
<span id="cb24-11">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Number of Instances'</span>)</span>
<span id="cb24-12">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'R-squared'</span>)</span>
<span id="cb24-13">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Number of MHC Instances vs. R-squared'</span>)</span>
<span id="cb24-14">plt.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>)</span>
<span id="cb24-15">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_44_output.png" class="img-fluid"></p>
<p>This plot reveals two key findings: (1) <strong>Prediction accuracy does not correlate with the number of MHC instances</strong>, suggesting that the model’s performance is driven more by the intrinsic biochemical or structural properties of the peptide-MHC pairs than by data volume. Indeed, the model did not necessarily perform better on MHCs that were abundant in the training data (e.g., DRB-0101 is very abundant yet has a relatively low <img src="https://latex.codecogs.com/png.latex?R%5E2">). (2) <strong>Some MHC interactions are inherently easier to predict.</strong> For example, HLA-DPA10201-DPB10101 achieves an <img src="https://latex.codecogs.com/png.latex?R%5E2"> &gt; 0.7. This reinforces the idea that intrinsic properties—or potentially higher-quality experimental data for these specific alleles—are the primary drivers of prediction success.</p>
</section>
<section id="test-set" class="level3">
<h3 class="anchored" data-anchor-id="test-set">Test Set</h3>
<div id="5631496c" class="cell" data-execution_count="22">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Evaluate performance on test data</span></span>
<span id="cb25-2">dnn_model.evaluate(X_test, y_test)</span></code></pre></div></div>
</details>
</div>
<p><strong>Test Results:</strong><br>
- R2Score: 0.5357<br>
- RootMeanSquaredError: 0.1793<br>
- loss: 0.0322<br>
</p>
<p>The test RMSE and loss are very close to the training data and even a little better than the validation data, suggesting that the model did not overfit too much.</p>
<div id="ce1b5e7d" class="cell" data-execution_count="23">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot scatter plot of predicted vs actual on test data</span></span>
<span id="cb26-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb26-3"></span>
<span id="cb26-4">y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnn_model.predict(X_test)</span>
<span id="cb26-5">y_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_test</span>
<span id="cb26-6"></span>
<span id="cb26-7">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb26-8">plt.scatter(y_true, y_pred, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb26-9">plt.plot([<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(y_true), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(y_true)], [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(y_pred), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(y_pred)], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'k--'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb26-10">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'True Values'</span>)</span>
<span id="cb26-11">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Predictions'</span>)</span>
<span id="cb26-12">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'True Values vs. Predictions'</span>)</span>
<span id="cb26-13"></span>
<span id="cb26-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add R-squared on the plot</span></span>
<span id="cb26-15"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> r2_score</span>
<span id="cb26-16">r2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_score(y_true, y_pred)</span>
<span id="cb26-17">plt.text(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'R-squared: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>r2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, transform<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>plt.gca().transAxes, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, verticalalignment<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'top'</span>)</span>
<span id="cb26-18"></span>
<span id="cb26-19">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_49_output.png" class="img-fluid"></p>
<p>Overall prediction accuracy is good (<img src="https://latex.codecogs.com/png.latex?R%5E2%20%5Capprox%200.53">). However, aggregate metrics can hide specific strengths. Let’s break down performance by MHC type.</p>
</section>
<section id="performance-by-mhc-type-in-test-set" class="level3">
<h3 class="anchored" data-anchor-id="performance-by-mhc-type-in-test-set">Performance by MHC Type in Test Set</h3>
<p>We calculate the <img src="https://latex.codecogs.com/png.latex?R%5E2"> score specifically for each MHC allele in the test set (filtering for those with &gt;10 instances).</p>
<div id="d6dfdab6" class="cell" data-execution_count="24">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Evaluate R-squared of predicted vs actual binding affinity for each MHC type (test data)</span></span>
<span id="cb27-2">y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnn_model.predict(X_test)</span>
<span id="cb27-3">y_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_test</span>
<span id="cb27-4"></span>
<span id="cb27-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ...code abbreviated for brevity...</span></span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_51_output.png" class="img-fluid"></p>
<p>Similar to the training set, we can see that prediction accuracy does not correlate with the number of MHC instances, and some MHCs are just easier to predict than others.</p>
<p>For example, looking at <strong>HLA-DPA10201-DPB10101</strong>:</p>
<div id="55cb9c1e" class="cell" data-execution_count="25">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot HLA-DPA10201-DPB10101 and peptide binding predicted vs actual scatter plot</span></span>
<span id="cb28-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb28-3"></span>
<span id="cb28-4">y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnn_model.predict(X_test)</span>
<span id="cb28-5">y_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_test</span>
<span id="cb28-6"></span>
<span id="cb28-7">mhc_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_me[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MHC_ID'</span>].values</span>
<span id="cb28-8">target_mhc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'HLA-DPA10201-DPB10101'</span></span>
<span id="cb28-9">target_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(mhc_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> target_mhc)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb28-10"></span>
<span id="cb28-11">y_pred <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_pred[target_index]</span>
<span id="cb28-12">y_true <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_true[target_index]</span>
<span id="cb28-13"></span>
<span id="cb28-14">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb28-15">plt.scatter(y_true, y_pred, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb28-16">plt.plot([<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(y_true), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(y_true)], [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(y_pred), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(y_pred)], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'k--'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb28-17">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'True Values'</span>)</span>
<span id="cb28-18">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Predictions'</span>)</span>
<span id="cb28-19">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'True Values vs. Predictions (HLA-DPA10201-DPB10101)'</span>)</span>
<span id="cb28-20"></span>
<span id="cb28-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add R-squared on the plot</span></span>
<span id="cb28-22"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> r2_score</span>
<span id="cb28-23">r2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r2_score(y_true, y_pred)</span>
<span id="cb28-24">plt.text(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'R-squared: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>r2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, transform<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>plt.gca().transAxes, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, verticalalignment<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'top'</span>)</span>
<span id="cb28-25"></span>
<span id="cb28-26">plt.show()</span></code></pre></div></div>
</details>
</div>
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/images/cell_52_output.png" class="img-fluid"></p>
<p>For this specific MHC type, the <img src="https://latex.codecogs.com/png.latex?R%5E2"> is <strong>0.71</strong>, which is significantly better than the global average. This demonstrates that for certain alleles, the model can reliably identify high-affinity binders (e.g., a predicted affinity cutoff of &gt; 0.6 corresponds well to high actual affinity).</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>By leveraging ESM2 embeddings and MLP, we built a pipeline to predict peptide-MHC II binding. This exercise showcases the potential of combining LLMs with machine learning to tackle complex biological challenges. These could range from predicting protein-protein interactions and drug-target binding to forecasting drug responses from gene expression data.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://github.com/facebookresearch/esm">ESM2</a></li>
<li><a href="https://www.tensorflow.org/">TensorFlow</a></li>
<li><a href="https://keras.io/">Keras</a></li>
<li><a href="https://www.oreilly.com/library/view/hands-on-machine-learning/9781492032632/">Hands-on Machine Learning with Scikit-Learn, Keras, and TensorFlow</a></li>
<li><a href="https://github.com/deep-learning-for-biology">Deep Learning for Biology</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Deep Learning</category>
  <category>Keras</category>
  <category>ESM2</category>
  <category>Protein Language Models</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/2026-01-18_peptide_affinity_llm_nn/</guid>
  <pubDate>Sun, 18 Jan 2026 08:00:00 GMT</pubDate>
</item>
<item>
  <title>Machine learning for drug sensitivity prediction (Part 3): Training an Elastic Net gene expression model to predict Erlotinib sensitivity</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/</link>
  <description><![CDATA[ 





<p>In my previous posts (<a href="../../posts/2025-11-29_depmap-multiomics-autoencoder/index.html">part 1</a> and <a href="../../posts/2025-12-03_ae_ml_validation/index.html">part 2</a>), I explored whether using autoencoders (AE) to compress high-dimensional multi-omics data could improve the performance of drug sensitivity prediction models. In my specific context, I showed that using AE did not necessarily improve model performance compared to using a common feature selection method.</p>
<p>In this post, I will use the best-performing model from my previous analyses (elastic net using features selected by Pearson correlation), and apply it to all available DepMap data to generate predictions for cell lines without measured drug sensitivity. I will then see if these predictions provide additional useful insights beyond the measured data.</p>
<p>I will demonstrate how to use R’s Caret package to train an elastic net model with hyperparameter tuning via cross-validation.</p>
<section id="aim-1-apply-the-elastic-net-model-to-all-available-depmap-data-to-generate-erlotinib-sensitivity-predictions" class="level2">
<h2 class="anchored" data-anchor-id="aim-1-apply-the-elastic-net-model-to-all-available-depmap-data-to-generate-erlotinib-sensitivity-predictions">Aim 1: Apply the elastic net model to all available DepMap data to generate Erlotinib sensitivity predictions</h2>
<p>Data location (pre-processed for this post): <a href="https://zenodo.org/records/17970100" class="uri">https://zenodo.org/records/17970100</a></p>
<section id="load-data-and-libraries" class="level3">
<h3 class="anchored" data-anchor-id="load-data-and-libraries">Load data and libraries</h3>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(data.table)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggpubr)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(caret)</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(doParallel)</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load data from the files directory</span></span>
<span id="cb1-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/CCLE_24Q2_GE_match_sample_info.RData"</span>)</span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/PRISM_24Q2_compound_screen_match_sample_info.RData"</span>)</span>
<span id="cb1-10">cmpd_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/Repurposing_Public_24Q2_Extended_Primary_Compound_List.csv"</span>)</span>
<span id="cb1-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/sample_info_match_biomarkers.RData"</span>)</span></code></pre></div></div>
</div>
</section>
<section id="preprocessing" class="level3">
<h3 class="anchored" data-anchor-id="preprocessing">Preprocessing</h3>
<p>First, we remove low variance genes and any cell lines containing NAs.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove low variance genes</span></span>
<span id="cb2-2">ge_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(ccle_ge_match_sam, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculate variance for each gene</span></span>
<span id="cb2-3">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ccle_ge_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(ge_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(ge_var, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># select high variance genes</span></span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove any cell lines (rows) that contains NAs</span></span>
<span id="cb2-6">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ge_dat_hv <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb2-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>()</span>
<span id="cb2-9"></span>
<span id="cb2-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Match data</span></span>
<span id="cb2-11">match_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_hv), sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName)</span>
<span id="cb2-12">sample_info_filt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info[match_idx, ]</span>
<span id="cb2-13">prism_dat_match_sam_filt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> prism_dat_match_sam[match_idx, ]</span>
<span id="cb2-14"></span>
<span id="cb2-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Verify alignment</span></span>
<span id="cb2-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_hv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sample_info_filt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] TRUE</code></pre>
</div>
</div>
<p>Now we prepare the drug response data for Erlotinib.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">cmpd_id <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cmpd_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb4-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Drug.Name <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ERLOTINIB"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb4-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(IDs)</span>
<span id="cb4-4">drug_LFC <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> prism_dat_match_sam_filt <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(cmpd_id) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Erlotinib LFC</span></span>
<span id="cb4-5"></span>
<span id="cb4-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove NAs in drug response</span></span>
<span id="cb4-7">valid_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(drug_LFC))</span>
<span id="cb4-8">ge_dat_final <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ge_dat_hv[valid_idx, ]</span>
<span id="cb4-9">drug_LFC_final <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> drug_LFC[valid_idx]</span>
<span id="cb4-10">sample_info_final <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info_filt[valid_idx, ]</span>
<span id="cb4-11"></span>
<span id="cb4-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Verify alignment</span></span>
<span id="cb4-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_final) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sample_info_final<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] TRUE</code></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Check drug response distribution</span></span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Erlotinib_LFC =</span> drug_LFC_final), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Erlotinib_LFC)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_density</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"purple"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density of Erlotinib LFC"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib LFC"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/prepare-drug-data-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="feature-selection" class="level3">
<h3 class="anchored" data-anchor-id="feature-selection">Feature Selection</h3>
<p>We select the top predictors correlating with the drug response.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Select top predictors correlating with drug response, Pearson correlation &gt; 0.1</span></span>
<span id="cb7-2">cor_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(ge_dat_final, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(x, drug_LFC_final, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pearson"</span>))</span>
<span id="cb7-3">cor_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(cor_values)</span>
<span id="cb7-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Correlation =</span> cor_values), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Correlation)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_density</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkgreen"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density of Gene-Drug Correlation Values"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Absolute Pearson Correlation"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/feature-selection-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">top_predictors <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(cor_values)[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(cor_values <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>)]</span>
<span id="cb8-2">ge_dat_final <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ge_dat_final <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all_of</span>(top_predictors))</span></code></pre></div></div>
</div>
</section>
<section id="elastic-net-hyperparameter-tuning" class="level3">
<h3 class="anchored" data-anchor-id="elastic-net-hyperparameter-tuning">Elastic Net Hyperparameter Tuning</h3>
<p>We perform hyperparameter tuning using <code>caret</code>.</p>
<p><em>Note: The training step is computationally intensive and is not evaluated here. We load the pre-trained model for subsequent analysis.</em></p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Elastic net hyperparameter tuning with caret</span></span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">detectCores</span>()</span>
<span id="cb9-3">cl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">makePSOCKcluster</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span>)</span>
<span id="cb9-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">registerDoParallel</span>(cl)</span>
<span id="cb9-5"></span>
<span id="cb9-6">glmnetGrid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand.grid</span>(</span>
<span id="cb9-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.lambda =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.005</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb9-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">.alpha =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb9-9">)</span>
<span id="cb9-10"></span>
<span id="cb9-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span>)</span>
<span id="cb9-12">enet_full_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">train</span>(ge_dat_final, drug_LFC_final,</span>
<span id="cb9-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"glmnet"</span>,</span>
<span id="cb9-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tuneGrid =</span> glmnetGrid,</span>
<span id="cb9-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">preProcess =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"center"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>),</span>
<span id="cb9-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rsquared"</span>,</span>
<span id="cb9-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trControl =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">trainControl</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"repeatedcv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">number =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">repeats =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb9-18">)</span>
<span id="cb9-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopCluster</span>(cl)</span>
<span id="cb9-20"></span>
<span id="cb9-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save the final model (Already saved in files/)</span></span>
<span id="cb9-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># save(enet_full_model, file = "files/enet_full_model_erlotinib.RData")</span></span></code></pre></div></div>
</div>
</section>
<section id="model-analysis" class="level3">
<h3 class="anchored" data-anchor-id="model-analysis">Model Analysis</h3>
<p>Let’s examine the tuning results and the best hyperparameters.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load the pre-trained model</span></span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/enet_full_model_erlotinib.RData"</span>)</span>
<span id="cb10-3"></span>
<span id="cb10-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># View hyperparameter tuning results</span></span>
<span id="cb10-5">enet_full_model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>results <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">desc</span>(Rsquared)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> gt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gt</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div id="ulycqvjfqd" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#ulycqvjfqd table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#ulycqvjfqd thead, #ulycqvjfqd tbody, #ulycqvjfqd tfoot, #ulycqvjfqd tr, #ulycqvjfqd td, #ulycqvjfqd th {
  border-style: none;
}

#ulycqvjfqd p {
  margin: 0;
  padding: 0;
}

#ulycqvjfqd .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#ulycqvjfqd .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#ulycqvjfqd .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#ulycqvjfqd .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#ulycqvjfqd .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#ulycqvjfqd .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#ulycqvjfqd .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#ulycqvjfqd .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#ulycqvjfqd .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#ulycqvjfqd .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#ulycqvjfqd .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#ulycqvjfqd .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#ulycqvjfqd .gt_spanner_row {
  border-bottom-style: hidden;
}

#ulycqvjfqd .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#ulycqvjfqd .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#ulycqvjfqd .gt_from_md > :first-child {
  margin-top: 0;
}

#ulycqvjfqd .gt_from_md > :last-child {
  margin-bottom: 0;
}

#ulycqvjfqd .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#ulycqvjfqd .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#ulycqvjfqd .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#ulycqvjfqd .gt_row_group_first td {
  border-top-width: 2px;
}

#ulycqvjfqd .gt_row_group_first th {
  border-top-width: 2px;
}

#ulycqvjfqd .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#ulycqvjfqd .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#ulycqvjfqd .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#ulycqvjfqd .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#ulycqvjfqd .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#ulycqvjfqd .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#ulycqvjfqd .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#ulycqvjfqd .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#ulycqvjfqd .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#ulycqvjfqd .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#ulycqvjfqd .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#ulycqvjfqd .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#ulycqvjfqd .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#ulycqvjfqd .gt_left {
  text-align: left;
}

#ulycqvjfqd .gt_center {
  text-align: center;
}

#ulycqvjfqd .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#ulycqvjfqd .gt_font_normal {
  font-weight: normal;
}

#ulycqvjfqd .gt_font_bold {
  font-weight: bold;
}

#ulycqvjfqd .gt_font_italic {
  font-style: italic;
}

#ulycqvjfqd .gt_super {
  font-size: 65%;
}

#ulycqvjfqd .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#ulycqvjfqd .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#ulycqvjfqd .gt_indent_1 {
  text-indent: 5px;
}

#ulycqvjfqd .gt_indent_2 {
  text-indent: 10px;
}

#ulycqvjfqd .gt_indent_3 {
  text-indent: 15px;
}

#ulycqvjfqd .gt_indent_4 {
  text-indent: 20px;
}

#ulycqvjfqd .gt_indent_5 {
  text-indent: 25px;
}

#ulycqvjfqd .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#ulycqvjfqd div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<thead>
<tr class="gt_col_headings header">
<th id="alpha" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">alpha</th>
<th id="lambda" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">lambda</th>
<th id="RMSE" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">RMSE</th>
<th id="Rsquared" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">Rsquared</th>
<th id="MAE" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">MAE</th>
<th id="RMSESD" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">RMSESD</th>
<th id="RsquaredSD" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">RsquaredSD</th>
<th id="MAESD" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">MAESD</th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">1.038</td>
<td class="gt_row gt_right" headers="RMSE">0.7246115</td>
<td class="gt_row gt_right" headers="Rsquared">0.3234841</td>
<td class="gt_row gt_right" headers="MAE">0.5678419</td>
<td class="gt_row gt_right" headers="RMSESD">0.06244775</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09552666</td>
<td class="gt_row gt_right" headers="MAESD">0.05504541</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">1.211</td>
<td class="gt_row gt_right" headers="RMSE">0.7243195</td>
<td class="gt_row gt_right" headers="Rsquared">0.3231371</td>
<td class="gt_row gt_right" headers="MAE">0.5668798</td>
<td class="gt_row gt_right" headers="RMSESD">0.06237722</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09620741</td>
<td class="gt_row gt_right" headers="MAESD">0.05451755</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">0.866</td>
<td class="gt_row gt_right" headers="RMSE">0.7259216</td>
<td class="gt_row gt_right" headers="Rsquared">0.3227335</td>
<td class="gt_row gt_right" headers="MAE">0.5697183</td>
<td class="gt_row gt_right" headers="RMSESD">0.06251476</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09492452</td>
<td class="gt_row gt_right" headers="MAESD">0.05557950</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">1.383</td>
<td class="gt_row gt_right" headers="RMSE">0.7246391</td>
<td class="gt_row gt_right" headers="Rsquared">0.3221409</td>
<td class="gt_row gt_right" headers="MAE">0.5665405</td>
<td class="gt_row gt_right" headers="RMSESD">0.06232075</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09689575</td>
<td class="gt_row gt_right" headers="MAESD">0.05382773</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">1.555</td>
<td class="gt_row gt_right" headers="RMSE">0.7254462</td>
<td class="gt_row gt_right" headers="Rsquared">0.3205662</td>
<td class="gt_row gt_right" headers="MAE">0.5668465</td>
<td class="gt_row gt_right" headers="RMSESD">0.06223333</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09753524</td>
<td class="gt_row gt_right" headers="MAESD">0.05317660</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">0.694</td>
<td class="gt_row gt_right" headers="RMSE">0.7287441</td>
<td class="gt_row gt_right" headers="Rsquared">0.3204541</td>
<td class="gt_row gt_right" headers="MAE">0.5731421</td>
<td class="gt_row gt_right" headers="RMSESD">0.06255456</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09446370</td>
<td class="gt_row gt_right" headers="MAESD">0.05612583</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">1.727</td>
<td class="gt_row gt_right" headers="RMSE">0.7265929</td>
<td class="gt_row gt_right" headers="Rsquared">0.3185779</td>
<td class="gt_row gt_right" headers="MAE">0.5676531</td>
<td class="gt_row gt_right" headers="RMSESD">0.06210627</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09802932</td>
<td class="gt_row gt_right" headers="MAESD">0.05253257</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.022</td>
<td class="gt_row gt_right" headers="lambda">0.694</td>
<td class="gt_row gt_right" headers="RMSE">0.7276708</td>
<td class="gt_row gt_right" headers="Rsquared">0.3185370</td>
<td class="gt_row gt_right" headers="MAE">0.5695071</td>
<td class="gt_row gt_right" headers="RMSESD">0.06120405</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09481046</td>
<td class="gt_row gt_right" headers="MAESD">0.05397744</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.022</td>
<td class="gt_row gt_right" headers="lambda">0.522</td>
<td class="gt_row gt_right" headers="RMSE">0.7298551</td>
<td class="gt_row gt_right" headers="Rsquared">0.3180041</td>
<td class="gt_row gt_right" headers="MAE">0.5726883</td>
<td class="gt_row gt_right" headers="RMSESD">0.06144171</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09315651</td>
<td class="gt_row gt_right" headers="MAESD">0.05466701</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.022</td>
<td class="gt_row gt_right" headers="lambda">0.866</td>
<td class="gt_row gt_right" headers="RMSE">0.7277250</td>
<td class="gt_row gt_right" headers="Rsquared">0.3168255</td>
<td class="gt_row gt_right" headers="MAE">0.5686165</td>
<td class="gt_row gt_right" headers="RMSESD">0.06109334</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09620112</td>
<td class="gt_row gt_right" headers="MAESD">0.05314454</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">1.900</td>
<td class="gt_row gt_right" headers="RMSE">0.7279475</td>
<td class="gt_row gt_right" headers="Rsquared">0.3163917</td>
<td class="gt_row gt_right" headers="MAE">0.5686306</td>
<td class="gt_row gt_right" headers="RMSESD">0.06199278</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09836348</td>
<td class="gt_row gt_right" headers="MAESD">0.05195792</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">0.522</td>
<td class="gt_row gt_right" headers="RMSE">0.7339054</td>
<td class="gt_row gt_right" headers="Rsquared">0.3158314</td>
<td class="gt_row gt_right" headers="MAE">0.5786809</td>
<td class="gt_row gt_right" headers="RMSESD">0.06262747</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09381218</td>
<td class="gt_row gt_right" headers="MAESD">0.05677975</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.033</td>
<td class="gt_row gt_right" headers="lambda">0.522</td>
<td class="gt_row gt_right" headers="RMSE">0.7303634</td>
<td class="gt_row gt_right" headers="Rsquared">0.3142904</td>
<td class="gt_row gt_right" headers="MAE">0.5715719</td>
<td class="gt_row gt_right" headers="RMSESD">0.06047743</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09405803</td>
<td class="gt_row gt_right" headers="MAESD">0.05348058</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">2.072</td>
<td class="gt_row gt_right" headers="RMSE">0.7294330</td>
<td class="gt_row gt_right" headers="Rsquared">0.3141275</td>
<td class="gt_row gt_right" headers="MAE">0.5697778</td>
<td class="gt_row gt_right" headers="RMSESD">0.06194162</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09867437</td>
<td class="gt_row gt_right" headers="MAESD">0.05146113</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.022</td>
<td class="gt_row gt_right" headers="lambda">1.038</td>
<td class="gt_row gt_right" headers="RMSE">0.7289549</td>
<td class="gt_row gt_right" headers="Rsquared">0.3140533</td>
<td class="gt_row gt_right" headers="MAE">0.5692525</td>
<td class="gt_row gt_right" headers="RMSESD">0.06118321</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09735362</td>
<td class="gt_row gt_right" headers="MAESD">0.05229037</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.022</td>
<td class="gt_row gt_right" headers="lambda">0.349</td>
<td class="gt_row gt_right" headers="RMSE">0.7362917</td>
<td class="gt_row gt_right" headers="Rsquared">0.3135250</td>
<td class="gt_row gt_right" headers="MAE">0.5805138</td>
<td class="gt_row gt_right" headers="RMSESD">0.06171108</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09216744</td>
<td class="gt_row gt_right" headers="MAESD">0.05541844</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.033</td>
<td class="gt_row gt_right" headers="lambda">0.694</td>
<td class="gt_row gt_right" headers="RMSE">0.7296913</td>
<td class="gt_row gt_right" headers="Rsquared">0.3129244</td>
<td class="gt_row gt_right" headers="MAE">0.5700855</td>
<td class="gt_row gt_right" headers="RMSESD">0.06080031</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09625073</td>
<td class="gt_row gt_right" headers="MAESD">0.05273691</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.011</td>
<td class="gt_row gt_right" headers="lambda">2.244</td>
<td class="gt_row gt_right" headers="RMSE">0.7309768</td>
<td class="gt_row gt_right" headers="Rsquared">0.3118847</td>
<td class="gt_row gt_right" headers="MAE">0.5711072</td>
<td class="gt_row gt_right" headers="RMSESD">0.06195602</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09901043</td>
<td class="gt_row gt_right" headers="MAESD">0.05102660</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="alpha">0.044</td>
<td class="gt_row gt_right" headers="lambda">0.522</td>
<td class="gt_row gt_right" headers="RMSE">0.7306761</td>
<td class="gt_row gt_right" headers="Rsquared">0.3116728</td>
<td class="gt_row gt_right" headers="MAE">0.5711300</td>
<td class="gt_row gt_right" headers="RMSESD">0.06048624</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09528180</td>
<td class="gt_row gt_right" headers="MAESD">0.05289960</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="alpha">0.033</td>
<td class="gt_row gt_right" headers="lambda">0.349</td>
<td class="gt_row gt_right" headers="RMSE">0.7355536</td>
<td class="gt_row gt_right" headers="Rsquared">0.3116308</td>
<td class="gt_row gt_right" headers="MAE">0.5781206</td>
<td class="gt_row gt_right" headers="RMSESD">0.06063449</td>
<td class="gt_row gt_right" headers="RsquaredSD">0.09156073</td>
<td class="gt_row gt_right" headers="MAESD">0.05410146</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p>The best hyperparameters for the model were alpha = 0.011 and lambda = 1.038. This indicates that the model prefers a nearly ridge regression approach (alpha close to 0) with moderate regularization (lambda value). This makes sense given that the predictors were pre-selected based on correlation with the response, so we want to retain most predictors while controlling for multicollinearity.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot tuning results</span></span>
<span id="cb11-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(enet_full_model) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Elastic Net tuning"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/plot-tuning-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>A major advantage of a linear model like elastic net is its interpretability. The coefficients correspond to how important each gene is for predicting Erlotinib sensitivity.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">final_coef <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coef</span>(enet_full_model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>finalModel, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s =</span> enet_full_model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>bestTune<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lambda))[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, ]</span>
<span id="cb12-2">final_coef_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb12-3">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Gene =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(final_coef),</span>
<span id="cb12-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Coefficient =</span> final_coef</span>
<span id="cb12-5">)</span>
<span id="cb12-6"></span>
<span id="cb12-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot a bar plot for the top 20 sensitivity and top 20 resistance predictor genes</span></span>
<span id="cb12-8">final_coef_sorted <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> final_coef[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">order</span>(final_coef, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">decreasing =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)]</span>
<span id="cb12-9">top20_pos_coef <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(final_coef_sorted[final_coef_sorted <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb12-10">top20_neg_coef <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tail</span>(final_coef_sorted[final_coef_sorted <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb12-11"></span>
<span id="cb12-12">top_coef_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb12-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Gene =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(top20_pos_coef), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(top20_neg_coef)),</span>
<span id="cb12-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Coefficient =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(top20_pos_coef, top20_neg_coef),</span>
<span id="cb12-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Direction =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Resistance predictors"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(top20_pos_coef)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sensitivity predictors"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(top20_neg_coef)))</span>
<span id="cb12-16">)</span>
<span id="cb12-17"></span>
<span id="cb12-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(top_coef_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reorder</span>(Gene, Coefficient), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Coefficient, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Direction)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_bar</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stat =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identity"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-21">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb12-22">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Top 40 predictor genes"</span>,</span>
<span id="cb12-23">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gene"</span>,</span>
<span id="cb12-24">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Coefficient"</span></span>
<span id="cb12-25">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sensitivity predictors"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkgreen"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Resistance predictors"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkred"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb12-27">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb12-28">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>,</span>
<span id="cb12-29">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb12-30">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb12-31">    )</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/coefficients-analysis-1.png" class="img-fluid figure-img" width="864"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="prediction-on-all-cell-lines" class="level3">
<h3 class="anchored" data-anchor-id="prediction-on-all-cell-lines">Prediction on All Cell Lines</h3>
<p>We now use the trained model to predict Erlotinib sensitivity for all CCLE cell lines with available RNA expression data.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predict on all CCLE cell lines with available RNA expression</span></span>
<span id="cb13-2">all_ccle_ge <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ccle_ge_match_sam <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>()</span>
<span id="cb13-3">all_ccle_ge <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> all_ccle_ge <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb13-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all_of</span>(top_predictors)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb13-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1517 cell lines with complete GE data</span></span>
<span id="cb13-6"></span>
<span id="cb13-7">enet_pred_all_ccle <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(enet_full_model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">newdata =</span> all_ccle_ge)</span>
<span id="cb13-8"></span>
<span id="cb13-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save predicted Erlotinib LFC for all CCLE cell lines</span></span>
<span id="cb13-10">predicted_erlotinib_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb13-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Cell_Line =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(all_ccle_ge),</span>
<span id="cb13-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predicted_Erlotinib_LFC =</span> enet_pred_all_ccle</span>
<span id="cb13-13">)</span>
<span id="cb13-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># fwrite(predicted_erlotinib_df, "files/predicted_erlotinib_LFC_all_CCLE_cell_lines.csv", sep = ",", row.names = FALSE, quote = FALSE)</span></span></code></pre></div></div>
</div>
</section>
</section>
<section id="aim-2-evaluate-whether-the-predicted-erlotinib-sensitivity-provides-additional-insights-beyond-the-measured-data" class="level2">
<h2 class="anchored" data-anchor-id="aim-2-evaluate-whether-the-predicted-erlotinib-sensitivity-provides-additional-insights-beyond-the-measured-data">Aim 2: Evaluate whether the predicted Erlotinib sensitivity provides additional insights beyond the measured data</h2>
<section id="comparison-of-actual-vs.-predicted" class="level3">
<h3 class="anchored" data-anchor-id="comparison-of-actual-vs.-predicted">Comparison of Actual vs.&nbsp;Predicted</h3>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load actual and predicted Erlotinib LFC data</span></span>
<span id="cb14-2">actual_erlotinib_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(</span>
<span id="cb14-3">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Cell_Line =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_final),</span>
<span id="cb14-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Actual_Erlotinib_LFC =</span> drug_LFC_final</span>
<span id="cb14-5">)</span>
<span id="cb14-6"></span>
<span id="cb14-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># If we didn't run the prediction above, we could load it:</span></span>
<span id="cb14-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># predicted_erlotinib_df &lt;- fread("files/predicted_erlotinib_LFC_all_CCLE_cell_lines.csv", data.table = FALSE)</span></span>
<span id="cb14-9"></span>
<span id="cb14-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Merge actual and predicted data</span></span>
<span id="cb14-11">erlotinib_compare_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">merge</span>(actual_erlotinib_df, predicted_erlotinib_df, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cell_Line"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">all =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb14-12"></span>
<span id="cb14-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add cancer lineage information</span></span>
<span id="cb14-14">erlotinib_compare_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">left_join</span>(sample_info <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(StrippedCellLineName, OncotreeLineage),</span>
<span id="cb14-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cell_Line"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"StrippedCellLineName"</span>)</span>
<span id="cb14-16">)</span>
<span id="cb14-17"></span>
<span id="cb14-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add EGFR mutation status</span></span>
<span id="cb14-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Note: Using tryCatch or existence check in case file is missing in user environment</span></span>
<span id="cb14-20"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file.exists</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/CCLE_24Q2_HOTMUT_match_sample_info.RData"</span>)) {</span>
<span id="cb14-21">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/CCLE_24Q2_HOTMUT_match_sample_info.RData"</span>)</span>
<span id="cb14-22">    egfr_mutation_status <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> hotmut_dat_match_sam <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb14-23">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames_to_column</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cell_Line"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb14-24">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(Cell_Line, EGFR) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb14-25">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">EGFR_Mutation_Status =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">recode</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.factor</span>(EGFR), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">0</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wildtype"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygous Mutant"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">2</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Homozygous Mutant"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb14-26">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(Cell_Line, EGFR_Mutation_Status)</span>
<span id="cb14-27">    erlotinib_compare_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">left_join</span>(egfr_mutation_status, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cell_Line"</span>)</span>
<span id="cb14-28">} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb14-29">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">warning</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"files/CCLE_24Q2_HOTMUT_match_sample_info.RData not found. Skipping EGFR analysis."</span>)</span>
<span id="cb14-30">}</span>
<span id="cb14-31"></span>
<span id="cb14-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot actual vs predicted Erlotinib LFC for cell lines with actual data</span></span>
<span id="cb14-33">plot_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(Actual_Erlotinib_LFC))</span>
<span id="cb14-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(plot_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Actual_Erlotinib_LFC, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Predicted_Erlotinib_LFC)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-35">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-36">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-37">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-38">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb14-39">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Elastic Net prediction of Erlotinib LFC"</span>,</span>
<span id="cb14-40">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual Erlotinib LFC"</span>,</span>
<span id="cb14-41">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted Erlotinib LFC"</span></span>
<span id="cb14-42">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-43">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stat_cor</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pearson"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label.x.npc =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label.y.npc =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkred"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb14-44">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_smooth</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lm"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkred"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/compare-actual-predicted-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p><strong>Note:</strong> This prediction performance result is evaluated on the training data, so it is expected to be better than on independent test data (overfitting). It is important to always evaluate model performance on independent test data. From my previous post, the prediction performance on independent test data looks like this (not bad but not as good as training data):</p>
<div class="cell" data-layout-align="left">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-left">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/files/selected_top_RNA_enet_erlotinib_pred_vs_actual_repeat_6.png" class="img-fluid quarto-figure quarto-figure-left figure-img" style="width:60.0%"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="cancer-lineage-distribution" class="level3">
<h3 class="anchored" data-anchor-id="cancer-lineage-distribution">Cancer Lineage Distribution</h3>
<p>We compare the cancer lineages covered by the actual measured data versus the predicted data.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1">actual_lineages <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(Actual_Erlotinib_LFC)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(Cell_Line, OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct</span>()</span>
<span id="cb15-5">predicted_lineages <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(Cell_Line, OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct</span>()</span>
<span id="cb15-8"></span>
<span id="cb15-9">actual_lineage_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> actual_lineages <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Count =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual data"</span>)</span>
<span id="cb15-13">predicted_lineage_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> predicted_lineages <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Count =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb15-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted data"</span>)</span>
<span id="cb15-17">lineage_counts_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(actual_lineage_counts, predicted_lineage_counts) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(OncotreeLineage <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb15-18"></span>
<span id="cb15-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Make missing lineage in actual data have count 0</span></span>
<span id="cb15-20">all_lineages <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(lineage_counts_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage)</span>
<span id="cb15-21"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (lineage <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> all_lineages) {</span>
<span id="cb15-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>(lineage <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> actual_lineage_counts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage)) {</span>
<span id="cb15-23">        lineage_counts_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(lineage_counts_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">OncotreeLineage =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Count =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual data"</span>))</span>
<span id="cb15-24">    }</span>
<span id="cb15-25">}</span>
<span id="cb15-26"></span>
<span id="cb15-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(lineage_counts_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reorder</span>(OncotreeLineage, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>Count), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Count, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Type)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-28">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_bar</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stat =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identity"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">position_dodge</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-29">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-30">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb15-31">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cancer Lineage Distribution"</span>,</span>
<span id="cb15-32">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cancer Lineage"</span>,</span>
<span id="cb15-33">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of Cell Lines"</span></span>
<span id="cb15-34">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-35">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_text</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> Count, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> Type), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">position_dodge</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">vjust =</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-36">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual data"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted data"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkorange"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-37">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual data"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted data"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkorange"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-38">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb15-39">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>,</span>
<span id="cb15-40">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb15-41">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb15-42">    )</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/lineage-distribution-1.png" class="img-fluid figure-img" width="768"></p>
</figure>
</div>
</div>
</div>
<p>You can see here that the predicted data covers many more cancer lineages than the actual data, which may improve the power of downstream analyses.</p>
</section>
<section id="predicted-sensitivity-by-lineage" class="level3">
<h3 class="anchored" data-anchor-id="predicted-sensitivity-by-lineage">Predicted Sensitivity by Lineage</h3>
<p>Next, let’s see if the predicted Erlotinib LFC can better capture differences across cancer lineages.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot actual vs predicted Erlotinib LFC boxplot faceted by LFC type and stratified by OncotreeLineage</span></span>
<span id="cb16-2">plot_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(Cell_Line, Actual_Erlotinib_LFC, Predicted_Erlotinib_LFC, OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(</span>
<span id="cb16-5">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cols =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(Actual_Erlotinib_LFC, Predicted_Erlotinib_LFC),</span>
<span id="cb16-6">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LFC_Type"</span>,</span>
<span id="cb16-7">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib_LFC"</span></span>
<span id="cb16-8">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>()</span>
<span id="cb16-10"></span>
<span id="cb16-11">lineage_counts <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> plot_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Count =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">n</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Count <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb16-15">plot_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> plot_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(OncotreeLineage <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%in%</span> lineage_counts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage)</span>
<span id="cb16-16"></span>
<span id="cb16-17">lineage_sort_by_predicted_LFC <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> plot_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-18">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(LFC_Type <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted_Erlotinib_LFC"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(OncotreeLineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarise</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Median_Predicted_LFC =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(Erlotinib_LFC)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-21">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrange</span>(Median_Predicted_LFC) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb16-22">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(OncotreeLineage)</span>
<span id="cb16-23"></span>
<span id="cb16-24">plot_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(plot_df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">levels =</span> lineage_sort_by_predicted_LFC)</span>
<span id="cb16-25"></span>
<span id="cb16-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(plot_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> OncotreeLineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Erlotinib_LFC, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> LFC_Type)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-27">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-28">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outliers =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey99"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-29">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>LFC_Type,</span>
<span id="cb16-30">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">scales =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"free_y"</span>,</span>
<span id="cb16-31">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labeller =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_labeller</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Actual_Erlotinib_LFC =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual Erlotinib LFC"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predicted_Erlotinib_LFC =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted Erlotinib LFC"</span>))</span>
<span id="cb16-32">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-33">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-34">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(</span>
<span id="cb16-35">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Actual_Erlotinib_LFC =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"steelblue"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predicted_Erlotinib_LFC =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkorange"</span>),</span>
<span id="cb16-36">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual Erlotinib LFC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted Erlotinib LFC"</span>)</span>
<span id="cb16-37">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-38">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb16-39">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib LFC by Cancer Lineage"</span>,</span>
<span id="cb16-40">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cancer Lineage"</span>,</span>
<span id="cb16-41">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib LFC"</span></span>
<span id="cb16-42">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-43">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_hline</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yintercept =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grey30"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-44">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb16-45">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb16-46">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span></span>
<span id="cb16-47">    )</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/lineage-sensitivity-1.png" class="img-fluid figure-img" width="960"></p>
</figure>
</div>
</div>
</div>
<p><strong>Result</strong>: Predicted data discovered lineage sensitivity for prostate, cervix, biliary tract; and showed that blood lineages are likely not sensitive.</p>
</section>
<section id="predicted-sensitivity-by-egfr-mutation-status" class="level3">
<h3 class="anchored" data-anchor-id="predicted-sensitivity-by-egfr-mutation-status">Predicted Sensitivity by EGFR Mutation Status</h3>
<p>Finally, let’s see whether the predicted Erlotinib LFC can capture known biological associations, such as sensitivity in EGFR mutant cell lines.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exists</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"egfr_mutation_status"</span>)) {</span>
<span id="cb17-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compare predicted vs actual Erlotinib LFC between EGFR mutant and wildtype cell lines</span></span>
<span id="cb17-3">    plot_df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> erlotinib_compare_df <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb17-4">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(Cell_Line, Actual_Erlotinib_LFC, Predicted_Erlotinib_LFC, EGFR_Mutation_Status) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb17-5">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pivot_longer</span>(</span>
<span id="cb17-6">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">cols =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(Actual_Erlotinib_LFC, Predicted_Erlotinib_LFC),</span>
<span id="cb17-7">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">names_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LFC_Type"</span>,</span>
<span id="cb17-8">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values_to =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib_LFC"</span></span>
<span id="cb17-9">        ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb17-10">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>()</span>
<span id="cb17-11"></span>
<span id="cb17-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot boxplot: EGFR mutant vs wildtype facet by actual vs predicted with test p-value</span></span>
<span id="cb17-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(plot_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> EGFR_Mutation_Status, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Erlotinib_LFC, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> EGFR_Mutation_Status)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-14">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outliers =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-15">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-16">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>LFC_Type, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labeller =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as_labeller</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Actual_Erlotinib_LFC =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Actual Erlotinib LFC"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Predicted_Erlotinib_LFC =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted Erlotinib LFC"</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-17">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-18">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb17-19">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib LFC by EGFR Mutation Status"</span>,</span>
<span id="cb17-20">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EGFR Hotspot Mutation Status"</span>,</span>
<span id="cb17-21">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Erlotinib LFC"</span></span>
<span id="cb17-22">        ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-23">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Wildtype"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkgreen"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heterozygous Mutant"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkorange"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Homozygous Mutant"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"darkred"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-24">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb17-25">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>,</span>
<span id="cb17-26">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axis.text.x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hjust =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb17-27">        ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb17-28">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stat_compare_means</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> EGFR_Mutation_Status), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label.y.npc =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb17-29">} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb17-30">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EGFR mutation data not loaded."</span>)</span>
<span id="cb17-31">}</span></code></pre></div></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/index_files/figure-html/egfr-status-1.png" class="img-fluid figure-img" width="864"></p>
</figure>
</div>
</div>
</div>
<p>It seems that even in the predicted data, there is only a marginal difference in Erlotinib LFC between EGFR mutant and wildtype cell lines. This could be due to the fact that EGFR mutation instances are relatively rare in all of DepMap cell lines.</p>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>Here I demonstrated how to train an elastic net model using R’s Caret package with hyperparameter tuning via cross-validation from end to end. I showed the top 20 sensitivity and resistance predictor genes identified by the final model. I then applied the final model to all available DepMap cell lines to generate Erlotinib sensitivity predictions.</p>
<p>Finally, I showed that the predicted data can provide additional insights beyond the measured data, such as covering more cancer lineages. However, some known biological associations (e.g.&nbsp;EGFR mutation status) may still be difficult to capture due to data limitations.</p>
<p>Overall, this framework can be useful for generating drug sensitivity predictions for cell lines without measured data, which can aid in drug repurposing and precision oncology efforts.</p>
<section id="references" class="level3">
<h3 class="anchored" data-anchor-id="references">References</h3>
<ul>
<li>DepMap Portal: <a href="https://depmap.org/portal/" class="uri">https://depmap.org/portal/</a></li>
<li>Caret Package Documentation: <a href="https://topepo.github.io/caret/" class="uri">https://topepo.github.io/caret/</a></li>
<li>Applied Predictive Modeling by Kuhn and Johnson: <a href="https://www.springer.com/gp/book/9781461468486" class="uri">https://www.springer.com/gp/book/9781461468486</a></li>
</ul>


</section>
</section>

 ]]></description>
  <category>R</category>
  <category>DepMap</category>
  <category>Machine Learning</category>
  <category>Elastic Net</category>
  <category>Caret</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/</guid>
  <pubDate>Fri, 26 Dec 2025 08:00:00 GMT</pubDate>
  <media:content url="https://tiny-lab-bioml.netlify.app/posts/2025-12-16_enet_predict_erlotinib/files/enet_tuning_plot_erlotinib.png" medium="image" type="image/png" height="108" width="144"/>
</item>
<item>
  <title>Training a Random Forest model with Scikit-Learn on DepMap data</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/2025-12-12_ml_with_scikitlearn/</link>
  <description><![CDATA[ 





<section id="introduction" class="level1">
<h1>Introduction</h1>
<p>In this specific blog post, we will explore the Cancer Dependency Map (DepMap) dataset to understand the relationship between genetic dependencies (CRISPR knockout effects) and gene expression levels. We will use Python’s <code>pandas</code> ecosystem for data loading, exploratory data analysis, and visualization. We will also use <code>scikit-learn</code>’s functions to build a Random Forest predictor pipeline that performs preprocessing, imputes missing values, and tunes hyperparameters. Finally, we will evaluate the model’s performance and extract genes that are most important for predicting gene dependency.</p>
</section>
<section id="data-loading" class="level1">
<h1>Data Loading</h1>
<p>First, we import the necessary libraries and load the datasets. We are using three main datasets:</p>
<ol type="1">
<li><strong>Sample Info</strong>: Metadata about the cell lines (lineage, disease subtype, etc.).</li>
<li><strong>Chronos Data</strong>: CRISPR knockout scores representing gene dependency (lower score = higher dependency).</li>
<li><strong>Gene Expression (GE) Data</strong>: RNA-seq expression levels for various genes.</li>
</ol>
<p>Data can be downloaded from here (modified from DepMap 24Q2): <a href="https://zenodo.org/records/17970100" class="uri">https://zenodo.org/records/17970100</a></p>
<div id="load-libraries-and-data" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> os</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define file paths (relative to the ML_practice directory)</span></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Here I have preprocessed the data for this demo so the cell lines (rows) are aligned</span></span>
<span id="cb1-8">sample_info_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ML_practice/sample_info.csv"</span></span>
<span id="cb1-9">chronos_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ML_practice/chronos_dat.csv"</span></span>
<span id="cb1-10">ge_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ML_practice/ccle_ge.csv"</span></span>
<span id="cb1-11"></span>
<span id="cb1-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load the datasets</span></span>
<span id="cb1-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample metadata containing cell line information</span></span>
<span id="cb1-14">sample_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(sample_info_path)</span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Chronos scores: Gene effect scores from CRISPR knockout screens</span></span>
<span id="cb1-17">chronos_dat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(chronos_path)</span>
<span id="cb1-18"></span>
<span id="cb1-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Gene Expression data: mRNA expression levels log2(TPM + 1)</span></span>
<span id="cb1-20">ge_dat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(ge_path)</span></code></pre></div></div>
</div>
</section>
<section id="exploratory-data-analysis" class="level1">
<h1>Exploratory Data Analysis</h1>
<p>Let’s inspect the structure and basic statistics of our datasets.</p>
<section id="sample-information" class="level2">
<h2 class="anchored" data-anchor-id="sample-information">Sample Information</h2>
<p>Checking the metadata to understand the cell lines we are working with.</p>
<div id="inspect-sample-data" class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Display dataset information: columns, non-null counts, and data types</span></span>
<span id="cb2-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sample Data Info:"</span>)</span>
<span id="cb2-3">sample_data.info()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Sample Data Info:
&lt;class 'pandas.core.frame.DataFrame'&gt;
RangeIndex: 1959 entries, 0 to 1958
Data columns (total 9 columns):
 #   Column                   Non-Null Count  Dtype 
---  ------                   --------------  ----- 
 0   ModelID                  1959 non-null   object
 1   StrippedCellLineName     1959 non-null   object
 2   CCLEName                 1902 non-null   object
 3   OncotreeLineage          1954 non-null   object
 4   OncotreeSubtype          1959 non-null   object
 5   OncotreePrimaryDisease   1959 non-null   object
 6   LegacySubSubtype         831 non-null    object
 7   LegacyMolecularSubtype   151 non-null    object
 8   PatientMolecularSubtype  138 non-null    object
dtypes: object(9)
memory usage: 137.9+ KB</code></pre>
</div>
</div>
</section>
<section id="chronos-dependency-data" class="level2">
<h2 class="anchored" data-anchor-id="chronos-dependency-data">Chronos (Dependency) Data</h2>
<p>This dataset contains dependency scores for key genes like <em>SMARCA2</em>, <em>SOX10</em>, and <em>KRAS</em>.</p>
<div id="inspect-chronos-data" class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Display dataset information for Chronos data</span></span>
<span id="cb4-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Chronos Data Info:"</span>)</span>
<span id="cb4-3">chronos_dat.info()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Chronos Data Info:
&lt;class 'pandas.core.frame.DataFrame'&gt;
RangeIndex: 1959 entries, 0 to 1958
Data columns (total 4 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   cell_line  1959 non-null   object 
 1   SMARCA2    1150 non-null   float64
 2   SOX10      1150 non-null   float64
 3   KRAS       1150 non-null   float64
dtypes: float64(3), object(1)
memory usage: 61.3+ KB</code></pre>
</div>
</div>
</section>
<section id="gene-expression-data" class="level2">
<h2 class="anchored" data-anchor-id="gene-expression-data">Gene Expression Data</h2>
<p>This dataset provides expression levels for a wide range of genes across the cell lines.</p>
<div id="cell-inspect-ge-data" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Display dataset information for Gene Expression data</span></span>
<span id="cb6-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Gene Expression Data Info:"</span>)</span>
<span id="cb6-3">ge_dat.info()</span>
<span id="cb6-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">First 5 rows of Gene Expression Data:"</span>)</span>
<span id="cb6-5">display(ge_dat.head())</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Gene Expression Data Info:
&lt;class 'pandas.core.frame.DataFrame'&gt;
RangeIndex: 1959 entries, 0 to 1958
Columns: 19153 entries, TSPAN6 to CDR1
dtypes: float64(19153)
memory usage: 286.3 MB

First 5 rows of Gene Expression Data:</code></pre>
</div>
<div id="inspect-ge-data" class="cell-output cell-output-display">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">TSPAN6</th>
<th data-quarto-table-cell-role="th">TNMD</th>
<th data-quarto-table-cell-role="th">DPM1</th>
<th data-quarto-table-cell-role="th">SCYL3</th>
<th data-quarto-table-cell-role="th">FIRRM</th>
<th data-quarto-table-cell-role="th">FGR</th>
<th data-quarto-table-cell-role="th">CFH</th>
<th data-quarto-table-cell-role="th">FUCA2</th>
<th data-quarto-table-cell-role="th">GCLC</th>
<th data-quarto-table-cell-role="th">NFYA</th>
<th data-quarto-table-cell-role="th">...</th>
<th data-quarto-table-cell-role="th">SPDYE11</th>
<th data-quarto-table-cell-role="th">H3C2</th>
<th data-quarto-table-cell-role="th">H3C3</th>
<th data-quarto-table-cell-role="th">DUS4L-BCAP29</th>
<th data-quarto-table-cell-role="th">C8orf44-SGK3</th>
<th data-quarto-table-cell-role="th">ELOA3BP</th>
<th data-quarto-table-cell-role="th">NPBWR1</th>
<th data-quarto-table-cell-role="th">ELOA3DP</th>
<th data-quarto-table-cell-role="th">ELOA3P</th>
<th data-quarto-table-cell-role="th">CDR1</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>5.183487</td>
<td>0.000000</td>
<td>7.497612</td>
<td>2.107688</td>
<td>4.217231</td>
<td>0.042644</td>
<td>0.903038</td>
<td>5.722193</td>
<td>4.676944</td>
<td>3.720278</td>
<td>...</td>
<td>0.056584</td>
<td>1.137504</td>
<td>0.000000</td>
<td>1.794936</td>
<td>0.201634</td>
<td>0.000000</td>
<td>0.028569</td>
<td>0.0</td>
<td>0.214125</td>
<td>0.014355</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>0.176323</td>
<td>0.000000</td>
<td>5.702103</td>
<td>1.238787</td>
<td>3.119356</td>
<td>4.141596</td>
<td>0.163499</td>
<td>4.134221</td>
<td>4.111866</td>
<td>2.347666</td>
<td>...</td>
<td>0.000000</td>
<td>1.952334</td>
<td>0.238787</td>
<td>1.516015</td>
<td>0.000000</td>
<td>0.000000</td>
<td>0.028569</td>
<td>0.0</td>
<td>0.000000</td>
<td>0.000000</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>5.309976</td>
<td>0.084064</td>
<td>7.846117</td>
<td>1.875780</td>
<td>3.894333</td>
<td>0.000000</td>
<td>0.056584</td>
<td>6.666615</td>
<td>4.738768</td>
<td>3.984589</td>
<td>...</td>
<td>0.014355</td>
<td>0.918386</td>
<td>0.000000</td>
<td>1.655352</td>
<td>0.000000</td>
<td>0.028569</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.028569</td>
<td>0.000000</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>2.176323</td>
<td>0.000000</td>
<td>5.454505</td>
<td>2.480265</td>
<td>3.921246</td>
<td>0.887525</td>
<td>4.958843</td>
<td>3.949535</td>
<td>4.877253</td>
<td>4.829850</td>
<td>...</td>
<td>0.014355</td>
<td>0.536053</td>
<td>0.505891</td>
<td>2.643856</td>
<td>0.097611</td>
<td>0.000000</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.000000</td>
<td>0.000000</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>2.451541</td>
<td>0.000000</td>
<td>5.884842</td>
<td>2.927896</td>
<td>5.299391</td>
<td>0.201634</td>
<td>5.759156</td>
<td>4.150560</td>
<td>5.531069</td>
<td>5.029895</td>
<td>...</td>
<td>0.000000</td>
<td>0.895303</td>
<td>1.350497</td>
<td>2.709291</td>
<td>0.678072</td>
<td>0.000000</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.000000</td>
<td>0.000000</td>
</tr>
</tbody>
</table>

<p>5 rows × 19153 columns</p>
</div>
</div>
</div>
</section>
<section id="data-distribution-and-correlations" class="level2">
<h2 class="anchored" data-anchor-id="data-distribution-and-correlations">Data Distribution and Correlations</h2>
<p>We can look at the overall distribution of the dependency data using a scatter matrix. This helps us spot potential correlations or clusters between different gene dependencies.</p>
<div id="cell-scatter-matrix" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pandas.plotting <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> scatter_matrix</span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create a scatter matrix to visualize pair-wise relationships in the Chronos dataset</span></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This includes histograms on the diagonal and scatter plots on off-diagonals</span></span>
<span id="cb8-5">scatter_matrix(chronos_dat)</span>
<span id="cb8-6">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div id="scatter-matrix" class="quarto-figure quarto-figure-center anchored">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-12_ml_with_scikitlearn/index_files/figure-html/scatter-matrix-output-1.png" width="583" height="432" class="figure-img"></p>
<figcaption>Scatter matrix of Chronos dependency scores for selected genes.</figcaption>
</figure>
</div>
</div>
</div>
<p>Let’s verify the correlations numerically. We drop the ‘cell_line’ column as it is categorical.</p>
<div id="chronos-correlation" class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate the correlation matrix for the numeric columns in Chronos data</span></span>
<span id="cb9-2">chronos_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chronos_dat.drop(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell_line"</span>, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).corr()</span>
<span id="cb9-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Correlation Matrix (Chronos Data):"</span>)</span>
<span id="cb9-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(chronos_corr)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Correlation Matrix (Chronos Data):
          SMARCA2     SOX10      KRAS
SMARCA2  1.000000 -0.032416  0.005902
SOX10   -0.032416  1.000000 -0.052455
KRAS     0.005902 -0.052455  1.000000</code></pre>
</div>
</div>
</section>
</section>
<section id="visualization-dependency-vs.-expression" class="level1">
<h1>Visualization: Dependency vs.&nbsp;Expression</h1>
<p>A key question in cancer biology is whether gene expression predicts dependency. For example, if a cell line highly expresses <em>SOX10</em>, is it more dependent on <em>SOX10</em> for survival (lower Chronos score)?</p>
<p>Let’s visualize the relationship between <em>SOX10</em> dependency (Chronos score) and <em>SOX10</em> gene expression.</p>
<div id="cell-plot-sox10-correlation" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot SOX10 Chronos score (x-axis) vs SOX10 Gene Expression (y-axis)</span></span>
<span id="cb11-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Note: Lower Chronos score means higher dependency.</span></span>
<span id="cb11-3">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb11-4">plt.scatter(chronos_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10"</span>], ge_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10"</span>], alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>)</span>
<span id="cb11-5">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10 Chronos Score (Dependency)"</span>)</span>
<span id="cb11-6">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10 Gene Expression"</span>)</span>
<span id="cb11-7">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10: Dependency vs Expression"</span>)</span>
<span id="cb11-8">plt.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb11-9">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div id="plot-sox10-correlation" class="quarto-figure quarto-figure-center anchored">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-12_ml_with_scikitlearn/index_files/figure-html/plot-sox10-correlation-output-1.png" width="651" height="523" class="figure-img"></p>
<figcaption>Scatter plot showing the relationship between SOX10 Gene Expression and SOX10 Dependency (Chronos Score).</figcaption>
</figure>
</div>
</div>
</div>
<p>Finally, let’s calculate the Pearson correlation coefficient between these two variables to quantify the relationship.</p>
<div id="calc-sox10-correlation" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate Pearson correlation between SOX10 dependency and expression</span></span>
<span id="cb12-2">sox10_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chronos_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10"</span>].corr(ge_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10"</span>])</span>
<span id="cb12-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Pearson Correlation between SOX10 Chronos and Gene Expression: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>sox10_corr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Pearson Correlation between SOX10 Chronos and Gene Expression: -0.8491</code></pre>
</div>
</div>
<p>This correlation value suggests a strong relationship between SOX10 gene expression and dependency.</p>
</section>
<section id="machine-learning" class="level1">
<h1>Machine Learning</h1>
<p>Now we will build a machine learning model to predict the <em>SOX10</em> dependency score based on the gene expression profile of the cell lines.</p>
<section id="data-preprocessing" class="level2">
<h2 class="anchored" data-anchor-id="data-preprocessing">Data Preprocessing</h2>
<p>Before training, we need to prepare our data.</p>
<ol type="1">
<li><strong>Alignment</strong>: Ensure the cell lines in the dependency dataset match those in the gene expression dataset.</li>
<li><strong>Merging</strong>: Combined the target variable (<em>SOX10</em> Chronos score) with the feature set (Gene Expression).</li>
<li><strong>Imputation</strong>: Dealing with missing values using K-Nearest Neighbors (KNN) imputation.</li>
</ol>
<div id="data-preprocessing" class="cell" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Align and merge data</span></span>
<span id="cb14-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The rows are already pre-aligned by cell line index</span></span>
<span id="cb14-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adding target variable to the dataframe for alignment</span></span>
<span id="cb14-4">ge_dat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(ge_path)</span>
<span id="cb14-5">ge_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10_chronos"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chronos_dat[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10"</span>]</span>
<span id="cb14-6"></span>
<span id="cb14-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove rows where the target (SOX10_chronos) is NaN, as we can't train/test on them</span></span>
<span id="cb14-8">ge_dat_clean <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ge_dat.dropna(subset<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10_chronos"</span>])</span>
<span id="cb14-9"></span>
<span id="cb14-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Separate features (X) and target (y)</span></span>
<span id="cb14-11">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ge_dat_clean.drop(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10_chronos"</span>, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb14-12">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ge_dat_clean[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SOX10_chronos"</span>]</span>
<span id="cb14-13"></span>
<span id="cb14-14"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Data shape after removing missing targets: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>X<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Data shape after removing missing targets: (1150, 19153)</code></pre>
</div>
</div>
<p>We will handle missing values in the features (Gene Expression) using KNN Imputation within our modeling pipeline.</p>
</section>
<section id="model-training" class="level2">
<h2 class="anchored" data-anchor-id="model-training">Model Training</h2>
<p>We will use a <strong>Random Forest Regressor</strong> to predict the dependency score.</p>
<section id="data-splitting" class="level3">
<h3 class="anchored" data-anchor-id="data-splitting">Data Splitting</h3>
<p>First, we split the data into training and testing sets (80% train, 20% test).</p>
<div id="train-test-split" class="cell" data-execution_count="10">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> train_test_split</span>
<span id="cb16-2"></span>
<span id="cb16-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Split data into training and testing set</span></span>
<span id="cb16-4">X_train, X_test, y_train, y_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_test_split(X, y, test_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="cb16-5"></span>
<span id="cb16-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Training samples: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>X_train<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb16-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Testing samples: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>X_test<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Training samples: 920
Testing samples: 230</code></pre>
</div>
</div>
</section>
<section id="pipeline-and-hyperparameter-tuning" class="level3">
<h3 class="anchored" data-anchor-id="pipeline-and-hyperparameter-tuning">Pipeline and Hyperparameter Tuning</h3>
<p>We create a pipeline that: 1. Imputes missing values using <code>KNNImputer</code>. 2. Scales features using <code>StandardScaler</code> (optional for RF but good practice). 3. Trains a <code>RandomForestRegressor</code>.</p>
<p>We will use <code>RandomizedSearchCV</code> to find the best hyperparameters (e.g., <code>max_features</code> for the Random Forest).</p>
<div id="model-training" class="cell" data-message="false" data-execution_count="11">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.ensemble <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomForestRegressor</span>
<span id="cb18-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomizedSearchCV</span>
<span id="cb18-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> scipy.stats <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> randint</span>
<span id="cb18-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.pipeline <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Pipeline</span>
<span id="cb18-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.preprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StandardScaler</span>
<span id="cb18-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.impute <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> KNNImputer</span>
<span id="cb18-7"></span>
<span id="cb18-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create a pipeline</span></span>
<span id="cb18-9">pipeline <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Pipeline([</span>
<span id="cb18-10">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"imputer"</span>, KNNImputer(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)),</span>
<span id="cb18-11">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scaler"</span>, StandardScaler()),</span>
<span id="cb18-12">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rf"</span>, RandomForestRegressor(random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>))</span>
<span id="cb18-13">])</span>
<span id="cb18-14"></span>
<span id="cb18-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define hyperparameter search space</span></span>
<span id="cb18-16">param_dist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb18-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rf__max_features'</span>: randint(low<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, high<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span>), <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of features to consider at each split</span></span>
<span id="cb18-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rf__n_estimators'</span>: randint(low<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, high<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of trees in the forest</span></span>
<span id="cb18-19">}</span>
<span id="cb18-20"></span>
<span id="cb18-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Initialize RandomizedSearchCV</span></span>
<span id="cb18-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># n_iter=5 to keep run time reasonable for this demo</span></span>
<span id="cb18-23">rnd_search <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RandomizedSearchCV(</span>
<span id="cb18-24">    pipeline, </span>
<span id="cb18-25">    param_distributions<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>param_dist, </span>
<span id="cb18-26">    n_iter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of parameter settings that are sampled</span></span>
<span id="cb18-27">    cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Number of folds in cross-validation</span></span>
<span id="cb18-28">    random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Random state for reproducibility</span></span>
<span id="cb18-29">    scoring<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"neg_root_mean_squared_error"</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Scoring metric</span></span>
<span id="cb18-30">    n_jobs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Use all available CPU cores</span></span>
<span id="cb18-31">)</span>
<span id="cb18-32"></span>
<span id="cb18-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fit the model</span></span>
<span id="cb18-34"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Training Random Forest model..."</span>)</span>
<span id="cb18-35">rnd_search.fit(X_train, y_train)</span>
<span id="cb18-36"></span>
<span id="cb18-37"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Best RMSE: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>rnd_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_score_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb18-38"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Best Parameters: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>rnd_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_params_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb18-39"></span>
<span id="cb18-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get the best model</span></span>
<span id="cb18-41">final_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rnd_search.best_estimator_</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Training Random Forest model...</code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Best RMSE: 0.2097
Best Parameters: {'rf__max_features': 3019, 'rf__n_estimators': 180}</code></pre>
</div>
</div>
</section>
</section>
<section id="model-evaluation" class="level2">
<h2 class="anchored" data-anchor-id="model-evaluation">Model Evaluation</h2>
<p>Now we evaluate the model’s performance on the unseen test set and investigate which genes are most important for predicting <em>SOX10</em> dependency.</p>
<section id="feature-importance" class="level3">
<h3 class="anchored" data-anchor-id="feature-importance">Feature Importance</h3>
<p>Which genes’ expression levels are most predictive of <em>SOX10</em> dependency?</p>
<div id="cell-feature-importance" class="cell" data-execution_count="12">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract feature importances</span></span>
<span id="cb21-2">rf_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> final_model.named_steps[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rf'</span>]</span>
<span id="cb21-3">importances <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rf_model.feature_importances_</span>
<span id="cb21-4">feature_names <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X.columns</span>
<span id="cb21-5"></span>
<span id="cb21-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create a dataframe for visualization</span></span>
<span id="cb21-7">feat_importances <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.Series(importances, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>feature_names)</span>
<span id="cb21-8">top_features <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> feat_importances.nlargest(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb21-9"></span>
<span id="cb21-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot top 20 features</span></span>
<span id="cb21-11">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb21-12">top_features.plot(kind<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bar'</span>)</span>
<span id="cb21-13">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Top 20 Feature Importances"</span>)</span>
<span id="cb21-14">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Importance"</span>)</span>
<span id="cb21-15">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gene"</span>)</span>
<span id="cb21-16">plt.xticks(rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'right'</span>)</span>
<span id="cb21-17">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div id="feature-importance" class="quarto-figure quarto-figure-center anchored">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-12_ml_with_scikitlearn/index_files/figure-html/feature-importance-output-1.png" width="821" height="563" class="figure-img"></p>
<figcaption>Top 20 most important features (genes) for predicting SOX10 dependency.</figcaption>
</figure>
</div>
</div>
</div>
<p>As expected, SOX10 gene expression is the most important feature for predicting <em>SOX10</em> dependency.</p>
</section>
<section id="prediction-performance" class="level3">
<h3 class="anchored" data-anchor-id="prediction-performance">Prediction Performance</h3>
<p>We calculate the Root Mean Squared Error (RMSE) on the test set and visualize the predictions vs actual values.</p>
<div id="cell-model-evaluation" class="cell" data-execution_count="13">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> mean_squared_error</span>
<span id="cb22-2"></span>
<span id="cb22-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predict on test set</span></span>
<span id="cb22-4">test_predictions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> final_model.predict(X_test)</span>
<span id="cb22-5"></span>
<span id="cb22-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate RMSE</span></span>
<span id="cb22-7">test_mse <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mean_squared_error(y_test, test_predictions)</span>
<span id="cb22-8">test_rmse <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.sqrt(test_mse)</span>
<span id="cb22-9"></span>
<span id="cb22-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Test Set RMSE: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>test_rmse<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb22-11"></span>
<span id="cb22-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot Predicted vs Expected</span></span>
<span id="cb22-13">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb22-14">plt.scatter(y_test, test_predictions, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>)</span>
<span id="cb22-15">plt.plot([y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()], [y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'k--'</span>, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Identity line</span></span>
<span id="cb22-16">plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expected Score (True)"</span>)</span>
<span id="cb22-17">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Predicted Score"</span>)</span>
<span id="cb22-18">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test Set: Predicted vs Expected"</span>)</span>
<span id="cb22-19">plt.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'--'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb22-20">plt.show()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>Test Set RMSE: 0.2139</code></pre>
</div>
<div class="cell-output cell-output-display">
<div id="model-evaluation" class="quarto-figure quarto-figure-center anchored">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-12_ml_with_scikitlearn/index_files/figure-html/model-evaluation-output-2.png" width="675" height="523" class="figure-img"></p>
<figcaption>Predicted vs Expected SOX10 Chronos Scores on Test Set.</figcaption>
</figure>
</div>
</div>
</div>
<p>We can see that the model predicts a more bimodal distribution of scores than the actual data, although it does somewhat differentiate between high and low dependency populations. To improve the model, we could try to tune the hyperparameters further, or try different feature selection methods.</p>
</section>
</section>
</section>
<section id="references" class="level1">
<h1>References</h1>
<ul>
<li><a href="https://scikit-learn.org/stable/index.html">Scikit-Learn Documentation</a></li>
<li><a href="https://pandas.pydata.org/pandas-docs/stable/index.html">Pandas Documentation</a></li>
<li><a href="https://matplotlib.org/stable/index.html">Matplotlib Documentation</a></li>
<li><a href="https://depmap.org/portal/">DepMap Portal</a></li>
<li><a href="https://www.oreilly.com/library/view/hands-on-machine-learning/9781098125967/">Hands-on Machine Learning with Scikit-Learn, Keras, and TensorFlow (3rd Edition)</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>Machine Learning</category>
  <category>DepMap</category>
  <category>Random Forest</category>
  <category>Scikit-Learn</category>
  <category>Pandas</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/2025-12-12_ml_with_scikitlearn/</guid>
  <pubDate>Mon, 15 Dec 2025 08:00:00 GMT</pubDate>
</item>
<item>
  <title>Machine learning for drug sensitivity prediction (Part 2): will deep features improve accuracy?</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/2025-12-03_ae_ml_validation/</link>
  <description><![CDATA[ 





<p>In <a href="../../posts/2025-11-29_depmap-multiomics-autoencoder/index.html">Part 1</a>, I explored using autoencoders (AE) to compress high-dimensional DepMap omics data into deep features. I visualized these features using UMAP and observed that they preserved biological signals related to cell lineage.</p>
<p>In this post (Part 2), I will evaluate whether these deep features actually improve drug sensitivity prediction accuracy compared to using either the full RNA expression data or a feature-selected subset of RNA expression data. The motivation is that deep features may capture complex, non-linear relationships in the data while reducing dimensionality, potentially enhancing model performance. We will focus on two drugs with known biomarkers but with different mechanisms of action: <strong>Erlotinib</strong> (an EGFR inhibitor) and <strong>JQ1</strong> (a BET inhibitor).</p>
<section id="setup-and-libraries" class="level2">
<h2 class="anchored" data-anchor-id="setup-and-libraries">Setup and Libraries</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(data.table)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggpubr)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(caret)</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(doParallel)</span></code></pre></div></div>
</div>
</section>
<section id="methods-machine-learning-models" class="level2">
<h2 class="anchored" data-anchor-id="methods-machine-learning-models">Methods: Machine Learning Models</h2>
<p>We will use two machine learning algorithms to predict drug sensitivity (log2 fold change) from the DepMap PRISM drug screen data:</p>
<ol type="1">
<li><strong>Random Forest (RF)</strong>: A tree-based ensemble method that can capture non-linear relationships.<br>
</li>
<li><strong>Elastic Net</strong>: A linear regression method with <img src="https://latex.codecogs.com/png.latex?l1"> and <img src="https://latex.codecogs.com/png.latex?l2"> regularization to prevent overfitting.</li>
</ol>
<p>We are using the R Caret package for model training and hyperparameter tuning. Caret is a versatile package that provides a unified interface for training various machine learning models with built-in cross-validation and hyperparameter tuning. Documentation can be found here: <a href="https://topepo.github.io/caret/" class="uri">https://topepo.github.io/caret/</a>.</p>
<p>We will evaluate performance using <strong>R-squared (<img src="https://latex.codecogs.com/png.latex?R%5E2">)</strong> on six independent test-train sets across multiple random splits.</p>
<section id="prediction-functions" class="level3">
<h3 class="anchored" data-anchor-id="prediction-functions">Prediction Functions</h3>
<p>We define helper functions to perform repeated train-test splits and model training.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Random Forest Prediction Function</span></span>
<span id="cb2-2">rf_drug_prediction <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(feature_dat, drug_response, output_file_prefix, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_repeats =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) {</span>
<span id="cb2-3">    r2_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb2-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_repeats) {</span>
<span id="cb2-5">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i)</span>
<span id="cb2-6">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 80-20 Train-Test Split</span></span>
<span id="cb2-7">        train_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(feature_dat), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(feature_dat)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb2-8">        test_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setdiff</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(feature_dat), train_idx)</span>
<span id="cb2-9"></span>
<span id="cb2-10">        train_x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> feature_dat[train_idx, ]</span>
<span id="cb2-11">        train_y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> drug_response[train_idx]</span>
<span id="cb2-12">        test_x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> feature_dat[test_idx, ]</span>
<span id="cb2-13">        test_y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> drug_response[test_idx]</span>
<span id="cb2-14"></span>
<span id="cb2-15">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Train Random Forest with caret</span></span>
<span id="cb2-16">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># caret will perform tuning for all available hyperparameters, and automatically pick the best model (highest R2 on cross-validation)</span></span>
<span id="cb2-17">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i)</span>
<span id="cb2-18">        rfTune <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">train</span>(train_x, train_y,</span>
<span id="cb2-19">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rf"</span>,</span>
<span id="cb2-20">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">importance =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb2-21">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ntree =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>,</span>
<span id="cb2-22">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">preProcess =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"center"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>),</span>
<span id="cb2-23">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rsquared"</span>,</span>
<span id="cb2-24">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tuneLength =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tune over 10 different mtry values</span></span>
<span id="cb2-25">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trControl =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">trainControl</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"repeatedcv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">number =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">repeats =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 10-fold cross-validation repeated 3 times</span></span>
<span id="cb2-26">        )</span>
<span id="cb2-27"></span>
<span id="cb2-28">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predict on Test Set</span></span>
<span id="cb2-29">        rf_pred <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(rfTune, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">newdata =</span> test_x)</span>
<span id="cb2-30">        r2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(rf_pred, test_y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pearson"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb2-31">        r2_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(r2_values, r2)</span>
<span id="cb2-32">    }</span>
<span id="cb2-33"></span>
<span id="cb2-34">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return R2 values</span></span>
<span id="cb2-35">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Repeat =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_repeats, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">R2 =</span> r2_values))</span>
<span id="cb2-36">}</span>
<span id="cb2-37"></span>
<span id="cb2-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Elastic Net Prediction Function</span></span>
<span id="cb2-39">enet_drug_prediction <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(feature_dat, drug_response, output_file_prefix, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_repeats =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) {</span>
<span id="cb2-40">    r2_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb2-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_repeats) {</span>
<span id="cb2-42">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i)</span>
<span id="cb2-43">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 80-20 Train-Test Split</span></span>
<span id="cb2-44">        train_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(feature_dat), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(feature_dat)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb2-45">        test_idx <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setdiff</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(feature_dat), train_idx)</span>
<span id="cb2-46"></span>
<span id="cb2-47">        train_x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> feature_dat[train_idx, ]</span>
<span id="cb2-48">        train_y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> drug_response[train_idx]</span>
<span id="cb2-49">        test_x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> feature_dat[test_idx, ]</span>
<span id="cb2-50">        test_y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> drug_response[test_idx]</span>
<span id="cb2-51"></span>
<span id="cb2-52">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Train Elastic Net</span></span>
<span id="cb2-53">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i)</span>
<span id="cb2-54">        enetTune <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">train</span>(train_x, train_y,</span>
<span id="cb2-55">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"glmnet"</span>,</span>
<span id="cb2-56">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">preProcess =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"center"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>),</span>
<span id="cb2-57">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metric =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rsquared"</span>,</span>
<span id="cb2-58">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tuneLength =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tune over 10 X 10 different alpha/lambda combinations</span></span>
<span id="cb2-59">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># alpha: mixing parameter (0 = ridge, 1 = lasso)</span></span>
<span id="cb2-60">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># lambda: regularization strength</span></span>
<span id="cb2-61">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">trControl =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">trainControl</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"repeatedcv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">number =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">repeats =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 10-fold cross-validation repeated 3 times</span></span>
<span id="cb2-62">        )</span>
<span id="cb2-63"></span>
<span id="cb2-64">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Predict on Test Set</span></span>
<span id="cb2-65">        enet_pred <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(enetTune, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">newdata =</span> test_x)</span>
<span id="cb2-66">        r2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cor</span>(enet_pred, test_y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pearson"</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb2-67">        r2_values <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(r2_values, r2)</span>
<span id="cb2-68">    }</span>
<span id="cb2-69"></span>
<span id="cb2-70">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return R2 values</span></span>
<span id="cb2-71">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Repeat =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_repeats, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">R2 =</span> r2_values))</span>
<span id="cb2-72">}</span></code></pre></div></div>
</div>
</section>
</section>
<section id="analysis-1-erlotinib-prediction" class="level2">
<h2 class="anchored" data-anchor-id="analysis-1-erlotinib-prediction">Analysis 1: Erlotinib Prediction</h2>
<p>Erlotinib is an EGFR inhibitor used in cancer treatment, which is a type of targeted cancer therapy used primarily to treat certain types of non-small cell lung cancer and pancreatic cancer.</p>
<section id="data-preparation" class="level3">
<h3 class="anchored" data-anchor-id="data-preparation">Data Preparation</h3>
<p>We load the data and prepare four feature sets:</p>
<ol type="1">
<li><strong>Full RNA</strong>: All high-variance genes.<br>
</li>
<li><strong>RNA AE</strong>: Deep features from RNA autoencoder.<br>
</li>
<li><strong>Multi-omics AE</strong>: Deep features from multi-omics autoencoder (including RNA, mutation, and CRISPR).<br>
</li>
<li><strong>Selected Top RNA</strong>: Top ~4000 gene expressions most correlated with Erlotinib response (a common feature selection strategy).</li>
</ol>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load Data</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCLE_24Q2_GE_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># RNA expression in log2(TPM+1)</span></span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PRISM_24Q2_compound_screen_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># PRISM drug response data in log2 fold change (LFC)</span></span>
<span id="cb3-4">cmpd_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Repurposing_Public_24Q2_Extended_Primary_Compound_List.csv"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compound metadata</span></span>
<span id="cb3-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample_info_match_biomarkers.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample info with DepMap IDs</span></span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... (Data filtering and matching code similar to Part 1) ...</span></span>
<span id="cb3-8"></span>
<span id="cb3-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get Erlotinib Response</span></span>
<span id="cb3-10">cmpd_id <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> cmpd_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb3-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(Drug.Name <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ERLOTINIB"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb3-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(IDs)</span>
<span id="cb3-13">drug_LFC <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> prism_dat_match_sam <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull</span>(cmpd_id)</span></code></pre></div></div>
</div>
<p>Let’s take a look at the PRISM drug screen data. Rows are cell lines and columns are compounds. Values are log2 fold change (LFC) in viability after drug treatment. You can see that there are a lot of NAs here, as many cell lines were not screened with all compounds.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PRISM_24Q2_compound_screen_match_sample_info.RData"</span>)</span>
<span id="cb4-2">prism_dat_match_sam[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> gt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gt</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div id="biainsuzjn" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#biainsuzjn table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#biainsuzjn thead, #biainsuzjn tbody, #biainsuzjn tfoot, #biainsuzjn tr, #biainsuzjn td, #biainsuzjn th {
  border-style: none;
}

#biainsuzjn p {
  margin: 0;
  padding: 0;
}

#biainsuzjn .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#biainsuzjn .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#biainsuzjn .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#biainsuzjn .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#biainsuzjn .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#biainsuzjn .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#biainsuzjn .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#biainsuzjn .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#biainsuzjn .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#biainsuzjn .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#biainsuzjn .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#biainsuzjn .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#biainsuzjn .gt_spanner_row {
  border-bottom-style: hidden;
}

#biainsuzjn .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#biainsuzjn .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#biainsuzjn .gt_from_md > :first-child {
  margin-top: 0;
}

#biainsuzjn .gt_from_md > :last-child {
  margin-bottom: 0;
}

#biainsuzjn .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#biainsuzjn .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#biainsuzjn .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#biainsuzjn .gt_row_group_first td {
  border-top-width: 2px;
}

#biainsuzjn .gt_row_group_first th {
  border-top-width: 2px;
}

#biainsuzjn .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#biainsuzjn .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#biainsuzjn .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#biainsuzjn .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#biainsuzjn .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#biainsuzjn .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#biainsuzjn .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#biainsuzjn .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#biainsuzjn .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#biainsuzjn .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#biainsuzjn .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#biainsuzjn .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#biainsuzjn .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#biainsuzjn .gt_left {
  text-align: left;
}

#biainsuzjn .gt_center {
  text-align: center;
}

#biainsuzjn .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#biainsuzjn .gt_font_normal {
  font-weight: normal;
}

#biainsuzjn .gt_font_bold {
  font-weight: bold;
}

#biainsuzjn .gt_font_italic {
  font-style: italic;
}

#biainsuzjn .gt_super {
  font-size: 65%;
}

#biainsuzjn .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#biainsuzjn .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#biainsuzjn .gt_indent_1 {
  text-indent: 5px;
}

#biainsuzjn .gt_indent_2 {
  text-indent: 10px;
}

#biainsuzjn .gt_indent_3 {
  text-indent: 15px;
}

#biainsuzjn .gt_indent_4 {
  text-indent: 20px;
}

#biainsuzjn .gt_indent_5 {
  text-indent: 25px;
}

#biainsuzjn .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#biainsuzjn div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<thead>
<tr class="gt_col_headings header">
<th id="BRD:BRD-A00047421-001-01-7" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">BRD:BRD-A00047421-001-01-7</th>
<th id="BRD:BRD-A00055058-001-01-0" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">BRD:BRD-A00055058-001-01-0</th>
<th id="BRD:BRD-A00077618-236-07-6" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">BRD:BRD-A00077618-236-07-6</th>
<th id="BRD:BRD-A00092689-236-04-9" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">BRD:BRD-A00092689-236-04-9</th>
<th id="BRD:BRD-A00100033-001-08-9" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">BRD:BRD-A00100033-001-08-9</th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_right" headers="BRD:BRD-A00047421-001-01-7">-1.207281</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00055058-001-01-0">0.5157434</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00077618-236-07-6">-0.01557664</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00092689-236-04-9">-0.39512253</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00100033-001-08-9">-0.4493321</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="BRD:BRD-A00047421-001-01-7">-4.231563</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00055058-001-01-0">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00077618-236-07-6">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00092689-236-04-9">-0.53837559</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00100033-001-08-9">NA</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="BRD:BRD-A00047421-001-01-7">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00055058-001-01-0">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00077618-236-07-6">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00092689-236-04-9">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00100033-001-08-9">NA</td>
</tr>
<tr class="even">
<td class="gt_row gt_right" headers="BRD:BRD-A00047421-001-01-7">-3.860672</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00055058-001-01-0">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00077618-236-07-6">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00092689-236-04-9">0.30697134</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00100033-001-08-9">NA</td>
</tr>
<tr class="odd">
<td class="gt_row gt_right" headers="BRD:BRD-A00047421-001-01-7">-2.271411</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00055058-001-01-0">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00077618-236-07-6">NA</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00092689-236-04-9">0.03509603</td>
<td class="gt_row gt_right" headers="BRD:BRD-A00100033-001-08-9">NA</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p>For brevity, we skip the data cleaning steps here. After filtering for missing data and matching cell lines across datasets, we obtain the final datasets for modeling. We also skip the codes for selecting the top RNA genes correlated with Erlotinib response - it is a simple apply function calculating Pearson correlation for each gene across the transcriptome, and selecting the top genes.</p>
</section>
<section id="model-training-erlotinib" class="level3">
<h3 class="anchored" data-anchor-id="model-training-erlotinib">Model Training (Erlotinib)</h3>
<p>We train models on all four feature sets.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Parallel Processing</span></span>
<span id="cb5-2">cl <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">makePSOCKcluster</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adjust number of cores as needed</span></span>
<span id="cb5-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">registerDoParallel</span>(cl)</span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Full RNA</span></span>
<span id="cb5-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rf_drug_prediction</span>(ge_dat_final, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"full_RNA"</span>)</span>
<span id="cb5-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enet_drug_prediction</span>(ge_dat_final, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"full_RNA"</span>)</span>
<span id="cb5-8"></span>
<span id="cb5-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. RNA AE Features</span></span>
<span id="cb5-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rf_drug_prediction</span>(RNA_AE_features_final, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RNA_AE"</span>)</span>
<span id="cb5-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enet_drug_prediction</span>(RNA_AE_features_final, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RNA_AE"</span>)</span>
<span id="cb5-12"></span>
<span id="cb5-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Multi-omics AE Features</span></span>
<span id="cb5-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rf_drug_prediction</span>(MultiOmics_AE_features_final, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MultiOmics_AE"</span>)</span>
<span id="cb5-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enet_drug_prediction</span>(MultiOmics_AE_features_final, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MultiOmics_AE"</span>)</span>
<span id="cb5-16"></span>
<span id="cb5-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 4. Selected Top RNA</span></span>
<span id="cb5-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rf_drug_prediction</span>(ge_dat_selected, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"selected_top_RNA"</span>)</span>
<span id="cb5-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enet_drug_prediction</span>(ge_dat_selected, drug_LFC_final, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"selected_top_RNA"</span>)</span>
<span id="cb5-20"></span>
<span id="cb5-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopCluster</span>(cl)</span></code></pre></div></div>
</div>
</section>
<section id="results-erlotinib" class="level3">
<h3 class="anchored" data-anchor-id="results-erlotinib">Results: Erlotinib</h3>
<p>Let’s look at the performance (<img src="https://latex.codecogs.com/png.latex?R%5E2">) of the different models.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load results (code omitted for brevity, loading CSVs from results folder)</span></span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot Random Forest Results</span></span>
<span id="cb6-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(rf_r2_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> R2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> Model)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outliers =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Random Forest Erlotinib LFC Prediction R2"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Model"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>)</span>
<span id="cb6-10"></span>
<span id="cb6-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot Elastic Net Results</span></span>
<span id="cb6-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(enet_r2_df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> R2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> Model, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> Model)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_boxplot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outliers =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_jitter</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Elastic Net Erlotinib LFC Prediction R2"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Model"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"R2"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-17">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>)</span></code></pre></div></div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-03_ae_ml_validation/rf_erlotinib_prediction_r2_summary.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:70.0%"></p>
</figure>
</div>
</div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-03_ae_ml_validation/enet_erlotinib_prediction_r2_summary.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:70.0%"></p>
</figure>
</div>
</div>
</div>
<p>This result is a bit surprising! In both models, the selected top RNA genes outperform all other feature sets. The full RNA set ranks second, while the AE features perform worse. The multi-omics AE features do not seem to add value in this case, and it performs even worse than the RNA AE features alone. I’ll speculate why this might be the case in the summary section. Is this specific to Erlotinib, or a general trend? Let’s check with another drug.</p>
</section>
</section>
<section id="analysis-2-jq1-prediction" class="level2">
<h2 class="anchored" data-anchor-id="analysis-2-jq1-prediction">Analysis 2: JQ1 Prediction</h2>
<p>Now let’s try to predict sensitivity to JQ1, a BET inhibitor that has a very different mechanism of action compared to Erlotinib.</p>
<section id="model-training-jq1" class="level3">
<h3 class="anchored" data-anchor-id="model-training-jq1">Model Training (JQ1)</h3>
<p>We repeat the same process for JQ1.</p>
</section>
<section id="results-jq1" class="level3">
<h3 class="anchored" data-anchor-id="results-jq1">Results: JQ1</h3>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... (Similar plotting code as Erlotinib) ...</span></span></code></pre></div></div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-03_ae_ml_validation/rf_JQ1_prediction_r2_summary.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:70.0%"></p>
</figure>
</div>
</div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-12-03_ae_ml_validation/enet_JQ1_prediction_r2_summary.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:70.0%"></p>
</figure>
</div>
</div>
</div>
<p>So the conclusion is pretty much the same for JQ1 as well. The selected top RNA genes outperform all other feature sets, followed by the full RNA set. The AE features again perform worse, and adding multi-omics data does not help.</p>
</section>
</section>
<section id="summary-and-conclusions" class="level2">
<h2 class="anchored" data-anchor-id="summary-and-conclusions">Summary and Conclusions</h2>
<p>Contrary to my initial hypothesis, the deep features extracted from autoencoders did not improve drug sensitivity prediction accuracy for either Erlotinib or JQ1. Instead, using a feature-selected subset of RNA expression data yielded the best performance, followed by using the full RNA expression data. The AE features, both RNA-only and multi-omics, underperformed in comparison.</p>
<p>So why is this the case? Here are some possible explanations:</p>
<ol type="1">
<li><p><strong>Information Loss</strong>: The AE compression may have discarded important predictive information present in the original RNA expression data. Rather than preserving features relevant for drug response, the AE might have prioritized reconstructing general patterns, which in this case is likely the lineage programs between different cell lines. A possible remedy could be to use supervised or semi-supervised autoencoders that incorporate drug response information during training. I also have not experimented with different AE architectures, latent dimensions, or training strategies that might better capture drug response signals.</p></li>
<li><p><strong>Multi-omics Integration Challenges</strong>: Combining multiple omics data types (RNA, mutation, CRISPR) into a single AE may introduce noise or conflicting signals that obscure relevant features for drug response. Each omics type has different sparsity and scales, making it difficult for a single AE to effectively learn a unified representation. More sophisticated integration methods or separate AEs for each omics type followed by feature fusion might yield better results.</p></li>
<li><p><strong>Drug-Specific Biology</strong>: Assuming that the AE mainly captures broad biological variation (e.g., lineage), it may not align well with the specific molecular mechanisms driving sensitivity to Erlotinib and JQ1. For example, one of the key biomarkers for Erlotinib sensitivity - EGFR hotspot mutations - are actually quite rare across the cell lines (I’ve counted around 10), and may not be well represented in the AE features. I also did not explore including other omics data types (e.g., proteomics, methylation) that might be relevant for these drugs. Finally, only two drugs were tested here; results may vary for other drugs with different mechanisms of action.</p></li>
<li><p><strong>Limitation of ML Models</strong>: The Random Forest and Elastic Net models used here may not fully leverage the complex representations learned by the AEs. More advanced models (e.g., deep neural networks) that can capture non-linear relationships in the AE feature space might yield different results. However, one significant drawback of deep learning is that it generally requires much larger training datasets to avoid overfitting, which may not be feasible with the limited number of cell lines available in a regular drug screen.</p></li>
</ol>
<p>Interestingly, between the 2 models, the Elastic Net seemed to slightly outperform Random Forest in most cases. Given that the training time for Elastic Net is significantly shorter than Random Forest, this suggests that for these specific drug response predictions, simpler linear models with regularization may be more effective than more complex non-linear models.</p>
<p>So there you have it! In the next and final part of this series, I will revisit the concept I introduced in my first post: enhancing statistical power of drug biomarker detection by ML. I will use the best performed model (selected top RNA with Elastic Net) to expand drug prediction to all DepMap available cell lines (e.g., there are only ~500 cell lines screened for Erlotinib, but DepMap has close to 2000 cell lines), and see if we can better recover known sensitivity biomarkers.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>DepMap Portal: <a href="https://depmap.org/portal/" class="uri">https://depmap.org/portal/</a></li>
<li>Caret Package Documentation: <a href="https://topepo.github.io/caret/" class="uri">https://topepo.github.io/caret/</a></li>
<li>Applied Predictive Modeling by Kuhn and Johnson: <a href="https://www.springer.com/gp/book/9781461468486" class="uri">https://www.springer.com/gp/book/9781461468486</a></li>
<li>An Introduction to Statistical Learning by James et al.: <a href="https://www.statlearning.com/" class="uri">https://www.statlearning.com/</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>DepMap</category>
  <category>Autoencoder</category>
  <category>Multi-omics</category>
  <category>Machine Learning</category>
  <category>Random Forest</category>
  <category>Elastic Net</category>
  <category>Caret</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/2025-12-03_ae_ml_validation/</guid>
  <pubDate>Mon, 08 Dec 2025 08:00:00 GMT</pubDate>
</item>
<item>
  <title>Machine learning for drug sensitivity prediction (Part 1): using autoencoders to extract deep features from DepMap OMICS</title>
  <dc:creator>Jay Chung</dc:creator>
  <link>https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/</link>
  <description><![CDATA[ 





<p>During my time in the industry, I have analyzed quite a few cell panel screens aiming to identify biomarkers of drug sensitivity. These screens are often carried out by CROs, and due to the costs associated with these experiments, the number of cell lines screened is often limited. Very often the average number of cell lines in each lineage is less than 10, which limits the power of biomarker detection. One way to mitigate this issue is to train a machine learning model based on the available cell lines and their corresponding DepMap omics data, and then use the trained model to predict sensitivity across thousands of DepMap cell lines. This expanded set of predicted sensitivities can then be used for biomarker detection with improved power.</p>
<p>In this post, I want to explore whether using autoencoders (AE) to compress high-dimensional omics data into deep features can improve drug sensitivity prediction accuracy. The concept can be summarized in the figure below:</p>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/concept1.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%"></p>
</figure>
</div>
</div>
</div>
<p>I demonstrate how to use AE to compress DepMap RNA expression data alone and multi-omics data (RNA expression + mutation + CRISPR dependency scores) into deep features. I then visualize and compare the embeddings from RNA alone vs.&nbsp;multi-omics data. In future work (part 2), I will compare the drug sensitivity prediction accuracy using deep features vs.&nbsp;full omics data.</p>
<p>These concepts can be summarized in Component 1 (AE embedding) and 2 (ML training) in the following figures:</p>
<p>Component 1: Autoencoder embedding</p>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/Autoencoder_workflow.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%"></p>
</figure>
</div>
</div>
</div>
<p>Component 2: ML training and prediction</p>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/ML_workflow.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%"></p>
</figure>
</div>
</div>
</div>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p><strong>Background</strong>: Cell panel drug screens are very useful during drug development in identifying sensitive biomarkers and understanding the mechanism-of-action; however, it can be costly and often result in only up to hundreds of cell lines available, limiting the power of biomarker detection. By leveraging machine learning (ML) approaches, one can expand sensitivity prediction to thousands of DepMap cell lines and thus improve the power of biomarker detection.</p>
<p><strong>Problem</strong>: DepMap OMICS data are high-dimensional, and such high-dimensional data may hinder ML prediction due to overfitting problems and noisy data.</p>
<p><strong>Proposal</strong>: By leveraging AutoEncoder (AE), a deep learning approach, high-dimensional OMICS data can be compressed into Deep Features (DF), thus overcoming the problem of overfitting and resulting in better drug sensitivity prediction accuracy. Unlike traditional dimensionality reduction methods (e.g., PCA), AE can capture non-linear relationships in the data, leading to more informative embeddings.</p>
</section>
<section id="setup-and-libraries" class="level2">
<h2 class="anchored" data-anchor-id="setup-and-libraries">Setup and Libraries</h2>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(data.table)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggpubr)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(h2o)</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(umap)</span>
<span id="cb1-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggrepel)</span>
<span id="cb1-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(microViz)</span></code></pre></div></div>
</div>
</section>
<section id="aim-1-rna-expression-autoencoder" class="level2">
<h2 class="anchored" data-anchor-id="aim-1-rna-expression-autoencoder">Aim 1: RNA Expression Autoencoder</h2>
<p>First, we use an autoencoder to embed cell lines based on RNA expression data alone.</p>
<section id="data-loading-and-preprocessing" class="level3">
<h3 class="anchored" data-anchor-id="data-loading-and-preprocessing">Data Loading and Preprocessing</h3>
<p>We filter for high-variance genes to reduce noise and dimensionality before feeding the data into the autoencoder.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># load data: RNA expression</span></span>
<span id="cb2-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Note: these RData files contain preprocessed data matrices with matched sample information</span></span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># DepMap data can be downloaded from https://depmap.org/portal/download/</span></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Here I am using the 24Q2 release</span></span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCLE_24Q2_GE_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># rows are cell lines, columns are genes, values are RNA-seq log2(TPM+1)</span></span>
<span id="cb2-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample_info_match_biomarkers.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sample info with lineage annotations</span></span>
<span id="cb2-7"></span>
<span id="cb2-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove low variance genes</span></span>
<span id="cb2-9">ge_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(ccle_ge_match_sam, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb2-10">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ccle_ge_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(ge_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(ge_var, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># select high variance genes (top 80th percentile)</span></span>
<span id="cb2-11"></span>
<span id="cb2-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove any cell lines (rows) that contains NAs</span></span>
<span id="cb2-13">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ge_dat_hv <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>()</span>
<span id="cb2-14"></span>
<span id="cb2-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># standardize the data</span></span>
<span id="cb2-16">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(ge_dat_hv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>()</span></code></pre></div></div>
</div>
<p>Let’s see what the RNA expression data looks like:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">ge_dat_hv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb3-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames_to_column</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CellLine"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb3-3">    gt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gt</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">rowname_col =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CellLine"</span>)</span></code></pre></div></div>
<div class="cell-output-display">
<div id="hdkwwohzar" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#hdkwwohzar table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#hdkwwohzar thead, #hdkwwohzar tbody, #hdkwwohzar tfoot, #hdkwwohzar tr, #hdkwwohzar td, #hdkwwohzar th {
  border-style: none;
}

#hdkwwohzar p {
  margin: 0;
  padding: 0;
}

#hdkwwohzar .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#hdkwwohzar .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#hdkwwohzar .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#hdkwwohzar .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#hdkwwohzar .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#hdkwwohzar .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#hdkwwohzar .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#hdkwwohzar .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#hdkwwohzar .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#hdkwwohzar .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#hdkwwohzar .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#hdkwwohzar .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#hdkwwohzar .gt_spanner_row {
  border-bottom-style: hidden;
}

#hdkwwohzar .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#hdkwwohzar .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#hdkwwohzar .gt_from_md > :first-child {
  margin-top: 0;
}

#hdkwwohzar .gt_from_md > :last-child {
  margin-bottom: 0;
}

#hdkwwohzar .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#hdkwwohzar .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#hdkwwohzar .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#hdkwwohzar .gt_row_group_first td {
  border-top-width: 2px;
}

#hdkwwohzar .gt_row_group_first th {
  border-top-width: 2px;
}

#hdkwwohzar .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#hdkwwohzar .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#hdkwwohzar .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#hdkwwohzar .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#hdkwwohzar .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#hdkwwohzar .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#hdkwwohzar .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#hdkwwohzar .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#hdkwwohzar .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#hdkwwohzar .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#hdkwwohzar .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#hdkwwohzar .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#hdkwwohzar .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#hdkwwohzar .gt_left {
  text-align: left;
}

#hdkwwohzar .gt_center {
  text-align: center;
}

#hdkwwohzar .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#hdkwwohzar .gt_font_normal {
  font-weight: normal;
}

#hdkwwohzar .gt_font_bold {
  font-weight: bold;
}

#hdkwwohzar .gt_font_italic {
  font-style: italic;
}

#hdkwwohzar .gt_super {
  font-size: 65%;
}

#hdkwwohzar .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#hdkwwohzar .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#hdkwwohzar .gt_indent_1 {
  text-indent: 5px;
}

#hdkwwohzar .gt_indent_2 {
  text-indent: 10px;
}

#hdkwwohzar .gt_indent_3 {
  text-indent: 15px;
}

#hdkwwohzar .gt_indent_4 {
  text-indent: 20px;
}

#hdkwwohzar .gt_indent_5 {
  text-indent: 25px;
}

#hdkwwohzar .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#hdkwwohzar div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<thead>
<tr class="gt_col_headings header">
<th id="a::stub" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col"></th>
<th id="TSPAN6" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">TSPAN6</th>
<th id="DPM1" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">DPM1</th>
<th id="FIRRM" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">FIRRM</th>
<th id="FGR" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">FGR</th>
<th id="CFH" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">CFH</th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<th id="stub_1_1" class="gt_row gt_left gt_stub" data-quarto-table-cell-role="th" scope="row">NIHOVCAR3</th>
<td class="gt_row gt_right" headers="stub_1_1 TSPAN6">1.0926276</td>
<td class="gt_row gt_right" headers="stub_1_1 DPM1">1.5011722</td>
<td class="gt_row gt_right" headers="stub_1_1 FIRRM">0.6858109</td>
<td class="gt_row gt_right" headers="stub_1_1 FGR">-0.3170060</td>
<td class="gt_row gt_right" headers="stub_1_1 CFH">-0.5737765</td>
</tr>
<tr class="even">
<th id="stub_1_2" class="gt_row gt_left gt_stub" data-quarto-table-cell-role="th" scope="row">HL60</th>
<td class="gt_row gt_right" headers="stub_1_2 TSPAN6">-1.9693314</td>
<td class="gt_row gt_right" headers="stub_1_2 DPM1">-1.2610758</td>
<td class="gt_row gt_right" headers="stub_1_2 FIRRM">-0.6848542</td>
<td class="gt_row gt_right" headers="stub_1_2 FGR">3.0178580</td>
<td class="gt_row gt_right" headers="stub_1_2 CFH">-0.8997009</td>
</tr>
<tr class="odd">
<th id="stub_1_3" class="gt_row gt_left gt_stub" data-quarto-table-cell-role="th" scope="row">CACO2</th>
<td class="gt_row gt_right" headers="stub_1_3 TSPAN6">1.1699782</td>
<td class="gt_row gt_right" headers="stub_1_3 DPM1">2.0373191</td>
<td class="gt_row gt_right" headers="stub_1_3 FIRRM">0.2826820</td>
<td class="gt_row gt_right" headers="stub_1_3 FGR">-0.3517010</td>
<td class="gt_row gt_right" headers="stub_1_3 CFH">-0.9468198</td>
</tr>
<tr class="even">
<th id="stub_1_4" class="gt_row gt_left gt_stub" data-quarto-table-cell-role="th" scope="row">HEL</th>
<td class="gt_row gt_right" headers="stub_1_4 TSPAN6">-0.7463001</td>
<td class="gt_row gt_right" headers="stub_1_4 DPM1">-1.6419864</td>
<td class="gt_row gt_right" headers="stub_1_4 FIRRM">0.3162823</td>
<td class="gt_row gt_right" headers="stub_1_4 FGR">0.3703802</td>
<td class="gt_row gt_right" headers="stub_1_4 CFH">1.2136680</td>
</tr>
<tr class="odd">
<th id="stub_1_5" class="gt_row gt_left gt_stub" data-quarto-table-cell-role="th" scope="row">HEL9217</th>
<td class="gt_row gt_right" headers="stub_1_5 TSPAN6">-0.5779999</td>
<td class="gt_row gt_right" headers="stub_1_5 DPM1">-0.9799468</td>
<td class="gt_row gt_right" headers="stub_1_5 FIRRM">2.0368574</td>
<td class="gt_row gt_right" headers="stub_1_5 FGR">-0.1876538</td>
<td class="gt_row gt_right" headers="stub_1_5 CFH">1.5663762</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p>Let’s see what the sample info looks like:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">sample_info[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, ] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> gt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gt</span>()</span></code></pre></div></div>
<div class="cell-output-display">
<div id="iibertzeff" style="padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
<style>#iibertzeff table {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#iibertzeff thead, #iibertzeff tbody, #iibertzeff tfoot, #iibertzeff tr, #iibertzeff td, #iibertzeff th {
  border-style: none;
}

#iibertzeff p {
  margin: 0;
  padding: 0;
}

#iibertzeff .gt_table {
  display: table;
  border-collapse: collapse;
  line-height: normal;
  margin-left: auto;
  margin-right: auto;
  color: #333333;
  font-size: 16px;
  font-weight: normal;
  font-style: normal;
  background-color: #FFFFFF;
  width: auto;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #A8A8A8;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #A8A8A8;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
}

#iibertzeff .gt_caption {
  padding-top: 4px;
  padding-bottom: 4px;
}

#iibertzeff .gt_title {
  color: #333333;
  font-size: 125%;
  font-weight: initial;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-color: #FFFFFF;
  border-bottom-width: 0;
}

#iibertzeff .gt_subtitle {
  color: #333333;
  font-size: 85%;
  font-weight: initial;
  padding-top: 3px;
  padding-bottom: 5px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-color: #FFFFFF;
  border-top-width: 0;
}

#iibertzeff .gt_heading {
  background-color: #FFFFFF;
  text-align: center;
  border-bottom-color: #FFFFFF;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#iibertzeff .gt_bottom_border {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#iibertzeff .gt_col_headings {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
}

#iibertzeff .gt_col_heading {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 6px;
  padding-left: 5px;
  padding-right: 5px;
  overflow-x: hidden;
}

#iibertzeff .gt_column_spanner_outer {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: normal;
  text-transform: inherit;
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 4px;
  padding-right: 4px;
}

#iibertzeff .gt_column_spanner_outer:first-child {
  padding-left: 0;
}

#iibertzeff .gt_column_spanner_outer:last-child {
  padding-right: 0;
}

#iibertzeff .gt_column_spanner {
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: bottom;
  padding-top: 5px;
  padding-bottom: 5px;
  overflow-x: hidden;
  display: inline-block;
  width: 100%;
}

#iibertzeff .gt_spanner_row {
  border-bottom-style: hidden;
}

#iibertzeff .gt_group_heading {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  text-align: left;
}

#iibertzeff .gt_empty_group_heading {
  padding: 0.5px;
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  vertical-align: middle;
}

#iibertzeff .gt_from_md > :first-child {
  margin-top: 0;
}

#iibertzeff .gt_from_md > :last-child {
  margin-bottom: 0;
}

#iibertzeff .gt_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  margin: 10px;
  border-top-style: solid;
  border-top-width: 1px;
  border-top-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 1px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 1px;
  border-right-color: #D3D3D3;
  vertical-align: middle;
  overflow-x: hidden;
}

#iibertzeff .gt_stub {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
}

#iibertzeff .gt_stub_row_group {
  color: #333333;
  background-color: #FFFFFF;
  font-size: 100%;
  font-weight: initial;
  text-transform: inherit;
  border-right-style: solid;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
  padding-left: 5px;
  padding-right: 5px;
  vertical-align: top;
}

#iibertzeff .gt_row_group_first td {
  border-top-width: 2px;
}

#iibertzeff .gt_row_group_first th {
  border-top-width: 2px;
}

#iibertzeff .gt_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#iibertzeff .gt_first_summary_row {
  border-top-style: solid;
  border-top-color: #D3D3D3;
}

#iibertzeff .gt_first_summary_row.thick {
  border-top-width: 2px;
}

#iibertzeff .gt_last_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#iibertzeff .gt_grand_summary_row {
  color: #333333;
  background-color: #FFFFFF;
  text-transform: inherit;
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
}

#iibertzeff .gt_first_grand_summary_row {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-top-style: double;
  border-top-width: 6px;
  border-top-color: #D3D3D3;
}

#iibertzeff .gt_last_grand_summary_row_top {
  padding-top: 8px;
  padding-bottom: 8px;
  padding-left: 5px;
  padding-right: 5px;
  border-bottom-style: double;
  border-bottom-width: 6px;
  border-bottom-color: #D3D3D3;
}

#iibertzeff .gt_striped {
  background-color: rgba(128, 128, 128, 0.05);
}

#iibertzeff .gt_table_body {
  border-top-style: solid;
  border-top-width: 2px;
  border-top-color: #D3D3D3;
  border-bottom-style: solid;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
}

#iibertzeff .gt_footnotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#iibertzeff .gt_footnote {
  margin: 0px;
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#iibertzeff .gt_sourcenotes {
  color: #333333;
  background-color: #FFFFFF;
  border-bottom-style: none;
  border-bottom-width: 2px;
  border-bottom-color: #D3D3D3;
  border-left-style: none;
  border-left-width: 2px;
  border-left-color: #D3D3D3;
  border-right-style: none;
  border-right-width: 2px;
  border-right-color: #D3D3D3;
}

#iibertzeff .gt_sourcenote {
  font-size: 90%;
  padding-top: 4px;
  padding-bottom: 4px;
  padding-left: 5px;
  padding-right: 5px;
}

#iibertzeff .gt_left {
  text-align: left;
}

#iibertzeff .gt_center {
  text-align: center;
}

#iibertzeff .gt_right {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

#iibertzeff .gt_font_normal {
  font-weight: normal;
}

#iibertzeff .gt_font_bold {
  font-weight: bold;
}

#iibertzeff .gt_font_italic {
  font-style: italic;
}

#iibertzeff .gt_super {
  font-size: 65%;
}

#iibertzeff .gt_footnote_marks {
  font-size: 75%;
  vertical-align: 0.4em;
  position: initial;
}

#iibertzeff .gt_asterisk {
  font-size: 100%;
  vertical-align: 0;
}

#iibertzeff .gt_indent_1 {
  text-indent: 5px;
}

#iibertzeff .gt_indent_2 {
  text-indent: 10px;
}

#iibertzeff .gt_indent_3 {
  text-indent: 15px;
}

#iibertzeff .gt_indent_4 {
  text-indent: 20px;
}

#iibertzeff .gt_indent_5 {
  text-indent: 25px;
}

#iibertzeff .katex-display {
  display: inline-flex !important;
  margin-bottom: 0.75em !important;
}

#iibertzeff div.Reactable > div.rt-table > div.rt-thead > div.rt-tr.rt-tr-group-header > div.rt-th-group:after {
  height: 0px !important;
}
</style>

<table class="gt_table caption-top table table-sm table-striped small" data-quarto-bootstrap="false">
<thead>
<tr class="gt_col_headings header">
<th id="ModelID" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">ModelID</th>
<th id="StrippedCellLineName" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">StrippedCellLineName</th>
<th id="CCLEName" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">CCLEName</th>
<th id="OncotreeLineage" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">OncotreeLineage</th>
<th id="OncotreeSubtype" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">OncotreeSubtype</th>
<th id="OncotreePrimaryDisease" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">OncotreePrimaryDisease</th>
<th id="LegacySubSubtype" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">LegacySubSubtype</th>
<th id="LegacyMolecularSubtype" class="gt_col_heading gt_columns_bottom_border gt_right" data-quarto-table-cell-role="th" scope="col">LegacyMolecularSubtype</th>
<th id="PatientMolecularSubtype" class="gt_col_heading gt_columns_bottom_border gt_left" data-quarto-table-cell-role="th" scope="col">PatientMolecularSubtype</th>
</tr>
</thead>
<tbody class="gt_table_body">
<tr class="odd">
<td class="gt_row gt_left" headers="ModelID">ACH-000001</td>
<td class="gt_row gt_left" headers="StrippedCellLineName">NIHOVCAR3</td>
<td class="gt_row gt_left" headers="CCLEName">NIHOVCAR3_OVARY</td>
<td class="gt_row gt_left" headers="OncotreeLineage">Ovary/Fallopian Tube</td>
<td class="gt_row gt_left" headers="OncotreeSubtype">High-Grade Serous Ovarian Cancer</td>
<td class="gt_row gt_left" headers="OncotreePrimaryDisease">Ovarian Epithelial Tumor</td>
<td class="gt_row gt_left" headers="LegacySubSubtype">high_grade_serous</td>
<td class="gt_row gt_right" headers="LegacyMolecularSubtype"></td>
<td class="gt_row gt_left" headers="PatientMolecularSubtype"></td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="ModelID">ACH-000002</td>
<td class="gt_row gt_left" headers="StrippedCellLineName">HL60</td>
<td class="gt_row gt_left" headers="CCLEName">HL60_HAEMATOPOIETIC_AND_LYMPHOID_TISSUE</td>
<td class="gt_row gt_left" headers="OncotreeLineage">Myeloid</td>
<td class="gt_row gt_left" headers="OncotreeSubtype">Acute Myeloid Leukemia</td>
<td class="gt_row gt_left" headers="OncotreePrimaryDisease">Acute Myeloid Leukemia</td>
<td class="gt_row gt_left" headers="LegacySubSubtype">M3</td>
<td class="gt_row gt_right" headers="LegacyMolecularSubtype"></td>
<td class="gt_row gt_left" headers="PatientMolecularSubtype">TP53(del), CDKN2A and NRAS mutations [PubMed=288488], No PML-RARA fusion</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="ModelID">ACH-000003</td>
<td class="gt_row gt_left" headers="StrippedCellLineName">CACO2</td>
<td class="gt_row gt_left" headers="CCLEName">CACO2_LARGE_INTESTINE</td>
<td class="gt_row gt_left" headers="OncotreeLineage">Bowel</td>
<td class="gt_row gt_left" headers="OncotreeSubtype">Colon Adenocarcinoma</td>
<td class="gt_row gt_left" headers="OncotreePrimaryDisease">Colorectal Adenocarcinoma</td>
<td class="gt_row gt_left" headers="LegacySubSubtype"></td>
<td class="gt_row gt_right" headers="LegacyMolecularSubtype"></td>
<td class="gt_row gt_left" headers="PatientMolecularSubtype"></td>
</tr>
<tr class="even">
<td class="gt_row gt_left" headers="ModelID">ACH-000004</td>
<td class="gt_row gt_left" headers="StrippedCellLineName">HEL</td>
<td class="gt_row gt_left" headers="CCLEName">HEL_HAEMATOPOIETIC_AND_LYMPHOID_TISSUE</td>
<td class="gt_row gt_left" headers="OncotreeLineage">Myeloid</td>
<td class="gt_row gt_left" headers="OncotreeSubtype">Acute Myeloid Leukemia</td>
<td class="gt_row gt_left" headers="OncotreePrimaryDisease">Acute Myeloid Leukemia</td>
<td class="gt_row gt_left" headers="LegacySubSubtype">M6</td>
<td class="gt_row gt_right" headers="LegacyMolecularSubtype"></td>
<td class="gt_row gt_left" headers="PatientMolecularSubtype">JAK2 and TP53 mutations,</td>
</tr>
<tr class="odd">
<td class="gt_row gt_left" headers="ModelID">ACH-000005</td>
<td class="gt_row gt_left" headers="StrippedCellLineName">HEL9217</td>
<td class="gt_row gt_left" headers="CCLEName">HEL9217_HAEMATOPOIETIC_AND_LYMPHOID_TISSUE</td>
<td class="gt_row gt_left" headers="OncotreeLineage">Myeloid</td>
<td class="gt_row gt_left" headers="OncotreeSubtype">Acute Myeloid Leukemia</td>
<td class="gt_row gt_left" headers="OncotreePrimaryDisease">Acute Myeloid Leukemia</td>
<td class="gt_row gt_left" headers="LegacySubSubtype">M6</td>
<td class="gt_row gt_right" headers="LegacyMolecularSubtype"></td>
<td class="gt_row gt_left" headers="PatientMolecularSubtype">JAK2 and TP53 mutations</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</section>
<section id="model-training" class="level3">
<h3 class="anchored" data-anchor-id="model-training">Model Training</h3>
<p>We perform a hyperparameter grid search to find the optimal autoencoder architecture.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hyperparameter search grid to find best AE model</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.init</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nthreads =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max_mem_size =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"60G"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># initialize H2O with 20 threads and 60GB memory</span></span>
<span id="cb5-3">rna_h2o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.h2o</span>(ge_dat_hv)</span>
<span id="cb5-4"></span>
<span id="cb5-5">hyper_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb5-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>),</span>
<span id="cb5-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>),</span>
<span id="cb5-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>),</span>
<span id="cb5-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>),</span>
<span id="cb5-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2000</span>),</span>
<span id="cb5-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)</span>
<span id="cb5-12">))</span>
<span id="cb5-13"></span>
<span id="cb5-14">ae_grid <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.grid</span>(</span>
<span id="cb5-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">algorithm =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"deeplearning"</span>,</span>
<span id="cb5-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(rna_h2o),</span>
<span id="cb5-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">training_frame =</span> rna_h2o,</span>
<span id="cb5-18">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">grid_id =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RNA_ae1"</span>,</span>
<span id="cb5-19">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">autoencoder =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb5-20">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TanhWithDropout"</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># I've also tried "RectifierWithDropout" but seemed to encounter exploding gradients</span></span>
<span id="cb5-21">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hyper_params =</span> hyper_grid,</span>
<span id="cb5-22">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nesterov_accelerated_gradient =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb5-23">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">epochs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>,</span>
<span id="cb5-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stopping_rounds =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb5-25">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span></span>
<span id="cb5-26">)</span>
<span id="cb5-27"></span>
<span id="cb5-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># get grid results, sorted by reconstruction error (MSE)</span></span>
<span id="cb5-29"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.getGrid</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RNA_ae1"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sort_by =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mse"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">decreasing =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb5-30"></span>
<span id="cb5-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># AE learning with best parameters (selected from grid search)</span></span>
<span id="cb5-32">ae_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.deeplearning</span>(</span>
<span id="cb5-33">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(rna_h2o),</span>
<span id="cb5-34">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">training_frame =</span> rna_h2o,</span>
<span id="cb5-35">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">autoencoder =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb5-36">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>),</span>
<span id="cb5-37">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_dropout_ratios =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>),</span>
<span id="cb5-38">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TanhWithDropout"</span>,</span>
<span id="cb5-39">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">epochs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>,</span>
<span id="cb5-40">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stopping_rounds =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb5-41">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nesterov_accelerated_gradient =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb5-42">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span></span>
<span id="cb5-43">)</span>
<span id="cb5-44"></span>
<span id="cb5-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># extract the compressed features</span></span>
<span id="cb5-46">compressed_features <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.deepfeatures</span>(ae_model, rna_h2o, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">layer =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># get deep features from the middle layer</span></span>
<span id="cb5-47"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(compressed_features) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_hv)</span>
<span id="cb5-48"></span>
<span id="cb5-49"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Save results</span></span>
<span id="cb5-50"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fwrite</span>(compressed_features, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">file =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"./results/output_files/RNA_AE_compressed_features.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb5-51"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.shutdown</span>()</span></code></pre></div></div>
</div>
<p>I want to point out that the choice of architecture (number of layers and nodes) and hyperparameters (dropout rates, activation functions) can significantly impact the quality of the learned embeddings. For example, using batch normalization layers or experimenting with different activation functions (e.g., ReLU, Leaky ReLU) might yield better results depending on the data characteristics. Readers interested in this topic should explore more sophisticated MLP training platform like Keras and TensorFlow.</p>
</section>
</section>
<section id="aim-2-multi-omics-autoencoder" class="level2">
<h2 class="anchored" data-anchor-id="aim-2-multi-omics-autoencoder">Aim 2: Multi-omics Autoencoder</h2>
<p>Next, we integrate RNA expression, mutation data (damaging, hotspot), and CRISPR dependency scores.</p>
<section id="data-integration" class="level3">
<h3 class="anchored" data-anchor-id="data-integration">Data Integration</h3>
<p>We process each data type separately (filtering, standardizing) and then combine them into a single multi-omics dataset.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># load data (all rows are cell lines and columns are genes)</span></span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCLE_24Q2_GE_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># RNA expression</span></span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DepMap_24Q2_Chronos_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CRISPR dependency scores (Chronos)</span></span>
<span id="cb6-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCLE_24Q2_DAMMUT_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Damaging mutations (0: non-mutated, 1: mutated heterozygous, 2: mutated homozygous)</span></span>
<span id="cb6-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCLE_24Q2_HOTMUT_match_sample_info.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hotspot mutations (0: non-mutated, 1: mutated heterozygous, 2: mutated homozygous)</span></span>
<span id="cb6-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample_info_match_biomarkers.RData"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sample info</span></span>
<span id="cb6-7"></span>
<span id="cb6-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># RNA processing</span></span>
<span id="cb6-9">ge_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(ccle_ge_match_sam, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb6-10">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ccle_ge_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(ge_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(ge_var, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))]</span>
<span id="cb6-11">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(ge_dat_hv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>()</span>
<span id="cb6-12"></span>
<span id="cb6-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Mutation processing</span></span>
<span id="cb6-14">dam_mut_dat_filt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> dammut_dat_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(dammut_dat_match_sam), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># filter genes with &gt;20 mutated events across cell lines</span></span>
<span id="cb6-15">hot_mut_dat_filt <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> hotmut_dat_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(hotmut_dat_match_sam), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(x) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)]</span>
<span id="cb6-16"></span>
<span id="cb6-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CRISPR processing</span></span>
<span id="cb6-18">crispr_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(chronos_dat_match_sam, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb6-19">crispr_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chronos_dat_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(crispr_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(crispr_var, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))]</span>
<span id="cb6-20">crispr_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(crispr_dat_hv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>()</span>
<span id="cb6-21"></span>
<span id="cb6-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Combine data</span></span>
<span id="cb6-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(ge_dat_hv) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(ge_dat_hv), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_RNA"</span>)</span>
<span id="cb6-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(dam_mut_dat_filt) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(dam_mut_dat_filt), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_DAMMUT"</span>)</span>
<span id="cb6-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(hot_mut_dat_filt) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(hot_mut_dat_filt), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_HOTMUT"</span>)</span>
<span id="cb6-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(crispr_dat_hv) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(crispr_dat_hv), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_CRISPR"</span>)</span>
<span id="cb6-27"></span>
<span id="cb6-28">multi_omics_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cbind</span>(ge_dat_hv, dam_mut_dat_filt, hot_mut_dat_filt, crispr_dat_hv)</span>
<span id="cb6-29"></span>
<span id="cb6-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove rows with too many NAs</span></span>
<span id="cb6-31">multi_omics_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> multi_omics_dat[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(multi_omics_dat)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ncol</span>(multi_omics_dat) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.8</span>, ] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># keep rows with &lt;=80% NAs</span></span></code></pre></div></div>
</div>
</section>
<section id="multi-omics-model-training" class="level3">
<h3 class="anchored" data-anchor-id="multi-omics-model-training">Multi-omics Model Training</h3>
<p>We train another autoencoder on this combined dataset.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.init</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nthreads =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max_mem_size =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"60G"</span>)</span>
<span id="cb7-2">rna_h2o <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.h2o</span>(multi_omics_dat)</span>
<span id="cb7-3"></span>
<span id="cb7-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (Grid search code omitted for brevity, similar to Aim 1)</span></span>
<span id="cb7-5"></span>
<span id="cb7-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># AE learning with best parameters</span></span>
<span id="cb7-7">ae_model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.deeplearning</span>(</span>
<span id="cb7-8">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colnames</span>(rna_h2o),</span>
<span id="cb7-9">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">training_frame =</span> rna_h2o,</span>
<span id="cb7-10">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">autoencoder =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb7-11">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>),</span>
<span id="cb7-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hidden_dropout_ratios =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>),</span>
<span id="cb7-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TanhWithDropout"</span>,</span>
<span id="cb7-14">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">epochs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>,</span>
<span id="cb7-15">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stopping_rounds =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,</span>
<span id="cb7-16">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nesterov_accelerated_gradient =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb7-17">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">seed =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span></span>
<span id="cb7-18">)</span>
<span id="cb7-19"></span>
<span id="cb7-20">compressed_features <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.deepfeatures</span>(ae_model, rna_h2o, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">layer =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># here we take 300-dim deep features</span></span>
<span id="cb7-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(compressed_features) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(multi_omics_dat)</span>
<span id="cb7-22"></span>
<span id="cb7-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fwrite</span>(compressed_features, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">file =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"./results/output_files/MultiOmics_AE_compressed_features.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb7-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h2o.shutdown</span>()</span></code></pre></div></div>
</div>
</section>
</section>
<section id="aim-3-visualization-and-comparison" class="level2">
<h2 class="anchored" data-anchor-id="aim-3-visualization-and-comparison">Aim 3: Visualization and Comparison</h2>
<p>Finally, we visualize the embeddings using UMAP and compare the clustering with known lineages.<br>
Here we are testing if the deep features preserve and/or enrich biological signals present in the original data.</p>
<section id="full-rna-umap-without-autoencoder" class="level3">
<h3 class="anchored" data-anchor-id="full-rna-umap-without-autoencoder">Full RNA UMAP (without Autoencoder)</h3>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># load data</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CCLE_24Q2_GE_match_sample_info.RData"</span>)</span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample_info_match_biomarkers.RData"</span>)</span>
<span id="cb8-4"></span>
<span id="cb8-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># remove low variance genes</span></span>
<span id="cb8-6">ge_var <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apply</span>(ccle_ge_match_sam, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, var, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">na.rm =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculate variance for each gene</span></span>
<span id="cb8-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(ge_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(ge_var, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how many genes passed variance cutoff: 15322</span></span>
<span id="cb8-8">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ccle_ge_match_sam[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">which</span>(ge_var <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(ge_var, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>))] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># select high variance genes</span></span>
<span id="cb8-9"></span>
<span id="cb8-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># standardize the data and match with sample info</span></span>
<span id="cb8-11">ge_dat_hv <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(ge_dat_hv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb8-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>()</span>
<span id="cb8-14">sample_info <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_hv), sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName), ]</span>
<span id="cb8-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(ge_dat_hv) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName)</span>
<span id="cb8-16"></span>
<span id="cb8-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run UMAP</span></span>
<span id="cb8-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(umap)</span>
<span id="cb8-19">umap_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">umap</span>(</span>
<span id="cb8-20">    ge_dat_hv,</span>
<span id="cb8-21">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_components =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb8-22">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_neighbors =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb8-23">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">random_state =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span>,</span>
<span id="cb8-24">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">verbose =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb8-25">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_threads =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span></span>
<span id="cb8-26">)</span>
<span id="cb8-27">umap_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>layout)</span>
<span id="cb8-28">umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>cell_line <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName</span>
<span id="cb8-29">umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage</span>
<span id="cb8-30">umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>subtype <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeSubtype</span>
<span id="cb8-31"></span>
<span id="cb8-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot UMAP embedding colored by lineage</span></span>
<span id="cb8-33"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(umap_dat, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(V1, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>V2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> lineage)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-34">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-35">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct_palette</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pal =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brewerPlus"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-36">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct_palette</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pal =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brewerPlus"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-37">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-38">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># add lineage labels at the center of each lineage cluster</span></span>
<span id="cb8-39">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_label_repel</span>(</span>
<span id="cb8-40">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> umap_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-41">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(lineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-42">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarize</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">V1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(V1), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">V2 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(V2)),</span>
<span id="cb8-43">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> lineage),</span>
<span id="cb8-44">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb8-45">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># color = "black",</span></span>
<span id="cb8-46">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>,</span>
<span id="cb8-47">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>,</span>
<span id="cb8-48">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span id="cb8-49">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max.overlaps =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb8-50">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-51">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb8-52">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>,</span>
<span id="cb8-53">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.title =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>),</span>
<span id="cb8-54">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.text =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_text</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb8-55">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb8-56">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(</span>
<span id="cb8-57">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UMAP1"</span>,</span>
<span id="cb8-58">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UMAP2"</span>,</span>
<span id="cb8-59">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UMAP of full CCLE RNA expression (no AE)"</span></span>
<span id="cb8-60">    )</span></code></pre></div></div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/CCLE_RNA_no_AE_UMAP_lineage.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%"></p>
</figure>
</div>
</div>
</div>
<p>As you can see, the full RNA data UMAP already shows some clustering by lineage, indicating that the transcriptomic profiles capture biological differences among cell lines.</p>
</section>
<section id="rna-deep-features-umap" class="level3">
<h3 class="anchored" data-anchor-id="rna-deep-features-umap">RNA deep features UMAP</h3>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load compressed features</span></span>
<span id="cb9-2">RNA_AE_compressed_features <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fread</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"./results/output_files/RNA_AE_compressed_features.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data.table =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb9-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">column_to_rownames</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"V1"</span>)</span>
<span id="cb9-4">RNA_AE_compressed_features <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> RNA_AE_compressed_features[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(RNA_AE_compressed_features) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, ]</span>
<span id="cb9-5"></span>
<span id="cb9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Match with sample info</span></span>
<span id="cb9-7">sample_info <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(RNA_AE_compressed_features), sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName), ]</span>
<span id="cb9-8"></span>
<span id="cb9-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run UMAP</span></span>
<span id="cb9-10">umap_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">umap</span>(RNA_AE_compressed_features, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_components =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_neighbors =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">random_state =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span>)</span>
<span id="cb9-11">umap_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>layout)</span>
<span id="cb9-12">umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage</span>
<span id="cb9-13"></span>
<span id="cb9-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot</span></span>
<span id="cb9-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(umap_dat, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(V1, V2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> lineage)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-17">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct_palette</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pal =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brewerPlus"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-18">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct_palette</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pal =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brewerPlus"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_label_repel</span>(</span>
<span id="cb9-21">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> umap_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(lineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarize</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">V1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(V1), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">V2 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(V2)),</span>
<span id="cb9-22">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> lineage),</span>
<span id="cb9-23">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max.overlaps =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb9-24">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-25">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb9-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UMAP of AE compressed CCLE RNA expression"</span>)</span></code></pre></div></div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/CCLE_RNA_AE_UMAP_lineage.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%"></p>
</figure>
</div>
</div>
</div>
<p>The RNA deep features UMAP also shows clustering by lineage, similar to the full RNA data, indicating that the autoencoder effectively preserves the biological signal in a lower-dimensional space.</p>
</section>
<section id="multi-omics-deep-features-umap" class="level3">
<h3 class="anchored" data-anchor-id="multi-omics-deep-features-umap">Multi-omics deep features UMAP</h3>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Load compressed features</span></span>
<span id="cb10-2">MultiOmics_AE_compressed_features <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fread</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"./results/output_files/MultiOmics_AE_compressed_features.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data.table =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span id="cb10-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">column_to_rownames</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">var =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"V1"</span>)</span>
<span id="cb10-4">MultiOmics_AE_compressed_features <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> MultiOmics_AE_compressed_features[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowSums</span>(MultiOmics_AE_compressed_features) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, ]</span>
<span id="cb10-5"></span>
<span id="cb10-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Match with sample info</span></span>
<span id="cb10-7">sample_info <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(MultiOmics_AE_compressed_features), sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>StrippedCellLineName), ]</span>
<span id="cb10-8"></span>
<span id="cb10-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run UMAP</span></span>
<span id="cb10-10">umap_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">umap</span>(MultiOmics_AE_compressed_features, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_components =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n_neighbors =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">random_state =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">524</span>)</span>
<span id="cb10-11">umap_dat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>layout)</span>
<span id="cb10-12">umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> sample_info<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>OncotreeLineage</span>
<span id="cb10-13"></span>
<span id="cb10-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot</span></span>
<span id="cb10-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(umap_dat, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>V1, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>V2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> lineage)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-17">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct_palette</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pal =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brewerPlus"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-18">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_color_manual</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">values =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">distinct_palette</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(umap_dat<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lineage)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pal =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brewerPlus"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">add =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lightgrey"</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_classic</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-20">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_label_repel</span>(</span>
<span id="cb10-21">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> umap_dat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(lineage) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summarize</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">V1 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(V1), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">V2 =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">median</span>(V2)),</span>
<span id="cb10-22">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> lineage, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> lineage),</span>
<span id="cb10-23">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha =</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show.legend =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max.overlaps =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb10-24">    ) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-25">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legend.position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb10-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UMAP of AE compressed CCLE Multi-omics"</span>)</span></code></pre></div></div>
</div>
<div class="cell" data-layout-align="center">
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/CCLE_MultiOmics_AE_UMAP_lineage.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%"></p>
</figure>
</div>
</div>
</div>
<p>The AE embedded multi-OMICS appears to increase the granularity of cell line clustering by lineage.</p>
</section>
</section>
<section id="conclusions" class="level2">
<h2 class="anchored" data-anchor-id="conclusions">Conclusions</h2>
<p>It appears that both RNA alone and multi-omics autoencoder embeddings preserve biological signals related to cell lineage. The multi-omics embedding seems to provide even richer structure, potentially capturing more nuanced cell states. But whether these embeddings lead to improved drug sensitivity prediction accuracy remains to be tested.</p>
<p>In the next post, I will compare ML prediction accuracy on independent test data using deep features vs.&nbsp;full omics data.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li>DepMap Portal: <a href="https://depmap.org/portal/" class="uri">https://depmap.org/portal/</a></li>
<li>H2O Documentation: <a href="https://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/deep-learning.html" class="uri">https://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/deep-learning.html</a></li>
<li>Hands-On Machine Learning with R: <a href="https://bradleyboehmke.github.io/HOML/" class="uri">https://bradleyboehmke.github.io/HOML/</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>DepMap</category>
  <category>Autoencoder</category>
  <category>Multi-omics</category>
  <category>Machine Learning</category>
  <guid>https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/</guid>
  <pubDate>Mon, 01 Dec 2025 08:00:00 GMT</pubDate>
  <media:content url="https://tiny-lab-bioml.netlify.app/posts/2025-11-29_depmap-multiomics-autoencoder/CCLE_MultiOmics_AE_UMAP_lineage.png" medium="image" type="image/png" height="115" width="144"/>
</item>
</channel>
</rss>
