From 9f17199e9bb75bc67e1941b2689565e26b2b13d2 Mon Sep 17 00:00:00 2001 From: Rayid Ghani Date: Thu, 18 Apr 2019 22:33:01 -0500 Subject: [PATCH] added lab3 --- labs/2019/lab3_lr_svm_eval.ipynb | 600 +++++++++++++++++++++++++++++++ labs/imgs/prk.png | Bin 0 -> 20067 bytes 2 files changed, 600 insertions(+) create mode 100644 labs/2019/lab3_lr_svm_eval.ipynb create mode 100644 labs/imgs/prk.png diff --git a/labs/2019/lab3_lr_svm_eval.ipynb b/labs/2019/lab3_lr_svm_eval.ipynb new file mode 100644 index 0000000..90decce --- /dev/null +++ b/labs/2019/lab3_lr_svm_eval.ipynb @@ -0,0 +1,600 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Lab 3: Logistic Regression, Support Vector Machines, and Evaluation\n", + "\n", + "\n", + "In this lab we'll get some hands on experience with two more classifiers we've seen in class\n", + "- Logitic Regression\n", + "- Support Vector Machines\n", + "\n", + "We will also explore evaluation metrics that we covered in class and understand how to calculate them." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Goals for this lab\n", + "\n", + "- Understand the practical implications for changing the parameters used in Logistic Regression and Support Vector Machines\n", + " \n", + "- Learn more about the evaluation metrics covered in class and learn how to calculate them (at different thresholds)\n", + " - accuracy\n", + " - precision\n", + " - recall\n", + " - AUC" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "import sklearn.tree as tree\n", + "from sklearn.tree import DecisionTreeClassifier\n", + "from sklearn.neighbors import KNeighborsClassifier\n", + "from sklearn.cross_validation import train_test_split\n", + "from sklearn.metrics import accuracy_score as accuracy\n", + "import graphviz # If you don't have this, install via pip/conda\n", + "%matplotlib inline\n", + "\n", + "# exercise: what additional modules should you import?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data\n", + "We'll continue to use the same data as in the previous lab.\n", + "\n", + "It is a subset of the data set from https://www.kaggle.com/new-york-state/nys-patient-characteristics-survey-pcs-2015\n", + "\n", + "The data has been downloaded, modified, and is in the github repo for the lab\n", + "\n", + "You should also try this with other data sets you have been provided for the homeworks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Change this to wherever you're storing your data\n", + "datafile = '../data/nysmedicaldata.csv'\n", + "df = pd.read_csv(dfile)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "df.dtypes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Some Quick Data Exploration\n", + "Before running any sort of model on your dataset, it's always a good idea to do some quick data exploration to get a sense of how your data looks like. Try to answer the following questions with some sort of plot/histogram/etc:\n", + "\n", + "1) What do the distributions of each feature look like?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Ex\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using scikitlearn for classification\n", + "\n", + "sklearn is a very useful python packager for building machiune learning models. To build a model in sklearn, you need to have a matrix (or dataframe) with X and y columns. X is your set of features/predictors. y is a single column that is your label. We'll take the foll;owing steps:\n", + "\n", + "1. Select/create column as label/outcome (y)\n", + "2. Select/create columns as features (X)\n", + "3. Create Training Set\n", + "4. Create Validation Set\n", + "5. Build model on Training Set\n", + "6. Predict risk scores for the Validation Set\n", + "7. Calculate performance metric(s)\n", + "\n", + "## Some useful things to know in sklearn\n", + "\n", + "fit = train an algorithm\n", + "\n", + "predict_proba = predict a \"risk\" score for all possible classes for a given record (classification only)\n", + "\n", + "\n", + "## Important- never use .predict\n", + "There is also a function called \"predict\" which first runs predict_probs and then predicts a 1 if the score > 0.5 and 0 otherwise. *Never* use that function since 0.5 is a completely arbitrary threshold to call a prediction 1 vs 0.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Create label/outcome\n", + "One thing we can do with this dataset is to try to use the various feature columns to classify whether a person has High Blood Pressure. Let's create a column that is 1 if a person has High Blood Pressure and 0 otherwise" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Question: what percentage of people have High Blood Pressure?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. create or select existing predictors/features\n", + "\n", + "For now, let's take a handful of existing columns to use.\n", + "\n", + "sklearn needs features to be numeric and not categorical so we'll have to turn our selected features to be binary (also known as dummy variables)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Train/Test Splits\n", + "\n", + "Create a train/test set split using sklearn's [train_test_split](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) function. We'll use these train/test splits for evaluating all our classification models." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# Logistic Regression\n", + "See the sklearn documentation on Logistic Regression to see its parameters. The one's we'll mostly be interested in are:\n", + "- penalty\n", + "- C" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Remember that when training a model, **you should only use the training data!** The test set is reserved exclusively for evaluating your model. Now let's use the classifier:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Logistic Regression Tasks:\n", + "\n", + "The goal here is to explore different penalty parameters and different C values. You can also try modofyinfg other parameters to see their impact. How does accuracy change, using different thresholds, as you vary penalty and C values? You can write a nested for loop that loops over all the parameters and values and store the results in a data frame (similar to last lab)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "Ref: http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html\n", + "\n", + "You'll notice that LogisticRegression takes a ton of parameters. We'll play around with the \"penalty\" and \"C\" parameters.\n", + "If we set the penalty parameter to ['l2'](http://mathworld.wolfram.com/L2-Norm.html), sklearn's LogisticRegression model solves the following minimization problem:\n", + "\n", + "$$ \\min_{\\beta} ||\\beta||_2 + C \\sum_{i} \\log ( -y_i (X_i^T \\beta) +1)$$\n", + "\n", + "Similarly, if we set the penalty parameter to ['l1'](http://mathworld.wolfram.com/L2-Norm.html), LogisticRegression will solve the following minimization problem:\n", + "\n", + "$$\\min_{\\beta} ||\\beta||_1 + C \\sum_{i} \\log ( -y_i (X_i^T \\beta) +1)$$\n", + "\n", + "where $$||\\beta||_2 = \\sqrt { \\sum_{i} \\beta_i^2 }$$ and $$||\\beta||_1 = \\sum_{i} | \\beta_i | $$ \n", + "\n", + "Try running logistic regression with both L1 and L2 penalties and a mix of C values. Something like $10^{-2}, 10^{-1}, 1, 10, 10^2)$ is reasonable." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding what's going on inside Logistic Regression" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To really see the difference between L1 and L2 regularization, we need to take a closer look at the models they produced. Plot a histogram of the weight values of LogisticRegression models for each C value. You can access these weight coefficients via the coef\\_ attribute in LogisticRegression. Do you notice anything interesting happening as the C value varies?" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Support Vector Machines" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ref: https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html#sklearn.svm.LinearSVC\n", + "The SVM Classifier also takes quite a few parameters. For now we will use Linear SVMs. The model is called LinearSVC in sklearn.\n", + "\n", + "We will be playing with following parameters:\n", + "* C: same as above\n", + "\n", + "SVM tries to find the hyperplane that maximizes the \"margin\" between the two classes of points. The \"C\" parameter in [SVC](http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC) has the same role as the \"C\" parameter in LogisticRegression: it tells you how much to penalize the \"size\" of the weight vector. Note that SVC only allows for L2 regularization.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Let's fit an SVM" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now predict scores on the test set and plot the distribution of scores\n", + "You might notice that the function you've been using to predict so far does not work. Is another function you need to use? Which one? Why?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### now we can select a threshold and calculate accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Let's now vary values of C and see the results." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Evaluation Metrics" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We covered several evaluation metrics in class:\n", + " - accuracy\n", + " - precision\n", + " - recall\n", + " - area under curve\n", + " - ROC curves\n", + " \n", + "Although sklearn has built-in functions to calculate these metrics,\n", + "in this lab we want to give you an understanding of these metrics \n", + "by writing functions to calculate them yourself.\n", + "\n", + "Remember that accuracy, precision, and recall are calculated at a specific threshold for turning scores into 0 and 1.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set Threshold\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "threshold = " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### We will first create a confusion matrix based on this threshold" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "true_positives =\n", + "false_positive =\n", + "true_negatives =\n", + "false_negatives = " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Let's now write functions that can calculate each metric" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def calculate_accuracy_at_threshold(predicted_scores, true_labels, threshold):\n", + "\n", + "\n", + "def calculate_precision_at_threshold(predicted_scores, true_labels, threshold):\n", + "\n", + "\n", + "def calculate_recall_at_threshold(predicted_scores, true_labels, threshold):\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now let's calculate all of these for a logistic regression model you built above" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now let's write a function that generates the precision, recall, k (% of population) graph that we covered in class\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def plot_precision_recall_k(predicted_scores, true_labels):" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### let's plot it for the same logistic regression model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now we build the same graph for an svm model and compare the two. Which one is better?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.14" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/labs/imgs/prk.png b/labs/imgs/prk.png new file mode 100644 index 0000000000000000000000000000000000000000..e346fbe51ec7e68a44d238098f1f39b5255de49e GIT binary patch literal 20067 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 literal 0 HcmV?d00001