Newer
Older
R_phipi / DNN.ipynb
@Davide Lancierini Davide Lancierini on 10 Oct 2018 32 KB gotta squash'em all
{
 "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 6151 while bkg data amounts to 17665\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)\n",
    "data_bkg = extract_array(data_bkg_dict, branches_needed, dim, n)"
   ]
  },
  {
   "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+n"
   ]
  },
  {
   "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": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Divide the dataset k \"equi populated\" sets\n",
    "\n",
    "k=2 #number of subsets\n",
    "i=0 #number of subset that is test set\n",
    "\n",
    "X_train, Y_train, X_test, Y_test, X_dict, Y_dict = k_subsets(i, k, X, Y_labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11908, 10)"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# SETTING UP THE NETWORK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "#task='TRAIN'\n",
    "task='TEST'\n",
    "\n",
    "PATH=l_flv[l_index]+'_test_'+str(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "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.001\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.8, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (32, 'bn', 0.8, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (16, 'bn', 0.8, lrelu, tf.glorot_uniform_initializer()),\n",
    "                        (8, 'bn', 0.8, lrelu, tf.glorot_uniform_initializer()),\n",
    "                    ],\n",
    "    'n_classes':2,\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "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": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "def bkg():\n",
    "    dim=X_train.shape[1]\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",
    "            batch_size_output=128\n",
    "            test_size=Y_test.shape[0]\n",
    "            n_batches_output = test_size//batch_size_output\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": 56,
   "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.9982\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": 62,
   "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-1] for i in range(NN_selected.shape[0])]\n",
    "    Ds_mass_train_NN =X_dict[k[i]][:,dim-1]\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": 49,
   "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": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "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
}