Newer
Older
R_phipi / DNN.ipynb
@Davide Lancierini Davide Lancierini on 10 Oct 2018 32 KB debugging
{
 "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\n",
    "mag_index=1\n",
    "Ds_mass= 1968"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Signal MC amounts to 23821 while bkg data amounts to 86051\n"
     ]
    }
   ],
   "source": [
    "MC_sig_dict, data_bkg_dict = load_datasets(l_index, mag_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_ENDVERTEX_NDOF\"]\n",
    "del MC_sig_dict[\"Ds_OWNPV_NDOF\"]\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_ENDVERTEX_NDOF\"]\n",
    "del data_bkg_dict[\"Ds_OWNPV_NDOF\"]\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_ENDVERTEX_NDOF\"]\n",
    "del data_bkg_dict[\"phi_OWNPV_NDOF\"]"
   ]
  },
  {
   "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.shape==data_bkg.shape\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": [
    {
     "data": {
      "text/plain": [
       "(101872, 4000, 4000)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Establish train/val/test sizes\n",
    "\n",
    "val_size=4000\n",
    "test_size=4000\n",
    "\n",
    "train_size=MC_sig.shape[0]+data_bkg.shape[0]-val_size-test_size\n",
    "(train_size, val_size, test_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "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)\n",
    "\n",
    "#Check that nothing is missing\n",
    "\n",
    "data.shape[0]==train_size+val_size+test_size"
   ]
  },
  {
   "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+val_size+test_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 in train/val/test sets \n",
    "\n",
    "X_train_0 = X[0:train_size]\n",
    "Y_train = Y_labels[0:train_size]\n",
    "\n",
    "X_val_0 = X[train_size:train_size+val_size]\n",
    "Y_val = Y_labels[train_size:train_size+val_size]\n",
    "\n",
    "X_test_0 = X[train_size+val_size:train_size+val_size+test_size]\n",
    "Y_test = Y_labels[train_size+val_size:train_size+val_size+test_size]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Ds_ENDVERTEX_CHI2',\n",
       " 'Ds_OWNPV_CHI2',\n",
       " 'Ds_IPCHI2_OWNPV',\n",
       " 'Ds_IP_OWNPV',\n",
       " 'Ds_DIRA_OWNPV',\n",
       " 'phi_ENDVERTEX_CHI2',\n",
       " 'phi_OWNPV_CHI2',\n",
       " 'phi_IPCHI2_OWNPV',\n",
       " 'phi_IP_OWNPV',\n",
       " 'phi_DIRA_OWNPV',\n",
       " 'Ds_ConsD_M']"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "branches_needed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Strip out the reconstructed Ds mass\n",
    "\n",
    "X_train = X_train_0[:,0:dim-1]\n",
    "X_val = X_val_0[:,0:dim-1]\n",
    "X_test = X_test_0[:,0:dim-1]\n",
    "dim=X_train.shape[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# SETTING UP THE NETWORK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "#task='TRAIN'\n",
    "task='TEST'\n",
    "\n",
    "PATH=l_flv[l_index]+'_Mag'+mag_status[mag_index]+'_test_4'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "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",
    "    m=hyper_dict[\"m\"]\n",
    "    test_size=hyper_dict[\"test_size\"]\n",
    "    val_size=hyper_dict[\"val_size\"]\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": 31,
   "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",
    "    m=hyper_dict[\"m\"]\n",
    "    test_size=hyper_dict[\"test_size\"]\n",
    "    val_size=hyper_dict[\"val_size\"]\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": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "def bkg():\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_val, Y_val)\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",
    "            output = nn.predict(X_test)\n",
    "            \n",
    "            return output\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "scrolled": true
   },
   "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_MagDown_test_4/CNN_model.ckpt\n",
      "Model restored.\n",
      "Test accuracy: 0.9963\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": 35,
   "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_test_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_train_0[i][dim] for i in range(X_train_0.shape[0])]\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": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "if task=='TRAIN':\n",
    "    hyper_dict={\n",
    "        'm':m,\n",
    "        'test_size':test_size,\n",
    "        'val_size':val_size,\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": []
  }
 ],
 "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
}