{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "0724f649", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Registered S3 methods overwritten by 'ggplot2':\n", " method from \n", " [.quosures rlang\n", " c.quosures rlang\n", " print.quosures rlang\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Registered S3 method overwritten by 'rvest':\n", " method from\n", " read_xml.response xml2\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "-- Attaching packages --------------------------------------- tidyverse 1.2.1 --\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "v ggplot2 3.1.1 v purrr 0.3.2 \n", "v tibble 2.1.1 v dplyr 0.8.0.1\n", "v tidyr 0.8.3 v stringr 1.4.0 \n", "v readr 1.3.1 v forcats 0.4.0 \n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "-- Conflicts ------------------------------------------ tidyverse_conflicts() --\n", "x dplyr::filter() masks stats::filter()\n", "x dplyr::lag() masks stats::lag()\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Warning message:\n", "\"package 'kableExtra' was built under R version 3.6.3\"" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n", "Attaching package: 'kableExtra'\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "The following object is masked from 'package:dplyr':\n", "\n", " group_rows\n", "\n" ] } ], "source": [ "library(tidyverse)\n", "library(kableExtra)\n", "library(ggplot2)\n", "options(readr.num_columns = 0)\n", "churn <- read_csv(\"../_build/data/churn_train.csv\")" ] }, { "cell_type": "markdown", "id": "c235064c", "metadata": {}, "source": [ "# (§) k-Nearest Neighbors (kNN)\n", "\n", ":::{note}\n", "This section is optional, and will not be covered in the DSM course.\n", ":::\n", "\n", "For many businesses, **customer churn** is an important metric for measuring customer retention. Banks, social media platforms, telecommunication companies, etc. all need to monitor customer turnover to help understand why customers leave their platform, and whether there are intervention strategies that can help prevent customer churn. \n", "\n", "Imagine that you work for a telecommunications provider and would like to reduce customer churn. To that end, you hope to develop a predictive model that will identify which customers are at a high risk of leaving for another provider. If you could identify these customers before they leave, you may be able to develop intervention strategies that would encourage them to stay. \n", "\n", "Using historical customer data that your company collected in the past quarter, you compile a data set with the account characteristics of each customer and whether or not they \"churned\" by the end of the previous quarter. This data is stored in a data frame called `churn`, the first few rows of which are shown below. A data dictionary which describes each variable in the data set is also provided below." ] }, { "cell_type": "code", "execution_count": 2, "id": "32a86f25", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "
account_lengthinternational_planvoice_mail_plannumber_vmail_messagestotal_day_minutestotal_day_callstotal_night_minutestotal_night_callstotal_intl_minutestotal_intl_callstotal_intl_chargenumber_customer_service_callschurn
165 no no 0 209.4 67 150.2 88 12.8 1 3.46 0 no
103 no no 0 180.2134 181.7134 8.4 3 2.27 1 no
90 no yes 27 156.7 51 123.2111 12.6 6 3.40 2 no
36 no no 0 177.9129 306.3102 10.8 6 2.92 2 no
95 no yes 35 229.1143 248.4110 3.9 3 1.05 0 no
119 no no 0 231.5 82 211.0118 7.4 10 2.00 1 no
\n" ], "text/latex": [ "\\begin{tabular}{r|lllllllllllll}\n", " account\\_length & international\\_plan & voice\\_mail\\_plan & number\\_vmail\\_messages & total\\_day\\_minutes & total\\_day\\_calls & total\\_night\\_minutes & total\\_night\\_calls & total\\_intl\\_minutes & total\\_intl\\_calls & total\\_intl\\_charge & number\\_customer\\_service\\_calls & churn\\\\\n", "\\hline\n", "\t 165 & no & no & 0 & 209.4 & 67 & 150.2 & 88 & 12.8 & 1 & 3.46 & 0 & no \\\\\n", "\t 103 & no & no & 0 & 180.2 & 134 & 181.7 & 134 & 8.4 & 3 & 2.27 & 1 & no \\\\\n", "\t 90 & no & yes & 27 & 156.7 & 51 & 123.2 & 111 & 12.6 & 6 & 3.40 & 2 & no \\\\\n", "\t 36 & no & no & 0 & 177.9 & 129 & 306.3 & 102 & 10.8 & 6 & 2.92 & 2 & no \\\\\n", "\t 95 & no & yes & 35 & 229.1 & 143 & 248.4 & 110 & 3.9 & 3 & 1.05 & 0 & no \\\\\n", "\t 119 & no & no & 0 & 231.5 & 82 & 211.0 & 118 & 7.4 & 10 & 2.00 & 1 & no \\\\\n", "\\end{tabular}\n" ], "text/markdown": [ "\n", "| account_length | international_plan | voice_mail_plan | number_vmail_messages | total_day_minutes | total_day_calls | total_night_minutes | total_night_calls | total_intl_minutes | total_intl_calls | total_intl_charge | number_customer_service_calls | churn |\n", "|---|---|---|---|---|---|---|---|---|---|---|---|---|\n", "| 165 | no | no | 0 | 209.4 | 67 | 150.2 | 88 | 12.8 | 1 | 3.46 | 0 | no |\n", "| 103 | no | no | 0 | 180.2 | 134 | 181.7 | 134 | 8.4 | 3 | 2.27 | 1 | no |\n", "| 90 | no | yes | 27 | 156.7 | 51 | 123.2 | 111 | 12.6 | 6 | 3.40 | 2 | no |\n", "| 36 | no | no | 0 | 177.9 | 129 | 306.3 | 102 | 10.8 | 6 | 2.92 | 2 | no |\n", "| 95 | no | yes | 35 | 229.1 | 143 | 248.4 | 110 | 3.9 | 3 | 1.05 | 0 | no |\n", "| 119 | no | no | 0 | 231.5 | 82 | 211.0 | 118 | 7.4 | 10 | 2.00 | 1 | no |\n", "\n" ], "text/plain": [ " account_length international_plan voice_mail_plan number_vmail_messages\n", "1 165 no no 0 \n", "2 103 no no 0 \n", "3 90 no yes 27 \n", "4 36 no no 0 \n", "5 95 no yes 35 \n", "6 119 no no 0 \n", " total_day_minutes total_day_calls total_night_minutes total_night_calls\n", "1 209.4 67 150.2 88 \n", "2 180.2 134 181.7 134 \n", "3 156.7 51 123.2 111 \n", "4 177.9 129 306.3 102 \n", "5 229.1 143 248.4 110 \n", "6 231.5 82 211.0 118 \n", " total_intl_minutes total_intl_calls total_intl_charge\n", "1 12.8 1 3.46 \n", "2 8.4 3 2.27 \n", "3 12.6 6 3.40 \n", "4 10.8 6 2.92 \n", "5 3.9 3 1.05 \n", "6 7.4 10 2.00 \n", " number_customer_service_calls churn\n", "1 0 no \n", "2 1 no \n", "3 2 no \n", "4 2 no \n", "5 0 no \n", "6 1 no " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "head(churn)" ] }, { "cell_type": "markdown", "id": "3a0607e4", "metadata": {}, "source": [ "+ `account_length`: number of months the customer has been with the provider.\n", "+ `internation_plan`: whether the customer has an international plan.\n", "+ `voice_mail_plan`: whether the customer has a voice mail plan.\n", "+ `number_vmail_messages`: number of voice-mail messages.\n", "+ `total_day_minutes`: total minutes of calls during the day.\n", "+ `total_day_calls`: total number of calls during the day.\n", "+ `total_night_minutes`: total minutes of calls during the night.\n", "+ `total_night_calls`: total number of calls during the night.\n", "+ `total_intl_minutes`: total minutes of international calls.\n", "+ `total_intl_calls`: total number of international calls.\n", "+ `total_intl_charge`: total charge on international calls.\n", "+ `number_customer_service_calls`: number of calls to customer service.\n", "+ `churn`: whether or not the customer churned. \n", "\n", "Our goal is to use the information stored in the `churn` data set to predict whether new customers will churn in the upcoming quarter. A straightforward way to accomplish this would be to identify the observations in `churn` that are most similar to our new customer, and then observe whether or not those customers churned in the previous period. For example, if our new customer is from the Midwest, has twenty voice mail messages, does not have an international plan, etc., we could identify the observations in `churn` that have the same (or very similar) characteristics. If the majority of those customers churned in the previous quarter, we might predict that our new customer is likely to churn; if the majority did not, we might predict that our new customer is at a low risk of churning. This is in essence how the k-nearest neighbors algorithm makes predictions.\n", "\n", "More formally, the **k-nearest neighbors (kNN)** algorithm starts by calculating the distance between a new observation and each of the observations in `churn`. The $k$ observations that are closest to the new observation are considered its \"neighbors\". If most of these neighbors churned in the previous quarter, the model predicts that the new customer will churn (and vice versa). The number of neighbors that the model considers is determined by $k$, which is set by the user. $k$ is known as a **hyperparameter**, or a model parameter whose value must be specified by the user.\n", "\n", "To demonstrate knn, let's start with a simplified data set that only has 100 observations and two independent features, `total_intl_charge` and `account_length`. Our **feature space**, or the geometric space that our data occupy, looks like the following:" ] }, { "cell_type": "code", "execution_count": 3, "id": "449714b3", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "image/png": "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\nqrH+AAAAAElFTkSuQmCC", "text/plain": [ "plot without title" ] }, "metadata": { "filenames": { "image/png": "C:\\Users\\phamilton\\Documents\\Projects\\dsm\\dsm_website\\_build\\jupyter_execute\\08_knn\\knn_4_0.png" } }, "output_type": "display_data" } ], "source": [ "churnSample <- read_csv(\"../_build/data/churn_sample.csv\")\n", "churnSample$churn = ifelse(churnSample$churn==1, \"churn\", \"no churn\")\n", "churnSample$account_length = churnSample$account_length*sd(churn$account_length) + mean(churn$account_length)\n", "churnSample$total_intl_charge = churnSample$total_intl_charge*sd(churn$total_intl_charge) + mean(churn$total_intl_charge)\n", "library(ggplot2)\n", "\n", "suppressMessages(print(ggplot(churnSample, aes(x=account_length, y=total_intl_charge, color=churn, shape=churn)) + geom_point(size=2) + theme_bw() +\n", " theme(axis.text=element_text(size=12),\n", " axis.title=element_text(size=14,face=\"bold\"))))" ] }, { "cell_type": "markdown", "id": "8fa9f76c", "metadata": {}, "source": [ "Suppose we have three new customers and would like to predict whether or not they will churn in the upcoming quarter. These customers are plotted as green squares in the figure below. If we use a $k$ of five, we can find the five customers in `churn` that are most similar to our new customers (based on their `account_length` and `total_intl_charge`):" ] }, { "cell_type": "code", "execution_count": 4, "id": "d555c4c3", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0gAAANICAMAAADKOT/pAAAAclBMVEUAAAAAZAAAv8QzMzNN\nTU1oaGhycnJ8fHyDg4OMjIyOjo6VlZWampqjo6Onp6evr6+ysrK5ubm9vb3BwcHHx8fJycnQ\n0NDR0dHW1tbY2NjZ2dne3t7h4eHk5OTp6enq6urr6+vv7+/w8PD19fX4dm3///9r+k69AAAA\nCXBIWXMAABJ0AAASdAHeZh94AAAgAElEQVR4nO2dDWPauJqFNYxZwpbSlObSHSaXpjT+/39x\n/f2BJfuVLFtHcJ7dmwkQDgfLT22EMSolhMxGhS5AyCNAkQjxAEUixAMUiRAPUCRCPECRCPEA\nRSLEAxSJEA84ivQ3IWHx68FsXEUaXPMxs8j8ACbAVFghgSKZiGH0okgAqECRpFAk3ASAChRJ\nCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXC\nTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCo\nQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGk\nUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTc\nBIAKFEkKRcJNAKhAkaQ8rUifn+E7LB0QRQJFMhHD6H0WhO2wfEAUCRTJRAyjR5FgEiiSiQhG\n7/Nz0iSAZwFQgSJJoUihOqwQEEUCRTIRw+hx1w4mgSKZiGH0KBJMAkUyEcPocfobJoEimYhh\n9KJIAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJN\nAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhA\nkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQ\nJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwE\ngAoUSQqCSIOzB8cw/iskAFSgSFLCi6Q5n30M479CAkAFiiSFIuEmAFSgSFKCi6T7zq8Yxn+F\nBIAKFEkKRcJNAKhAkUb4b9K5EFwk7tohV6BIZv68UKQ4EgAqUCQz3xIskTj9DVyBIhn5J4ET\niQmwFSiSid/JV4oUSQJABYpk4mvymyJFkgBQgSIZ+E/yT1qL9HfBByEhiVKkX8m3NOUWKZIE\ngArcIun58vKHIkWTAFCBImn5nvybUqRoEgAqUCQtSUNzFUXCTQCoQJG0UKSoEgAqUKQRuGsX\nSQJABYo0AkWKJAGgAkUagSJFkgBQgSJJoUi4CQAVKJIUioSbAFCBIkmhSLgJABUokhSKhJsA\nUIEiSaFIuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJIUioSbAFCBIkmhSLgJABUokhSKhJsAUIEi\nSaFIuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJIUioSbAFCBIkmhSLgJABUokhSKhJsAUIEiSaFI\nuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJIUioSbAFCBIkmhSLgJABUokhSKhJsAUIEiSaFIuAkA\nFSiSFIqEmwBQgSJJoUi4CQAVKJIUioSbAFCBIkmhSLgJABUokhSKhJsAUIEiSaFIuAkAFSiS\nFIqEmwBQgSJJoUi4CQAVKJIUioSbAFCBIkmhSLgJABUokhSKhJsAUIEiSaFIuAkAFSiSFIqE\nmwBQgSJJoUi4CQAV/CRsxm6nSCZARi/+BIAKXhI2FMkJjNF7gASACp5EGjOJIpnAGL0HSACo\n4CNhQ5HcgBi9R0gAqOAhYbMZN4kimUAYvYdIAKhAkaRQJNwEgArzEzabCZMokgmA0XuMBIAK\nFEkKRcJNAKgwO2GzmTKJIpkIP3oPkgBQgUc2SKFIuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJIU\nioSbAFCBIkmhSLgJABUokhSKhJsAUIEiSaFIuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJIUioSb\nAFCBIkmhSLgJABUokhSKhJsAUIEiSaFIuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJKU5xLptFNq\n92a4zymx7aBKDhebDnKAF6THBIpkAmT0Pj/vr7wm5Yq/099H9RahhUhKnQ0d5gGyIBdOoEgm\nIEbvs6B/ZaIO1zQ9J+qkvY+LSMV/XtVW20GQMArEglw8gSKZgBg9jUhval/896yS2oHi52ui\ntqdy85Jduh5U4dtHdmmf3eO6Vftbdv0tv/5W3Oc9qbZptXpKu/AfY0EunkCRTCCM3ufn0KS9\nql7LvKddkY7FztmpEulW7P4lt1ykffbb2zZ/EZTmm7OMbXGfXXFF2tkiHRd5FggLkiIJeSKR\netuNViSlruml2Ugd81dQu8yMj9yfN5X99pbfUMhyVMWW69iGVLMNyzwLhAVJkYQ8qEi6XTuD\nSNkrp3N71TbTKr1mm56PXLDsult5w7b8+30pXhNSsl/mWUAsyMUTKJIJiNGTi3TOdtq21/qq\n5vqP9mK53SrpxVS/vnHXbkYCRTIBMnqD6e/mNVJ66U02pO9blVxmiJSq3jtQ3p4FyIJcOIEi\nmUAdvXrW7pIcKgeutQmnxpDurl3aEWnbLF+dSJy1c0+gSCZgR695H+k9//0tve3K10iX9F07\n2ZB2RDrmu29v+Y0DkW5H/Yukx12QXhMokgnY0btuy92z/BVNMen92k5/v+ZaJP3p77QjUnl9\nrmBPpIr3RZ4F7IL0mkCRTACP3vmQ1MfaHZNMnnIjlKgk8yjbv8tf6nTfkO2+bsqv311SjUjJ\nQevRQy9IjwkUyUQMoxdFAkAFiiSFIuEmAFSgSFIoEm4CQAWKJIUi4SYAVKBIUiIRafjhovU7\nrJ4AUIEiSYlCJN2Hi9buECABoAJFkkKRcBMAKlAkKTGIpPtMxNodQiQAVKBIUigSbgJABYok\nJQaRuGv3yAkUyQRF8pQAUIEiSfn7Iwo+P0M3IAvxKCINronlH9LRTVQ3wfY9KIsOyyYAVOAW\nSUqsIk3s7X1I/3BOh6UTACpQJCkUyb3D0gkAFSiSlEhFmpoR/5D+4YwOiyf4qbAB6DAGRTJB\nkewSjGu6lwqbzSyTKJKQSEV6oF0785pOkUJAkfQJLiLlf7+WSJtlRdqM5MsS5ncYhyKZiH36\nu1RvTZEMa7qHChuKZMvTibRYwhyRutKKEsbWdG8izTCJIgmhSPc4T0/c70ZKOmzG1vT5i2Ez\nmi+BIgmhSPdQJL8dKJIrkYvkvmt3p6AgYTO6ps9eDJvxfAkUSQhFGrCiSOPEviBlCRTJRAyj\nN47r9Lf9rt0ooRfDOgkUyQTA6Lkd8D27A0VySKBIJoKPnvNkwfwO5ulv6KOUQiZQJBPBRy+g\nSKYEp0rBF+QqCRTJROjRmzF/7a3DfQJFMkKRTIQePUCR3CqFXpDrJFAkE8FHb8Ybqt46pBRJ\nmECRTAQfPUeRPM+5cddOlkCRTACM3koH+IxDkUQJFMlEDKOnwfdxCZz+liVQJBMBR2+OBguL\nFCIgigSKZCLY6HVEADguIeIFuWoCRTLxECIFOsjIb0AUCRTJRKjR6+6bzTzAB+PYiBg0mJ9A\nkUwEGr3P+SLdZc3LiHZBrpxAkUwEnXObsWs3DJsVMtFBkB6DBvMTKJIJipROdhDlx6DB/ASK\nZCLE6H3erfvou3YUqYEimQgpklWCeU1eWiTZJi8GDeYnUCQTAXftbBLGV+Vlp78pUgtFMvEQ\nIi38LLhr10CRTASb/rZKmNooUKSVEiiSiRhGL7RInP5uoEgmYhi9NPCu3ToBUSRQJBMxjF5K\nkVASKJKJGEavQPzFMO4dwL/kCyGBIpmIYfRWSkD/tjyEBIpkIobRWylBePb65b4fKYKEJxPp\ntFNq92YIOSXTAQOUMlaOYfwlCaavgbjbp1zua11iSHgqka6JKtgZHrv34LJlf87izobbvI9e\nmBMmGL5QZTDLQZGQWFSkRB2u2bqfqJP+sR1EOqi9Ohhu8zx6TkfOrSfSct+PFEXCM4n0pvbF\nf88qqa0pfr4mansqdtLyS9eDKnz7yC7ts3tct2p/y66/5dffivu8J802Tambcd8uPpF08Ybv\n+Bq8E0yRoFhSpL26lL+8p12RjsXu3qkS6Vbs/iW3XKR99tvbNvuRb3OK67fFfXbNRuic/XYw\n7dv5Gr1ybXX7dJFNB32+UCTzV+rFoMH8hGcSqbfpaEVS6ppemo3UMX8FtVPHXKRDthHLfnvL\nb3jNfsluLLZcxyYll+hs2rfzM3r1+hpIJOPXTuo2SFqTYtBgfgJFyl85ndurtplW6TXb9Hzk\nguW7buUN2/Lv96V4vRTTvp1fkRbftTOYakrQbpAoEgoBRDpnO23ba9qzIvv50V4st1slvZhz\ndaV+387L6LWrN5hI/VdUI9+XHIMG8xOeSaTmNVJ66U02pO9blVxcRDpUV+r37TyLtPj0t97U\n2c8iBg3mJzyTSPWs3SU5VDpcaylOjSHdXbu0I9K2adYRKVHFfJ7qvZM7VsGS3q6dc4KU2SLx\nfSQc1nkf6T3//S297crXSJf0XTvZkHZEOuZTDG/5ja1Il2pTdGg2dZMV7FhXJP0mT57AN2SB\nWFSk67bcE8tn3YpJ79d2+vs1NyTpT3+nHZHK63MFW5GOlUDnzjzeRAU7utPfcxLmd5DA95GA\nWFSkbJU/JPWxdsckk6fcCCUqyTzK9u/yXbTuG7Ld10359btL2hUpSe5/EVSwIaoEviGLxMIi\nWRDD6CEl8A1ZKChSrAkUCYqnEUn0wgdtDRr5WBLfkMXiSUQSTsWBrUFjn++jSFhQpPoPFu9g\nelBzwsgnZXlkw+xH8MtjiDSlwegBqNnV9a2rrkGGSm2CaVrOX4WIEyiSCfeAaQ1GRPpsARPJ\nOJvgr0LECRTJxJIijezafXZNWnMNMslNkUQJFMmEc4BEA8kGCUwk82yCtwoxJ1AkE3NEUmpS\nA+MLJNRdO0uR2r+LQYP5CRTJhHtAoZGrBqgijUzL6ej8XQwazE+gSCZcA0qNZoqEOf1tAUUK\nTOwilUe0ztLA7ovGJgiU0N10RfskrBIokgmXAJcz4/nuAJHQ3QmM9klYJVAkE/YB9ydBiWH8\nl0nYUKTQxCvS8FxCi48e7NF6vXmJGDSYn0CRTNgF6E7JtfDojRxltFoHPf0Zvhg0mJ9AkUzY\nBOjPbPe0IsFVoEhSgoq07AkiTYwcr7dah3UCokigSCakAaG+H4kiQSVQJBOyALNG3LXDqUCR\npAQSaUwjbJHkp/iiSKIEimRiOmBcI+Tpb5GDsg4rBESRQJFMTAVMaYQ8/hTJewJFMjEeMK0R\n8PjnFimpSRRJlECRTIwFSDQCHv/KI4rkMYEimTAHyDRCHn+LDRJFkiVQJBOmAKlGK4+/wQuD\nSPINEkWSJVAkE/oAuUa+Rk+0whtnDwwdFKe/PSdQJBO6ABuN/IyecH7NUiSbp0GRRAkUycQw\nwE6jNUUyHy5EkVZKoEgm7gNsNfIyerID6kbms7Ud1t2uxqDB/ASKZKIfYK/RmiJVJgk7yJ6K\nt1MuxKDB/IQ4RfrzPUm+/+pc4VWkvzpUrZz8Xvk1kl+R/H1SPAYN5ifEKdJLktMxaVGR3DRa\nVaRick9XU9NBuEGiSFYJUYr0I/me//jWXrOgSK4a+Z/+nhLKp0geT7nwMfb9ZMKE+R2WTohS\npJfkT9r/BuTFRHLXyPfoCbZNmq6auUfRI/sUye3bYLoJcytQpDGSl/b3hUSao1EAkTRLb9DB\nwiNP5y5x/FqlDhTJHvma+yP52V5YRCSl6skGN7yOnmj+zrdIG12CLY7fBtOBItkjFemfJPlR\n/vZ3wYdHWo3++stn7ixqkcb/Sk3FTP5BQXM6LdFfS7I8BGETq0g/v70k/2kvet8iKVWK5J4S\nYtduuPgGbyuLHrd7YrqZz8L5a5U6cItkj8WLku+dfTvPIuUW5f8XnUiD5fcxfrNlBwcoUhgs\nRvpPZ7bBq0iNRUivkVLhceB3CzC0SJZfq7REhXUSIhapO//tUaR8l678/7+gZu2EjIrk8nT4\nhqwoIUqRyveRfidfmmu8iZSrU841VFMObjFzKowm2O7cfZhvcu6wdkAUCVGKVBzZ8Oeb/9dI\n1RYo/6k+LArpmTF6lS/3CfYTDhRppYQoRaqOtfvaXuFFpHpHrvhPLdIMk5xHr/HFr0huz4Qi\niRLiFCn98ZJ86bwf60Ok5vVQtVVqApxN8i6S8EMV3cIUaaWESEW6Z7ZI7bRCvXfXBria5Dp6\nrS9eRXJ8GhRJlECRikdtH7bZvQu3ChpFkn6ootM33D8H/gKiSKBI/Q9KtPt3AXeK5r1GSrt9\nKdJKCRSp915RZwfvw/hHUvyLJP0WCY1I67/S8xYQRcKzi9Q3pLuHdxfgUMz/9LeYpi1FWinh\nuUW629D0dvHuA+ybBRz/gUgBJvG9BUSR8MwijeyvKU2AdbWQ41+XpUgrJTyvSEON+nMOwwDb\nbkHHX/US3D2iSLKEZxVJszW6m3TQBFiWwxFphkcUSZbwnCLpduruZx10AXbtwo6/6iRQpMUT\nnlEk7WujwbSDNsCqHoxIczyiSLKEJxKpmlLWTzGowUX9klv/a12cUU0CRaJIQqZFqt7kNIgw\n9Mi45OQNQ49//SxmeUSRZAnPJZJpe3J/9ZhI8oqhx796FvM8okiyhGcR6bP65hPZg46KJO4Y\ndvybT/mGPvNEDBrMT3gqkQwHfOpnwsdmK2SlgotUn8GFIlEkIeLXSPIWY0tO1pIi+QmIIoEi\n6R5ySiRZzfAiVacVo0gUSYjF9LfgEduJYyOSnhTJT0AUCU8kkvwBBSJJ3lACEOkvgBMvx6DB\n/IQIRLq97rK1dncZu5v755GMV04GTJoEIFJ+0tjsf6E6+AmIIgFfpHOSn9A+2wIcR+7mKtLI\n27PTAVMmYYhUfiNAmA5+AqJIgBfpqlQlkjqb7+b6wb6RqwUBE6tneJGql0hhv8AzBg3mJ8CL\ndFTJJV8Nbju1N9/NTaQxj+YEWFQYx59IuUpuLlEkUQK8SIl6L/89vY2tCG6fkB29fs4mTVxh\ngpki1d8FUL9GcnKJIokS4EUqxr79YcDv17pYBIytmaHHX6WaowitXdJ3sPiWltCLYZ0EeJGa\nLdJFJbo7lLiIZFyjbEQaMyn0+GfVlCbB0iVtB5vvOwq9GNZJgBfpoJJzLtI5UQfz3VzO2TBx\ni/iNKGV6rzfw+BcbJH1Cx6XJw6YokigBXqRq1i7n3Xw3e5FG/lW2Eyn7e8PRR7gipfWOsuAI\nRF2C1VfwxaDB/AR4kdJz7dHI7LfDyU8mb5Iv+0+FKFLxNMwilZsliuQrAV+k9HbcKrU93sbu\nZivS2KsEW5HKDzppVse5o/f5OXvGZEyktHBp0iRNgt23wsagwfyECESSYHsWIcGNNiIVJtlV\nEMWKP/cxRCRS8aFhZ5GEJsWgwfyEpxRp/EHsd+0WeY1kSBW6VT2JCZHEu3Y9Zyy/qDwGDeYn\nPKNIE4+BIZL+I7223+viSaS+NBs7k2LQYH4CvEiqy/5kuJuNSFOuWou0yPT3OiIJp79tZru1\nAfOIISEukZTa6e/m8ciGukHo0TN7NG1SsxSnRZrkw3KSThcwvwJ8QmwiKf02yUIk4QYp+Ojh\niGQ1R6cLmF8BPwFepHSXvN3S9HZK8o3RwbBJkos0+SIMRSTN9PdGuGvXPkePIjmbFH5BUqQ0\n/xhFdUDDJd8YXQ3HiYlFmp7MwBHpPmEjFKnjkY8OlpN0w4D5FSJIgBcpaXdTtqnxEHCpSIJJ\nQTCROtoU67LVl5pTpNUS4EVqDrF7H/sshVAkyeQ6lEjdLZB0XVbdX+d3aCe7HU2CWJCLJ8CL\ntFXJOX+NdE7yLZLpsxQykWw8whi9jkiidTm/3bNIsxMAKlCkNH3rTdgpw2cpRCKJ3uyFEqk7\nSycRKf+D7rMMIdKgIsKCpEj5bENFfhYh0zHgEpFEHsGKJNq9ym7vPcsAIg0rIixIipTxfsiP\n/j4UL5XUq/5uApFkHmGJ9HG/QRoXaUORgiVEIJIEf0c2gIokecVfeNS7fX2RNBUhFuTiCfAi\nGQ+v6zEmUvkvutRQLJHER3vnlCJ1V2OKtFoCvEiyM3WYRar+Tbf2KIrR66HZZq0ukm6rGd2C\ndEqAF2mrRj8aWzElkniPkSJ56eAcML9CoAR4ka7b3XlaJaNIlUfi/aN4RdK9cbq2SNoXcrEt\nSLcEeJG6R36b7zYukum7Y0cfP4bRm0CFk9kxYH6FUAmPLpLdqQ+6+4AxjN4Eq4u0TEAUCRSp\npb8TCDh6tge7UaT1EuBFkjE9/S2gvxOIN3rWh41SpPUSnkAkKdWrqdokvNGjSMAJFKkBXST7\nTzJQpPUSIhLp3e9J9If0X07BjV4UImkKwi3IRRLwRTrvZk02WIAtksOH69YXSVcQbUEukwAv\n0mXmrJ0V3XkJtNFz+JgqRVovAV6kfaPR9mq+m9dv7PMU4DfB5fPeYd6QnRMwv0KoBHiR8g/G\n7tQ1ve4W+FbzMWBGr1wzJZ+juAdZJJt/EGCGYoQIRErTV/WWn/zEcJbVnAcWyXrSu2VtkfSm\nawOsnhXKUIwRhUiX4kwNq30Zs6eACEXSPZK9SILPI9ltWVGGYgx4kfKPUdzyc3KdnlMk+0nv\nBmXbQftI8gTDzqdJpMf6Flp4kU5qd013YyfQz6FIGoKJNPnBPssXeyBDMQq8SLlE1Rz4xXy3\nhxXJ4d2jBluR9I+0wIK0nTbBGIpx8EVKT9s0PW/VdsSjhxfJySRLkQwPRJFECRGIJOFRRXJ5\n96jBSST/bwMNAqxn8iGGYuJ2imQCYvRc3j1qsBPJ9EiPsSAXT8AX6f2w3iFCXgOCJ1CkFRPg\nRXpf81g7rwHBE6xE2pg2flyQogR4kQ4UyRXr6e8FOmBUoEj58QxHwYntKJIGirRigkgk2dlO\nvaARSXI3iqQBQKRN+AorJcCLtKVIroQXqXjBFXoxrJMAL9Jx7ICGBoo0RIXvQJFKrnuVlF/v\nla3P9W/VT6Xek132s/4bTwxEuiXJyOeQaijSEBV8v6qcA4x+QYoSxkS6JflU2T6XZl99ZV5X\npJ06ZD+T+sv0/NAVSd1jvhtFGqKCbw4oUskxM+VSSXNLX/PvQe6KVG6hsltOhm9IdoEi+UrY\nBBepelsq9gUpSxgTqflGlWwHLq31SZvfrr1bPEGRfCXkIoXdHMw5TtBThfUSxkRq1tyuPsPf\nFhPJAop0zya4SLMOuPVTYcUEimRi5dHTrm6ztgYq8H7VrANu/VRYMUG4a1f/LH67UiTvCfrV\nbf5uFcA6CFAh+GTDMT9mtKtLot7S225dkc7b/Od29EuZKdIgDma/KgYN5ieMiXQtpra3XV2O\n+TWvq4p0rB9jbI49dpEM63wMa1AMFUK/IfuebXsO154ux0S9rvoa6azqxxg9QeRH3JS7YSRe\n4I/+3uXvVGVkO5R7890i3yKZdsNi+Kc4hgqht0gBGIik6hmP2wO/j2R6QRPDGhRDBYrU3W18\nXJGMMwMxrEExVKBI+Tzhe/nLZexApAcRyfv5EhASACpQpHzSLnnNVHo/jk7bxS3SYycAVKBI\n9SHoBU/9/UjxJgBUoEgZ75VJyVOeafUBEgAqUKSCt71S+7fRu1EkrITui71on4RVQgwiCaBI\nUAkbihSaKZEMc+AUaUD5xdKhROqYFPuClCVQJBPBRq/z1eruHT4LAj2LDUUKztOLVBsws0NI\nke7eEotBg/kJFMlE1CJ9VlCktRIokokwo9cYMK9DSJHuj9KIQYP5CRTJRNQihdy1o0gIPLtI\n8b9GGhw4GIMG8xMokom4Rbqf/nb/yHmsC3LlBIpkIu7p77uEGSdviHdBrppAkUzEMHo6Oh6m\nFGm1BIpkIobRG9LbM2wS5pxP6EkXpG0CRTIRw+gN0Yo068RcnQ5uEXEuSNsEsUj9PQYNUwrI\noEizEvqz52lPJEeT2g6OCVEuSOsEoUj3/9BpoEgACVqR5p0ssiuSU0KUC9I6AVmkJ/82Cqfj\nEnS7dp5Eck0IviBXSZCJNPiHrku1iqu0/m/5I7/cXCmGIlUI/umS3O2j+w7pLA+cE2LQYH7C\nfJEacSqL+pcbtYRQpApHkQzT3zOgSKKE+bt2qvtfNfyvu0gWPJxIo/sAK3XoJbhv1GLQYH4C\nRTJBkXoJYpEe8yyXK0x/U6RFEvx45O1ZiF9nPehZLld4Q3ZhkZpXRrfD455EXwOYSKn0bSSK\n5IpOILWASA987m89gT7fakwQvUDSbLSgnsRiCR4OEWqmv9PaIuVpi3R44lk7uATZCySKBEJf\nlqTn0VPt2qElyKYadK+jgJ7EggnYIl06GiWHkbtRpKUTpDMNw78DehILJmCLlEq/VpMiLZwg\nm7OjSDBQJMwEkUj6g5FwnsSSCfAiyaBIyybMOVwP5kksmoAv0mXHWbuoEwAqUKT+fIP5bhQJ\nNwGgAkVK0x1FijwBoAJFyicbDrfpu1Ek3ASAChTpOWftvJwgEiYBoAJFyg9ukNztkUTqHK4a\nwxoUQwWKlKYndRbcjSL57eAzAaACRcrYJQKTHkik7kf6YliDYqhAkfonbjDfjSJ57eA1AaAC\nRXpCkbhrF2UCRTJBkTwlAFSAEsn9G3ZsEM3RDYlbpPuPlHP6O74EsUju3wtixROKpD87Q3FN\nDGtQDBWwRHIwyV4LitS9LoY1KIYKQCK5HUE/T6TiVdHDv0bSnsGOIsWWIBTJ8bMoFGkanUj1\ndTGsQTFUiEKk5jz53VW9ObOQsjyx/vOJpNu1o0jRJchEGvt45P3J85v/KJcT6/M1Uve6GNag\nGCrEIVL1YyCS5jbVvVLLE4qkOx00RYotQSTS6Cf21xXpab6xj9PfcSX4P2Vx5z8UiQkQFSjS\n8HaKFFsCQIW4RboTSHZifYq0ZoLkDQ0uSFGCP5H009/tbdwiwSWI3hq07XDaKbV7MwScEsu0\n4k7/c5doTwwi+YUirZcge4/drsO1+t6DnT7A7pu5TYn2UKTB7RTJW4LsaBW7Dok6XNP0nKiT\nNsBBpCzx/+4S7ZF2dJ8AABdrSURBVKFIg9spkq8E4WFfVh3equ/eOaukHqvi52uitqdmj/96\nUIVv+W377B7Xrdrn51y7HaqTryn1nuzaxI860RmKNLidInlKkJ7M26rDXl3KX97TrkjHYufs\nVIl0K3bWklt+2z777W2b/ci/tKe4flvcZ6cObeJHnegMRRrcTpE8JSwiUm94WpGUuqaXZiN1\nzF/v7NQxv3jINjnZb2/5Da/5VUdVbLmO3RDsBVlCkUzEMHozEsTfL+FDpOx1zrm9aptplV7z\nTU8uWPbjVt6wLf9+X13fhkAvyAqKZCKG0ZuTsKZI52ynbXutr+puqbrXtQf5d2IokhsUaa0E\n6SbJ7TVSeulNNqTvW5VcXERqXiOll9QdijS4nSIhJ9Szdpf8G3/LGbp6xE6NId1du7TzY9uM\nbWeU61m7y+h3CHt9Ek4JyCKpe8x3o0ggCc37SO/572/pbVe+Rrqk79rJhrTz45hf9Zbf2B3q\n5n2kOdN2FIkixZVw3ZZDlc+6FZPer+3092s+pEl/+jvt/Civz4XpDnU3caUn4ZJAkUzEtxJj\nJJwPSX1k3DHJ5Ck3QolKMo+y/bv8bdXuG7LdH/n1u0t6vwN//t+Ex9rZMvUayQBFwk0AqECR\npFAkU8Ls83pyQYoSKJKJGEZvGqfTEfrtgLAYKFKH95H5T4pkgCKtlIAv0nnHyQZn3M7r6bcD\nwGKgSGl64aydmUlHKNJaCfAi7RuNtlfdHUqeU6RJR4QHeM/psEJAFAnwIuUfY9mpa3rdjX0r\n87OKNOGI9KMSMzqsEBBFQgQi5R9UeUvT97FP7T+lSJOKSA/wntFh2YCNpwoUqRTpUnxckq+R\n+kw7Iv7MkXOHZQPq4vBDkUYg0lbd0lt+ANaJIvXx/2miZRIoUggGspzU7prupk7I9IQiLfBp\nomUSnAOapwfwJOIXKZeomgMf+WQXRQrSYdkAijQDze7baZum563ajn1C8vlEGn/901wJ8Cxc\nA9qnB/AkHkEkHT+/JC8//rSXn0+kUVq9AJ6F+5NQlUkAT+JBRfqR5Ly0JlGkLptHEKn2iCI5\noZ3+Lrgd9vV1v5LvmUM/k+/NX1GkLp09vtkHGYUXaRPFUMQjUue3b+XZa5P2JLYUqcNGLpL3\nc397DGhXhRiGAlqkw/hHzSmSlt4kxNyDjMItyM5oxzAU0CKlSc+jff9P/yRfm98pUouFSJKD\nHgItyO6KEMNQYIvU/QzF4LxmP5N/8//8XfBBKtp5ceGfrtDJARW6gCXYIqUjR9j9fvnWXuAW\nySVhnYOMnAJ6ow6/IFP0LVJqFunPy9fOJYrkkLDSsREuAf1BR1+QOfAimfj6pXuJIjkkUCSP\nCTGI9LZXat8/QeDvL19/dy9TJPsE4YcsQizIu7UAfEEW4It0rU5+sut80vzf5Gv/jygSboJ9\nwP1KAPAkHkCkZgp821z1+94jigScQJFCMBDpValT/i0gJ9V+rfX3pKL5K4qEm2AdMFgHAJ5E\n/CJtVfXq6K39YF9CkSJKsA0Y7pQAPIn4RdIdazeEIq2T4HLyB8sKmlGGWwwaKJKJGEZv7QSn\n06hQpBAMFuNOs2s3hCKtkrCCSLp/LdEWgw54kU6ayYYhFGmNBLcze1lV0O51gC0GLfAitdPf\niebPayjSGglu58ijSCHQvCFbmZSMnPqbIq2R4HiySZsK+pfBWItBD75I2kOE7qFIwoQ5e2ay\nY/MmK4xgmE5CXJD3xCCSAIokS5izQREemzdVYQTT4AMuyAEUyUQMo2ebsPhLnHkBFMkf5veR\nOmcRGkKRRAkL75nNDDD+I4q3IIfEIxLfkJ2dsPRLnHkB5uGFW5AaoEWaOItQB4okSFj6Jc7M\nAIrkk/7SHD2LUBeKJEjAFmnkn0m0BakDW6TRswh1oUjTCY6zbistyLFZJrAFqQVbpHT8lVEL\nRcJNoEghoEgPlyAKGB1lgCcRv0gyKFKH7q7b2h00u42SgPFhj2EoKJKJGEZPS+9F0ModdK+/\nBAETox7DUFAkEzGMnpawIg1NokghoEgOCb2Vtz8vt+6z0E4JTgdMDXoMQ0GRTMQweiW9tXcT\nUCT95PpkwOSYxzAUFMlEDKNXohEpzJcxUyQcKJJ1Qm/tvX/Tdc1nYXi/dypgeshjGAqKZCKG\n0Svorb2xiPRXg/rLY4VwCRTJRAyjl9Nbe9vDgIRfxuynw91jCwIo0sJQJNuE8QPoAJ7FuEjq\nL4q0BBTJMmHiUFSAZzEqUuYRRVoCivRwCWMi5R5RpCWgSA+XQJFCQJEeLsEskio8okhLQJEe\nLsEkUvl5TYq0DBTp4RL0IhUOKc7aLQVFergEXUC1LVJ8H2kpKNLDJQwDlEpVO9cw/RlogCdB\nkZyJYfSiSLgPyMVRnUm7v/gxigWgSMYEl6+dRHgW/YBCo3qUVefKJStQJClPIJLDabu9d5gd\nUBjTjrHutyUqUCQpFGmVDjMDSo06Q6z/1X8FiiTl8UVyOW237w7zAkqDegPcvTCyewfwJCiS\nM1ij53T+e88d5gRUZ26/s2Xsks8KFEnKI4mkPQeQ02m73Tv4TPho/bkfXTV60V8FiiTlgUTS\nnrrE7bTdzh28JnwMJukaBmLphx/gSVAkZwKNnv4cQKuJ5HRautGQVqPh2EqucauwegJFMhFQ\npME5gAafIF+qg8tJgDQh7e+ZPVWAbmQ11+k2ShTJnmcXycepS2ac+9uTSHVIZsWmnmzQ/aXw\nSopkz5OL5OMcQBt3kVzOpqUNKX7J5dmUIhmGVX9199qNU4UBFEnIo4k05xxAPResEpxOS2cK\nKbdB2a8f5reITH41128okiPPLdL9ayHXnUPHDvKzaU2GVC7kv36Yx9R4S31D2YYi2fPcInlI\nuHPBJkE/oWH/KivXaNO5YP7jEcXq7RlFcoMizUwAECnTaLPpXBj563HJ6jYxDAVFMhHD6A25\nd8EiwTDH7jBdUWfkHo1P2Y8Nt6JIM6BIgwSrt45miDTWwQ3tFq7H6HAXW7ZNNe83D4ok5IFF\nGl0R7xlsVEI+C/0WrsfocDf3RhmKMSiSCZTRsxJpoQ6LBYwNd+shwJOgSM6AjN7EvtEqHZYL\nkA03wJOgSM6AjN7Uq4w1OiwXQJGWgiL1EyZfrq/QYcEAirQUFKmfMD3xtXyHBQMo0lJQpF6C\nYOJr8Q5LBlCkpaBID5dAkUJAkR4ugSKF4BlEku+mxbAGzQoYPRDPXwWKJCUmkSxe8MSwBs0K\noEhLQZFW6bBmwrhIkmUB8CQokjNLLXubObgY1qA5ARuKtBRPIpLQpBjWoBkB5acsVqhAkaTE\nI5LV20IxrEEzAijScjyLSDKTYliD3AOmP/fnqwJFkhKNSHaHKsSwBrkHiJcEwJOgSM7EMHpR\nJBjfThP/mwLwJCiSMzGMXhQJABUokhSK1AfjnA0wFSiSFIrUA+TkJzAVKJIUitQD4+QnOBUo\nkhSK1AXkLEI4FSiSFIrUoTsVBvAsACpQJCkUqQNFCpBAkUzEMHpaeu/OADwLgAoUSQpFaqFI\nIRIokokYRk9H/4ABgGcBUIEiSaFIuAkAFSiSFIqEmwBQgSJJoUi4CQAVKJIUioSbAFCBIkmh\nSLgJABUokpS/PwgJyaOINLiG/5CiJABU4BZJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQ\nJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwE\ngAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoU\nSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpF\nwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0A\nqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECR\npFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk\n3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASA\nChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJ\nCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXC\nTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCo\nQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGk\nUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTc\nBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAK\nFMnMz6R7iSLhJgBUoEhGfiUUKZIEgAoUycSvF4oUSwJABYpk4GfylSLFkgBQgSIZSH6kFCmW\nBIAKFMnAr5QiRZMAUIEimWlE+rvgg5CQxC9SAbdIuAkAFbhFMkORYkkAqECRzFCkWBIAKlAk\nMxQplgSAChTJDEWKJQGgAkUyQ5FiSQCoQJHMUKRYEgAqUCQzFCmWBIAKFEkKRcJNAKhAkaRQ\nJNwEgAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwE\ngAoUSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoU\nSQpFwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpF\nwk0AqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0A\nqECRpFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECR\npFAk3ASAChRJCkXCTQCoQJGkUCTcBIAKFEkKRcJNAKhAkaRQJNwEgAoUSQpFwk0AqECRpFAk\n3ASAChRJytOKtAHogF+BIkl5VpE2mwmTAJ4FQAWKJIUiheuweEAUCRTJRAyjt9lMmQTwLAAq\nUCQpzynShiLBJFAkExGM3mbaJIBnAVCBIkl5SpE2m2mTAJ4FQAWKJIUiBeqwRkAUCRTJBPzo\nbTYCkwCeBUAFiiTlGUWKJQGgAkWSQpFwEwAqUCQpFAk3AaACRZJCkXATACpQJCkUCTcBoAJF\nkkKRcBMAKlAkKRQJNwGgAkWSQpFwEwAqUCQpFAk3AaACRZJCkXATACpQJCkUCTcBoAJFkkKR\ncBMAKlAkKRQJNwGgAkWSQpFwEwAqUCQpFAk3AaACRZJCkXATACpQJCkUCTcBoAJFkkKRcBMA\nKlAkKRQJNwGgAkWSQpFwEwAqUCQpFAk3AaACRZJCkXATACpQJCkUCTcBoAJFkkKRcBMAKlAk\nKRQJNwGgAkWSQpFwEwAqUCQpFAk3AaACRZJCkXATACpQJCkUCTcBoAJFkkKRcBMAKlAkKRRp\n0YSJb3xeowJ6AkUyEcPorZQw+d3py1eAT6BIJmIYvXUSJr/xefkK+AkUyUQMo7dOwvR3py9e\nAT+BIpmIYfRWSRB8d/rSFSJIoEgmYhi9NRIE3/i8dIUYEh5FpA+yEM03Pocugs2jiDS4hlsk\nPwmi705ftkIUCRTJRAyjF0UCQAWKJIUi4SYAVKBIUigSbgJABYokhSLhJgBUoEhSKBJuAkAF\niiSFIuEmAFSgSFIoEm4CQAWKJIUi4SYAVKBIUigSbgJABYokhSLhJgBUoEhSKBJuAkAFiiSF\nIuEmAFSgSFIoEm4CQAWKJIUi4SYAVKBIUigSbgJABYokhSLhJgBUoEhSKBJuAkAFiiSFIuEm\nAFSgSFIoEm4CQAWKJIUi4SYAVKBIUigSbgJABYokhSLhJgBUoEhSKBJuAkAFiiSFIuEmAFSg\nSFIoEm4CQAWKJIUi4SYAVKBIUigSbgJABYokhSLhJgBUoEhSKBJuAkAFiiSFIuEmAFSgSFIo\nEm4CQAWKJIUi4SYAVKBIUv4mJCx+PZiNo0hDAJ4YQAWEDgAVIDqsC0XyC0AHgAoQHdaFIvkF\noANABYgO6+JNJEKeGYpEiAcoEiEeoEiEeIAiEeIBikSIB/yI9OMlefnxx0uUPUlJuCI/k+qX\nzqOvXKSuEG5Z/Pyie+5BV4xV8SLS12L0vviIsudXZ+UJUuRXteJ2H33lInWFcMviR/FoL3/S\nkIshJD5E+m/y8iv99ZL810OWPb+Sb0GLZI+X3D/6ykWaCsGWxa/k+598u/g95GIIig+RfiT/\nZj//Sf7jIcuen+3jhijyM/la70q1j75ukbZCsGXxrXz8vEawxRAWHyJ9S36nvX8NV+Vn8jNk\nkeRHWq3FnUdft0hbIfCyKGoEWwxh8SFSknT/szbfkn+/Z69oQxX5df+w+X/WLdJWCLws/iRf\nAy6GsDyCSAVfwxUJLVLaESnosviZ78pRJGfCLq8k+Sf7t/BHvlPz9CKFXRa/X76lFGkGCMvr\nTz7J+vQilQRaFn9evnYekSLZ84KwvPJHD1SkerzOo69epP9IYZbF1/L9opCLISD+Zu1+h52c\naSeMVi/Sm7X73U5XrVhkKNLaFX5/+fq7+CXkYgiID5H+U7xd8G/yw0OWPS9J/nZ6MVqBilRr\ncefRVy/SbBRDLYt/ixmOnJCLISDxH9nwIx+nP8V7f4GKBD+yoakQbFn8bjzikQ0z+NJMugbg\nz0vx6D/CFan3qzqPvnaRqkKwZfE9aY/yC7gYAuJFpD/FQb4+klwf/cvPgEVqkTqPvnaRboUQ\nyyLpiBRwMQSEn0cixAMUiRAPUCRCPECRCPEARSLEAxSJEA9QJEI8QJEI8QBFIsQDFAkFpRzH\nwvmOxCMcgyAchlc5+HBwvSPxDscgAJdEs9itfahTKBICHIMAaFd9ax/qO1AkBDgGAaBIjwfH\nYJLTNltV95fywu2YKLU7ay6kp51S29fy97uVPP/PKf/bS3lBaVb++qrrIVHJ8ZoO7pfxts1u\nKv+yTcl+3o5Zx8O7/+dOpFCkKXbVKlv48p6UF46DC9fqQlIoMBSpirlMiXTuPlzvfml6LH7d\nDUWqHpsmhYMiTXBSu1v+U+3yS9nG4j297cr1/O6Cess2GdXfDUVKsj863N3ao7zypvLQTNHk\nNrjfe31bu5mrwy+FZZq5QLISFGmCrepsYjJP8n23bG3fDi+c8r87FT5pRDqXf9pToEd55bH8\ny0uZ3b/fobz0NhSpG06CwGU/ze3yWu5Opfvu7tP9hUK4a/ZyKtW+RtJc7FFeuW3+cje4X3Zb\nvpm615GTDghw2U9xqV8kpXfrqv5C/w+tRVItg/uNh1KkoHDZT5C/+D+8XSkSGYXLfoJtuQO3\n9q5d9zru2kUAl/0E5ep5bSYb8rnuZn6hd+FusiFf5y/WIh2bmYPha6RqsuFEkQDhsp9gmxvy\nXk025JPcl2LG+6S50Jn+3heSXTQz1VVKert/oHb6uwy9DO5XTn83oXUKRUKAy36CS/mCpdrD\nqy6V78H2LtRvyG6vnZt2epEOSvOej+q/IXvU3O/YC61TKBICXPZT5LN2u/O1WvWv+VFB++qo\noN6F4hCh3am6kG/DtifTvMC+fCXVo77t/dCG3t/vtO2E1ikUCQEu+/igMYBwSOJDszkjoaFI\n8aCKGYjroZogJEhQpFCoHpJ7vNZ/vFu6G7GGIoXCXqT0nM9DtBMaBAiKRIgHKBIhHqBIhHiA\nIhHiAYpEiAcoEiEeoEiEeOD/AXpdeFut19JjAAAAAElFTkSuQmCC", "text/plain": [ "plot without title" ] }, "metadata": { "filenames": { "image/png": "C:\\Users\\phamilton\\Documents\\Projects\\dsm\\dsm_website\\_build\\jupyter_execute\\08_knn\\knn_6_0.png" } }, "output_type": "display_data" } ], "source": [ "churnSample <- read_csv(\"../_build/data/churn_sample.csv\")\n", "churnSample$churn = ifelse(churnSample$churn==1, \"churn\", \"no churn\")\n", "\n", "churnSample$account_length = churnSample$account_length*sd(churn$account_length) + mean(churn$account_length)\n", "churnSample$total_intl_charge = churnSample$total_intl_charge*sd(churn$total_intl_charge) + mean(churn$total_intl_charge)\n", "library(ggplot2)\n", "\n", "pointA = data.frame(account_length=25, total_intl_charge=3)\n", "pointANearest = data.frame(c(4.564370,pointA$account_length,7.721684,pointA$account_length,20.697285,pointA$account_length,42.072091,pointA$account_length,48.209354, pointA$account_length), \n", " c(2.6889498,pointA$total_intl_charge,2.8776394,pointA$total_intl_charge,2.6624903,pointA$total_intl_charge,2.7909322,pointA$total_intl_charge,3.1609721,pointA$total_intl_charge),\n", " c(\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\"))\n", "names(pointANearest) = c(\"account_length\", \"total_intl_charge\", \"churn\")\n", "pointB = data.frame(account_length=160, total_intl_charge=1.8)\n", "pointBNearest = data.frame(c(172.389055,pointB$account_length,171.992009,pointB$account_length,160.344819,pointB$account_length,148.586736,pointB$account_length,144.073490,pointB$account_length), \n", " c(1.6791425,pointB$total_intl_charge,2.0317458,pointB$total_intl_charge,1.5954999,pointB$total_intl_charge,1.6851977,pointB$total_intl_charge,1.6953439,pointB$total_intl_charge), c(\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\"))\n", "names(pointBNearest) = c(\"account_length\", \"total_intl_charge\", \"churn\")\n", "pointC = data.frame(account_length=100, total_intl_charge=2.85)\n", "pointCNearest = data.frame(c(93.494871,pointC$account_length,91.650732,pointC$account_length,98.252319,pointC$account_length,109.494056,pointC$account_length,112.812032,pointC$account_length),\n", " c(2.7048315,pointC$total_intl_charge,3.0463884,pointC$total_intl_charge,2.5214656,pointC$total_intl_charge,3.0806561,pointC$total_intl_charge,2.7891426,pointC$total_intl_charge),\n", " c(\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\",\"no churn\"))\n", "names(pointCNearest) = c(\"account_length\", \"total_intl_charge\", \"churn\")\n", "\n", "suppressWarnings(print(ggplot(churnSample, aes(x=account_length, y=total_intl_charge, color=churn, shape=churn)) + geom_point(size=2) + theme_bw() +\n", " theme(axis.text=element_text(size=12),\n", " axis.title=element_text(size=14,face=\"bold\"))+\n", " geom_point(aes(x=pointA$account_length, y=pointA$total_intl_charge), colour=\"darkgreen\", shape=15, size=3) + annotate(\"text\", x = 25, y = 3.25, label = \"Customer A\") + \n", " geom_path(data=pointANearest, colour=\"black\")+\n", " geom_point(aes(x=pointB$account_length, y=pointB$total_intl_charge), colour=\"darkgreen\", shape=15, size=3) + annotate(\"text\", x = 100, y = 3.6, label = \"Customer B\") + \n", " geom_path(data=pointBNearest, colour=\"black\")+\n", " geom_point(aes(x=pointC$account_length, y=pointC$total_intl_charge), colour=\"darkgreen\", shape=15, size=3) + annotate(\"text\", x = 160, y = 2.15, label = \"Customer C\") + \n", " geom_path(data=pointCNearest, colour=\"black\"))) " ] }, { "cell_type": "markdown", "id": "3fde41a4", "metadata": {}, "source": [ "We see that five nearest neighbors of Customer A all churned in the previous quarter, so the algorithm would predict that Customer A will churn. Similarly, all five nearest neighbors of customer C did *not* churn in the previous quarter, so the algorithm would predict that Custer C will *not* churn. \n", "\n", "For Customer B, three of the nearest neighbors churned and two did *not*. Therefore, for this observation, the model would predict a 60% chance of churning (3 churns / 5 neighbors = 0.60). Ultimately, we need to make a binary decision about whether to intervene on this customer's account or not. To do this, we need to convert the predicted probability of 60% into a binary prediction of \"churn\" or \"no churn\". Because the predicted chance of churning is greater than 50%, the model is predicting that it is more likely than not that the customer will churn. Therefore, one may choose to treat this as a prediction of \"churn\". In this case, we have used a cutoff of 50% to convert the model's prediction into a binary outcome; if the predicted probability is less than 50% we interpret the prediction as \"no churn\", and if it is greater than 50% we interpret it as \"churn\".\n", "\n", "Although 50% seems like a natural cutoff, consider the following scenario. Suppose that when our model predicts a customer will churn, we offer that customer a very large discount to convince them to stay with the service. Because this discount is so costly, we only want to offer it to customers when we are very confident that they will churn in the upcoming quarter. If this were the case, we may want to be more than 50% confident before we intervene. For example, we may choose to intervene only if the model is 80% or more confident that the customer will churn in the next quarter. In this scenario, we would apply a cutoff of 80% instead of 50%. This is an example of how managerial judgment is an important component of any data science project. Without understanding the costs of an intervention (and the relative benefit of retaining customers), it would be difficult to find the optimum cutoff to apply to the model's predictions.\n", "\n", "## Calculating Distance\n", "\n", "So far we have not discussed how the model calculates the distance between observations. It turns out that there are several different ways to calculate distance, and each method has its own advantages (*see* [here](https://www.kdnuggets.com/2020/11/most-popular-distance-metrics-knn.html) for more information). Here we will only cover the most basic distance measure, called Euclidean distance. However, be aware that there are other methods that may be useful depending on the context of the problem.\n", "\n", "The **Euclidean distance** between two points is simply the distance between those points in Euclidean space. Let's say we want to calculate the Euclidean distance between Customer A and one of their neighbors:" ] }, { "cell_type": "code", "execution_count": 5, "id": "bb13a32b", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "image/png": "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\nNyEYYF4UAk8CkQYzzbLvd6iChzVoeAAiTci1i3SDCcG308z/pwg8CUQajIfRc5EgUAGRrCBS\nk1ygg1AFRLKCSA1ETn4iUwGRrCBSg+PrDoFnIVABkawgUp0ckWZPQKQQHkavnfpUmMCzEKiA\nSFYQqQYiJUhApBAeRq+VxrszAs9CoAIiWUGkI4iUIgGRQngYvTaaBwwIPAuBCohkBZF0EwQq\nIJIVRNJNEKiASFYQSTdBoAIiWUEk3QSBCohkBZF0EwQqIJKVf/4ApORaRDq7hv9IVRIEKrBF\nsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSb\nIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJ\nCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6C\nQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQr\niKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkC\nFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawg\nkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghU\nQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJI\nugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFAB\nkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLp\nJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVE\nsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSb\nIFABkawgkm6CQAVEsoJIugkCFRDJCiLpJghUQCQriKSbIFABkawgkm6CQAVEsoJIugkCFRDJ\nCiLpJghUQKQwv4r6JUTSTRCogEhBfheI5CRBoAIihfh9h0heEgQqIFKAX8VXRPKSIFABkQIU\nP0tE8pIgUAGRAvwuEclNgkAFRApzEOmfDX8AUuJfpA1skXQTBCqwRQqDSF4SBCogUhhE8pIg\nUAGRwiCSlwSBCogUBpG8JAhUQKQwiOQlQaACIoVBJC8JAhUQKQwieUkQqIBIVhBJN0GgAiJZ\nQSTdBIEKiGQFkXQTBCogkhVE0k0QqIBIVhBJN0GgAiJZQSTdBIEKiGQFkXQTBCogkhVE0k0Q\nqIBIVhBJN0GgAiJZQSTdBIEKiGQFkXQTBCogkhVE0k0QqIBIVhBJN0GgAiJZQSTdBIEKiGQF\nkXQTBCogkhVE0k0QqIBIVhBJN0GgAiJZQSTdBIEKiGQFkXQTBCogkhVE0k0QqIBIVhBJN0Gg\nAiJZQSTdBIEKiGQFkXQTBCogkhVE0k0QqIBIVhBJN0GgAiJZQSTdBIEKiGQFkXQTBCogkhVE\n0k0QqIBIVhBJN0GgAiJZQSTdBIEKiGQFkXQTBCogkhVE0k0QqIBIVhBJN0GgAiJZQSTdBIEK\niGQFkXQTBCogkhVE0k0QqIBIVhBJN0GgAiJZQSTdBIEKiGQFkXQTBCogkhVE0k0QqIBIVm5W\npFygg34FRLJyqyLleZ68w+QBLhIQKYSH0UMkmQRECuFh9PL8kkkCz0KgAiJZuU2RckSSSUCk\nEA5GL79sksCzEKiASFZuUqQ8v2ySwLMQqIBIVhApUYc5AlwkIFII+dHLc4NJAs9CoAIiWblF\nkbwkCFRAJCuIpJsgUAGRrCCSboJABUSygki6CQIVEMkKIukmCFRAJCuIpJsgUAGRrCCSboJA\nBUSygki6CQIVEMkKIukmCFRAJCuIpJsgUAGRrCCSboJABUSygki6CQIVEMkKIukmCFRAJCuI\npJsgUAGRrCCSboJABUSygki6CQIVEMkKIukmCFRAJCuIpJsgUAGRrCCSboJABUSygki6CQIV\nEMkKIukmCFRAJCuIpJsgUAGRrCCSboJABUSygki6CQIVEMkKIukmCFRAJCuIpJsgUAGRrCCS\nboJABUSygki6CQIVEMkKIukmCFRAJCuIpJsgUAGRrCDSpAl5+grqCYgUwsPozZRw8bvTp68g\nn4BIITyM3jwJF7/xefoK+gmIFMLD6M2TcPm70yevoJ+ASCE8jN4sCYbvTp+6goMERArhYfTm\nSDB84/PUFTwkXItIf2AiDt/4nLqINtci0tk1bJHiJJi+O33aCi4SECmEh9FzkSBQAZGsIJJu\ngkAFRLKCSLoJAhUQyQoi6SYIVEAkK4ikmyBQAZGsIJJugkAFRLKCSLoJAhUQyQoi6SYIVEAk\nK4ikmyBQAZGsIJJugkAFRLKCSLoJAhUQyQoi6SYIVEAkK4ikmyBQAZGsIJJugkAFRLKCSLoJ\nAhUQyQoi6SYIVEAkK4ikmyBQAZGsIJJugkAFRLKCSLoJAhUQyQoi6SYIVEAkK4ikmyBQAZGs\nIJJugkAFRLKCSLoJAhUQyQoi6SYIVEAkK4ikmyBQAZGsIJJugkAFRLKCSLoJAhUQyQoi6SYI\nVEAkK4ikmyBQAZGsIJJugkAFRLKCSLoJAhUQyQoi6SYIVEAkK/8ApCWuB6MZKNI5Ak9MoIJC\nB4EKEh3mBZHiItBBoIJEh3lBpLgIdBCoINFhXqKJBHDLIBJABBAJIAKIBBABRAKIACIBRCCO\nSD/virufH1Gi+lNsSVfkV7H7pfboMxfZV0i3LH59aXvuSVeMWYki0tfN6H2JEdWf37WVJ0mR\n37sVt/7oMxfZV0i3LH5uHu3uo0y5GFISQ6T/FXe/y993xf8iZPXnd/EtaZH14xWnjz5zkUOF\nZMvid/Hjo9ou/ki5GJISQ6Sfxb/rn/8t/hMhqz+/jo+bosiv4ut+V+r46PMWOVZItiy+bR+/\nqpFsMaQlhkjfir9l43/DWflV/EpZpPhZ7tbi2qPPW+RYIfGy2NRIthjSEkOkoqj/Mzffin9/\nrF/Rpiry+/Rhq3/mLXKskHhZfBRfEy6GtFyDSBu+piuSWqSyJlLSZfGr2pVDpMGkXV5F8d/1\n/4U/q52amxcp7bL4e/etRKQRKCyvj2qS9eZF2pJoWXzcfa09IiL1505heVWPnqjI7vFqjz57\nkeYjpVkWX7fvF6VcDAmJN2v3N+3kzHHCaPYijVm7v8fpqhmLnIs0d4W/X77+3fyScjEkJIZI\n/9m8XfBv8TNCVn/uiurt9M1oJSqyW4trjz57kcNGMdWy+Hczw1GRcjEkxP+RDT+rcfrYvPeX\nqEjyIxsOFZIti78HjziyYQRfDpOuCfi42zz6z3RF9vtVtUefu8iuQrJl8aM4HuWXcDEkJIpI\nH5uDfGMkDX30L78SFtmLVHv0uYvUK6RYFkVNpISLISF8HgkgAogEEAFEAogAIgFEAJEAIoBI\nABFAJIAIIBJABBAJIAKIpEKWDRyLwXeEiDAGSVidXzXAh9XQO0J0GIMEvBQti723D/sURFKA\nMUhA66rf24f9HRBJAcYgAYh0fTAGF3lcrFfV+5fthfeHIsuWzy0Xysdlli2+b38/Wcmrfx6r\n275sL2QtK//+qrdVkRUPb+XZ/dY8LdZ/2t7ymLL++f6w7rh6jf/cwQoiXWK5W2U3vrwW2wsP\nZxfedheKjQLnIu1iXi6J9Fx/uMb9yvJh8+vyXKTdY2NSOhDpAo/Z8r36mS2rS+uNxWv5vtyu\n5ycXsqf1JmN3u3ORivWNVid/bbC98j2rQteKFu9n93vd/+24mduHv2wsa5kLhJlApAssstom\nZu1Jte+2XtsX5xceq9s9bnxqEel5e9OGAg22Vz5sb/myzW7eb7W99HQuUj0cksCyv8z7y/ft\n7lR5X999Or2wEe5t/XKqbH2N1HKxwfbKxeGWy7P7rf9WbaZOdWTSQQGW/SVe9i+SypN1tf1C\n84a9RcqOnN2vOxSRksKyv0D14n/19IZI0AnL/gKL7Q7c3Lt29evYtXMAy/4C29Xz7TDZUM11\nH+YXGhdOJhuqdf6lt0gPh5mD89dIu8mGR0QShGV/gUVlyOtusqGa5H7ZzHg/tlyoTX/fbyR7\naZmp3qWU76cPdJz+3oa+nN1vO/19CN2nIJICLPsLvGxfsOz28HaXtu/BNi7s35BdvNX+tGwX\naZW1vOeTNd+QfWi530MjdJ+CSAqw7C9Rzdotn992q/5bdVTQ/e6ooMaFzSFCy8fdhWobtngM\nzQvcb19JNdj/7XV1DD293+OiFrpPQSQFWPb+wBhBGBJ/tGzOIDWI5IdsMwPxttpNEIISiJSK\nrIHlHt/3N15O3Q16g0ip6C9S+VzNQxwnNEAIRAKIACIBRACRACKASAARQCSACCASQAQQCSAC\n/w/+SoEtw2L4yAAAAABJRU5ErkJggg==", "text/plain": [ "plot without title" ] }, "metadata": { "filenames": { "image/png": "C:\\Users\\phamilton\\Documents\\Projects\\dsm\\dsm_website\\_build\\jupyter_execute\\08_knn\\knn_8_0.png" } }, "output_type": "display_data" } ], "source": [ "churnSample <- read_csv(\"../_build/data/churn_sample.csv\")\n", "churnSample$churn = ifelse(churnSample$churn==1, \"churn\", \"no churn\")\n", "\n", "churnSample$account_length = churnSample$account_length*sd(churn$account_length) + mean(churn$account_length)\n", "churnSample$total_intl_charge = churnSample$total_intl_charge*sd(churn$total_intl_charge) + mean(churn$total_intl_charge)\n", "library(ggplot2)\n", "\n", "pointA = data.frame(account_length=25, total_intl_charge=3)\n", "pointANearest = data.frame(c(4.564370,pointA$account_length), \n", " c(2.6889498,pointA$total_intl_charge),\n", " c(\"no churn\",\"no churn\"))\n", "names(pointANearest) = c(\"account_length\", \"total_intl_charge\", \"churn\")\n", "\n", "suppressWarnings(print(ggplot(churnSample, aes(x=account_length, y=total_intl_charge, color=churn, shape=churn)) + geom_point(size=2) + theme_bw() +\n", " theme(axis.text=element_text(size=12),\n", " axis.title=element_text(size=14,face=\"bold\"))+\n", " geom_point(aes(x=pointA$account_length, y=pointA$total_intl_charge), colour=\"darkgreen\", shape=15, size=3) + annotate(\"text\", x = 25, y = 3.25, label = \"Customer A\") + \n", " geom_path(data=pointANearest, colour=\"black\")))" ] }, { "cell_type": "markdown", "id": "1c96964a", "metadata": {}, "source": [ "For two points ($x_1$, $y_1$) and ($x_2$, $y_2$), the Euclidean distance between them is calculated as:\n", "\n", "$$\n", "\\sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}\n", "$$\n", "\n", "The coordinates for Customer A are (25, 3), and the coordinates for the other point are (4.56, 2.69). Applying the formula above, we can calculate the distance between them as:\n", "\n", "\n", "$$\n", "\\sqrt{(4.56 - 25)^2 + (2.69 - 3)^2} \\approx 20.44\n", "$$\n", "\n", "The larger this value, the further away the two points are in Euclidean space. Therefore, the kNN algorithm finds the $k$ observations with the smallest Euclidean distance from the new observation. Note that although we are currently working in two dimensions, this formula can be extended to higher dimensions when we are working with more than two independent features.\n", "\n", "## Normalizing Data\n", "\n", "If you review the plot from the previous section, you will notice that the $x$ and $y$ axes are on very different scales. The `account_length` variable ranges from around zero to over 200, while `total_intl_charge` ranges from from about two to four. This is problematic for the calculation of Euclidean distance, because the distance between points is impacted by the magnitude of each variable.\n", "\n", "For example, imagine two observations with the same `total_intl_charge` but a different `account_length`: (50, 2) and (100, 2). The Euclidean distance between these observations would be:\n", "\n", "$$\n", "\\sqrt{(100 - 50)^2 + (2 - 2)^2} = \\sqrt{(50)^2} = 50\n", "$$\n", "Now imagine two observations with the same `account_length` but a different `total_intl_charge`: (150, 2) and (150, 3). The Euclidean distance between these observations would be:\n", "\n", "$$\n", "\\sqrt{(150 - 150)^2 + (3 - 2)^2} = \\sqrt{(1)^2} = 1\n", "$$\n", "\n", "If we plot these points in our feature space, they seem to be roughly the same distance from each other. However, they have very different Euclidean distances. The reason for this is that `account_length` is measured on a greater scale than `total_intl_charge`, so it has a greater impact the distance metric." ] }, { "cell_type": "code", "execution_count": 6, "id": "2d09a7e0", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "image/png": "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\nMb3NRQAAAABJRU5ErkJggg==", "text/plain": [ "plot without title" ] }, "metadata": { "filenames": { "image/png": "C:\\Users\\phamilton\\Documents\\Projects\\dsm\\dsm_website\\_build\\jupyter_execute\\08_knn\\knn_10_0.png" } }, "output_type": "display_data" } ], "source": [ "churnSample <- read_csv(\"../_build/data/churn_sample.csv\")\n", "churnSample$churn = ifelse(churnSample$churn==1, \"churn\", \"no churn\")\n", "\n", "churnSample$account_length = churnSample$account_length*sd(churn$account_length) + mean(churn$account_length)\n", "churnSample$total_intl_charge = churnSample$total_intl_charge*sd(churn$total_intl_charge) + mean(churn$total_intl_charge)\n", "library(ggplot2)\n", "\n", "pointA = data.frame(account_length=50, total_intl_charge=2,churn=\"churn\")\n", "pointB = data.frame(c(100,pointA$account_length), \n", " c(2,pointA$total_intl_charge),\n", " c(\"no churn\",\"no churn\"))\n", "names(pointB) = c(\"account_length\", \"total_intl_charge\", \"churn\")\n", "\n", "pointC = data.frame(account_length=150, total_intl_charge=2,churn=\"churn\")\n", "pointD = data.frame(c(150,pointC$account_length), \n", " c(3,pointC$total_intl_charge),\n", " c(\"no churn\",\"no churn\"))\n", "names(pointD) = c(\"account_length\", \"total_intl_charge\", \"churn\")\n", "\n", "suppressWarnings(print(ggplot(churnSample, aes(x=account_length, y=total_intl_charge, color=churn, shape=churn)) + geom_point(size=2) + theme_bw() +\n", " theme(axis.text=element_text(size=12),\n", " axis.title=element_text(size=14,face=\"bold\"))+\n", " geom_point(aes(x=pointA$account_length, y=pointA$total_intl_charge), colour=\"darkgreen\", shape=15, size=3) +\n", " geom_path(data=pointB, colour=\"black\") + \n", " geom_point(aes(x=pointB[1,]$account_length, y=pointB[1,]$total_intl_charge), colour=\"darkgreen\", shape=15, size=3)+\n", " geom_point(aes(x=pointC$account_length, y=pointC$total_intl_charge), colour=\"darkgreen\", shape=15, size=3) +\n", " geom_path(data=pointD, colour=\"black\") + \n", " geom_point(aes(x=pointD[1,]$account_length, y=pointD[1,]$total_intl_charge), colour=\"darkgreen\", shape=15, size=3)))" ] }, { "cell_type": "markdown", "id": "5ef20ab2", "metadata": {}, "source": [ "When applying the kNN algorithm, we want to eliminate the impact of magnitude on the distance between points. One common method to accomplish this is to **normalize** the data so that each variable is measured on the same scale. A common method of normalization is **min-max scaling**, which converts each variable to the range [0, 1]. For a given variable $x$, the formula for min-max scaling is:\n", "\n", "$$\n", "x' = \\frac{x - min(x)}{max() - min(x)}\n", "$$\n", "\n", "If we apply this process to our data set, our feature space will look the same, but `account_length` and `total_intl_charge` will both be in the range [0, 1]:" ] }, { "cell_type": "code", "execution_count": 7, "id": "12c2a8b9", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "image/png": "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\nB7kuUnUPtb/mweMvJEtQpKlSKNKkKUN72ekvquwP4PKjPvnps9fGNZGgSBOljNqTY3cJeHZX\nxcbNh/ey055b16f72WQiRYIiFYzakynS6BSKFM5kU0qjpFRRS4oUcsLRGkSqHdodP5afvVKk\n+CE9KT473gWRHAOB9l6gKgGLDXfFOaN1XbLkd/65mVekx6vi45X3H2WmSKPvE4D2XqAq3iK9\nlkvbV3Vd7opLfs4q0t3xd/iusWsVyetYSMt+N2/I0k/Ivuzve25eG7rcZcnPWR8jPSbH32Hs\nDSL9HlRo2e/mDVlapAXoiLQpnqnasz+g/OEXqVqkFKLLgilAVXSLlBxXPD5tPY/kudClZb+b\nN4Qi1Q8bKdJSXZZMAaqiW6Qseak+efI9EUmlSOdltnTxLoumAFXRLdJdkv3cq/Ry571sp1Ik\npsQMoUjHU9BL+PeRDKYAVdEtUv5yMCnjO61aTAGqolykPP/9I0l+/PaOpEhLpqQxQoKhSBGg\nSAumeL4KqRkSDkXqXD/eNIpU8v0dI2UMFGlBKFIf7hJIKd8lMbq48+55vuA0VSZOoUjhTH9f\n4i4BRVoohSKFo0Ck7+9RJsW6Rf4vjI1eZeoUihTOxFMaJQGkSGlQSJwqU6dQpHAUiLTMoV3A\nK8xjV5k8hSKFo+DQbmGR0oCQOFUmT6FI4WgQqbXyl/qmjEHFxo2VQpHC0bD83eTSfQTQ3gtU\nhSLJGJh1n4QUKXqKUpF222y7+zpfnFX0XmdapN7DwosPW4BuEVCVFYp0W2pzfbr0rSZS+zqK\nNIlIgz/vnDJTCJJIFw/T45xu6iTSv2z7lr9ts3/HS9+y++OnnetMi9S7dH55Je1yF5eVuLVv\n3AaOIjksHM0o0i573n/8L/tzvPTv+dPOdRRJECkN6UKRWiCLJP41ivvsI2/cDf3N/orXrUmk\ny6t3Dod2Dk/uXOzi9OSQso0bluIm0uCT64ddPMmP/1Yfiq9PFzrjJNJhVSE7vRvKffb8K9vu\neq9bj0guzyeNESn17uL2LKuqjRuaEi7SSZyDRc2vT2o54itSyW37uv+VvK+Eagbjfyp+k4OI\n8YP1En5ol9T/Tbr/+osk0hEpy/7L869dcYC33nskp3PuZunieOaPpo0bnLIOkSq+ikVvijR9\nF1eRLlwfowpMSvjy9wIibftFKi/oXrcWkbweI03R5fwgK73wfZNXwUkJf0J2YpFOj4w+b05v\n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", "text/plain": [ "plot without title" ] }, "metadata": { "filenames": { "image/png": "C:\\Users\\phamilton\\Documents\\Projects\\dsm\\dsm_website\\_build\\jupyter_execute\\08_knn\\knn_12_0.png" } }, "output_type": "display_data" } ], "source": [ "churnSample <- read_csv(\"../_build/data/churn_sample.csv\")\n", "churnSample$account_length <- (churnSample$account_length - min(churnSample$account_length)) / (max(churnSample$account_length) - min(churnSample$account_length))\n", "churnSample$total_intl_charge <- (churnSample$total_intl_charge - min(churnSample$total_intl_charge)) / (max(churnSample$total_intl_charge) - min(churnSample$total_intl_charge))\n", "churnSample$churn = ifelse(churnSample$churn==1, \"churn\", \"no churn\")\n", "library(ggplot2)\n", "\n", "suppressWarnings(print(ggplot(churnSample, aes(x=account_length, y=total_intl_charge, color=churn, shape=churn)) + geom_point(size=2) + theme_bw() +\n", " theme(axis.text=element_text(size=12),\n", " axis.title=element_text(size=14,face=\"bold\"))))" ] }, { "cell_type": "markdown", "id": "1614bfd8", "metadata": {}, "source": [ "Now when we calculate Euclidean distance *after* applying min-max normalization, the scale that each variable is measured on will not impact the distance metric.\n", "\n", "## Applying kNN in R\n", "\n", "Now that we understand how the kNN algorithm works, let's see how it can be applied to our `churn` data set in R. \n", "\n", "Instead of working with just `account_length` and `total_intl_charge`, we will now work with all relevant features in our data set. As we saw in the previous section, the first thing to do is normalize the continuous variables in the data set so that they are on the same scale. We can apply min-max scaling with the `preProcess()` function from the `caret` package, which uses the following syntax:\n", "\n", "```{admonition} Syntax\n", "`caret::preProcess(x, method = c(\"center\", \"scale\"))`\n", "+ *Required arguments*\n", " - `x`: A data frame with the variables to scale. \n", "+ *Optional arguments*\n", " - `method`: Used to specify the desired type of preprocessing. To apply min-max scaling, this can be set to \"range\".\n", "``` \n", " \n", "This function creates an object (which we call `scaler` below) that we can then pass in to `predict()` to scale our data set. As you can see, the continuous variables in `churnScaled` are all in the range [0,1]. Note also that `preProcess()` knows to ignore non-continuous variables (*e.g.*, `international_plan`), which do not need to be normalized." ] }, { "cell_type": "code", "execution_count": 8, "id": "fc8ee1b5", "metadata": { "tags": [ "remove-output" ] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Loading required package: lattice\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n", "Attaching package: 'caret'\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "The following object is masked from 'package:purrr':\n", "\n", " lift\n", "\n" ] } ], "source": [ "library(caret)\n", "\n", "# Create min-max scaler\n", "scaler <- preProcess(churn, method=\"range\")\n", "\n", "# Apply scaler to our data set\n", "churnScaled <- predict(scaler, churn)" ] }, { "cell_type": "code", "execution_count": 9, "id": "5fe3bd3d", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "
account_lengthinternational_planvoice_mail_plannumber_vmail_messagestotal_day_minutestotal_day_callstotal_night_minutestotal_night_callstotal_intl_minutestotal_intl_callstotal_intl_chargenumber_customer_service_callschurn
0.6776860no no 0.00 0.59573260.40606060.38025320.51764710.640 0.05 0.64074070.0000000no
0.4214876no no 0.00 0.51266000.81212120.46000000.78823530.420 0.15 0.42037040.1111111no
0.3677686no yes 0.54 0.44580370.30909090.31189870.65294120.630 0.30 0.62962960.2222222no
0.1446281no no 0.00 0.50611660.78181820.77544300.60000000.540 0.30 0.54074070.2222222no
0.3884298no yes 0.70 0.65177810.86666670.62886080.64705880.195 0.15 0.19444440.0000000no
0.4876033no no 0.00 0.65860600.49696970.53417720.69411760.370 0.50 0.37037040.1111111no
\n" ], "text/latex": [ "\\begin{tabular}{r|lllllllllllll}\n", " account\\_length & international\\_plan & voice\\_mail\\_plan & number\\_vmail\\_messages & total\\_day\\_minutes & total\\_day\\_calls & total\\_night\\_minutes & total\\_night\\_calls & total\\_intl\\_minutes & total\\_intl\\_calls & total\\_intl\\_charge & number\\_customer\\_service\\_calls & churn\\\\\n", "\\hline\n", "\t 0.6776860 & no & no & 0.00 & 0.5957326 & 0.4060606 & 0.3802532 & 0.5176471 & 0.640 & 0.05 & 0.6407407 & 0.0000000 & no \\\\\n", "\t 0.4214876 & no & no & 0.00 & 0.5126600 & 0.8121212 & 0.4600000 & 0.7882353 & 0.420 & 0.15 & 0.4203704 & 0.1111111 & no \\\\\n", "\t 0.3677686 & no & yes & 0.54 & 0.4458037 & 0.3090909 & 0.3118987 & 0.6529412 & 0.630 & 0.30 & 0.6296296 & 0.2222222 & no \\\\\n", "\t 0.1446281 & no & no & 0.00 & 0.5061166 & 0.7818182 & 0.7754430 & 0.6000000 & 0.540 & 0.30 & 0.5407407 & 0.2222222 & no \\\\\n", "\t 0.3884298 & no & yes & 0.70 & 0.6517781 & 0.8666667 & 0.6288608 & 0.6470588 & 0.195 & 0.15 & 0.1944444 & 0.0000000 & no \\\\\n", "\t 0.4876033 & no & no & 0.00 & 0.6586060 & 0.4969697 & 0.5341772 & 0.6941176 & 0.370 & 0.50 & 0.3703704 & 0.1111111 & no \\\\\n", "\\end{tabular}\n" ], "text/markdown": [ "\n", "| account_length | international_plan | voice_mail_plan | number_vmail_messages | total_day_minutes | total_day_calls | total_night_minutes | total_night_calls | total_intl_minutes | total_intl_calls | total_intl_charge | number_customer_service_calls | churn |\n", "|---|---|---|---|---|---|---|---|---|---|---|---|---|\n", "| 0.6776860 | no | no | 0.00 | 0.5957326 | 0.4060606 | 0.3802532 | 0.5176471 | 0.640 | 0.05 | 0.6407407 | 0.0000000 | no |\n", "| 0.4214876 | no | no | 0.00 | 0.5126600 | 0.8121212 | 0.4600000 | 0.7882353 | 0.420 | 0.15 | 0.4203704 | 0.1111111 | no |\n", "| 0.3677686 | no | yes | 0.54 | 0.4458037 | 0.3090909 | 0.3118987 | 0.6529412 | 0.630 | 0.30 | 0.6296296 | 0.2222222 | no |\n", "| 0.1446281 | no | no | 0.00 | 0.5061166 | 0.7818182 | 0.7754430 | 0.6000000 | 0.540 | 0.30 | 0.5407407 | 0.2222222 | no |\n", "| 0.3884298 | no | yes | 0.70 | 0.6517781 | 0.8666667 | 0.6288608 | 0.6470588 | 0.195 | 0.15 | 0.1944444 | 0.0000000 | no |\n", "| 0.4876033 | no | no | 0.00 | 0.6586060 | 0.4969697 | 0.5341772 | 0.6941176 | 0.370 | 0.50 | 0.3703704 | 0.1111111 | no |\n", "\n" ], "text/plain": [ " account_length international_plan voice_mail_plan number_vmail_messages\n", "1 0.6776860 no no 0.00 \n", "2 0.4214876 no no 0.00 \n", "3 0.3677686 no yes 0.54 \n", "4 0.1446281 no no 0.00 \n", "5 0.3884298 no yes 0.70 \n", "6 0.4876033 no no 0.00 \n", " total_day_minutes total_day_calls total_night_minutes total_night_calls\n", "1 0.5957326 0.4060606 0.3802532 0.5176471 \n", "2 0.5126600 0.8121212 0.4600000 0.7882353 \n", "3 0.4458037 0.3090909 0.3118987 0.6529412 \n", "4 0.5061166 0.7818182 0.7754430 0.6000000 \n", "5 0.6517781 0.8666667 0.6288608 0.6470588 \n", "6 0.6586060 0.4969697 0.5341772 0.6941176 \n", " total_intl_minutes total_intl_calls total_intl_charge\n", "1 0.640 0.05 0.6407407 \n", "2 0.420 0.15 0.4203704 \n", "3 0.630 0.30 0.6296296 \n", "4 0.540 0.30 0.5407407 \n", "5 0.195 0.15 0.1944444 \n", "6 0.370 0.50 0.3703704 \n", " number_customer_service_calls churn\n", "1 0.0000000 no \n", "2 0.1111111 no \n", "3 0.2222222 no \n", "4 0.2222222 no \n", "5 0.0000000 no \n", "6 0.1111111 no " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "head(churnScaled)" ] }, { "cell_type": "markdown", "id": "b4bd908f", "metadata": {}, "source": [ "
\n", "\n", "Next, we need to convert the categorical features in our data set to numeric dummy variables. If you recall from Section [Dummy Variables](../05_linear_regression/dummy.html#dummy-variables), the `lm()` and `glm()` functions automatically convert categorical variables to binary dummy variables when one is using linear or logistic regression. Unfortunately, the function we will use for kNN does *not* do this automatically, so we need to do it ourselves." ] }, { "cell_type": "code", "execution_count": 10, "id": "c405e037", "metadata": {}, "outputs": [], "source": [ "# Convert categorical variables to dummy variables\n", "churnScaled$international_plan <- ifelse(churnScaled$international_plan==\"yes\", 1, 0)\n", "churnScaled$voice_mail_plan <- ifelse(churnScaled$voice_mail_plan==\"yes\", 1, 0)" ] }, { "cell_type": "code", "execution_count": 11, "id": "f8490658", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "
account_lengthinternational_planvoice_mail_plannumber_vmail_messagestotal_day_minutestotal_day_callstotal_night_minutestotal_night_callstotal_intl_minutestotal_intl_callstotal_intl_chargenumber_customer_service_callschurn
0.67768600 0 0.00 0.59573260.40606060.38025320.51764710.640 0.05 0.64074070.0000000no
0.42148760 0 0.00 0.51266000.81212120.46000000.78823530.420 0.15 0.42037040.1111111no
0.36776860 1 0.54 0.44580370.30909090.31189870.65294120.630 0.30 0.62962960.2222222no
0.14462810 0 0.00 0.50611660.78181820.77544300.60000000.540 0.30 0.54074070.2222222no
0.38842980 1 0.70 0.65177810.86666670.62886080.64705880.195 0.15 0.19444440.0000000no
0.48760330 0 0.00 0.65860600.49696970.53417720.69411760.370 0.50 0.37037040.1111111no
\n" ], "text/latex": [ "\\begin{tabular}{r|lllllllllllll}\n", " account\\_length & international\\_plan & voice\\_mail\\_plan & number\\_vmail\\_messages & total\\_day\\_minutes & total\\_day\\_calls & total\\_night\\_minutes & total\\_night\\_calls & total\\_intl\\_minutes & total\\_intl\\_calls & total\\_intl\\_charge & number\\_customer\\_service\\_calls & churn\\\\\n", "\\hline\n", "\t 0.6776860 & 0 & 0 & 0.00 & 0.5957326 & 0.4060606 & 0.3802532 & 0.5176471 & 0.640 & 0.05 & 0.6407407 & 0.0000000 & no \\\\\n", "\t 0.4214876 & 0 & 0 & 0.00 & 0.5126600 & 0.8121212 & 0.4600000 & 0.7882353 & 0.420 & 0.15 & 0.4203704 & 0.1111111 & no \\\\\n", "\t 0.3677686 & 0 & 1 & 0.54 & 0.4458037 & 0.3090909 & 0.3118987 & 0.6529412 & 0.630 & 0.30 & 0.6296296 & 0.2222222 & no \\\\\n", "\t 0.1446281 & 0 & 0 & 0.00 & 0.5061166 & 0.7818182 & 0.7754430 & 0.6000000 & 0.540 & 0.30 & 0.5407407 & 0.2222222 & no \\\\\n", "\t 0.3884298 & 0 & 1 & 0.70 & 0.6517781 & 0.8666667 & 0.6288608 & 0.6470588 & 0.195 & 0.15 & 0.1944444 & 0.0000000 & no \\\\\n", "\t 0.4876033 & 0 & 0 & 0.00 & 0.6586060 & 0.4969697 & 0.5341772 & 0.6941176 & 0.370 & 0.50 & 0.3703704 & 0.1111111 & no \\\\\n", "\\end{tabular}\n" ], "text/markdown": [ "\n", "| account_length | international_plan | voice_mail_plan | number_vmail_messages | total_day_minutes | total_day_calls | total_night_minutes | total_night_calls | total_intl_minutes | total_intl_calls | total_intl_charge | number_customer_service_calls | churn |\n", "|---|---|---|---|---|---|---|---|---|---|---|---|---|\n", "| 0.6776860 | 0 | 0 | 0.00 | 0.5957326 | 0.4060606 | 0.3802532 | 0.5176471 | 0.640 | 0.05 | 0.6407407 | 0.0000000 | no |\n", "| 0.4214876 | 0 | 0 | 0.00 | 0.5126600 | 0.8121212 | 0.4600000 | 0.7882353 | 0.420 | 0.15 | 0.4203704 | 0.1111111 | no |\n", "| 0.3677686 | 0 | 1 | 0.54 | 0.4458037 | 0.3090909 | 0.3118987 | 0.6529412 | 0.630 | 0.30 | 0.6296296 | 0.2222222 | no |\n", "| 0.1446281 | 0 | 0 | 0.00 | 0.5061166 | 0.7818182 | 0.7754430 | 0.6000000 | 0.540 | 0.30 | 0.5407407 | 0.2222222 | no |\n", "| 0.3884298 | 0 | 1 | 0.70 | 0.6517781 | 0.8666667 | 0.6288608 | 0.6470588 | 0.195 | 0.15 | 0.1944444 | 0.0000000 | no |\n", "| 0.4876033 | 0 | 0 | 0.00 | 0.6586060 | 0.4969697 | 0.5341772 | 0.6941176 | 0.370 | 0.50 | 0.3703704 | 0.1111111 | no |\n", "\n" ], "text/plain": [ " account_length international_plan voice_mail_plan number_vmail_messages\n", "1 0.6776860 0 0 0.00 \n", "2 0.4214876 0 0 0.00 \n", "3 0.3677686 0 1 0.54 \n", "4 0.1446281 0 0 0.00 \n", "5 0.3884298 0 1 0.70 \n", "6 0.4876033 0 0 0.00 \n", " total_day_minutes total_day_calls total_night_minutes total_night_calls\n", "1 0.5957326 0.4060606 0.3802532 0.5176471 \n", "2 0.5126600 0.8121212 0.4600000 0.7882353 \n", "3 0.4458037 0.3090909 0.3118987 0.6529412 \n", "4 0.5061166 0.7818182 0.7754430 0.6000000 \n", "5 0.6517781 0.8666667 0.6288608 0.6470588 \n", "6 0.6586060 0.4969697 0.5341772 0.6941176 \n", " total_intl_minutes total_intl_calls total_intl_charge\n", "1 0.640 0.05 0.6407407 \n", "2 0.420 0.15 0.4203704 \n", "3 0.630 0.30 0.6296296 \n", "4 0.540 0.30 0.5407407 \n", "5 0.195 0.15 0.1944444 \n", "6 0.370 0.50 0.3703704 \n", " number_customer_service_calls churn\n", "1 0.0000000 no \n", "2 0.1111111 no \n", "3 0.2222222 no \n", "4 0.2222222 no \n", "5 0.0000000 no \n", "6 0.1111111 no " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "head(churnScaled)" ] }, { "cell_type": "markdown", "id": "f3d6726e", "metadata": {}, "source": [ "
\n", "\n", "Now that we have prepared the data set we will use to build the model (`churnedScaled`), let's prepare the data set with the observation we would like to make a prediction on. Suppose we have a file called `\"churn_new.csv\"` that contains the information of a new customer, and we would like to predict whether that customer will churn in the next quarter." ] }, { "cell_type": "code", "execution_count": 12, "id": "f93a7f07", "metadata": {}, "outputs": [], "source": [ "churnNew <- read_csv(\"../_build/data/churn_new.csv\")" ] }, { "cell_type": "code", "execution_count": 13, "id": "7a9a0f8b", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\t\n", "\n", "
account_lengthinternational_planvoice_mail_plannumber_vmail_messagestotal_day_minutestotal_day_callstotal_night_minutestotal_night_callstotal_intl_minutestotal_intl_callstotal_intl_chargenumber_customer_service_calls
12 no no 0 250 118 280 90 11.83 3.191
\n" ], "text/latex": [ "\\begin{tabular}{r|llllllllllll}\n", " account\\_length & international\\_plan & voice\\_mail\\_plan & number\\_vmail\\_messages & total\\_day\\_minutes & total\\_day\\_calls & total\\_night\\_minutes & total\\_night\\_calls & total\\_intl\\_minutes & total\\_intl\\_calls & total\\_intl\\_charge & number\\_customer\\_service\\_calls\\\\\n", "\\hline\n", "\t 12 & no & no & 0 & 250 & 118 & 280 & 90 & 11.8 & 3 & 3.19 & 1 \\\\\n", "\\end{tabular}\n" ], "text/markdown": [ "\n", "| account_length | international_plan | voice_mail_plan | number_vmail_messages | total_day_minutes | total_day_calls | total_night_minutes | total_night_calls | total_intl_minutes | total_intl_calls | total_intl_charge | number_customer_service_calls |\n", "|---|---|---|---|---|---|---|---|---|---|---|---|\n", "| 12 | no | no | 0 | 250 | 118 | 280 | 90 | 11.8 | 3 | 3.19 | 1 |\n", "\n" ], "text/plain": [ " account_length international_plan voice_mail_plan number_vmail_messages\n", "1 12 no no 0 \n", " total_day_minutes total_day_calls total_night_minutes total_night_calls\n", "1 250 118 280 90 \n", " total_intl_minutes total_intl_calls total_intl_charge\n", "1 11.8 3 3.19 \n", " number_customer_service_calls\n", "1 1 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "head(churnNew)" ] }, { "cell_type": "markdown", "id": "94e5d171", "metadata": {}, "source": [ "
\n", "\n", "As with our other data set, we need to (1) normalize the variables, and (2) convert the categorical variables into dummies. To normalize the data, we can apply the `scaler` object that we created above. To do this we can now just pass `scaler` and `churnNew` into `predict()`. This will apply the min-max formula to `churnNew` based on the minimum and maximum values used to create `churnScaled`." ] }, { "cell_type": "code", "execution_count": 14, "id": "f945da53", "metadata": {}, "outputs": [], "source": [ "churnNewScaled <- predict(scaler, churnNew)" ] }, { "cell_type": "code", "execution_count": 15, "id": "d79424db", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\t\n", "\n", "
account_lengthinternational_planvoice_mail_plannumber_vmail_messagestotal_day_minutestotal_day_callstotal_night_minutestotal_night_callstotal_intl_minutestotal_intl_callstotal_intl_chargenumber_customer_service_calls
0.04545455no no 0 0.7112376 0.7151515 0.7088608 0.5294118 0.59 0.15 0.5907407 0.1111111
\n" ], "text/latex": [ "\\begin{tabular}{r|llllllllllll}\n", " account\\_length & international\\_plan & voice\\_mail\\_plan & number\\_vmail\\_messages & total\\_day\\_minutes & total\\_day\\_calls & total\\_night\\_minutes & total\\_night\\_calls & total\\_intl\\_minutes & total\\_intl\\_calls & total\\_intl\\_charge & number\\_customer\\_service\\_calls\\\\\n", "\\hline\n", "\t 0.04545455 & no & no & 0 & 0.7112376 & 0.7151515 & 0.7088608 & 0.5294118 & 0.59 & 0.15 & 0.5907407 & 0.1111111 \\\\\n", "\\end{tabular}\n" ], "text/markdown": [ "\n", "| account_length | international_plan | voice_mail_plan | number_vmail_messages | total_day_minutes | total_day_calls | total_night_minutes | total_night_calls | total_intl_minutes | total_intl_calls | total_intl_charge | number_customer_service_calls |\n", "|---|---|---|---|---|---|---|---|---|---|---|---|\n", "| 0.04545455 | no | no | 0 | 0.7112376 | 0.7151515 | 0.7088608 | 0.5294118 | 0.59 | 0.15 | 0.5907407 | 0.1111111 |\n", "\n" ], "text/plain": [ " account_length international_plan voice_mail_plan number_vmail_messages\n", "1 0.04545455 no no 0 \n", " total_day_minutes total_day_calls total_night_minutes total_night_calls\n", "1 0.7112376 0.7151515 0.7088608 0.5294118 \n", " total_intl_minutes total_intl_calls total_intl_charge\n", "1 0.59 0.15 0.5907407 \n", " number_customer_service_calls\n", "1 0.1111111 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "head(churnNewScaled)" ] }, { "cell_type": "markdown", "id": "e73f02c7", "metadata": {}, "source": [ "
\n", "\n", "Next, we need to convert our categorical variables into dummies:" ] }, { "cell_type": "code", "execution_count": 16, "id": "4d84e29d", "metadata": {}, "outputs": [], "source": [ "churnNewScaled$international_plan <- ifelse(churnNewScaled$international_plan==\"yes\", 1, 0)\n", "churnNewScaled$voice_mail_plan <- ifelse(churnNewScaled$voice_mail_plan==\"yes\", 1, 0)" ] }, { "cell_type": "code", "execution_count": 17, "id": "b49ce372", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\t\n", "\n", "
account_lengthinternational_planvoice_mail_plannumber_vmail_messagestotal_day_minutestotal_day_callstotal_night_minutestotal_night_callstotal_intl_minutestotal_intl_callstotal_intl_chargenumber_customer_service_calls
0.045454550 0 0 0.7112376 0.7151515 0.7088608 0.5294118 0.59 0.15 0.5907407 0.1111111
\n" ], "text/latex": [ "\\begin{tabular}{r|llllllllllll}\n", " account\\_length & international\\_plan & voice\\_mail\\_plan & number\\_vmail\\_messages & total\\_day\\_minutes & total\\_day\\_calls & total\\_night\\_minutes & total\\_night\\_calls & total\\_intl\\_minutes & total\\_intl\\_calls & total\\_intl\\_charge & number\\_customer\\_service\\_calls\\\\\n", "\\hline\n", "\t 0.04545455 & 0 & 0 & 0 & 0.7112376 & 0.7151515 & 0.7088608 & 0.5294118 & 0.59 & 0.15 & 0.5907407 & 0.1111111 \\\\\n", "\\end{tabular}\n" ], "text/markdown": [ "\n", "| account_length | international_plan | voice_mail_plan | number_vmail_messages | total_day_minutes | total_day_calls | total_night_minutes | total_night_calls | total_intl_minutes | total_intl_calls | total_intl_charge | number_customer_service_calls |\n", "|---|---|---|---|---|---|---|---|---|---|---|---|\n", "| 0.04545455 | 0 | 0 | 0 | 0.7112376 | 0.7151515 | 0.7088608 | 0.5294118 | 0.59 | 0.15 | 0.5907407 | 0.1111111 |\n", "\n" ], "text/plain": [ " account_length international_plan voice_mail_plan number_vmail_messages\n", "1 0.04545455 0 0 0 \n", " total_day_minutes total_day_calls total_night_minutes total_night_calls\n", "1 0.7112376 0.7151515 0.7088608 0.5294118 \n", " total_intl_minutes total_intl_calls total_intl_charge\n", "1 0.59 0.15 0.5907407 \n", " number_customer_service_calls\n", "1 0.1111111 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "head(churnNewScaled)" ] }, { "cell_type": "markdown", "id": "7ce9d197", "metadata": {}, "source": [ "
\n", "\n", "Now that our data has been processed, we can actually apply the kNN algorithm! We can do this in R with the `knn()` function from the `class` package, which uses the following syntax:\n", "\n", "```{admonition} Syntax\n", "`class::knn(train, test, cl, k = 1, prob = FALSE)`\n", "+ *Required arguments*\n", " - `train`: A data frame with the observations used to build the model. This should only contain the independent ($X$) features, not the target feature ($Y$).\n", " - `test`: A data frame with the observation(s) the model should be applied to. \n", " - `cl`: A vector with the correct labels ($Y$) of the observations used to build the model.\n", "+ *Optional arguments*\n", " - `k`: The number of nearest neighbors considered.\n", " - `prob`: Whether or not the probability of each prediction is returned. If `prob` equals `FALSE`, the function returns a binary prediction (*e.g.* \"churn\" or \"no churn\"). \n", "``` \n", " \n", "Below we apply this function, with `churnScaled` used to build the model and `churnNewScaled` used to make predictions. Note that the `train` parameter only accepts the $X$ features (and not the target feature $Y$), so we exclude the thirteen column in `churnScaled` when passing the data to `train`." ] }, { "cell_type": "code", "execution_count": 18, "id": "d630e883", "metadata": {}, "outputs": [ { "data": { "text/html": [ "no\n", "
\n", "\t\n", "\t\tLevels:\n", "\t\n", "\t
    \n", "\t\t
  1. 'no'
  2. \n", "\t\t
  3. 'yes'
  4. \n", "\t
\n", "
" ], "text/latex": [ "no\n", "\\emph{Levels}: \\begin{enumerate*}\n", "\\item 'no'\n", "\\item 'yes'\n", "\\end{enumerate*}\n" ], "text/markdown": [ "no\n", "**Levels**: 1. 'no'\n", "2. 'yes'\n", "\n", "\n" ], "text/plain": [ "[1] no\n", "attr(,\"prob\")\n", "[1] 0.8\n", "Levels: no yes" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "library(class)\n", "knnModelK5 <- knn(train = churnScaled[,-13], test = churnNewScaled, \n", " cl = churnScaled$churn, k = 5, prob=TRUE)\n", "\n", "knnModelK5" ] }, { "cell_type": "markdown", "id": "fc4c8333", "metadata": {}, "source": [ "Based on this output, our model predicts that the new customer will *not* churn." ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "formats": "md:myst", "text_representation": { "extension": ".md", "format_name": "myst", "format_version": 0.13, "jupytext_version": "1.11.5" } }, "kernelspec": { "display_name": "R", "language": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "3.6.1" }, "source_map": [ 16, 23, 37, 40, 62, 73, 77, 110, 124, 144, 178, 208, 218, 229, 249, 260, 263, 268, 274, 277, 282, 286, 289, 294, 298, 301, 306, 311, 314, 332, 338 ] }, "nbformat": 4, "nbformat_minor": 5 }