Newer
Older
R_phipi / DNN.ipynb
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "import pickle\n",
    "import math\n",
    "\n",
    "trunc_normal= tf.truncated_normal_initializer(stddev=1)\n",
    "normal = tf.random_normal_initializer(stddev=1)\n",
    "\n",
    "from architectures.data_processing import *\n",
    "from architectures.utils.toolbox import *\n",
    "from architectures.DNN import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# IMPORTING THE DATASET"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "l_index=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Signal MC amounts to 47950 while bkg data amounts to 188715\n"
     ]
    }
   ],
   "source": [
    "MC_sig_dict, data_bkg_dict = load_datasets(l_index)\n",
    "m=MC_sig_dict[\"Ds_ConsD_M\"].shape[0]\n",
    "n=data_bkg_dict[\"Ds_ConsD_M\"].shape[0]\n",
    "\n",
    "print('Signal MC amounts to {0} while bkg data amounts to {1}'.format(m,n))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Normalising the Chi2 vertex fits to the NDoF\n",
    "\n",
    "MC_sig_dict[\"Ds_ENDVERTEX_CHI2\"]=MC_sig_dict[\"Ds_ENDVERTEX_CHI2\"]/MC_sig_dict[\"Ds_ENDVERTEX_NDOF\"]\n",
    "MC_sig_dict[\"Ds_OWNPV_CHI2\"]=MC_sig_dict[\"Ds_OWNPV_CHI2\"]/MC_sig_dict[\"Ds_OWNPV_NDOF\"]\n",
    "MC_sig_dict[\"Ds_IPCHI2_OWNPV\"]=MC_sig_dict[\"Ds_IPCHI2_OWNPV\"]/MC_sig_dict[\"Ds_ENDVERTEX_NDOF\"]\n",
    "\n",
    "del MC_sig_dict[\"Ds_OWNPV_NDOF\"]\n",
    "del MC_sig_dict[\"Ds_ENDVERTEX_NDOF\"]\n",
    "\n",
    "\n",
    "data_bkg_dict[\"Ds_ENDVERTEX_CHI2\"]=data_bkg_dict[\"Ds_ENDVERTEX_CHI2\"]/data_bkg_dict[\"Ds_ENDVERTEX_NDOF\"]\n",
    "data_bkg_dict[\"Ds_OWNPV_CHI2\"]=data_bkg_dict[\"Ds_OWNPV_CHI2\"]/data_bkg_dict[\"Ds_OWNPV_NDOF\"]\n",
    "data_bkg_dict[\"Ds_IPCHI2_OWNPV\"]=data_bkg_dict[\"Ds_IPCHI2_OWNPV\"]/data_bkg_dict[\"Ds_ENDVERTEX_NDOF\"]\n",
    "\n",
    "del data_bkg_dict[\"Ds_OWNPV_NDOF\"]\n",
    "del data_bkg_dict[\"Ds_ENDVERTEX_NDOF\"]\n",
    "\n",
    "\n",
    "data_bkg_dict[\"phi_ENDVERTEX_CHI2\"]=data_bkg_dict[\"phi_ENDVERTEX_CHI2\"]/data_bkg_dict[\"phi_ENDVERTEX_NDOF\"]\n",
    "data_bkg_dict[\"phi_OWNPV_CHI2\"]=data_bkg_dict[\"phi_OWNPV_CHI2\"]/data_bkg_dict[\"phi_OWNPV_NDOF\"]\n",
    "data_bkg_dict[\"phi_IPCHI2_OWNPV\"]=data_bkg_dict[\"phi_IPCHI2_OWNPV\"]/data_bkg_dict[\"phi_ENDVERTEX_NDOF\"]\n",
    "\n",
    "del data_bkg_dict[\"phi_OWNPV_NDOF\"]\n",
    "del data_bkg_dict[\"phi_ENDVERTEX_NDOF\"]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "branches_needed = [\n",
    "                    \"Ds_ENDVERTEX_CHI2\",\n",
    "                    #\"Ds_ENDVERTEX_NDOF\",\n",
    "                    \"Ds_OWNPV_CHI2\",\n",
    "                    #\"Ds_OWNPV_NDOF\",\n",
    "                    \"Ds_IPCHI2_OWNPV\",\n",
    "                    \"Ds_IP_OWNPV\",\n",
    "                    \"Ds_DIRA_OWNPV\",\n",
    "                    #l_flv[l_index]+\"_plus_MC15TuneV1_ProbNN\"+l_flv[l_index],\n",
    "                    #\"Ds_Hlt1TrackMVADecision_TOS\",\n",
    "                    #\"Ds_Hlt2RareCharmD2Pi\"+l_flv[l_index].capitalize()+l_flv[l_index].capitalize()+\"OSDecision_TOS\",\n",
    "                    #\"Ds_Hlt2Phys_TOS\",\n",
    "                    \"phi_ENDVERTEX_CHI2\",\n",
    "                    #\"phi_ENDVERTEX_NDOF\",\n",
    "                    \"phi_OWNPV_CHI2\",\n",
    "                    #\"phi_OWNPV_NDOF\",\n",
    "                    \"phi_IPCHI2_OWNPV\",\n",
    "                    \"phi_IP_OWNPV\",\n",
    "                    \"phi_DIRA_OWNPV\",\n",
    "                    \"Ds_ConsD_M\",\n",
    "                  ] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Number of input features\n",
    "\n",
    "dim=len(branches_needed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Convert data dictionaries to arrays for NN\n",
    "\n",
    "MC_sig = extract_array(MC_sig_dict, branches_needed, dim, m//2)\n",
    "data_bkg = extract_array(data_bkg_dict, branches_needed, dim, m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Add 0/1 label for bkg/sig\n",
    "\n",
    "MC_sig_labelled=add_labels(MC_sig,signal=True)\n",
    "data_bkg_labelled=add_labels(data_bkg,signal=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#SOME CROSS CHECKS\n",
    "#MC_sig_labelled.shape[1]==dim+1==data_bkg_labelled.shape[1]\n",
    "#data_bkg_labelled[:,dim].sum()==0\n",
    "#(MC_sig_labelled[:,dim].sum()/m)==1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Merge MC sig and data bkg, shuffle it\n",
    "\n",
    "data=np.concatenate((MC_sig_labelled,data_bkg_labelled), axis =0)\n",
    "np.random.seed(1)\n",
    "np.random.shuffle(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Establish train/val/test sizes\n",
    "train_size=m+m//2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Strip away the label column and convert it to a one-hot encoding\n",
    "\n",
    "X=data[:,0:dim]\n",
    "Y_labels=data[:,dim].astype(int)\n",
    "Y_labels=Y_labels.reshape(train_size,1)\n",
    "Y_labels_hot = to_one_hot(Y_labels)\n",
    "Y_labels=Y_labels_hot\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Divide the dataset k \"equi populated\" sets\n",
    "k=2\n",
    "k_batch_size=train_size//k\n",
    "\n",
    "X_dict={}\n",
    "Y_dict={}\n",
    "\n",
    "for i in range(k):\n",
    "    X_dict[i]=X[k_batch_size*i:k_batch_size*(i+1)]\n",
    "    Y_dict[i]=Y_labels[k_batch_size*i:k_batch_size*(i+1)]\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "k=range(k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Strip out the reconstructed Ds mass and build train and test sets\n",
    "i=0\n",
    "\n",
    "X_test = X_dict[k[i]][:,0:dim-1]\n",
    "Y_test = Y_dict[k[i]][:,0:dim-1]\n",
    "\n",
    "k=np.delete(k, i)\n",
    "\n",
    "X_train = np.concatenate([X_dict[j][:,0:dim-1] for j in k],axis=0)\n",
    "Y_train = np.concatenate([Y_dict[j][:,0:dim-1] for j in k],axis=0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(35962, 10)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dim=X_train.shape[1]\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# SETTING UP THE NETWORK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "#task='TRAIN'\n",
    "task='TEST'\n",
    "\n",
    "PATH=l_flv[l_index]+'_test_'+str(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "if task =='TRAIN' and os.path.exists(PATH+'/hyper_parameters.pkl'):\n",
    "    with open(PATH+'/hyper_parameters.pkl', 'rb') as f:  \n",
    "        hyper_dict = pickle.load(f)\n",
    "        \n",
    "    k=hyper_dict[\"k\"]\n",
    "    LEARNING_RATE=hyper_dict[\"LEARNING_RATE\"]\n",
    "    BETA1=hyper_dict[\"BETA1\"]\n",
    "    BATCH_SIZE=hyper_dict[\"BATCH_SIZE\"]\n",
    "    EPOCHS=hyper_dict[\"EPOCHS\"]\n",
    "    VAL_PERIOD=hyper_dict[\"VAL_PERIOD\"]\n",
    "    SEED=hyper_dict[\"SEED\"]\n",
    "    sizes=hyper_dict[\"sizes\"]\n",
    "    LAMBD=hyper_dict[\"LAMBD\"]\n",
    "    PATH=hyper_dict[\"PATH\"]\n",
    "\n",
    "elif task=='TRAIN' and not os.path.exists(PATH+'/hyper_parameters.pkl'):\n",
    "    \n",
    "    \n",
    "    LEARNING_RATE = 0.0001\n",
    "    BETA1 = 0.5\n",
    "    BATCH_SIZE = 64\n",
    "    EPOCHS = 20\n",
    "    VAL_PERIOD = 5\n",
    "    SEED=1\n",
    "    LAMBD=1.\n",
    "    \n",
    "    sizes = {\n",
    "    'dense_layers': [\n",
    "                        #(16, 'bn', 0.8, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        #(8, 'bn', 0.5, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (16, 'bn',0.5, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (32, 'bn', 0.5, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (16, 'bn', 0.5, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (8, 'bn', 0.5, lrelu, tf.glorot_uniform_initializer()),\n",
    "                    ],\n",
    "    'n_classes':2,\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "if task == 'TEST' and os.path.exists(PATH+'/hyper_parameters.pkl'):\n",
    "    with open(PATH+'/hyper_parameters.pkl', 'rb') as f:  \n",
    "        hyper_dict = pickle.load(f)\n",
    "        #for key, item in hyper_dict.items():\n",
    "        #    print(key+':'+str(item))\n",
    "            \n",
    "    k=hyper_dict[\"k\"]\n",
    "    LEARNING_RATE=hyper_dict[\"LEARNING_RATE\"]\n",
    "    BETA1=hyper_dict[\"BETA1\"]\n",
    "    BATCH_SIZE=hyper_dict[\"BATCH_SIZE\"]\n",
    "    EPOCHS=hyper_dict[\"EPOCHS\"]\n",
    "    VAL_PERIOD=hyper_dict[\"VAL_PERIOD\"]\n",
    "    SEED=hyper_dict[\"SEED\"]\n",
    "    sizes=hyper_dict[\"sizes\"]\n",
    "    LAMBD=hyper_dict[\"LAMBD\"]\n",
    "    PATH=hyper_dict[\"PATH\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def bkg():\n",
    "    \n",
    "    batch_size_output=128\n",
    "    test_size=k_batch_size\n",
    "    n_batches_output = test_size//batch_size_output\n",
    "    \n",
    "    tf.reset_default_graph()\n",
    "    nn = DNN(dim, sizes,\n",
    "              lr=LEARNING_RATE, beta1=BETA1, lambd=LAMBD,\n",
    "              batch_size=BATCH_SIZE, epochs=EPOCHS,\n",
    "              save_sample=VAL_PERIOD, path=PATH, seed=SEED)\n",
    "    \n",
    "    vars_to_train= tf.trainable_variables()\n",
    "    \n",
    "    if task == 'TRAIN':\n",
    "        init_op = tf.global_variables_initializer()\n",
    "        \n",
    "    if task == 'TEST':\n",
    "        vars_all = tf.global_variables()\n",
    "        vars_to_init = list(set(vars_all)-set(vars_to_train))\n",
    "        init_op = tf.variables_initializer(vars_to_init)\n",
    "    \n",
    "    # Add ops to save and restore all the variables.\n",
    "    saver = tf.train.Saver()\n",
    "    gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)\n",
    "    \n",
    "    with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess:\n",
    "        \n",
    "        sess.run(init_op)\n",
    "\n",
    "        if task=='TRAIN':\n",
    "            print('\\n Training...')\n",
    "            \n",
    "            if os.path.exists(PATH+'/CNN_model.ckpt.index'):\n",
    "                saver.restore(sess,PATH+'/CNN_model.ckpt')\n",
    "                print('Model restored.')\n",
    "            \n",
    "            nn.set_session(sess)\n",
    "            nn.fit(X_train, Y_train, X_test, Y_test)\n",
    "            \n",
    "            save_path = saver.save(sess, PATH+'/CNN_model.ckpt')\n",
    "            print(\"Model saved in path: %s\" % save_path)\n",
    "        \n",
    "        if task=='TEST':\n",
    "            print('\\n Evaluate model on test set...')\n",
    "            saver.restore(sess,PATH+'/CNN_model.ckpt')\n",
    "            print('Model restored.')\n",
    "            \n",
    "            nn.set_session(sess)\n",
    "            nn.test(X_test, Y_test)\n",
    "            \n",
    "            \n",
    "            output_dict={}\n",
    "            \n",
    "            for i in range(n_batches_output):\n",
    "                small_dataset = X_test[i*batch_size_output:(i+1)*batch_size_output]\n",
    "                output_dict[i] = nn.predict(small_dataset)\n",
    "                \n",
    "            output=np.concatenate([output_dict[i] for i in range(n_batches_output)])\n",
    "            return output\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input for propagation (?, 10)\n",
      "Logits shape (?, 2)\n",
      "Input for propagation (?, 10)\n",
      "Logits shape (?, 2)\n",
      "\n",
      " Evaluate model on test set...\n",
      "INFO:tensorflow:Restoring parameters from mu_test_0/CNN_model.ckpt\n",
      "Model restored.\n",
      "Test accuracy: 0.9935\n"
     ]
    }
   ],
   "source": [
    "if __name__=='__main__':\n",
    "\n",
    "    if task == 'TRAIN':\n",
    "        if not os.path.exists(PATH):\n",
    "            os.mkdir(PATH)\n",
    "    \n",
    "        elif os.path.exists(PATH):\n",
    "            if os.path.exists(PATH+'/checkpoint'):\n",
    "                ans = input('A previous checkpoint already exists, choose the action to perform \\n \\n 1) Overwrite the current model saved at '+PATH+'/checkpoint \\n 2) Start training a new model \\n 3) Restore and continue training the previous model \\n ')\n",
    "                \n",
    "                if ans == '1':\n",
    "                    print('Overwriting existing model in '+PATH)\n",
    "                    for file in os.listdir(PATH):\n",
    "                        file_path = os.path.join(PATH, file)\n",
    "                        try:\n",
    "                            if os.path.isfile(file_path):\n",
    "                                os.unlink(file_path)\n",
    "                            #elif os.path.isdir(file_path): shutil.rmtree(file_path)\n",
    "                        except Exception as e:\n",
    "                            print(e)\n",
    "                            \n",
    "                elif ans == '2':\n",
    "                    PATH = input('Specify the name of the model, a new directory will be created.\\n')\n",
    "                    os.mkdir(PATH)         \n",
    "        bkg()\n",
    "\n",
    "    elif task == 'TEST': \n",
    "        if not os.path.exists(PATH+'/checkpoint'):\n",
    "            print('No checkpoint to test')\n",
    "        else:\n",
    "            output = bkg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x576 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "if task=='TEST':\n",
    "\n",
    "    Ds_mass_MC =[MC_sig_dict[\"Ds_ConsD_M\"][i][0] for i in range(m)]\n",
    "    NN_selected = X_dict[k[i]][0:output.shape[0]][np.argmax(output, axis=1).astype(np.bool)]\n",
    "    Ds_mass_sel_NN = [NN_selected[i][dim] for i in range(NN_selected.shape[0])]\n",
    "    Ds_mass_train_NN =X_dict[k[i]][:,dim]\n",
    "\n",
    "    plt.subplot(1,2,1)\n",
    "    plt.hist(Ds_mass_MC,bins=70);\n",
    "    plt.subplot(1,2,2)\n",
    "    plt.hist(Ds_mass_sel_NN,alpha=0.8,bins=70);\n",
    "    plt.hist(Ds_mass_train_NN,alpha=0.2,bins=70);\n",
    "\n",
    "    fig=plt.gcf();\n",
    "    fig.set_size_inches(20,8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "if task=='TRAIN':\n",
    "    hyper_dict={\n",
    "        'k':k,\n",
    "        'LEARNING_RATE':LEARNING_RATE,\n",
    "        'BETA1':BETA1,\n",
    "        'BATCH_SIZE':BATCH_SIZE,\n",
    "        'EPOCHS':EPOCHS,\n",
    "        'VAL_PERIOD':VAL_PERIOD,\n",
    "        'SEED':SEED,\n",
    "        'sizes':sizes,\n",
    "        'LAMBD':LAMBD,\n",
    "        'PATH':PATH,\n",
    "    }\n",
    "    with open(PATH+'/hyper_parameters.pkl', 'wb') as f:  \n",
    "        pickle.dump(hyper_dict, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}