Skip to content
Snippets Groups Projects
class1_allele_specific_models.ipynb 82.1 KiB
Newer Older
Tim O'Donnell's avatar
Tim O'Donnell committed
{
 "cells": [
  {
   "cell_type": "code",
Tim O'Donnell's avatar
Tim O'Donnell committed
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using Theano backend.\n",
      "/Users/tim/miniconda3/envs/py3k/lib/python3.5/site-packages/matplotlib/__init__.py:872: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.\n",
      "  warnings.warn(self.msg_depr % (key, alt_key))\n",
      "/Users/tim/miniconda3/envs/py3k/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.\n",
      "  \"This module will be removed in 0.20.\", DeprecationWarning)\n"
     ]
    }
   ],
Tim O'Donnell's avatar
Tim O'Donnell committed
   "source": [
    "import mhcflurry\n",
    "import numpy\n",
    "import seaborn\n",
    "import logging\n",
    "from matplotlib import pyplot\n",
    "\n",
    "% matplotlib inline\n",
    "logging.basicConfig(level=\"DEBUG\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making predictions\n",
    "Note: if you haven't already, run `mhcflurry-downloads fetch` in a shell to download the trained models."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simplest way to run predictions: `mhcflurry.predict()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function predict in module mhcflurry.predict:\n",
      "\n",
      "predict(alleles, peptides, predictor=None)\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      "    Make predictions across all combinations of the specified alleles and\n",
      "    peptides.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    alleles : list of str\n",
      "        Names of alleles to make predictions for.\n",
      "    \n",
      "    peptides : list of str\n",
      "        Peptide amino acid sequences.\n",
      "    \n",
      "    predictor : Predictor to use. Defaults to downloaded Class1SingleModelMultiAllelePredictor.\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      "    \n",
      "    Returns DataFrame with columns \"Allele\", \"Peptide\", and \"Prediction\"\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(mhcflurry.predict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Allele</th>\n",
       "      <th>Peptide</th>\n",
       "      <th>Prediction</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>HLA-A0201</td>\n",
       "      <td>SIINFEKL</td>\n",
       "      <td>10672.347656</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>HLA-A0201</td>\n",
       "      <td>SIINFEQL</td>\n",
       "      <td>7828.974121</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      Allele   Peptide    Prediction\n",
       "0  HLA-A0201  SIINFEKL  10672.347656\n",
       "1  HLA-A0201  SIINFEQL   7828.974121"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mhcflurry.predict(alleles=[\"HLA-A0201\"], peptides=[\"SIINFEKL\", \"SIINFEQL\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Instantiating a model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 10672.34765625,  30577.02539062,  10565.78222656], dtype=float32)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = mhcflurry.class1_allele_specific.class1_single_model_multi_allele_predictor.from_allele_name(\"HLA-A0201\")\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "model.predict([\"SIINFEKL\", \"SIQNPEKP\", \"SYNFPEPI\"])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Instantiating a model from a custom set of models on disk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/Users/tim/Library/Application Support/mhcflurry/4/0.1.0/models_class1_allele_specific_single/'"
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "models_dir = mhcflurry.downloads.get_path(\"models_class1_allele_specific_single\")\n",
    "models_dir"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 10672.34765625,  30577.02539062,  10565.78222656], dtype=float32)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Make a Loader first\n",
    "loader = mhcflurry.Class1SingleModelMultiAllelePredictor.load_from_download_directory(\n",
    "    models_dir)\n",
    "model = loader.predictor_for_allele(\"HLA-A0201\")\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "model.predict([\"SIINFEKL\", \"SIQNPEKP\", \"SYNFPEPI\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Loading a `Dataset`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AffinityMeasurementDataset(n=192550, alleles=['ELA-A1', 'Gogo-B0101', 'H-2-DB', 'H-2-DD', 'H-2-KB', 'H-2-KBM8', 'H-2-KD', 'H-2-KK', 'H-2-LD', 'H-2-LQ', 'HLA-A0101', 'HLA-A0201', 'HLA-A0202', 'HLA-A0203', 'HLA-A0204', 'HLA-A0205', 'HLA-A0206', 'HLA-A0207', 'HLA-A0210', 'HLA-A0211', 'HLA-A0212', 'HLA-A0216', 'HLA-A0217', 'HLA-A0219', 'HLA-A0250', 'HLA-A0301', 'HLA-A0302', 'HLA-A0319', 'HLA-A1', 'HLA-A11', 'HLA-A1101', 'HLA-A1102', 'HLA-A2', 'HLA-A2301', 'HLA-A24', 'HLA-A2402', 'HLA-A2403', 'HLA-A2501', 'HLA-A26', 'HLA-A2601', 'HLA-A2602', 'HLA-A2603', 'HLA-A2902', 'HLA-A3', 'HLA-A3/11', 'HLA-A3001', 'HLA-A3002', 'HLA-A3101', 'HLA-A3201', 'HLA-A3207', 'HLA-A3215', 'HLA-A3301', 'HLA-A6601', 'HLA-A6801', 'HLA-A6802', 'HLA-A6823', 'HLA-A6901', 'HLA-A7401', 'HLA-A8001', 'HLA-B0702', 'HLA-B0801', 'HLA-B0802', 'HLA-B0803', 'HLA-B1401', 'HLA-B1402', 'HLA-B1501', 'HLA-B1502', 'HLA-B1503', 'HLA-B1509', 'HLA-B1517', 'HLA-B1542', 'HLA-B1801', 'HLA-B27', 'HLA-B2701', 'HLA-B2702', 'HLA-B2703', 'HLA-B2704', 'HLA-B2705', 'HLA-B2706', 'HLA-B2710', 'HLA-B2720', 'HLA-B3501', 'HLA-B3503', 'HLA-B3508', 'HLA-B3701', 'HLA-B3801', 'HLA-B39', 'HLA-B3901', 'HLA-B40', 'HLA-B4001', 'HLA-B4002', 'HLA-B4013', 'HLA-B4201', 'HLA-B4202', 'HLA-B44', 'HLA-B4402', 'HLA-B4403', 'HLA-B4501', 'HLA-B4506', 'HLA-B4601', 'HLA-B4801', 'HLA-B51', 'HLA-B5101', 'HLA-B5201', 'HLA-B5301', 'HLA-B5401', 'HLA-B5701', 'HLA-B5702', 'HLA-B5703', 'HLA-B58', 'HLA-B5801', 'HLA-B5802', 'HLA-B60', 'HLA-B62', 'HLA-B7', 'HLA-B7301', 'HLA-B8', 'HLA-B8101', 'HLA-B8301', 'HLA-BOLA102101', 'HLA-BOLA200801', 'HLA-BOLA201201', 'HLA-BOLA402401', 'HLA-BOLA601301', 'HLA-BOLA601302', 'HLA-BOLAHD6', 'HLA-C0303', 'HLA-C0401', 'HLA-C0501', 'HLA-C0602', 'HLA-C0702', 'HLA-C0802', 'HLA-C1', 'HLA-C1203', 'HLA-C1402', 'HLA-C1502', 'HLA-C4', 'HLA-E0101', 'HLA-E0103', 'HLA-EQCA100101', 'HLA-RT1A', 'HLA-RT1BL', 'HLA-SLA10401', 'Mamu-A01', 'Mamu-A02', 'Mamu-A07', 'Mamu-A100101', 'Mamu-A100201', 'Mamu-A101101', 'Mamu-A11', 'Mamu-A20102', 'Mamu-A2201', 'Mamu-A2601', 'Mamu-A70103', 'Mamu-B01', 'Mamu-B01704', 'Mamu-B03', 'Mamu-B04', 'Mamu-B06502', 'Mamu-B08', 'Mamu-B1001', 'Mamu-B17', 'Mamu-B3901', 'Mamu-B52', 'Mamu-B6601', 'Mamu-B8301', 'Mamu-B8701', 'Patr-A0101', 'Patr-A0301', 'Patr-A0401', 'Patr-A0602', 'Patr-A0701', 'Patr-A0901', 'Patr-B0101', 'Patr-B0901', 'Patr-B1301', 'Patr-B1701', 'Patr-B2401'])"
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "full_training_data = mhcflurry.AffinityMeasurementDataset.from_csv(\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "    mhcflurry.downloads.get_path(\"data_combined_iedb_kim2014\", \"combined_human_class1_dataset.csv\"))\n",
    "full_training_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(179692, 137654, 27680)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kim2014_full = mhcflurry.AffinityMeasurementDataset.from_csv(\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "    mhcflurry.downloads.get_path(\"data_kim2014\", \"bdata.20130222.mhci.public.1.txt\"))\n",
    "\n",
    "kim2014_train = mhcflurry.AffinityMeasurementDataset.from_csv(\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "    mhcflurry.downloads.get_path(\"data_kim2014\", \"bdata.2009.mhci.public.1.txt\"))\n",
    "kim2014_test = mhcflurry.AffinityMeasurementDataset.from_csv(\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "    mhcflurry.downloads.get_path(\"data_kim2014\", \"bdata.2013.mhci.public.blind.1.txt\"))\n",
    "\n",
    "len(kim2014_full), len(kim2014_train), len(kim2014_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predicting affinities from a `Dataset`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  3514.14550781,  12429.5390625 ,   4227.02197266, ...,\n",
       "         5949.32763672,  17837.0859375 ,   6724.96728516], dtype=float32)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = loader.predictor_for_allele(\"HLA-A0201\")\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
    "model.predict(kim2014_train.get_allele(\"HLA-A0201\").peptides)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fit a model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on class Class1BindingPredictor in module mhcflurry.class1_allele_specific.class1_binding_predictor:\n",
      "\n",
      "class Class1BindingPredictor(mhcflurry.class1_allele_specific.class1_allele_specific_kmer_ic50_predictor_base.Class1AlleleSpecificKmerIC50PredictorBase)\n",
      " |  Allele-specific Class I MHC binding predictor which uses\n",
      " |  fixed-length (k-mer) index encoding for inputs and outputs\n",
      " |  a value between 0 and 1 (where 1 is the strongest binder).\n",
      " |  \n",
      " |  Method resolution order:\n",
      " |      Class1BindingPredictor\n",
      " |      mhcflurry.class1_allele_specific.class1_allele_specific_kmer_ic50_predictor_base.Class1AlleleSpecificKmerIC50PredictorBase\n",
      " |      mhcflurry.ic50_predictor_base.IC50PredictorBase\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __getstate__(self)\n",
      " |  \n",
      " |  __init__(self, model=None, name=None, max_ic50=50000.0, allow_unknown_amino_acids=True, kmer_size=9, n_amino_acids=20, verbose=False, **hyperparameters)\n",
      " |      Initialize self.  See help(type(self)) for accurate signature.\n",
      " |  \n",
      " |  __setstate__(self, state)\n",
      " |  \n",
      " |  fit_kmer_encoded_arrays(self, X, ic50, sample_weights=None, right_censoring_mask=None, X_pretrain=None, ic50_pretrain=None, sample_weights_pretrain=None, n_random_negative_samples=None, pretrain_decay=None, n_training_epochs=None, batch_size=None, verbose=False)\n",
      " |      Train predictive model from index encoding of fixed length k-mer\n",
      " |      peptides.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      X : array\n",
      " |          Training data with shape (n_samples, n_dims)\n",
      " |      \n",
      " |      ic50 : array\n",
      " |          Training IC50 values with shape (n_samples,)\n",
      " |      \n",
      " |      sample_weights : array\n",
      " |          Weight of each training sample with shape (n_samples,)\n",
      " |      \n",
      " |      right_censoring_mask : array, optional\n",
      " |          Boolean array which indicates whether each IC50 value is actually\n",
      " |          right censored (a lower bound on the true value). Censored values\n",
      " |          are transformed during training by sampling between the observed\n",
      " |          and maximum values on each iteration.\n",
      " |      \n",
      " |      X_pretrain : array\n",
      " |          Extra samples used for soft pretraining of the predictor,\n",
      " |          should have same number of dimensions as X.\n",
      " |          During training the weights of these samples will decay after\n",
      " |          each epoch.\n",
      " |      \n",
      " |      ic50_pretrain : array\n",
      " |          IC50 values for extra samples, shape\n",
      " |      \n",
      " |      pretrain_decay : int -> float function\n",
      " |          decay function for pretraining, mapping epoch number to decay\n",
      " |          factor\n",
      " |      \n",
      " |      sample_weights_pretrain : array\n",
      " |          Initial weights for the rows of X_pretrain. If not specified then\n",
      " |          initialized to ones.\n",
      " |      \n",
      " |      n_random_negative_samples : int\n",
      " |          Number of random samples to generate as negative examples.\n",
      " |      \n",
      " |      n_training_epochs : int\n",
      " |      \n",
      " |      verbose : bool\n",
      " |      \n",
      " |      batch_size : int\n",
      " |  \n",
      " |  get_weights(self)\n",
      " |      Returns weights, which can be passed to set_weights later.\n",
      " |  \n",
      " |  predict_ic50_for_kmer_encoded_array(self, X)\n",
      " |      Given an encoded array of amino acid indices,\n",
      " |      returns a vector of IC50 predictions.\n",
      " |  \n",
      " |  predict_scores_for_kmer_encoded_array(self, X)\n",
      " |      Given an encoded array of amino acid indices, returns a vector\n",
      " |      of affinity scores (values between 0 and 1).\n",
      " |  \n",
      " |  set_weights(self, weights)\n",
      " |      Reset the model weights.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data and other attributes defined here:\n",
      " |  \n",
      " |  fit_hyperparameter_defaults = <mhcflurry.hyperparameters.Hyperparamete...\n",
      " |  \n",
      " |  hyperparameter_defaults = <mhcflurry.hyperparameters.HyperparameterDef...\n",
      " |  \n",
      " |  network_hyperparameter_defaults = <mhcflurry.hyperparameters.Hyperpara...\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from mhcflurry.class1_allele_specific.class1_allele_specific_kmer_ic50_predictor_base.Class1AlleleSpecificKmerIC50PredictorBase:\n",
      " |  \n",
      " |  __repr__(self)\n",
      " |      Return repr(self).\n",
      " |  \n",
      " |  __str__(self)\n",
      " |      Return str(self).\n",
      " |  \n",
      " |  encode_peptides(self, peptides)\n",
      " |  \n",
      " |  fit_dataset(self, dataset, pretraining_dataset=None, sample_censored_affinities=False, **kwargs)\n",
      " |      Fit the model parameters on the given training data.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      dataset : AffinityMeasurementDataset\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      " |      \n",
      " |      pretraining_dataset : AffinityMeasurementDataset\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      " |      \n",
      " |      sample_censored_affinities : bool\n",
      " |          If a column named 'inequality' is in the AffinityMeasurementDataset then every\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      " |          peptide with a value of '>' on each training epoch, gets a\n",
      " |          randomly sampled IC50 between its observed value and the\n",
      " |          max_ic50 of the predictor. Default is False.\n",
      " |      \n",
      " |      **kwargs : dict\n",
      " |          Extra arguments are passed on to the fit_encoded_kmer_arrays()\n",
      " |          method.\n",
      " |  \n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      " |      Given a list of peptides of any length, returns an array of predicted\n",
      " |      normalized affinity values. Unlike IC50, a higher value here\n",
      " |      means a stronger affinity. Peptides of lengths other than 9 are\n",
      " |      transformed into a set of k-mers either by deleting or inserting\n",
      " |      amino acid characters. The prediction for a single peptides will be\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      " |      the average of expanded k-mers.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from mhcflurry.class1_allele_specific.class1_allele_specific_kmer_ic50_predictor_base.Class1AlleleSpecificKmerIC50PredictorBase:\n",
      " |  \n",
      " |  amino_acids\n",
      " |      Amino acid alphabet used for encoding peptides, may include\n",
      " |      \"X\" if allow_unknown_amino_acids is True.\n",
      " |  \n",
      " |  max_amino_acid_encoding_value\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from mhcflurry.ic50_predictor_base.IC50PredictorBase:\n",
      " |  \n",
      " |  fit_dictionary(self, peptide_to_ic50_dict, **kwargs)\n",
      " |      Fit the model parameters using the given peptide->IC50 dictionary,\n",
      " |      all samples are given the same weight.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      peptide_to_ic50_dict : dict\n",
      " |          Dictionary that maps peptides to IC50 values.\n",
      " |  \n",
      " |  fit_sequences(self, peptides, affinities, sample_weights=None, alleles=None, **kwargs)\n",
      " |  \n",
      " |  predict(self, peptides)\n",
      " |      Predict IC50 affinities for peptides of any length\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from mhcflurry.ic50_predictor_base.IC50PredictorBase:\n",
      " |  \n",
      " |  __dict__\n",
      " |      dictionary for instance variables (if defined)\n",
      " |  \n",
      " |  __weakref__\n",
      " |      list of weak references to the object (if defined)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(mhcflurry.class1_allele_specific.Class1BindingPredictor)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AffinityMeasurementDataset(n=3040, alleles=['HLA-A3301'])"
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data = kim2014_train.get_allele(\"HLA-A3301\")\n",
    "train_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'activation': 'tanh',\n",
       " 'batch_normalization': True,\n",
       " 'batch_size': 128,\n",
       " 'dropout_probability': 0.0,\n",
       " 'embedding_output_dim': 32,\n",
       " 'fraction_negative': 0.0,\n",
       " 'init': 'glorot_uniform',\n",
       " 'kmer_size': 9,\n",
       " 'layer_sizes': [64],\n",
       " 'loss': 'mse',\n",
       " 'max_ic50': 50000.0,\n",
       " 'n_training_epochs': 250,\n",
       " 'optimizer': 'rmsprop',\n",
       " 'output_activation': 'sigmoid',\n",
       " 'pretrain_decay': 'numpy.exp(-epoch)'}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# We'll use the default hyper parameters here. Could also specify them as kwargs:\n",
    "new_model = mhcflurry.class1_allele_specific.Class1BindingPredictor()\n",
    "new_model.hyperparameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1min 11s, sys: 5.66 s, total: 1min 16s\n",
      "Wall time: 1min 12s\n"
Tim O'Donnell's avatar
Tim O'Donnell committed
     ]
    }
   ],
   "source": [
    "# This will run faster if you have a GPU.\n",
    "%time new_model.fit_dataset(train_data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluate the fit model on held-out test data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generate predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nBieumzNQAAAAAElFTkSuQmCC\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11d2d7da0>"
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "test_data = kim2014_test.get_allele(\"HLA-A3301\")\n",
    "predictions = new_model.predict(test_data.peptides)\n",
    "\n",
    "seaborn.set_context('notebook')\n",
    "seaborn.regplot(numpy.log10(test_data.affinities), numpy.log10(predictions))\n",
    "pyplot.xlim(xmin=0)\n",
    "pyplot.ylim(ymin=0)\n",
    "pyplot.xlabel(\"Measured affinity (log10 nM)\")\n",
    "pyplot.ylabel(\"Predicted affinity (log10 nM)\")\n",
    "pyplot.title(\"MHCflurry on test data\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate AUC, F1, and Kendall's Tau scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function make_scores in module mhcflurry.class1_allele_specific.scoring:\n",
      "\n",
      "make_scores(ic50_y, ic50_y_pred, sample_weight=None, threshold_nm=500, max_ic50=50000)\n",
      "    Calculate AUC, F1, and Kendall Tau scores.\n",
      "    \n",
      "    Parameters\n",
      "    -----------\n",
      "    ic50_y : float list\n",
      "        true IC50s (i.e. affinities)\n",
      "    \n",
      "    ic50_y_pred : float list\n",
      "        predicted IC50s\n",
      "    \n",
      "    sample_weight : float list [optional]\n",
      "    \n",
      "    threshold_nm : float [optional]\n",
      "    \n",
      "    max_ic50 : float [optional]\n",
      "    \n",
      "    Returns\n",
      "    -----------\n",
      "    dict with entries \"auc\", \"f1\", \"tau\"\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(mhcflurry.class1_allele_specific.scoring.make_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'auc': 0.88567942942942945,\n",
       " 'f1': 0.73814432989690715,\n",
       " 'tau': 0.4912073299323329}"
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mhcflurry.class1_allele_specific.scoring.make_scores(test_data.affinities, predictions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cross validation for hyperparameter selection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function cross_validation_folds in module mhcflurry.class1_allele_specific.cross_validation:\n",
      "\n",
      "cross_validation_folds(train_data, alleles=None, n_folds=3, drop_similar_peptides=False, imputer=None, impute_kwargs={'min_observations_per_allele': 2, 'min_observations_per_peptide': 2}, parallel_backend=None)\n",
      "    Split a AffinityMeasurementDataset into n_folds cross validation folds for each allele,\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      "    optionally performing imputation.\n",
      "    \n",
      "    Parameters\n",
      "    -----------\n",
      "    train_data : mhcflurry.AffinityMeasurementDataset\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      "    \n",
      "    alleles : string list, optional\n",
      "        Alleles to run cross validation on. Default: all alleles in\n",
      "        train_data.\n",
      "    \n",
      "    n_folds : int, optional\n",
      "        Number of cross validation folds for each allele.\n",
      "    \n",
      "    drop_similar_peptides : boolean, optional\n",
      "        For each fold, remove peptides from the test data that are similar\n",
      "        to peptides in the train data. Similarity is defined as in the\n",
      "        similar_peptides function.\n",
      "    \n",
      "    imputer : fancyimpute.Solver, optional\n",
      "        Imputer to use. If not specified, no imputation is done.\n",
      "    \n",
      "    impute_kwargs : dict, optional\n",
      "        Additional kwargs to pass to mhcflurry.AffinityMeasurementDataset.impute_missing_values.\n",
Tim O'Donnell's avatar
Tim O'Donnell committed
      "    \n",
      "    parallel_backend : mhcflurry.parallelism.ParallelBackend, optional\n",
      "        Futures implementation to use for running on multiple threads,\n",
      "        processes, or nodes\n",
      "    \n",
      "    Returns\n",
      "    -----------\n",
      "    list of AlleleSpecificTrainTestFold of length num alleles * n_folds\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(mhcflurry.class1_allele_specific.cross_validation.cross_validation_folds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[AlleleSpecificTrainTestFold(allele='HLA-A3301', train=AffinityMeasurementDataset(n=2026, alleles=['HLA-A3301']), imputed_train=None, test=AffinityMeasurementDataset(n=1014, alleles=['HLA-A3301'])),\n",
       " AlleleSpecificTrainTestFold(allele='HLA-A3301', train=AffinityMeasurementDataset(n=2027, alleles=['HLA-A3301']), imputed_train=None, test=AffinityMeasurementDataset(n=1013, alleles=['HLA-A3301'])),\n",
       " AlleleSpecificTrainTestFold(allele='HLA-A3301', train=AffinityMeasurementDataset(n=2027, alleles=['HLA-A3301']), imputed_train=None, test=AffinityMeasurementDataset(n=1013, alleles=['HLA-A3301']))]"
Tim O'Donnell's avatar
Tim O'Donnell committed
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "folds = mhcflurry.class1_allele_specific.cross_validation.cross_validation_folds(train_data)\n",
    "folds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'activation': 'tanh',\n",
       " 'batch_normalization': True,\n",
       " 'batch_size': 128,\n",
       " 'dropout_probability': 0.0,\n",
       " 'embedding_output_dim': 32,\n",
       " 'fraction_negative': 0.0,\n",
       " 'impute': False,\n",
       " 'init': 'glorot_uniform',\n",
       " 'kmer_size': 9,\n",
       " 'layer_sizes': [64],\n",
       " 'loss': 'mse',\n",
       " 'max_ic50': 50000.0,\n",
       " 'n_training_epochs': 250,\n",
       " 'optimizer': 'rmsprop',\n",
       " 'output_activation': 'sigmoid',\n",
       " 'pretrain_decay': 'numpy.exp(-epoch)'}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Take a look at what hyperparameters are available for searching over.\n",
    "mhcflurry.class1_allele_specific.train.HYPERPARAMETER_DEFAULTS.defaults"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Searching over 2 models.\n",
      "First model: \n",
      "{'kmer_size': 9, 'n_training_epochs': 250, 'loss': 'mse', 'max_ic50': 50000.0, 'fraction_negative': 0.1, 'layer_sizes': [8], 'batch_size': 128, 'activation': 'tanh', 'init': 'glorot_uniform', 'dropout_probability': 0.0, 'pretrain_decay': 'numpy.exp(-epoch)', 'optimizer': 'rmsprop', 'impute': False, 'embedding_output_dim': 32, 'batch_normalization': True, 'output_activation': 'sigmoid'}\n"
Tim O'Donnell's avatar
Tim O'Donnell committed
     ]
    }
   ],
   "source": [
    "models_to_search = mhcflurry.class1_allele_specific.train.HYPERPARAMETER_DEFAULTS.models_grid(\n",
    "    fraction_negative=[.1],\n",
    "    layer_sizes=[[8], [12]])\n",
    "print(\"Searching over %d models.\" % len(models_to_search))\n",
    "print(\"First model: \\n%s\" % models_to_search[0])"
   ]
  },
  {
   "cell_type": "code",
Tim O'Donnell's avatar
Tim O'Donnell committed
   "execution_count": 21,
Tim O'Donnell's avatar
Tim O'Donnell committed
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function train_across_models_and_folds in module mhcflurry.class1_allele_specific.train:\n",
      "\n",
      "train_across_models_and_folds(folds, model_descriptions, cartesian_product_of_folds_and_models=True, return_predictors=False, folds_per_task=1, parallel_backend=None)\n",
      "    Train and optionally test any number of models across any number of folds.\n",
      "    \n",
      "    Parameters\n",
      "    -----------\n",
      "    folds : list of AlleleSpecificTrainTestFold\n",
      "    \n",
      "    model_descriptions : list of dict\n",
      "        Models to test\n",
      "    \n",
      "    cartesian_product_of_folds_and_models : boolean, optional\n",
      "        If true, then a predictor is treained for each fold and model\n",
      "        description.\n",
      "        If false, then len(folds) must equal len(model_descriptions), and\n",
      "        the i'th model is trained on the i'th fold.\n",
      "    \n",
      "    return_predictors : boolean, optional\n",
      "        Include the trained predictors in the result.\n",
      "    \n",
      "    parallel_backend : mhcflurry.parallelism.ParallelBackend, optional\n",
      "        Futures implementation to use for running on multiple threads,\n",
      "        processes, or nodes\n",
      "    \n",
      "    Returns\n",
      "    -----------\n",
      "    pandas.DataFrame\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(mhcflurry.class1_allele_specific.train.train_across_models_and_folds)"
   ]
  },
  {
   "cell_type": "code",
Tim O'Donnell's avatar
Tim O'Donnell committed
   "execution_count": 22,
Tim O'Donnell's avatar
Tim O'Donnell committed
   "metadata": {
    "collapsed": false
   },
Tim O'Donnell's avatar
Tim O'Donnell committed
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>allele</th>\n",
       "      <th>fold_num</th>\n",
       "      <th>model_num</th>\n",
       "      <th>train_size</th>\n",
       "      <th>test_size</th>\n",
       "      <th>imputed_train_size</th>\n",
       "      <th>train_tau</th>\n",
       "      <th>train_f1</th>\n",
       "      <th>train_auc</th>\n",
       "      <th>test_tau</th>\n",
       "      <th>...</th>\n",
       "      <th>model_batch_size</th>\n",
       "      <th>model_activation</th>\n",
       "      <th>model_init</th>\n",
       "      <th>model_dropout_probability</th>\n",
       "      <th>model_pretrain_decay</th>\n",
       "      <th>model_optimizer</th>\n",
       "      <th>model_impute</th>\n",
       "      <th>model_embedding_output_dim</th>\n",
       "      <th>model_batch_normalization</th>\n",
       "      <th>model_output_activation</th>\n",