{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from sklearn.cross_validation import train_test_split\n", "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.neighbors import KNeighborsClassifier\n", "from sklearn.linear_model import LogisticRegression\n", "from sklearn import svm\n", "from sklearn import datasets\n", "from sklearn.calibration import CalibratedClassifierCV\n", "from tqdm import tqdm\n", "\n", "np.set_printoptions(formatter={'float': lambda x: \"{0:0.3f}\".format(x)})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Classification with Refusals: Controlling the Error Rate\n", "\n", "We want to control the error rate for a classification task to a prespecified error rate $\\epsilon$ by refusing to make predictions on some inputs. In the following, we will use two different approaches to this problem:\n", "\n", "**1. Probability calibration:** We will calibrate our classifier by using existing probability calibration tools (sigmoid and isotonic) in the scikit-learn package and decide to refuse or predict based on the calibrated probability estimates.\n", "\n", "**2. Conjugate prediction:** Calibrate a threshold instead of probability distributions: we discover an appropriate threshold value (which we call the \"acceptance threshold\") on calibration data and refuse to predict on the test data when multiple labels are above the threshold. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mathematical Description\n", "\n", "Given the training data $(X_1,Y_1), \\ldots, (X_n,Y_n)$ $\\sim$ $\\mathcal{D}^n$ for some fixed but unknown $\\mathcal{D}$ and tolerance level $\\epsilon \\in (0,1)$ train a _selective_ classifier $C:\\mathcal{X}\\rightarrow \\mathcal{Y} \\cup \\{refuse\\}$, such that:\n", "\\begin{eqnarray} P\\left(C(X) \\neq Y ~ | ~ C(X) \\neq refuse \\right) & \\leq & \\epsilon \\end{eqnarray}\n", "where $(X,Y) \\sim \\mathcal{D}$ and independent from the training data. Intuitively, our error on the data items on which we guess is less than $\\epsilon$." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "\n", "# LOAD THE DATA\n", "# MNIST DATA SET (MULTI-LABEL)\n", "digits = datasets.fetch_mldata('mnist-original')\n", "X, y = digits.data, digits.target\n", "y = y.astype(int)\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# THE OTHER DATA-SETS\n", "# MAKE SURE THE LABELS ARE INTEGERS STARTING FROM 0.\n", "\n", "# COD\n", "#cod = datasets.fetch_mldata('cod-rna')\n", "#X, y = cod.data, cod.target\n", "#y = (y + 1)/2\n", "#y = y.astype(int)\n", "\n", "## CONNECT\n", "#connect = datasets.fetch_mldata('connect-4')\n", "#X, y = connect.data, connect.target\n", "#y = (y +1)/2\n", "#y = y.astype(int)\n", "\n", "## COVER\n", "#covtype = datasets.fetch_covtype()\n", "#X, y = covtype.data, covtype.target\n", "\n", "## LETTER\n", "#letter = datasets.fetch_mldata('letter')\n", "#X, y = letter.data, letter.target\n", "#y = y - 1\n", "#y = y.astype(int)\n", "\n", "## SATI\n", "#sati = datasets.fetch_mldata('satimage')\n", "#X, y = sati.data, sati.target\n", "#y = y - 1\n", "#y = y.astype(int)\n", "\n", "## SENSIT\n", "#sensit = datasets.fetch_mldata('sensit-vehicle-combined')\n", "#X, y = sensit.data, sensit.target\n", "#y = y - 1\n", "#y = y.astype(int)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# SPLIT THE DATA TRAIN:TEST 3:1\n", "train_X, test_X, train_y, test_y = train_test_split(X, y, train_size=0.75)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0324571428571\n" ] } ], "source": [ "# COMPUTE THE BASE ERROR LEVEL (FOR DEMONSTRATION)\n", "classifier = RandomForestClassifier(n_estimators=100, min_samples_leaf=1, oob_score=False, n_jobs=-1)\n", "classifier.fit(train_X,train_y)\n", "epsilon_0 = 1 - classifier.score(test_X,test_y)\n", "\n", "# CHOOSE THE TARGET ERROR RATE AS 0.01\n", "epsilon = 0.01\n", "print(epsilon_0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Probability Calibration:\n", "\n", "In this section we first approach the problem by employing probability calibration methods from Scikit-Learn. For detailed information about these methods we refer to [the documentation of the calibration module](http://scikit-learn.org/stable/modules/calibration.html) and the references therein. \n", "\n", "Most ML algorithms compute probability estimates as well as the simple point predictions, i.e. they estimate $\\hat{P}\\left(Y~|~X\\right)$ and then make the prediction $\\hat{Y} = argmax_{y}~\\hat{P}\\left(y~|~X\\right)$. \n", "In scikit-learn these probability estimates can be obtained by predict_proba method for many of the classifiers. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Intuitive idea of calibration:\n", "* Calibration is needed because the machine learning tools give inaccurate estimates of probabilities (usually systematically under- or over-confident) so Scikit-Learn uses calibration to correct for those inaccuracies. We will show later that these corrections aren't always, well, correct.\n", "\n", "* Probability calibration is typically implemented as learning an appropriate monotonic transformation of the estimated probabilities from an hold-out set (\"calibration set \" from now on). The goal is finding the transformation such that in the calibration set among the points with transformed probabilities $x$, roughly fraction $x$ of them are correctly labelled. \n", "\n", "In this demo, we will use two of the most common calibration techniques Platt's regression and isotonic regression. The main difference between those two is while Platt's regression assumes the transformation we try to learn has a sigmoid shape (i.e, $f(x) = (1+e^{ax+b})^{-1}$) and infers the parameters of the sigmoid ($a$ and $b$); isotonic regression assumes a non-parametric transformation, in particular it fits a piecewise constant function. \n", "\n", "In the following, we first split the training data as 2:1 as the core training and calibration sets, train a random forest classifier on the core training set, and calibrate that classifier using the calibration set.\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# SPLIT THE TRAINING DATA AS THE CORE TRAINING AND CALIBRATION SETS (2:1)\n", "core_X, cal_X, core_y, cal_y = train_test_split(train_X, train_y, train_size=0.66)\n", "n_core, n_features = core_X.shape\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n", " max_depth=None, max_features='auto', max_leaf_nodes=None,\n", " min_samples_leaf=1, min_samples_split=2,\n", " min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=-1,\n", " oob_score=False, random_state=None, verbose=0,\n", " warm_start=False)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# TRAIN YOUR CLASSIFIER ON THE CORE SET\n", "classifier = RandomForestClassifier(n_estimators=100, min_samples_leaf=1, oob_score=False, n_jobs=-1)\n", "\n", "## ALTERNATIVE CLASSIFIERS\n", "## NOTE THE FOLLOWING CODE SIMPLY USES THE DEFAULT SETTING FOR THE HYPER PARAMETERS, \n", "## ONE CAN CHOOSE BETTER PARAMETERS WITH VALIDATION FOR LOWER REFUSE RATES.\n", "\n", "# classifier = svm.SVC()\n", "# classifier = KNeighborsClassifier(n_neighbors=10)\n", "# classifier = LogisticRegression()\n", "\n", "# TRAIN THE CLASSIFIER\n", "classifier.fit(core_X, core_y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Up to here all three methods (isotonic, sigmoid, and our method) do the same thing. Below we use sigmoid and isotonic (the current Scikit-Learn methods)." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "CalibratedClassifierCV(base_estimator=RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n", " max_depth=None, max_features='auto', max_leaf_nodes=None,\n", " min_samples_leaf=1, min_samples_split=2,\n", " min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=-1,\n", " oob_score=False, random_state=None, verbose=0,\n", " warm_start=False),\n", " cv='prefit', method='isotonic')" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# CALIBRATE THE CLASSIFIER\n", "classifier_sigmoid = CalibratedClassifierCV(base_estimator = classifier, method = 'sigmoid', cv = 'prefit')\n", "classifier_sigmoid.fit(cal_X,cal_y)\n", "classifier_isotonic = CalibratedClassifierCV(base_estimator = classifier, method = 'isotonic', cv = 'prefit')\n", "classifier_isotonic.fit(cal_X,cal_y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, predict the labels of the points in the test set while refusing if the classifier is not confident enough. To quantify that we plugged-in the calibrated probabilities to the Chow's rule (for each of isotonic and sigmoid):\n", "* **Calibrated Refusals:** Refuse if $(1 - max_{y}~\\hat{P}\\left(y~|~X\\right)) > \\epsilon$. Intuitively, refuse if not sure enough about any $y$ value.\n", "\n", "Note that in the case of the perfect estimation of the posteriors this method would give a stronger guarantee than the Conjugate approach. In particular it would control the error rate conditioned on the test object $X$ as well." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# UNDERLYING ALGORITM (e.g. RANDOM FORESTS) PREDICTS THE LABELS FOR THE TEST SET\n", "pred = classifier.predict(test_X)\n", "err = pred != test_y\n", "\n", "# NOW FILTER OUT REFUSED PREDICTIONS.\n", "\n", "# PROBABILITY CALIBRATION (Maximum Likelihood) \n", "# REFUSE PREDICTIONS IF NO LABEL HAS CONFIDENCE MORE THAN 1-epsilon\n", "ref_sigmoid = (classifier_sigmoid.predict_proba(test_X) >= 1-epsilon).sum(axis=1) == 0\n", "ref_isotonic = (classifier_isotonic.predict_proba(test_X) >= 1-epsilon).sum(axis=1) == 0" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MNIST\n", "Dimensions:\t\t\t\t (70000, 784) \n", "Number of Labels:\t\t\t 10 \n", "Error rate on all predictions:\t\t 0.0361\n", "\n", "PLATT'S REGRESSION \n", "Error Rate on non-refused predictions:\t0.0000\n", "Refuse Rate:\t0.9623\n", "\n", "ISOTONIC REGRESSION \n", "Error Rate on non-refused predictions:\t0.0005\n", "Refuse Rate:\t0.3333\n" ] } ], "source": [ "print(\"MNIST\")\n", "print(\"Dimensions:\\t\\t\\t\\t\" ,X.shape, \"\\nNumber of Labels:\\t\\t\\t\",10, \"\\nError rate on all predictions:\\t\\t {:0.4f}\".format(np.mean(err)))\n", "\n", "print(\"\\nPLATT'S REGRESSION \")\n", "print(\"Error Rate on non-refused predictions:\\t{:0.4f}\".format(np.sum(err*(1-ref_sigmoid))/np.sum(1-ref_sigmoid)))\n", "print(\"Refuse Rate:\\t{:0.4f}\".format(np.mean(ref_sigmoid)))\n", "\n", "print(\"\\nISOTONIC REGRESSION \")\n", "print(\"Error Rate on non-refused predictions:\\t{:0.4f}\".format(np.sum(err*(1-ref_isotonic))/np.sum(1-ref_isotonic)))\n", "print(\"Refuse Rate:\\t{:0.4f}\".format(np.mean(ref_isotonic)))\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For now, please observe that the error rates are below our target rate (1%) and, as a result, the refusal rate is unnecessarily high." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CONJUGATE PREDICTION\n", "\n", "Instead of trying to calibrate probabilities, infer an acceptance threshold $\\alpha$ directly based on the errors in the calibration set. That is, \n", "\n", "\n", "\n", "* **Calibration Step:** For each $\\alpha$, refuse if $\\hat{P}\\left(y~|~X\\right) <= \\alpha$ for all the labels. Operationally, we start from the minimum $\\alpha$ (=0, for which we won't refuse any data point, so our error rate will equal the error rate on the whole calibration set) and increase until the error rate on non-refused data points in the calibration set satisfies the conditions given in the presentation.\n", "\n", "* Mathematically: Increase $\\alpha$ till $$ \\frac{E_\\alpha + 1 }{E_\\alpha + C_\\alpha + 1 } < \\epsilon \\frac{1+ 1/E_0}{1 + 1/N_{cal}} $$ where $E_x$ and $C_x$ stand for the number of errors and correct predictions assuming $\\alpha = x$. \n", "\n", "We are looking for the minimum such $\\alpha$ because that will have the smallest number of refusals, respectively.\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def conj_calibrate(C,Xcal, ycal, eps):\n", " # COMPUTE THE ACCEPTANCE THRESHOLD FOR CLASSIFIER C, CALIBRATION DATA (Xcal,ycal) AND TARGET RATE eps\n", " # NOTE: WORKS ONLY FOR CLASSIFIERS THAT SUPPORT predict_proba()\n", " A = C.predict_proba(Xcal)\n", " pred_cal = C.predict(Xcal)\n", " n_cal, n_features = Xcal.shape\n", " \n", " # COMPUTE THE POTENTIAL THRESHOLD POINTS\n", " pt = A.max(axis=1)\n", " \n", " # STEP 1 : FIND THE SMALLEST TEMPORARY THRESHOLD TO SATISFY THE CONDITION\n", " a = np.argsort(pt)\n", " #a = np.argsort(-pt)[:ncal]\n", " errors = sum(pred_cal != ycal) + 1 \n", " eps_ = eps * (1 + 1/errors) / (1 + 1/n_cal)\n", " \n", " predictions = n_cal + 1\n", " threshold = 1\n", " \n", " if errors/predictions > eps_:\n", " for i in a: # As we change the threshold, we refuse one more data point each time.\n", " if pred_cal[i] != ycal[i]:\n", " errors = errors - 1 # We got rid of one error\n", " predictions = predictions - 1\n", " if errors/predictions <= eps_:\n", " threshold = pt[i]\n", " break\n", " else:\n", " threshold = 0 \n", " return threshold" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* **Test Step:** Given $\\alpha$ discovered in the calibration step, use it on the test set. So we will refuse to predict if there is not any label with $\\hat{P}\\left(y~|~X\\right) > \\alpha$. \n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": true, "nbpresent": { "id": "e08205d9-9e81-464d-a068-f70a2c73a41f" } }, "outputs": [], "source": [ "def conj_test(C,Xtest, threshold):\n", " # PREDICT LABELS OF THE POINTS IN Xtest AND CHOOSE THE POINTS TO REFUSE RELATIVE TO THE ACCEPTANCE THRESHOLD threshold\n", " test_A = C.predict_proba(Xtest)\n", " pred_test = C.predict(Xtest)\n", " refused = np.sum(test_A>threshold, axis=1) == 0\n", " return pred_test, refused" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "By combining these two steps:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "nbpresent": { "id": "4c43a165-eb79-474f-98fe-eede08f2e63f" } }, "outputs": [], "source": [ "def conj_calibrate_test(C,Xcal, ycal, Xtest, eps):\n", " # CALIBRATE CLASSIFIER C ON (Xcal, ycal) WITH TARGET RATE eps AND PREDICT THE CORRESPONDING LABELS FOR Xtest\n", " th = conj_calibrate(C,Xcal, ycal, eps)\n", " return conj_test(C,Xtest, th)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "nbpresent": { "id": "ccda2bb3-e8b3-48d5-b021-d50c3ddd93c3" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MNIST\n", "Dimensions:\t\t\t (70000, 784) \n", "Number of Labels:\t\t 10 \n", "Error rate on all predictions:\t 0.0361\n", "\n", "CONJUGATE PREDICTION\n", "Target Error Rate: \t0.0100\n", "Selective Error Rate: \t0.0087 \n", "Refusal Rate:\t\t0.0912\n" ] } ], "source": [ "# PREDICT THE TEST LABELS\n", "pred, ref = conj_calibrate_test(classifier, cal_X,cal_y,test_X,epsilon)\n", "err = pred != test_y\n", "\n", "print(\"MNIST\")\n", "print(\"Dimensions:\\t\\t\\t\" ,X.shape, \"\\nNumber of Labels:\\t\\t\",10, \"\\nError rate on all predictions:\\t {:0.4f}\".format(np.mean(err)))\n", "\n", "print(\"\\nCONJUGATE PREDICTION\")\n", "print(\"Target Error Rate: \\t{:0.4f}\".format(epsilon))\n", "print(\"Selective Error Rate: \\t{:0.4f}\".format(np.sum(err*(1-ref))/np.sum(1-ref)),\"\\nRefusal Rate:\\t\\t{:0.4f}\".format(np.mean(ref)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Online Setup\n", "\n", "In this setup, we apply the described methods to predict the upcoming point in a data stream $(X_1,Y_1), (X_2,Y_2), \\ldots $. To do so, we first split the data-stream into $L$ sub-streams $S_1,\\ldots,S_L$, such that,\n", "$S_l = (X_l,Y_l), (X_{l+L},Y_{l+L}), , (X_{l+2L},Y_{l+2L}) \\ldots$ for all $l=1,\\ldots, L$. \n", "\n", "Next, to predict the $t^{th}$ data point we use the substream $t~ (mod~L)$ as the calibration set and all the remaining data points as the core training set in the offline procedure described above. " ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Predict from 43 to 10000\n" ] } ], "source": [ "# LOAD THE DATA\n", "\n", "# MNIST DATA SET (MULTI-LABEL)\n", "digits = datasets.fetch_mldata('mnist-original')\n", "X, y = digits.data, digits.target\n", "y = y.astype(int)\n", "\n", "\n", "# THE OTHER DATA-SETS\n", "# PLEASE MAKE SURE THE LABELS ARE INTEGERS STARTING FROM 0.\n", "\n", "# COD\n", "#cod = datasets.fetch_mldata('cod-rna')\n", "#X, y = cod.data, cod.target\n", "#y = (y + 1)/2\n", "#y = y.astype(int)\n", "\n", "## CONNECT\n", "#connect = datasets.fetch_mldata('connect-4')\n", "#X, y = connect.data, connect.target\n", "#y = (y +1)/2\n", "#y = y.astype(int)\n", "\n", "## COVER\n", "# covtype = datasets.fetch_covtype()\n", "# X, y = covtype.data, covtype.target\n", "\n", "## LETTER\n", "#letter = datasets.fetch_mldata('letter')\n", "#X, y = letter.data, letter.target\n", "#y = y - 1\n", "#y = y.astype(int)\n", "\n", "## SATI\n", "#sati = datasets.fetch_mldata('satimage')\n", "#X, y = sati.data, sati.target\n", "#y = y - 1\n", "#y = y.astype(int)\n", "\n", "## SENSIT\n", "#sensit = datasets.fetch_mldata('sensit-vehicle-combined')\n", "#X, y = sensit.data, sensit.target\n", "#y = y - 1\n", "#y = y.astype(int)\n", "\n", "\n", "## OPTIONAL: TAKE THE FIRST 10000 DATAPOINTS\n", "from sklearn.utils import shuffle\n", "X, y = shuffle(X, y, random_state=0)\n", "X = X[:10000,:]\n", "y= y[:10000]\n", "T = y.size\n", "\n", "\n", "# MAKE SURE WE SAW EACH LABEL AT LEAST ONCE BEFORE THE START\n", "c = [0 for k in range(max(y)+1)]\n", "for tl in range(T):\n", " c[y[tl]] = tl\n", " if sum(np.equal(c,0))==0:\n", " break\n", " \n", "print('Predict from',tl,'to',T)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false, "scrolled": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ " 24%|██▍ | 2406/10000 [14:17<1:16:03, 1.66it/s]" ] }, { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m>\u001b[0m\u001b[0mtl\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0ml\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m%\u001b[0m\u001b[0mL\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0mpredictor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mtr_seq\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0ml\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mtr_seq\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0ml\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 23\u001b[0m \u001b[0mpred\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mref\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mtl\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mconj_calibrate_test\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpredictor\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mX\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mcal_seq\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0ml\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mcal_seq\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0ml\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mepsilon\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mtl\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mpred\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mref\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mtl\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/ensemble/forest.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, X, y, sample_weight)\u001b[0m\n\u001b[1;32m 288\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mX\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msample_weight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtrees\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 289\u001b[0m verbose=self.verbose, class_weight=self.class_weight)\n\u001b[0;32m--> 290\u001b[0;31m for i, t in enumerate(trees))\n\u001b[0m\u001b[1;32m 291\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 292\u001b[0m \u001b[0;31m# Collect newly grown trees\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/externals/joblib/parallel.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, iterable)\u001b[0m\n\u001b[1;32m 798\u001b[0m \u001b[0;31m# was dispatched. In particular this covers the edge\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 799\u001b[0m \u001b[0;31m# case of Parallel used with an exhausted iterator.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 800\u001b[0;31m \u001b[0;32mwhile\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdispatch_one_batch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterator\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 801\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_iterating\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 802\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/externals/joblib/parallel.py\u001b[0m in \u001b[0;36mdispatch_one_batch\u001b[0;34m(self, iterator)\u001b[0m\n\u001b[1;32m 656\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 657\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 658\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_dispatch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtasks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 659\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 660\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/externals/joblib/parallel.py\u001b[0m in \u001b[0;36m_dispatch\u001b[0;34m(self, batch)\u001b[0m\n\u001b[1;32m 564\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 565\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_pool\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 566\u001b[0;31m \u001b[0mjob\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mImmediateComputeBatch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 567\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_jobs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mjob\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 568\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_dispatched_batches\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/externals/joblib/parallel.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, batch)\u001b[0m\n\u001b[1;32m 178\u001b[0m \u001b[0;31m# Don't delay the application, to avoid keeping the input\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 179\u001b[0m \u001b[0;31m# arguments in memory\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 180\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbatch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 181\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 182\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/externals/joblib/parallel.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 71\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 72\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 73\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 74\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__len__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/externals/joblib/parallel.py\u001b[0m in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 71\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 72\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 73\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 74\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__len__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/ensemble/forest.py\u001b[0m in \u001b[0;36m_parallel_build_trees\u001b[0;34m(tree, forest, X, y, sample_weight, tree_idx, n_trees, verbose, class_weight)\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[0mcurr_sample_weight\u001b[0m \u001b[0;34m*=\u001b[0m \u001b[0mcompute_sample_weight\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'balanced'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindices\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 115\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 116\u001b[0;31m \u001b[0mtree\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msample_weight\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcurr_sample_weight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcheck_input\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 117\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 118\u001b[0m \u001b[0mtree\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msample_weight\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msample_weight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcheck_input\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/home/kocak_anil/anaconda3/lib/python3.5/site-packages/sklearn/tree/tree.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, X, y, sample_weight, check_input, X_idx_sorted)\u001b[0m\n\u001b[1;32m 348\u001b[0m max_leaf_nodes)\n\u001b[1;32m 349\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 350\u001b[0;31m \u001b[0mbuilder\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuild\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtree_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mX\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msample_weight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mX_idx_sorted\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 351\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 352\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_outputs_\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } ], "source": [ "# CHOOSE A TARGET ERROR RATE\n", "epsilon = 0.05\n", "# SPLIT INTO L STREAMS\n", "L = 2\n", "\n", "# CORE TRAINING SET FOR EACH SUBSTREAM KEPT AS AN ELEMENT OF THIS LIST \n", "tr_seq = [[] for l in range(L)]\n", "# CALIBRATION SET FOR EACH SUBSTREAM KEPT AS AN ELEMENT OF THIS LIST\n", "cal_seq = [[] for l in range(L)]\n", "\n", "# SET THE BASE PREDICTOR\n", "predictor = RandomForestClassifier(n_estimators=100, min_samples_leaf=1, oob_score=False, n_jobs=-1)\n", "\n", "# ERROR AND REFUSE FLAGS\n", "err_0 = np.empty(T-tl)\n", "err = np.empty(T-tl)\n", "ref = np.empty(T-tl)\n", "for t in tqdm(range(T)):\n", " # PREDICT THE t^TH LABEL\n", " if t>tl:\n", " l = t%L\n", " predictor.fit(X[tr_seq[l],:],y[tr_seq[l]])\n", " pred, ref[t-tl] = conj_calibrate_test(predictor, X[cal_seq[l],:],y[cal_seq[l]],X[t,:].reshape(1,-1),epsilon)\n", " err[t-tl] = (pred != y[t])*(1-ref[t-tl])\n", " err_0[t-tl] = pred != y[t]\n", " \n", " \n", " # UPDATE THE TRAINING AND CALIBRATION SETS \n", " for l in range(L):\n", " if t%L != l:\n", " tr_seq[l].append(t)\n", " else:\n", " cal_seq[l].append(t)\n" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/kocak_anil/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:5: RuntimeWarning: divide by zero encountered in true_divide\n", "/home/kocak_anil/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:7: RuntimeWarning: divide by zero encountered in true_divide\n", "/home/kocak_anil/anaconda3/lib/python3.5/site-packages/ipykernel/__main__.py:8: RuntimeWarning: divide by zero encountered in true_divide\n" ] }, { "data": { "image/png": "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\nSUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# PLOT THE ERROR AND REFUSE RATES\n", "\n", "time = np.array(range(T-tl))\n", "with plt.style.context('fivethirtyeight'):\n", " plt.plot(time,np.cumsum(ref)/time, 'r', linewidth=2, label = \"Refusal Rate\")\n", " plt.plot(time, np.array([epsilon]*len(time)), '--k', linewidth=2, label = \"Target Error Rate\")\n", " plt.plot(time, np.cumsum(err_0)/time, 'g', linewidth=2, label = \"Error Rate w/o Refusals\")\n", " plt.plot(time-np.cumsum(ref), np.cumsum(err)/(time-np.cumsum(ref)), 'b', linewidth=2, label = \"Error Rate with Refusals\")\n", " plt.ylim(0,1.1); plt.xlabel(\"Number of Data Points\")\n", " plt.xlim(0,T-tl)\n", " plt.legend(loc =\"best\")\n", " " ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### Discussion\n", "* The basic idea is based on _Conformal Prediction Framework_ and extends to \n", " * Arbitrary score functions\n", " * Online prediction (stochastic)\n", " * ...\n", "* PAC-type guarantees for conditioned probability of error.\n", "* Ongoing/Future Work:\n", " * Focus on the online prediction framework \n", " * Asymptotic error guarantees on adversarial/non-stochastic setups\n", " * Efficient and reliable predictors for changing environments, i.e. concept drift" ] } ], "metadata": { "anaconda-cloud": {}, "celltoolbar": "Raw Cell Format", "kernelspec": { "display_name": "Python [default]", "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.5.2" }, "nbpresent": { "slides": {}, "themes": {} } }, "nbformat": 4, "nbformat_minor": 1 }