{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Demystifying Machine Learning \n", "## Using Local Interpretable Model-Agnostic Explanations (LIME)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "by [Alejandro Correa Bahnsen](http://www.albahnsen.com/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Machine learning models are often dismissed on the grounds of lack of interpretability. There is a popular story about modern algorithms that goes as follows: Simple linear statistical models such as logistic regression yield to interpretable models, on the other hand, advanced models such as random forest or deep neural networks are black boxes. Meaning that it is nearly impossible to understand how a model is making a prediction. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The infosec industry is very used to rules, blacklisting, fingerprints and indicators of compromise so explaining why an alert went off is easy and natural. In contrast, machine learning models are able to identify complex nonlinear patterns in large data sets, extrapolate answers and make predictions based on non-trivial compositions that make it nearly impossible to get a feeling for its inner workings.\n", "\n", "Then, if I can use simple expert rules, or regression/decision tree models that are interpretable, why should I use non-interpretable models? Well, because complex machine learning models are much more powerful. \n", "\n", "For example, in the next figure I’m showing the implicit tradeoff between model performance, measured in accuracy, and model complexity, measured in number of parameters. This is built using the common [MINST handwritten digits dataset](http://yann.lecun.com/exdb/mnist/), where the objective is to identify which number was written by looking only at the pixel values of each image.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
\n", "* [Notebook to create the above plot](http://nbviewer.jupyter.org/github/albahnsen/Talk_Demystifying_Machine_Learning/blob/master/figures/Create_Model_Complexity_Figure.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we can see, as a general rule, the more complex the model the higher its performance. In this case, using a simple interpretable decision tree yields an accuracy of 86%, on the other hand a convolutional neural network has an accuracy of 99.3%, however, it must train more than a million parameters, compared with only 1,700 of the decision tree. \n", "\n", "Big efforts are being invested in finding ways to explain the output of machine learning models. Just over a couple months ago, a novel method [LIME](http://arxiv.org/abs/1602.04938) was presented during the 2016 ACM's Conference on Knowledge Discovery and Data Mining. LIME stands for Local Interpretable Model-agnostic Explanations, and its objective is to explain the result from any classifier so that a human can understand individual predictions.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
\n", "* [Source](https://www.oreilly.com/learning/introduction-to-local-interpretable-model-agnostic-explanations-lime)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The LIME algorithm approximates the underlying model with an interpretable one. This is done by learning on perturbations of the original example, and training a sparse linear model in the nearest neighborhood around the target instance. Let's see how that is done with this example. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An *interpretable representation* is a point in a space whose dimensions can be interpreted by a human. Practically speaking, this paper uses small binary vectors of simple features. For instance, a text classifier might use a large space of word embeddings and ngrams as its input representation, while the explanation would use the presence or absence of a handful of particular words as an interpretable representation. The paper specifically focuses on finding sparse linear models as explanations, but notes that the same technique could be used to generate decision trees or falling rule lists as interpretable models. All of these are assumed to be over a domain \\\\( \\\\{0,1\\\\}^{d'} \\\\) of interpretable components -- i.e. a reasonably small number of human interpretable features.\n", "\n", "LIME frames the search for an interpretable explanation as an optimization problem. Given a set \\\\({G}\\\\) of potentially interpretable models, we need a measure \\\\( \\mathcal{L}(f,g,x) \\\\) of how poorly the interpretable model \\\\( g \\in G \\\\) approximates the original model \\\\(f\\\\) for point \\\\(x\\\\) -- this is the loss function. We also need some measure \\\\( \\Omega(g) \\\\) of the complexity of the model (e.g. the depth of a decision tree). We then pick a model which minimizes both of these\n", "\n", "\\\\[\n", " \\xi(x) = argmin_{g \\in G} \\mathcal{L}(f,g,x) + \\Omega(g)\n", "\\\\]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a given example in the original input space \\\\( x \\in R^d \\\\), we want to learn a locally faithful linear model in a relatively small feature space. The intuition is shown in the following diagram." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
\n", "* [Source](https://github.com/marcotcr/lime)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the figure, the black-box complex decision function is represented by the blue/pink background. As expected there is no easy way to generalize this non-linear model. However, if we look locally, we can extract linear explanations. LIME, first select the nearest neighbors to the prediction that we want to explain. These nearest neighbours are represented by the big crosses and circles. Afterwards, we can fit an explainable linear model using only the selected instances, and use the coefficients of the linear model to explain a particular prediction. The bold red cross represents the instance being explained. The pink blob in the background represents the complex model \\\\( f \\\\). The dashed line is the learned linear model \\\\( g \\\\) which will be used as an explanation. This function is locally faithful to \\\\( f \\\\) but globally does not behave at all similarly.\n", "\n", "The general approach is to search for the optimal explanatory model \\\\( g(x) \\\\) by sampling in the vecinity of the example x. We then search the space of potential explanatory models for one which optimizes the objective function \\\\( \\mathcal{L} + \\Omega \\\\).\n", "\n", "The paper focuses on a couple concrete implementations of this approach. For text classification, the interpretable representation is a bag of words of maximum size \\\\( K \\\\). For image recognition, the interpretable representation is a binary vector of \"super-pixels\" of maximum size \\\\( K \\\\). The K features are selected first, using a regression technique, and then the weights of the linear model \\\\( g \\\\) are selected using a least-squares regression, weighted by the distance between the sample \\\\( z \\\\) and the original point \\\\( x \\\\). \n", "\n", "* Starting from a point \\\\(x\\\\) in the original input space map it to a corresponding point \\\\(x' \\in \\\\{0,1\\\\}^{d'} \\\\) in the interpretable space.\n", "* Then take random samples \\\\( z' \\\\) around \\\\( x' \\\\)\n", "* Map each sample \\\\(z'\\\\) back to a point \\\\(z\\\\) in the original space and get the prediction \\\\( f(z) \\\\) using the original global model.\n", "* Calculate the distance \\\\( \\Pi_x(z) \\\\) between the sample point and the original point\n", "* Fit the weights of \\\\(g\\\\) to minimize the error \\\\(f(z) - g(z')\\\\) between the explanatory model and the global model for the set of perturbed examples, weighted by the distance of the perturbed example from the original example.\n", "\n", "[LIME summary from michaelrkytch](http://michaelrkytch.github.io/papers/machine%20learning/2016/07/12/lime-explainability.html)\n", "\n", "I know this sounds way to confusing, but allow me to show an example of using LIME to explain the prediction of a Phishing URLs classifier model." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Case Study: URL phishing detection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Phishing, by definition, is the act of defrauding an online user in order to obtain personal information by posing as a trustworthy institution or entity. Users usually have a hard time differentiating between legitimate and malicious sites because they are made to look exactly the same. Therefore, there is a need to create better tools to combat attackers.\n", "\n", "Phishing attacks can be launched from anywhere in the\n", "world by people with little to no technical skills at insignificant\n", "costs. Organizations trying to protect their users from these\n", "attacks have a hard time dealing with massive amount of\n", "emerging sites which must be identified and labeled either as\n", "malicious or harmless before users access them.\n", "\n", "Being able to determine the maliciousness of a website by\n", "just looking at its URL provides a major strategic advantage,\n", "since the number of victims can be reduced to nearly zero\n", "while minimizing operational efforts by avoiding massive use\n", "of more complex methods such content analysis." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Data\n", "\n", "To evaluate create a phishing classifier, lets use a corpus of one\n", "million phishing URLs extracted from Phishtank and one\n", "million harmless URLs from the CommonCrawl. (Actually a small sample here)\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import pandas as pd\n", "import zipfile\n", "with zipfile.ZipFile('phishing.csv.zip', 'r') as z:\n", " f = z.open('phishing.csv')\n", " data = pd.read_csv(f, index_col=False)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
urlphishing
0http://www.subalipack.com/contact/images/sampl...1
1http://fasc.maximecapellot-gypsyjazz-ensemble....1
2http://theotheragency.com/confirmer/confirmer-...1
3http://aaalandscaping.com/components/com_smart...1
4http://paypal.com.confirm-key-21107316126168.s...1
\n", "
" ], "text/plain": [ " url phishing\n", "0 http://www.subalipack.com/contact/images/sampl... 1\n", "1 http://fasc.maximecapellot-gypsyjazz-ensemble.... 1\n", "2 http://theotheragency.com/confirmer/confirmer-... 1\n", "3 http://aaalandscaping.com/components/com_smart... 1\n", "4 http://paypal.com.confirm-key-21107316126168.s... 1" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.head()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
urlphishing
39995http://www.diaperswappers.com/forum/member.php...0
39996http://posting.bohemian.com/northbay/Tools/Ema...0
39997http://www.tripadvisor.jp/Hotel_Review-g303832...0
39998http://www.baylor.edu/content/services/downloa...0
39999http://www.phinfever.com/forums/viewtopic.php?...0
\n", "
" ], "text/plain": [ " url phishing\n", "39995 http://www.diaperswappers.com/forum/member.php... 0\n", "39996 http://posting.bohemian.com/northbay/Tools/Ema... 0\n", "39997 http://www.tripadvisor.jp/Hotel_Review-g303832... 0\n", "39998 http://www.baylor.edu/content/services/downloa... 0\n", "39999 http://www.phinfever.com/forums/viewtopic.php?... 0" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.tail()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1 20000\n", "0 20000\n", "Name: phishing, dtype: int64" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.phishing.value_counts()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Creating features" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['http://dothan.com.co/gold/austspark/index.htm\\n',\n", " 'http://78.142.63.63/%7Enetsysco/process/fc1d9c7ea4773b7ff90925c2902cb5f2\\n',\n", " 'http://verify95.5gbfree.com/coverme2010/\\n',\n", " 'http://www.racom.com/uploads/productscat/bookmark/ii.php?.rand=13vqcr8bp0gud&cbcxt=mai&email=abuse@tradinghouse.ca\\n',\n", " 'http://www.cleanenergytci.com/components/update.logon.l3an7lofamerica/2342343234532534546347677898765432876543345687656543876/\\n',\n", " 'http://209.148.89.163/-/santander.co.uk/weblegn/AccountLogin.php\\n',\n", " 'http://senevi.com/confirmation/\\n',\n", " 'http://www.hellenkeller.cl/tmp/new/noticias/Modulo_de_Atualizacao_Bradesco/index2.php?id=PSO1AM04L3Q6PSBNVJ82QUCO0L5GBSY2KM2U9BYUEO14HCRDVZEMTRB3DGJO9HPT4ROC4M8HA8LRJD5FCJ27AD0NTSC3A3VDUJQX6XFG519OED4RW6Y8J8VC19EAAAO5UF21CHGHIP7W4AO1GM8ZU4BUBQ6L2UQVARVM\\n',\n", " 'http://internet-sicherheit.co/de/konflikt/src%3Dde/AZ00276ZZ75/we%3Dhs_0_2/sicherheit/konto_verifizieren/verifizierung.php\\n',\n", " 'http://alen.co/docs/cleaner\\n']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.url[data.phishing==1].sample(10, random_state=1).tolist()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Contain any of the following:\n", "* https\n", "* login\n", "* .php\n", "* .html\n", "* @\n", "* sign\n", "* ?" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "keywords = ['https', 'login', '.php', '.html', '@', 'sign']\n", "for keyword in keywords:\n", " data['keyword_' + keyword] = data.url.str.contains(keyword).astype(int)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Length of the url\n", "* Length of domain\n", "* is IP?\n", "* Number of .com" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true }, "outputs": [], "source": [ "data['length'] = data.url.str.len() - 2\n", "domain = data.url.str.split('/', expand=True).iloc[:, 2]\n", "data['length_domain'] = domain.str.len()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0 www.subalipack.com\n", "1 fasc.maximecapellot-gypsyjazz-ensemble.nl\n", "2 theotheragency.com\n", "3 aaalandscaping.com\n", "4 paypal.com.confirm-key-21107316126168.securepp...\n", "5 lcthomasdeiriarte.edu.co\n", "6 livetoshare.org\n", "7 www.i-m.co\n", "8 manuelfernando.co\n", "9 www.bladesmithnews.com\n", "10 www.rasbaek.com\n", "11 199.231.190.160\n", "Name: 2, dtype: object" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "domain.head(12)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "data['isIP'] = (domain.str.replace('.', '') * 1).str.isnumeric().astype(int)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "data['count_com'] = data.url.str.count('com')" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
urlphishingkeyword_httpskeyword_loginkeyword_.phpkeyword_.htmlkeyword_@keyword_signlengthlength_domainisIPcount_com
28607http://pennstatehershey.org/web/ibd/home/event...0000000802000
3689http://guiadesanborja.com/multiprinter/muestra...1011000811801
6405http://paranaibaweb.com/faleconosco/accounting...1000100651601
35355http://courts.delaware.gov/Jury%20Services/Hel...0000000941900
16520http://erpa.co/tmp/getproductrequest.htm\\n100000039700
16196http://pulapulapipoca.com/components/com_media...10110002391804
3810http://www.dag.or.kr/zboard/icon/visa/img/Atua...1000000621300
3005http://www.amazingdressup.com/wp-content/theme...1000100942201
9003http://web.indosuksesfutures.com/content_file/...1000000802501
34704http://www.nutritionaltree.com/subcat.aspx?cid...0000000692301
\n", "
" ], "text/plain": [ " url phishing \\\n", "28607 http://pennstatehershey.org/web/ibd/home/event... 0 \n", "3689 http://guiadesanborja.com/multiprinter/muestra... 1 \n", "6405 http://paranaibaweb.com/faleconosco/accounting... 1 \n", "35355 http://courts.delaware.gov/Jury%20Services/Hel... 0 \n", "16520 http://erpa.co/tmp/getproductrequest.htm\\n 1 \n", "16196 http://pulapulapipoca.com/components/com_media... 1 \n", "3810 http://www.dag.or.kr/zboard/icon/visa/img/Atua... 1 \n", "3005 http://www.amazingdressup.com/wp-content/theme... 1 \n", "9003 http://web.indosuksesfutures.com/content_file/... 1 \n", "34704 http://www.nutritionaltree.com/subcat.aspx?cid... 0 \n", "\n", " keyword_https keyword_login keyword_.php keyword_.html keyword_@ \\\n", "28607 0 0 0 0 0 \n", "3689 0 1 1 0 0 \n", "6405 0 0 0 1 0 \n", "35355 0 0 0 0 0 \n", "16520 0 0 0 0 0 \n", "16196 0 1 1 0 0 \n", "3810 0 0 0 0 0 \n", "3005 0 0 0 1 0 \n", "9003 0 0 0 0 0 \n", "34704 0 0 0 0 0 \n", "\n", " keyword_sign length length_domain isIP count_com \n", "28607 0 80 20 0 0 \n", "3689 0 81 18 0 1 \n", "6405 0 65 16 0 1 \n", "35355 0 94 19 0 0 \n", "16520 0 39 7 0 0 \n", "16196 0 239 18 0 4 \n", "3810 0 62 13 0 0 \n", "3005 0 94 22 0 1 \n", "9003 0 80 25 0 1 \n", "34704 0 69 23 0 1 " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.sample(10, random_state=4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Create a model" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "X = data.drop(['url', 'phishing'], axis=1)\n", "y = data.phishing" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.model_selection import cross_val_score" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "clf = RandomForestClassifier(n_jobs=-1, n_estimators=100)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0.809 , 0.808 , 0.8085 , 0.79075, 0.80225, 0.81425,\n", " 0.80325, 0.805 , 0.80275, 0.7905 ])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(clf, X, y, cv=10)" ] }, { "cell_type": "code", "execution_count": 16, "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_impurity_split=1e-07, min_samples_leaf=1,\n", " min_samples_split=2, min_weight_fraction_leaf=0.0,\n", " n_estimators=100, n_jobs=-1, oob_score=False,\n", " random_state=None, verbose=0, warm_start=False)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "clf.fit(X, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Feature Importances" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "plt.style.use('fivethirtyeight')" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": true }, "outputs": [], "source": [ "importances = clf.feature_importances_\n", "std = np.std([tree.feature_importances_ for tree in clf.estimators_],axis=0)\n", "indices = np.argsort(importances)[::-1]" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\ngFatWiE8PBweHh5ITEyEjY2NyvEPHz5Ez5490bp1axw4cACXL1+Gn58fKleujNGjR5f6iyCickom\nU7459vTmNEo+S5YsgaenJ7y8vAAA8+bNw/79+xEREYHAwECV4zdv3ownT55g2bJleOedd+Do6IhL\nly5h6dKlGDVqFPT09Er3VRARlTK5dP+9cRzjG0t/foMELbIbUi8rK+uVfWF5eXmwsrLCTz/9hB49\neijLJ02ahAsXLmDPnj0qvzNixAjcv38fkZGRyrKTJ0/C3d0dSUlJsLOzK71XQEREZc5rx3wyMzOR\nn58Pc3NzSbm5uTnu3Lmj9nfu3Lmj9viix4iIqHzjVGsiIhLutcnH1NQU+vr6yMjIkJRnZGSgZs2a\nan+nZs2aao8veoyIiMq31yYfAwMDODs7IyYmRlIeExMDV1dXtb/TsmVLHD58GLm5uZLjraysUKdO\nnX8ZMhERlXUadbv5+flh/fr1WLNmDVJSUuDv74+0tDR4e3sDAIKCgtCtWzfl8Z9//jneeecd+Pr6\n4sKFC4iKikJISAh8fX05042IiDSbat2rVy/cu3cP8+bNQ3p6Oho1aoTIyEjY2toCANLS0pCamqo8\n/t1338W2bdswadIkfPTRRzA2Noafnx9GjRqlnVdBRERlymunWpNYubm5KCgokJRVrlxZR9EQEWkH\n13aTgRs3bsDf3x9xcXHIzs5WefzevXs6iKrwLu2Xl0QyMTHRSSyk6tmzZ6hUqZKw8924cQMHDx7E\n06dP0bZtWzRq1EjYuentU+6Tz/HjxxEbG4uMjAyVFsf3338vJIYRI0YgNzcXc+fORc2aNXU6Lnbj\nxg1MmDABcXFxyMvLU5YrFAro6ekJTYRbt24t9r3ZuHGjsDh27dqFJUuWICUlBQDg4OAAX19fdO3a\nVVgMy5cvh5WVFbp37w4AGDVqFDZs2AB7e3ts2LAB9evX1+r54+Pj0adPH+Tk5AAAKlasiGXLluHz\nzz/X6nlf1rp1a42Pfd36k6Xp5MmT2L17N+7fvw97e3v0798fNWrUEHb+InL4PtNUuU4+YWFhCAgI\nQN26dWFpaSn50heZAM6cOYMDBw7AwcFB2DmL4+fnhwcPHiAsLEzlmog0ffp0LFu2DG5ubjqNIyws\nDDNmzEDfvn3h6ekJADh27BiGDRuGadOmCVur8Mcff8TixYsBFCaC7du3Izw8HFFRUfjmm2+wadMm\nrZ5/1qxZcHNzQ0hICAwNDREcHIzAwEDhyefFiU1ykJubCx8fH5w+fRq9e/dG48aNcfr0abi5uWHb\ntm1o0KAWu0JYAAAgAElEQVSBsFjk8n2mqXI95tO4cWOMHTsWw4cP12kcnTp1QkBAANq0aaPTOACg\ndu3aiI6OhqOjo07jqF+/PubPn6+s6euKg4MDvv76a+W6hkVWr16N7777Ttka0jZLS0scP34c1tbW\nmD59Ou7du6dsjf33v//F1atXtXp+Ozs77NmzR/m5yM7Oho2NDa5evaqyqGZ50qdPH5iZmSE0NBQV\nK/6vLr9+/Xps2LABO3fuxO7du/Hpp59qPRa5fJ9pqly3fB49eoSOHTvqOgyEhITA398fI0aMgKOj\no+RDDEDtyuHaUqdOHUl3m64UFBTgP//5j67DQHZ2Ntzc3FTK3dzc1I7PaUu1atVw9+5dWFtbIyYm\nBmPGjAEAVKpUCU+fPtX6+R88eCBZMqtKlSqoXLkysrKyym3y2bFjB65fv47169cjLCxM8nfz7Nkz\nJCYmIicnB4sXL0ZWVhb69++v1Xjk8n2mqXKdfHr37o0//vgDQ4cO1WkcBQUFyMjIwIABAyTNY12M\ns8yePRtBQUFYsGAB6tatK+y8Lxs0aBA2bdqEqVOn6iwGAOjSpQt27NiB8ePHS8qjoqLw3//+V1gc\nH330EcaMGYOmTZsiNTUVHTp0AABcvHhR2I3b58+flyQahUKBixcvSrYPcHZ2FhILUDghZvbs2Th0\n6BDu3r2rMsbx119/afX8GzduxNChQ1GxYkVkZmbixx9/RJs2bVClShUcOHAAPXv2xPPnzzFx4kR8\n++23Wk8+cvk+01S5Sz5F/eZAYRfT7NmzceTIETRu3FilxSHqviQfHx+YmZlh48aNOp9w0L9/fzx9\n+hTNmzeHoaGhyjW5efOmkDgePHiAzZs34+DBg2rfG1GDp3Xr1sXChQtx6NAhtGjRAkDhoO6xY8fg\n5+cn+Txp8/Myf/58zJgxA7du3cLq1auVsw6LxhpE6NWrl8rsx6JxMADCK0ojRoxAcnIy+vXrp5O/\nm/Pnz8Pf3x8AkJ6ejqCgIPj6+gIADh8+jIkTJ6J69epwc3PDxYsX8ejRI1SrVk1r8cjl+0xT5W7M\nx8nJSaPj9PT0cPr0aS1HU8jKygqHDh1CvXr1hJzvVdavX//Kx1/8stGmzz77rNjH9PT0sHPnTiFx\nyPHzogs3btzQ6LiiG89FsLa2xq5du4S2tl5Ur149bN++HU2aNEGDBg2wbds2NG5cuJeOQqFAzZo1\ncfbsWVhaWsLCwgKnTp1CrVq1tBbPqz6rcvx8lruWz5kzZ3QdgopmzZrh+vXrskg+opLL6+zatUvX\nIQCQ1+clNzcXmzdvlkz5LlrKSttEJhVN2dnZqbTERKpduzauXbuGJk2aoE6dOpLks3PnThgaGqJm\nzZq4c+cOFAoFzMzMtBqPnD6rmih3LZ8XzZ07F6NHj1ZZQeDJkycIDQ1VNqm1bevWrZgzZw5GjRql\ndsKBtmt29+/fV3bj3L9//5XH8iZT3UhKSkLfvn3x5MkT5YyzixcvwtDQEJs2bRLyGdGEyM9HXFyc\nsjvS0dER+vr6ws4NAN9++y2uX7+On3/+GUePHoWnpydMTEzwzjvv4MqVK1i4cCH69OmDn376Cdu2\nbZNNhUouynXyqVGjBlJSUlQ2vrt37x7q1asnrP/6VX+wIvrRX7wOJiYmavvORUx+6Nu3L1asWIHq\n1aujb9++rzxW5E2mcrjZtX379rCzs8OSJUtQpUoVAIUz8UaNGoXU1FQcPHhQq+cv7nNRRBeTY27f\nvo3Bgwfj6NGjah/Xdix///03PvjgA/z6669o2bIlHj58iCNHjiAvLw8uLi6wtLTE3bt34ebmhsWL\nF+Pjjz/Wajx+fn5qy/X09GBkZAR7e3v06tULVlZWWo1DU+Wu2+1FRX8wLztz5ozQGpyu+2KjoqKU\nr1fUWIo6NWrUUL4furg7XB253OyanJyM5cuXKxMPUDjdefLkyfjoo4+0fn5dfi6KM2TIEDx8+FC5\nMohotWvXxoIFCzBw4EAsW7YM7u7uylmIAHD58mV4eXmhR48eWk88AHD37l0cPnwYFSpUUC59dPHi\nRSgUCjg7O2Pnzp2YPXs29uzZo/FYpjaVy5aPtbU19PT0kJ2djcqVK0u+UPLz85Gbm4vBgwdj/vz5\nOoyS5EAuN7u6ublhxowZaN++vaT84MGDmDZtGuLj43UTmA5ZWVlh//79Or8hOjo6Gl999RVq1KiB\nli1bwsjICOfOncPJkycxceLEYlskpS0sLAxJSUkICwtTDiXk5ORg7NixaNy4MXx9fTFy5EjcvXsX\nUVFRQmJ6lXKZfNavXw+FQoFRo0Zh9uzZqF69uvIxAwMD2NraomXLlkJjOnfuHMLCwpCSkgI9PT04\nODhgzJgxOv3DSk9PV7nhVOQNr3Lw3nvvITo6Wqf3PAHAvn37EBAQgMmTJ6N58+YACqd8z58/H4GB\ngZKNHbXZak9OToa+vr5yLbmYmBhs2LABDRs2xNixY4WOu7Rv3x5z584tdlNLkfLz8xEfH49z587h\n+fPnsLe3R/v27bU6tfpljRo1wvbt21WW6UpOTkb37t2RkpKC06dPo0ePHpItcHSlXCafInFxcXB1\ndRW6MrA6e/bswcCBA/HBBx+gVatWAIDExEQkJiZi7dq1Qm9mfPDgAfz9/bF9+3a1Kx2I6tP/7LPP\n1HZxvdh/3a9fP60PtM+YMQMVK1bU+c2uLyaUoutSNNPrxZ+1Pe7yySefwMfHB71798atW7fQokUL\ntG3bFufPn8cXX3yBwMBArZ37ZX/88QfmzJmDb775Bo6Ojip/x3KbHNOnTx+EhobC0tJSK89vbW2N\ndevWoV27dpLy2NhY9O/fH7du3UJqairatWun8dR5bSrXYz516tRBWlqaSnnRF5y2p0YWmTlzJiZO\nnIivv/5aUj5r1izMnDlTaPKZPn06zp07h3Xr1mHgwIFYvHgxbt++jeXLl2PWrFnC4mjYsCEiIyNh\nYWGBZs2aAQBOnTqF9PR0fPrppzh8+DB++uknbNmyReWP7d+aPHmy8t8KhQKRkZE6v9lVLmMuly5d\nQtOmTQEULi/j4uKCzZs3488//4Sfn5/Q5OPh4QEA6Nmzp85XBtFEQkICcnNztfb8n376KUaPHo3g\n4GC8//77AAr/ZgICApT3zZ04cQLvvfee1mJ4E+U6+Tg5Ob1yALlatWro378/goODVb50StOVK1fU\nzu7q27cvQkNDtXZedf744w+Eh4ejdevW0NfXh7OzM3r16gVLS0v8/PPPwsY+3nnnHXh6emLOnDmS\n8mnTpgEA/vzzT/j7+2PmzJmlnnwuXLgg+blojblLly5JykVOPqhTp45yrPJFCoUCt27dEtYdWlBQ\noGxh/Pnnn8q1xOzt7ZGRkSEkhiJySchysXDhQkybNg3Dhw/H8+fPARRufTFgwADMmDEDANCgQQMs\nWrRIl2EqlevkExERgYCAAHh7e8PFxQVAYc1g1apV8Pf3x8OHDzF//nxUrVpVpVVSmszNzZGUlKQy\nrpCUlKQyDVzbHjx4oPwiq169Ou7du4e6deuiRYsWysUsRVi3bh2io6NVyr29vdGhQwfMmjULXl5e\n2LBhQ6mfW473YzRt2lTtbQH3799H06ZNhdXyGzVqhIiICHTq1AmxsbEICAgAAPzzzz8wNTUVEkOR\n1yXk8qZy5cpYuHAhZs6cqRzTsbe3l8yQlMMstyLlPvnMmjVLskdIu3btUK9ePSxfvhx79uyBubk5\nZs+erdXk8+WXX2LcuHG4evWqcqLDkSNHEBYWJvQLHyi8a/zatWuwsbFBgwYNsGXLFri4uGDnzp1C\n+9ALCgpw8eJFlS6C5ORk5ViHgYGBsNbHkydPJH/QIlYVeFFxtwU8fvwYRkZGwuIoWiAzNDQUnp6e\nyjv69+7dq+weFUUuCVluqlSpgiZNmug6jNcq18nn2LFjCAkJUSl3dHTEqVOnAAAtWrTA7du3tRrH\nV199hSpVqmDJkiXKcRUrKytMnToVI0eO1Oq5X+bp6Ynz58/Dzc0N48aNQ9++fbFy5UoUFBSodIFp\nU79+/TB69GhcvXpV0n8dEhKiXAIoPj5e67MBnz59isDAQKxatQp5eXlQKBQwNDSEl5cXgoKCtP7F\nXzT+pKenh6CgIEnSKygowIkTJ4RuPdGmTRtcuXIFjx49kqxwPWjQIEkNWwS5JGRdkuuN2Zoo18nH\nxsYGq1atUvaHFlm9ejWsra0BAJmZmVqv8evp6cHPzw9+fn549OgRAAidovmiF+9JaNeuHY4ePYpT\np07hvffeU9ZyRZg5cyZq1qyJpUuXIj09HQBgYWGBMWPGKHcPdXd3xyeffKLVOCZMmICYmBiEhoYq\nW6VHjx5FcHAwHj9+jCVLlmj1/EXjTwqFApcuXZLM6DIwMEDTpk21vpuq3L7g5JaQdUmON2Zrqlwn\nn5kzZ+LLL79EdHS0snadlJSE1NRUrFmzBkDh3uw9evTQahwXL15Efn4+mjRpIkk6586dQ8WKFdGw\nYUOtnv9VbGxsdHJvj76+PsaPH4/x48fj4cOHACC5H6soNm3bsWMH1q5dK1lFwM7ODubm5vjyyy+1\nnnyKxp98fX0xZ84clWsggty+4OSQkEtiwoQJpb7x3tKlS9X+uywo1/f5AMCtW7fw008/4fLlywAK\nZ4N4e3sL/cLt1KkTRowYgV69eknKt2zZgpUrV+K3334TFgtQuNxPcRt0BQcHC43l2rVrSE5OVt54\na2dnJ/T8DRo0QFRUlEoFIDk5GV27dlV+brTNz88Pc+bMUWkRZ2dnY/LkyVpPgnKky4T8JhNd+vXr\np8VIivfkyRMcOXIEdevWleWq5OU++ciBtbU14uLiVL5YdXFD2KJFi/Dtt9/CxsZGZYMuPT09/P77\n70LiePjwIUaPHo2oqChUqFABQGFNt1u3bggLCxPWLTl//nycP38eS5cuVXbvPHnyBKNGjULDhg3x\n1VdfCYmjuEVwMzMz0aBBA2RmZgqJgwoVdcsXycvLw7Nnz5Sf1aIp6YaGhsI2YPTx8YGLiwuGDh2K\nvLw8tG/fHhcvXoSBgQF++eUXybpzclCuu92AwrWPzp49q3bF4hdnwWlThQoVJFsRF8nKyhK+X8nS\npUvxww8/wNvbW+h5XzZlyhScP38eO3fuVC6fkpiYiAkTJmDq1KmSHUS16dixY0hISECjRo2UY14X\nLlxAfn4+srOzJWMg2hjvuH//PhQKBRQKBbKysiT3m+Xn52Pfvn06WVRTDnJzc7F8+fJiVxxPSEjQ\n2rlfnMq9b98+zJkzB7Nnz5YsfTRt2jRhlRMAOHDgAEaMGAGgcPbho0ePcOnSJfzyyy+YM2eO7JJP\nuW75HDx4EEOGDFE7JVPkHdL9+vWDvr4+Vq9erVwb6/nz5/Dy8sLz58+xadMmIXEAhQtp7tu3T+dr\nmdnb22PdunVo3bq1pDw+Ph4DBgwQtjZV0bbImtBGn/vrtjLQ09PD1KlTMWnSpFI/t9z5+flh165d\n6NGjh9oVx6dMmSIkjpYtW2Lx4sUq60EePXoUvr6+OH78uJA4LCwscPLkSdSuXRujR49G9erVMWvW\nLFy/fh1t2rSR3b1P5brlM2XKFHTs2BEBAQE63eMiODgYnTt3xvvvvy9Z2y07Oxt79uwRGsvgwYOx\nbt06TJ8+Xeh5X5abm6t2cNvExARPnz4VFoeuB3F37typ7G5cs2aNZOalgYEBbGxsZLM/i2i7d+/G\n6tWrVVb6Fu3GjRsqG1IChat0iPzCr1mzJi5evAhLS0scOHBAeRtJdna2VldoKaly3fKpVasW4uPj\nYW9vr+tQkJaWhpUrV+Ls2bMACu9EHjJkiPAvFoVCAQ8PD6Snp6NRo0YqizWKGtju0aMHqlWrhh9/\n/FH5h52dnY2RI0fi0aNH2L59u5A45OLGjRuwtrZWjilQ4f14O3bsUK6wrSuffvopAGDlypWoVasW\ngMKN7kaMGAGFQiFsxYy5c+diyZIlsLS0xJMnT3DixAkYGBhgzZo1+OWXX4SN12qqXCefnj17wsfH\nR7k+ldwVLT6qzWVMgoODERISgqZNm6odSxDVBXjhwgX07t0bOTk5krGWypUrY8uWLcrNsnRlxowZ\nSE9PFzb2BMhjfFJOli9fjuTkZCxcuFBnm/wBwNWrVzFgwABcunRJWVn8559/UL9+faxbt05oF/aO\nHTtw69Yt9OjRA7Vr1wZQuIXMu+++q0ySclGuk09UVBRmzZoFPz8/ODo6qjRNtb1c/5uysbHBoUOH\ntDrd2NbWFiEhISrTvnUhJycHmzdvVi7o6eDgAA8PD+FL26jTrVs3XL9+XdgutHIZn9S1l29yTUhI\nQPXq1dGwYUOVv1+Rd/QrFArExMRIPqvt27fXaVIsjra3dtBUuU4+r1q5QI5/0MVNyS5NDg4O2L17\nN+rVq6e1c9Cba9WqFd5//32dj0/qmq4ngLzs2bNn6Ny5M5YvX67z7j9Nifge0YT8RqEEElVrLUt8\nfX2xbNkyzJ8/X3it7U229pVbN5O2a5M3btzAhg0bynXiAXQ/AeRllSpVwvXr12XZwpG7cp185HjX\nr64lJCTg8OHD2Ldvn/CuDC8vL42Ok2OrVNsbhbm6uuLy5cuymBxDUv369cPq1atV1oikVyvXyQcA\noqOjER4ejmvXrmHLli2wtrbGmjVrUKdOnVLfpKwsMDU1Ve56KNr9+/d1cl65SkpKUv7b29sb06dP\nR1paWpkYn9Ql0ZNBisYmY2Ji4OzsrDLtWtRut2VNuU4+kZGRmDBhAgYOHIjY2Fjl7n/5+flYtGhR\nuUw+cuvWeB25DJ5qw0cffQQ9PT3JKhdjx45VOU6OLUFdOnbsGK5fvy7sfCkpKcpN2q5duyZ5jN1x\nxSvXyWfRokVYtGgRevfujbVr1yrLmzdvju+++05YHDdv3tRoi+Q+ffoIW9NM1wt6akrb3V26xDHJ\nknmTscPSIMedb8uCcp18rl69ihYtWqiUV61aVbmvjgia7sj4ww8/aD0WuSzoSSUbk3ybW4IlJeqa\n5Obm4urVq9DT04O9vb1sN7TTxtYOJVGuk4+lpSWuXLmi8kcuetUDOe3IKJcFPalk3uaWYElp+5o8\ne/YMwcHBWLlypWS32+HDh2P69Okqq4SUppJs7TBhwgRthfNGynXyGTRoEPz9/REaGgqgcKXahIQE\nBAYGClmUUI47Mu7du1dlQU83NzeEhIRgwIABTD7FkEttksQLDAzEli1b8MMPP+CDDz4AUJjwgoOD\nUVBQgJkzZ2rt3C+vmv2qrR10ta9Qccp18hk7diwePnyInj17Ijc3F127doWhoSFGjRqFYcOGaf38\nctyRUS4LeupSWa5Nkni//vorFi9eLFmmy97eHmZmZhgzZoxWk48ct3bQVLle4aBITk4OUlJSUFBQ\nAAcHB1StWlXo+XW5I+PLytqCntq4W1uOG4VpSi53r8uJtq+JpaUlDh06pLLCwaVLl/Dhhx8iLS1N\nK+d9mVy2dtBUuWv5vLw21KuIWhtKTtObv/vuO/Tu3Vtl87SiBT3lRhvdXWW5NkniNWnSBD/++CPm\nz58vKV++fLnQbnO5bO2gqXLX8pHb2lCAbndkVEdXC3qWpLtL28pabZItH1Xavibx8fHo06cPrKys\nJBWUtLQ0bN68WTkOpG1y2dpBU+Uu+ciRXHZk1DU5dndZWlrijz/+QJMmTSTlZ8+eRYcOHYR1qWjq\nhx9+wODBgzn54QUirsnt27fx008/SSpsovfjktPWDppg8pEBOzs7rFq1Smc7MsqxxfG67q7OnTsL\niUOXtUk5vi+6xmvyamVpawcmHxnQ9Y6McmxxyKW7S5e1STm+L7omx2vSs2dPtG3bFm5ubmjWrJlO\ntqwui1s7cE9eGRgzZgyWLFkiWcNLpFu3bin/++mnn9C4cWPs3bsX6enpSE9Px969e/Gf//wHK1eu\nFBaTXAZP69ati/j4eERGRsLPzw9+fn7YvHkzEhIStN6NIcf3RdfkeE1cXFzwxx9/oGvXrrCzs0PP\nnj2xYMECHDlyRLlepLaVxa0d2PKRgS+++AKHDx+WxY6McmlxyGHwVE61Sbm8L3Iit2vy5MkTHD16\nFIcOHUJ8fDyOHz8OIyMjYS2w6dOnA0CZ2dqh3E21liNdbmPwMrm0OMLCwjBgwAA4OTmp7e4SQU61\nSbm8L3Iit2vy6NEjZGZm4u7du7hz5w4qVqyIpk2bCjt/WdvagS0fkpBDi6OIHAZP5VKblNP7Ihdy\nuSYTJ05EXFwcbt68CRcXF7Rp0wZt27ZFixYtYGhoKCQGAK+swOrp6WHnzp3CYtEEkw9JpKamon//\n/jqdrimn7q6JEydi8+bNsLW11WltsqxNoxVBLtfExMQEZmZmGDZsGDp06ABnZ2dZtJbljslHBl5c\nxFMd0TeZyqHFUa9ePfz222+oV6+esHOqI6fapBzeF7mRwzVJTU3FoUOHEBcXh4SEBDx69AitWrWC\nm5sb2rZtK3yX2bKytQOTjwzMmTNH8vPz589x9uxZJCYmYtiwYfjmm290FFnxWrdujcjISJWpr6VF\nLt1dciCnlqBcyPmaXLp0CYsWLUJkZCTy8/OF7TKry60dSoITDmSguBUMQkNDZXv/xo0bN7Q6jVRu\ng6e6rE3KaeKDXMjpmhQUFODUqVPK1s+RI0eQm5sLZ2dntG3bVlgcutzaoSTY8pGx1NRUtG/fXuh+\n9JrS9npZcunukkttki1BVXK5JjY2Nnj69CmaNm2Ktm3bom3btmjVqhWqVKkiNI4GDRqobO0AFK4W\nMmbMGKSkpAiN53XY8pGx+Ph4tVNJywO5zN6SS21Sbi1BOZDLNVm1apVOks3LHj58qHYHZnt7ezx4\n8EAHEb0ak48MvLzNg0KhQHp6Os6cOQN/f38dRSUPuh481eVGYS9KSUmBk5MTAODatWuSx+TQ9aQL\ncrkmKSkpaNasmc6Tj1y2dtAUu91k4OVtHipUqAAzMzN8+OGHcHd311FUr6btbje5dHfJZaMwkq8m\nTZogIyMD//3vf/Hll1/q7G9WLls7aIrJh0pE28nn66+/xpYtWxAYGKjS3eXh4SGsxfHJJ5/A2dlZ\npTY5YcIEnD17FtHR0ULiKKLrlqAc6fqaKBQKHDhwAOvWrcOePXtgZmaGfv36YcCAAahTp47QWOSw\ntYOmmHxk5Nq1a0hOToaenh4cHBxkvSHY5s2b0aVLF611Nchl8FQutUm5tATlRI7X5P79+4iMjMS6\ndetw/vx5uLm5YeDAgejRowf09fWFxyNnHPORgYcPH2L06NGIiopSLg2vUCjQrVs3hIWFoVq1akLj\nOX78eLG7qhYN4np4eGg1BrkMnrZp0wbHjh2T1CZ79OghvDYpl4kPciLHa2JiYgJnZ2ecPXsWKSkp\nuH79OiZNmoSAgAAsXboU7dq109q55bC1w5tgy0cGfH19cfToUYSEhMDV1RUAkJiYiAkTJsDV1RWL\nFy8WFktYWBgCAgJQt25dlV1VRU5xllt3l67JpSUoJ3K6Jnfu3MGGDRuwbt063Lx5E127dsXAgQPh\n5uaG3NxczJs3D5s2bcK5c+e0FsPMmTMRHx+PkydPolKlSmjRooVy6reLi4vskhGTjwzY29tj3bp1\nKsvsxMfHY8CAAUhNTRUWS+PGjTF27FgMHz5c2DnVkUt3l1xqk5z4oEou1+SLL77AgQMHUL9+fXz5\n5Zfo27evypbdGRkZaNCgAe7fv6/1eHS9tYOmuJmcDOTm5qJGjRoq5SYmJnj69KnQWB49eqRSk9SF\nou6u7t27Izs7G9nZ2ejRoweOHTsmdNaOHDYKA/43jfZlcp1GK4Jcrom5uTn27NmDhIQEjBw5UiXx\nAICZmRlOnz4tJB5db+2gKbZ8ZKBHjx6oVq0afvzxR+WNctnZ2Rg5ciQePXqE7du3C4tl/PjxaNy4\nMYYOHSrsnGWBrmuTcmkJygmviZRctnbQFJOPDJw/fx6ff/45cnJy0LhxYwDAhQsX8M4772Dr1q1o\n1KiRVs//4phSbm4uli1bBnd3dzRu3Film2nUqFFajaWIXLq7ity5cwdxcXH4888/cejQIdy+fRsu\nLi5CV2IoS9NoRZHLNQkPD0d4eDiuX7+Ow4cPw87ODgsXLlS2lkUoa1s7MPnIRNFSIS/+EXl4eOCd\nd97R+rmL7hJ/HT09PWFdB3IZPC1rtUkSb+nSpQgNDcXYsWMRFBSExMRE2NnZYePGjVi9ejX27t0r\nJA65be3wOkw+MjBjxgxYW1vD29tbUh4REYHbt2/LcksFUXTd3SWX2qTcWoJyIJdr0qJFC8ycOROd\nOnWS3Hx98eJFdOnSReiEoRfpamsHTXHCgQxs2rRJba2kadOm2Lhxo9BY5s6di5ycHJXyJ0+eYO7c\nuUJjAXQ/eHry5ElMnz4df/31FwYOHAg7Ozt88cUXWLx4MZKSkoTFIZeJD3Iil2ty8+ZNtV3jlSpV\nQm5urrA4CgoKcOLECYSEhODzzz/Hxx9/jMjISDg7O2Ps2LHC4tAUWz4yYGFhgSNHjqisaHDt2jW4\nuroiPT1dWCw1atRASkoKzM3NJeX37t1DvXr1hNWe5NrdpevapK5bgnKk62vSqlUrTJs2DV27dpW0\nfJYuXYrIyEgcPHhQSBxy2dpBU2y7y4C1tTUSEhJUkk98fDxq1aolNBaFQqG2W+nMmTMwMTERFkdE\nRATMzMwwbtw4nXZ3yWWjsCK6bgnKka6vyahRozB58mQ8efIECoUCR48excaNGxEaGir0BnG5bO2g\nKSYfGRg0aBC+/vprPHv2DB9++CEAIDY2FkFBQRg3bpyQGKytraGnpwc9PT2VL/r8/Hzk5uZi8ODB\nQmIBCru7ir7w16xZo7PB0zp16khqkz4+Pjr5A1fXEly0aJHOW4K6JJdrMmDAAOTn5yM4OBg5OTkY\nMWIErKysMGfOHPTq1UtYHHLZ2kFT7HaTiaCgICxbtgx5eXkAAAMDA4wcORLffvutkPOvX78eCoUC\no542rpQAAAdLSURBVEaNwuzZs1G9enXlYwYGBrC1tUXLli2FxKKOrrq79u/fL4vapFwmPsiJXK7J\nqlWrMGjQIABAZmYmCgoKlN3W48ePx8KFC4XEIZetHTTF5CMj2dnZyvWoGjRogKpVqwqPIS4uDq6u\nrjpfJfl13V2BgYFC4li6dCn69esntMtRnbI2jVYEuVyTOnXqIDQ0FN27d5eUjx8/HtHR0Vpdz+1F\nctraQRNMPiRR3CCtnp4ejIyMYGZmJiQOuQyeyrU2qeuJD3Kkq2sSGxuLgQMHYu3atcpVq8eOHYv9\n+/dj165dOtkapSxs7cDkQxImJiav7LqoVq0a+vfvj+DgYK3eVyGX7i651Cbl0hKUEzldkx07dmDM\nmDHYsmUL1qxZgwMHDugs8RQ5cuQI1q5di82bN6NWrVrIyspC5cqVtb61g6aYfEhi27ZtCAgIgLe3\nN1xcXAAAJ06cwKpVq+Dv74+HDx9i/vz5GDJkCL7++mutxSGX7q4X6bI2KZeWoJzI7ZqsXr0aX331\nFSwsLLBr1y6ddHXJYWsHTTH5kETXrl0xbNgwdOvWTVIeFRWF5cuXY8+ePfj1118xe/ZsnDhxQmtx\nyLW7S1e1Sbm0BOVEl9dk8uTJast3796NJk2aSBJP0QaM2ia3rR1eh1OtSeLYsWMICQlRKXd0dMSp\nU6cAFC4ncvv2ba3GcfbsWWV3l6enp04HT9XVJn/99VdJbdLPz0+rtcmyNo1WBF1ekwsXLqgtt7e3\nR3Z2tvJxkbPvirZ2aNGiRbHHiNza4XXY8iGJFi1aoHPnzpgxY4akfPr06fjtt99w7NgxnDx5EgMG\nDCj2D7C06bK7Sy61Sbm2BHWJ16Rs49puJDFz5kysWLECrVq1go+PD3x8fPDBBx9g5cqVmDVrFoDC\nG0B79OghLCYTExM4OzvDyckJFStWxPXr1zFp0iQ4OTkhNjZWq+eWy0ZhZ8+exfr161GhQgV4enqi\nSZMmmDVrFq5fv67V88oZr4mq8PBwtGrVClZWVrh27RoAYOHChdi2bZtuA1ODLR9ScevWLfz000+4\nfPkygMJ7jry9vWFjYyM0jrI0eCpSWZhGKxqviXy2dtAUkw/Jkly6uwB5bBT2MrlPo9WF8n5N5Lq1\nQ3E44YBU5OTk4OzZs8jIyEBBQYHksZdnwWmLXAZPX65NFrGyssKKFSuEJh85THyQG16T/5HL1g6a\nYvIhiYMHD2LIkCFq7w7X09MTdte4JqsB6+npwdbWVqtx/Pzzz1i0aBE6deqkHPMCCvdaSk5O1uq5\nX/RiS3Dw4MEqLUEjIyOMHDkSP/zwg7CYdI3XRMrOzg6nT59W+Zv4/fff4eDgoKOoisfkQxJTpkxB\nx44dERAQACsrK53GIofuLrnUJuXSEpQTXhMpuWztoCkmH5K4ceMGNmzYoPPEI5fuLrnUJuXSEpQT\nXhMpuWztoClOtSYJV1dX5Sw3XSrq7vLx8ZGsISe6u6uoNhkZGamsTc6ZMwczZ87EmDFjhMUBlK1p\ntKLwmvzPqlWr4OXlhXPnzuGvv/7CpUuXcOHCBXz55ZcYP368rsNTweRDEt7e3pg+fTrWrFmD48eP\nIykpSfKfKHLp7howYACmTJkiqU2uWbNGeG1y6dKlmD9/Pry8vKBQ/G+CalFLsDziNZEKDAzEjh07\nAACmpqaSPYWio6N1GZpa7HYjCS8vLwCFS8K/TOSEA7l0dxVtFObl5aXTjcLkMvFBTnhNpNasWYOB\nAwfC2NhY7dYOcsPkQxJyGZyVy+BpYGAgTExM0L17d5iamirLRdcm5dISlBNeE6l27dohLCwMX375\npay2digOkw9JyGVwVi6Dp3KpTcqlJSgnvCaqunfvjqysLHTp0gUWFhbYvXu3LHcxBZh8SI3o6GiE\nh4fj2rVr2LJlC6ytrbFmzRrUqVNH2J3icunukkttUi4tQTnhNSl+awdzc3M4OjpiyZIlyjJRWzto\nismHJCIjIzFhwgQMHDgQsbGxeP78OQAgPz8fixYtEpZ85NLdBcijNimXlqCc8JrIc2sHTXFtN5Jo\n06YNJkyYgN69e0vWhzp79ix69eolbBp2bGwsBg4ciLVr16rt7tJmq0OOG4UVtQQB6LQlKCe8JmUb\nWz4kcfXqVbV3jFetWhWPHj0SFocuu7vkWJuUU0tQLnhNyjYmH5KwtLTElStXVAZx4+PjYW9vLzQW\nXXV3yXFaqlwmPsgJr0nZxuRDEoMGDYK/vz9CQ0MBFO7tk5CQgMDAQEyZMkWr5y7Lg6faJpeJD3LC\na1K2MfmQxNixY/Hw4UP07NkTubm56Nq1KwwNDTFq1CgMGzZMq+eWY3eXnMhh4oPc8JqUXZxwQGrl\n5OQgJSUFBQUFcHBwQNWqVXUdUrkjx4kPusZr8vZgy4fQt29fjY/duHGjFiOhF7ElqIrX5O3B5EOo\nUaOGrkMgNThororX5O3BbjciIhKOWyoQEZFwTD5ERCQckw8REQnH5ENERMIx+RARkXD/B71NkQDm\nzzE9AAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.title(\"Feature importances\")\n", "plt.bar(range(X.shape[1]), importances[indices], yerr=std[indices], align=\"center\")\n", "plt.xticks(range(X.shape[1]), X.columns.values[indices], rotation='90')\n", "plt.xlim([-1, X.shape[1]])\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Feature importance is an interesting tool to evaluate in a general way which features are more important during training. But it does not gives any insight regarding the feature importance of a given individual prediction." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Explaining individual predictions using LIME" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First install lime using\n", "\n", "```pip install lime```" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import lime\n", "import lime.lime_tabular" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/al/anaconda3/lib/python3.5/site-packages/sklearn/utils/validation.py:429: DataConversionWarning: Data with input dtype int64 was converted to float64 by StandardScaler.\n", " warnings.warn(msg, _DataConversionWarning)\n" ] } ], "source": [ "explainer = lime.lime_tabular.LimeTabularExplainer(X.values ,feature_names = X.columns.values,class_names=['ham','phish'],\n", " categorical_features=[0, 1, 2, 3, 4, 5, 8], kernel_width=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Function to explain a single instance using LIME" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def explain_instance(X_test):\n", " if X_test.phishing.values == 1:\n", " print(\"Phishing URL\")\n", " else:\n", " print(\"Legitimate URL\")\n", " print(X_test.url.values[0])\n", " y_pred_proba = clf.predict_proba(X_test.drop(['url', 'phishing'], axis=1))\n", " print(\"Predicted Probabilites: \", y_pred_proba[0])\n", "\n", " # Explain prediction\n", " predict_fn = lambda x: clf.predict_proba(x).astype(float)\n", " exp = explainer.explain_instance(X_test.drop(['url', 'phishing'], axis=1).values[0], predict_fn, num_features=5)\n", "\n", " # Organize explinations\n", " temp = pd.DataFrame(exp.as_list())\n", " vals = temp.iloc[:, 1].tolist()\n", " features = temp.iloc[:, 0].tolist()\n", " loc = np.arange(temp.shape[0])[::-1]\n", "\n", " # Plot\n", " print()\n", " print(\"Feature importances:\")\n", " fig, ax = plt.subplots(figsize=(6,4))\n", " # Plot positive impact features\n", " plt.barh(loc, [max(val, 0) for val in vals], height=0.5, color='r')\n", " # Plot negative impact features\n", " plt.barh(loc, [min(val, 0) for val in vals], height=0.5)\n", "\n", " # Plot to fix range\n", " plt.barh([0, 0], [-np.abs(vals).max()*1.2, np.abs(vals).max()*1.2], alpha=0)\n", "\n", "\n", " # Add labels\n", " for label, x, y in zip(features, np.zeros(loc.shape[0]), loc):\n", " if vals[features.index(label)] > 0:\n", " plt.annotate(label, xy = (x, y), xytext = (5, 27),\n", " textcoords = 'offset points', ha = 'left', va = 'top')\n", " else:\n", " plt.annotate(label, xy = (x, y), xytext = (-5, 27),\n", " textcoords = 'offset points', ha = 'right', va = 'top')\n", " plt.yticks([]) \n", " plt.xticks([0], [''])\n", " plt.annotate('HAM', xy = (np.min(vals)*0.5, max(loc)+1.05), xytext = (0, 0),\n", " textcoords = 'offset points', ha = 'right', va = 'top')\n", " plt.title(' HAM Phish ', y=1.13)\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test with a random phishing URL" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Phishing URL\n", "http://login.paypal.com.convexcentral.com/Update/ab770f624342b07b71e56c1bae5d9bcb/\n", "\n", "Predicted Probabilites: [ 0. 1.]\n", "\n", "Feature importances:\n" ] }, { "data": { "image/png": "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\nXl4eq1atolSpUvz9738v6RLlPqGNO3JNVzbsVKlS5YbBduXWaVpamjYwyAOhXbt2dOzYkf/9738s\nX76cadOmsXnzZlq2bMmaNWtu6X8ZkT82h5MnT+qb3CIiIteglaSIiIgJhaSIiIgJhaSIiIgJhaSI\niIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJ\nhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSI\niIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIABAZ\nGcngwYNLuox7wtvbm/fff/+m+rq6urJ8+fK7ev64uDiioqLu6pzy+3Aq6QJERP7oxo0bR1FR0T09\nx4QJE/j3v//N9u3bOXv2LCdPnryn53tYaCUpIn8IBQUFJV2CqUqVKuHq6npPz3HhwgVatWpFXFzc\nPT3Pw0YhKSLXtH79enx8fJgzZw4AaWlpBAcH4+HhQePGjZk2bRo2mw2A3r17F7udaLPZaNCgASkp\nKaxdu5bq1atTWFgIwN69e3F1dSU+Pt7on5CQQJs2bYzXGzduJDw8HA8PD/z9/Rk6dKhdEEZGRjJg\nwABGjBhB7dq1ef755425IyMj8fDwoEmTJqxevfqO3ocdO3bQpk0bPD098fX1JS4ujlOnThnthYWF\nDB06lJo1a+Lr68uIESMYOHAgkZGRRp/f3m6NjIxk4MCBjB07Fj8/P+rUqcOIESOM9/N2DB8+nL59\n+/LEE0/c9hxSnEJSRIpZvnw5HTt2JDk5ma5du5Kamso//vEPhg0bxqZNm0hISCA5OZn33nsPgM6d\nO7N27VqOHDlizJGens7Ro0fp0KEDISEhnD9/nm3btgGQmZlJlSpVyMzMNPpnZmZitVoBOHToEO3b\nt+eJJ55gw4YNTJ06lQ8//JAxY8bY1blkyRKKior47LPPmDlzJjabjY4dO2Kz2VizZg0pKSmMGzeO\nCxcu3Nb7cObMGV566SXKlSvHF198QVpaGps3b6ZPnz5Gn6lTp7Jw4UKmTJnCv//9by5evMjSpUtv\nOPfSpUspVaoUa9asISkpiRkzZvDRRx8Z7fHx8Xh7e1/3Jy8v77auS26enkmKiJ158+YxcuRIUlNT\nadGiBQBJSUmMGTPGWOn5+vqyb98+Zs+eTY8ePQgKCiIgIIBFixYZq8O0tDQiIiKoWrUqAI0aNSIj\nI4PAwEAyMzPp3r07kydP5siRI1SsWJFvvvmGUaNGATB79mw8PT2ZOHEijo6OWCwWRo0aRXx8PMOH\nD8fFxQUAHx8f3nzzTaP2devWsWvXLr777jtq1KgBQGJiIhEREbf1XixbtoyzZ8/y7rvvUqFCBQAm\nT55M69at2bt3L35+fsycOZP+/fsb7824ceP44osvbji3xWJh+PDhANSpU4fU1FTWr19Pu3btABg2\nbBh9+/a97hzVqlW7reuSm6eQFHnI7N69G39//2u2ffrpp8ydO5dVq1YRFBQEwM8//8yBAweIj49n\n4MCBRt/CwkK7zSgxMTHMnj2b+Ph48vPzWbVqFWlpaUa71WolMzOTAQMGsHHjRnr27ElGRgaZmZlU\nrVoVJycnGjduDEBOTg5NmjTB0fH/bnaFhoZSUFDA3r17adCgAXA5eK+Wk5ODl5eXEZBAsXluRU5O\nDvXr1zcCEiA4OBhHR0d27dpFlSpVOHr0KE899ZTR7uDgwFNPPcXBgwevO3f9+vXtXnt6enL8+HHj\ntZubG25ubrdVt9w9CkkRMTRo0ICdO3eyYMECAgMDcXBwMJ6TTZo0ieDgYNOxHTp0YPTo0WRlZZGd\nnU3VqlUJDw832q1WK7NmzSInJ4fTp0/TqFEjrFYrGRkZuLm5ERgYSJkyZW5Yo4ODg/HncuXK3cHV\n3pmr67gdpUuXLjbf1R864uPjWbJkyXXn+Oqrr+w+EMjdp5AUEUPNmjUZP348rVq1ol+/fiQnJ+Pu\n7k61atXYt28f0dHRpmMrV65M69atSUtLIzs7m+joaLsVXEhICBcuXCA5OZmQkBBKlSqF1WqlX79+\nuLu72wWqxWLh448/xmazGXNkZWVRpkwZatWqZVqDxWLh0KFDHDhwgOrVqwOwdevW294QY7FYSEtL\n4/Tp08ZqctOmTdhsNiwWC5UqVcLDw4Nt27bRrFkzAIqKiti2bRvu7u63dc4rdLv1/qCNOyJix9fX\nlxUrVvDFF1/Qv39/ioqKGDp0KFOmTGHatGns3r2bnTt3smjRIiZNmmQ3NiYmhqVLl/L999/TsWNH\nu7by5cvTqFEjlixZQlhYGACBgYEcOnSILVu2GJt2ALp168aRI0cYOHAgOTk5fP7554wZM4bu3bsb\nzyOvpXnz5gQEBBAbG0t2djabN29m2LBhODnd3nqgffv2uLi4EBsby44dO9i4cSPx8fG0bt0aPz8/\nAGJjY0lOTmbFihXs3r2b4cOHc/To0Tteabq5ueHn53fdn6uvKy8vj+zsbPbv3w9AdnY22dnZ/Prr\nr3dUx8NOISkixdSqVYuVK1eydu1a+vfvT6dOnUhJSWHx4sVYrVYiIiJITU2lZs2aduPCwsLw8vLC\narXi6+tbbF6r1UphYaERiGXLlqVx48Y4OzsbzyMBvLy8WLp0KdnZ2YSFhdGnTx9eeuklRo4ced26\nHR0dSUtLw2az8eyzzxIbG8ugQYNwdna+rffBxcWFDz/8kNOnTxMeHs4rr7xCYGAgKSkpRp++ffsS\nFRVF7969efbZZykqKiIyMpKyZcve1jlv11tvvUXTpk154403AGjatClNmzY1dhTL7XE4efLkvf01\nECJyX7nexp07de7cOerWrcv48eN5+eWX78k5HgRhYWGEhISQlJRU0qXIHdIzSRG5YzabjRMnTjBz\n5kweeeQR2rZtW9Il/W7279/PunXrePrpp7l48SKpqans2LGDKVOmlHRpchcoJEXkjuXl5dGwYUO8\nvb2ZNm1asZ2b94uJEycWe456RWhoKMuWLbvlOR0dHfnggw8YOXKksaFn2bJlPPnkk3dartwHdLtV\n5CFzL2+33u/y8/PJz8+/ZlvZsmXx8vL6nSuS+51CUuQhU+ke/6Jtefic+gP/jyPa3SoiImJCISki\nImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJC\nISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISkiImJCISki\nImJCISkiImLCqaQLEJHf19dbtuDv71/SZYg8ELSSFBERMaGQFBERMaGQFBERMaGQFBERMaGQFBER\nMaGQFBERMaGQFBERMaGQFJH7SmRkJIMHDy7pMkrExo0b6dChA3Xr1sXV1ZX333//psbt2LGD//f/\n/h+enp7UrVuXt99+m6KiIrs+mZmZNGvWDA8PDxo2bMicOXPuxSX84SgkRUTukry8vDsaf+bMGerV\nq8e4ceN45JFHbmrML7/8Qtu2bXF3d2fdunWMGzeOqVOnkpKSYvT56aefePnllwkKCmLDhg0MGDCA\n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\niAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmF\npIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiI\niAmnki5ARH5fX2/Zgr+/f0mXIfJA0EpSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETE\nhEJSDJGRkQwePLiky7gnvL29ef/99+/Z/H/k907kYaaQFHmA5eXlERUVhZeXF35+frz22msUFBSU\ndFkifxj6ZQLyh1FQUECZMmVKuozfzaVLl4iKiqJy5cqsWrWK/Px84uLiKCoqIikpqaTLE/lD0EpS\nTK1fvx4fHx/mzJkDQFpaGsHBwXh4eNC4cWOmTZuGzWYDoHfv3kRFRdmNt9lsNGjQgJSUFNauXUv1\n6tUpLCwEYO/evbi6uhIfH2/0T0hIoE2bNsbrjRs3Eh4ejoeHB/7+/gwdOtRulRQZGcmAAQMYMWIE\ntWvX5vnnnzfmjoyMxMPDgyZNmrB69eo7eh/i4uKIiooiKSkJf39/vL296dWrF+fOnSt2vWPHjsXP\nz486deowYsQI4/0BePzxx0lMTKRHjx54e3sTEBDA1KlTb7uudevW8cMPP/Duu+/SqFEjnnnmGcaM\nGcP8+fP55ZdfbnteEfk/Ckm5puXLl9OxY0eSk5Pp2rUrqamp/OMf/2DYsGFs2rSJhIQEkpOTee+9\n9wDo3Lkza9eu5ciRI8Yc6enpHD16lA4dOhASEsL58+fZtm0bAJmZmVSpUoXMzEyjf2ZmJlarFYBD\nhw7Rvn17nnjiCTZs2MDUqVP58MMPGTNmjF2dS5YsoaioiM8++4yZM2dis9no2LEjNpuNNWvWkJKS\nwrhx47hw4cIdvR8bN27k+++/Z/ny5cyfP5/09HRGjRpl12fp0qWUKlWKNWvWkJSUxIwZM/joo4/s\n+kyfPp2AgADWr1/P0KFDGTt2LJ988onR3q5dO7y9va/7c8XmzZuxWCxUr17dOBYeHs6FCxf49ttv\n7+h6ReQy3W6VYubNm8fIkSNJTU2lRYsWACQlJTFmzBhjpefr68u+ffuYPXs2PXr0ICgoiICAABYt\nWmSsDtPS0oiIiKBq1aoANGrUiIyMDAIDA8nMzKR79+5MnjyZI0eOULFiRb755hsjeGbPno2npycT\nJ07E0dERi8XCqFGjiI+PZ/jw4bi4uADg4+PDm2++adS+bt06du3axXfffUeNGjUASExMJCIi4o7e\nE0dHR6ZNm0b58uWpV68eo0ePpm/fvowaNYpy5coBYLFYGD58OAB16tQhNTWV9evX065dO2Oexo0b\nM2jQIKPPN998w/Tp03nhhRcAmDJlCufPn7+pmo4dO4abm5vdsSpVqlCqVCmOHTt2R9crIpcpJMXO\np59+yty5c1m1ahVBQUEA/Pzzzxw4cID4+HgGDhxo9C0sLKSoqMh4HRMTw+zZs4mPjyc/P59Vq1aR\nlpZmtFutVjIzMxkwYAAbN26kZ8+eZGRkkJmZSdWqVXFycqJx48YA5OTk0KRJExwd/+9mR2hoKAUF\nBezdu5cGDRoAl4P3ajk5OXh5eRkBCRSb53bUr1+f8uXLG6+DgoIoKChg3759Ri3169e3G+Pp6cnx\n48ftjgUGBhZ7vWLFCuO1l5fXHdUpIneXQlLsNGjQgJ07d7JgwQICAwNxcHAwnqtNmjSJ4OBg07Ed\nOnRg9OjRZGVlkZ2dTdWqVQkPDzfarVYrs2bNIicnh9OnT9OoUSOsVisZGRm4ubkRGBh4UxtvHBwc\njD9fWcXdD0qXLm332sHBwe5DxM1o164dWVlZ1+1z8OBBANzd3dm0aZNd24kTJ7h06RLu7u63dF4R\nuTaFpNipWbMm48ePp1WrVvTr14/k5GTc3d2pVq0a+/btIzo62nRs5cqVad26NWlpaWRnZxMdHW23\nggsJCeHChQskJycTEhJCqVKlsFqt9OvXD3d3d7tAtVgsfPzxx9hsNmOOrKwsypQpQ61atUxrsFgs\nHDp0iAMHDhjP6rZu3Wq3geZ27Ny5kzNnzhihvGXLlhvWci1ff/11sdcWi8V4fSu3W4OCgpgwYQIH\nDx40nlWmp6fj7OxcbIUtIrdHG3ekGF9fX1asWMEXX3xB//79KSoqYujQoUyZMoVp06axe/dudu7c\nyaJFi5g0aZLd2JiYGJYuXcr3339Px44d7drKly9Po0aNWLJkCWFhYcDl242HDh1iy5YtxqYdgG7d\nunHkyBEGDhxITk4On3/+OWPGjKF79+7G88hrad68OQEBAcTGxpKdnc3mzZsZNmwYTk43/3nwhRde\nKLZB6NKlS/Tp04cffviB9PR0xowZQ+fOnW95Jfv1118zadIk9uzZQ2pqKh988AG9evUy2q983/F6\nP1e0aNGCunXrEhsby3fffcd//vMfRo4cSUxMDBUrVrylukTk2hSSck21atVi5cqVrF27lv79+9Op\nUydSUlJYvHgxVquViIgIUlNTqVmzpt24sLAwvLy8sFqt+Pr6FpvXarVSWFhoBGLZsmVp3Lgxzs7O\nxvNIuBwWS5cuJTs7m7CwMPr06cNLL73EyJEjr1u3o6MjaWlp2Gw2nn32WWJjYxk0aBDOzs43fe37\n9u2z26UL8PTTT/PYY4/RunVrOnbsSFhYWLEgvRm9evVix44dNG3alISEBIYNG2b3tZdbUapUKRYv\nXoyLiwstW7akS5cutG7dmoSEhNuaT0SKczh58uStPTQRuY5z585Rt25dxo8fz8svv1zS5dwVcXFx\n/O9//2Px4sV3NM/jjz9Ojx496Nu3712q7Pbs3r0bf3//Eq1B5EGhZ5JyV9hsNk6cOMHMmTN55JFH\naNu2bUmXJCJyxxSSclfk5eXRsGFDvL29mTZtWrGdnveLiRMnFnuOekVoaCjLli37nSsSkfuZbrfK\nQyU/P5/8/PxrtpUtW/ah+J6ibreK3DytJOUPy3XuQZMWs008RYDZmD+OLdYb9xGRy7S7VURExIRC\nUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRE\nxIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRC\nUkRExIRCUkRExIRTSRcgcq+c7OJd0iXcl3bv3l3SJYg8MLSSFBERMaGQFBERMaGQFBERMaGQFBER\nMaGQFBERMaGQFBERMaGQFBERMaGQFBERMaGQFBERMaGQFBERMaGQFBERMaGQFBERMaGQFBERMaGQ\nFBERMaGQFBERMaGQFBERMeFw8uTJopIuQkRE5H6klaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSI\niIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJ\nhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSI\niIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJ\nhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIgJhaSIiIiJ/w+Vqpw1tpCS\n4gAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "explain_instance(data.query('phishing == 1').sample(1, random_state=7))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test with a random legitimate URL" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Legitimate URL\n", "http://www.redeyechicago.com/entertainment/tv/redeye-banshee-ivana-milicevic-interview-20140120-story.html\n", "\n", "Predicted Probabilites: [ 0.97166667 0.02833333]\n", "\n", "Feature importances:\n" ] }, { "data": { "image/png": "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\n/fTTHDt2jPXr1+Pg4MAf//jHsi5RHhPauCN3dXvDTo0aNe4ZbLeXTtPS0rSBQcqFLl260KNHD374\n4QfWrFnDzJkzyczMpG3btmzcuLFE/8uI/LLZ5ebm6pvcIiIid6GZpIiIiAmFpIiIiAmFpIiIiAmF\npIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiI\niAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmF\npIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmFpIiIiAmF5BMu\nMjKSkSNHlnUZj4S3tzfvv//+fbV1cXFhzZo1D/X94+LiiIqKeqhjisjPSyEp8ohMnDiRuXPnPtL3\nyM3NpV+/fvj4+ODj40O/fv3Izc19pO8p8iRRSEq5lpeXV9YlmKpevTouLi6P9D3+8Ic/kJWVxapV\nq1i1ahVZWVn079//kb6nyJNEISmFbNu2DR8fH+bPnw9AWloawcHBeHp6EhAQwMyZM7HZbAAMHDiw\nyHKizWajSZMmzJgxg02bNlG7dm3y8/MBOHToEC4uLsTHxxvtExMT6dixo/F6+/bthIeH4+npia+v\nL6NGjSoUhJGRkQwbNoyxY8fSsGFD2rRpY4wdGRmJp6cnzZs3Z8OGDQ90H/bu3UvHjh2pWbMm9erV\nIy4ujosXLxrn8/PzGTVqFHXr1qVevXqMHTuW4cOHExkZabT57+XWyMhIhg8fzoQJE2jQoAHPPPMM\nY8eONe5nSWVnZ7Np0yamTp1KUFAQQUFBvPPOO3zyySfk5OSU/uJFxKCQFMOaNWvo0aMHKSkp9O7d\nm9TUVP785z8zevRodu7cSWJiIikpKbz33nsA9OrVi02bNnHq1CljjK1bt3L69Gmio6MJCQnh2rVr\n7N69G4CMjAxq1KhBRkaG0T4jIwOr1QrAyZMn6dq1K02bNuXTTz9l+vTprF69moSEhEJ1rlixgoKC\nAj7++GPmzJmDzWajR48e2Gw2Nm7cyIwZM5g4cSLXr18v1X24fPkynTt3pnLlymzevJm0tDQyMzMZ\nNGiQ0Wb69OksWbKEadOm8Y9//IMbN26wcuXKe469cuVKHBwc2LhxI8nJycyePZsPPvjAOB8fH4+3\nt3exP8eOHQMgMzOTKlWqEBwcbPQPCQmhcuXK7Ny5s1TXLiKFVSjrAuTxsHDhQsaNG0dqaiqtW7cG\nIDk5mYSEBGOmV69ePQ4fPsy8efPo168fQUFB+Pn5sXTpUmN2mJaWRkREBG5ubgD4+/uTnp5OYGAg\nGRkZ9O3bl6lTp3Lq1CmqVavGl19+yfjx4wGYN28eNWvWZPLkydjb22OxWBg/fjzx8fGMGTMGZ2dn\nAHx8fHjrrbeM2rds2cKBAwf46quvqFOnDgBJSUlERESU6l6sWrWKK1euMHfuXKpWrQrA1KlTad++\nPYcOHaJBgwbMmTOHoUOHGvdm4sSJbN68+Z5jWywWxowZA8AzzzxDamoq27Zto0uXLgCMHj2awYMH\nFztGrVq1ADhz5gw1atTAzs7OOGdnZ4ebmxtnzpwp+YWLSBEKSeGjjz5iwYIFrF+/nqCgIADOnTvH\n8ePHiY+PZ/jw4Ubb/Px8CgoKjNcxMTHMmzeP+Ph4Lly4wPr160lLSzPOW61WMjIyGDZsGNu3b6d/\n//6kp6eTkZGBm5sbFSpUICAgALi1fNi8eXPs7f+zwBEaGkpeXh6HDh2iSZMmwK3gvVN2djZeXl5G\nQAJFximJ7OxsGjdubAQkQHBwMPb29hw4cIAaNWpw+vRpnn/+eeO8nZ0dzz//PCdOnCh27MaNGxd6\nXbNmTc6ePWu8dnd3x93dvVR136+cnBx8fX0f6XuI/FIoJIUmTZqwb98+Fi9eTGBgIHZ2dsZzsilT\nphRazvtv0dHRvPnmm+zYsYOsrCzc3NwIDw83zlutVt59912ys7O5dOkS/v7+WK1W0tPTcXd3JzAw\nkEqVKt2zxjtnS5UrV36Aq30wd9ZRGhUrViwy3p0fOuLj41mxYkWxY3z++efUqVMHDw8Pzp8/T0FB\ngVFXQUEB586dw8PD44HqFJFbFJJC3bp1mTRpEu3atWPIkCGkpKTg4eFBrVq1OHz4MN26dTPt6+rq\nSvv27UlLSyMrK4tu3boVmsGFhIRw/fp1UlJSCAkJwcHBAavVypAhQ/Dw8CgUqBaLhQ8//BCbzWaM\nsWPHDipVqkT9+vVNa7BYLJw8eZLjx49Tu3ZtAL744otSb4ixWCykpaVx6dIlYza5c+dObDYbFouF\n6tWr4+npye7du3nxxReBW+G0e/fuBw6nkiy3BgUF8dNPP5GZmWl8kMnMzOTy5cvFfrARkfunjTsC\n3HreuHbtWjZv3szQoUMpKChg1KhRTJs2jZkzZ5KTk8O+fftYunQpU6ZMKdQ3JiaGlStX8s0339Cj\nR49C56pUqYK/vz8rVqwgLCwMgMDAQE6ePMmuXbuMTTsAffr04dSpUwwfPpzs7Gw++eQTEhIS6Nu3\nr/E88m5atWqFn58fsbGxZGVlkZmZyejRo6lQoXSfAbt27YqzszOxsbHs3buX7du3Ex8fT/v27WnQ\noAEAsbGxpKSksHbtWnJychgzZgynT59+4Jmmu7s7DRo0KPbn9nVZLBZefvll4uPjyczMJDMzk/j4\neNq0aaPlVJGHRCEphvr167Nu3To2bdrE0KFD6dmzJzNmzGD58uVYrVYiIiJITU2lbt26hfqFhYXh\n5eWF1WqlXr16Rca1Wq3k5+cbgejk5ERAQACOjo7G80gALy8vVq5cSVZWFmFhYQwaNIjOnTszbty4\nYuu2t7cnLS0Nm83Gyy+/TGxsLCNGjMDR0bFU98HZ2ZnVq1dz6dIlwsPD6d69O4GBgcyYMcNoM3jw\nYKKiohg4cCAvv/wyBQUFREZG4uTkVKr3LK333nuPJk2a0LlzZzp37kyTJk0e+S8wEHmS2OXm5hbc\nu5mIuatXr9KoUSMmTZrEK6+8UtbllJmwsDBCQkJITk4u61KKpY07IvdPzySl1Gw2G+fPn2fOnDk8\n9dRTdOrUqaxL+tkcPXqULVu20KJFC27cuEFqaip79+5l2rRpZV2aiDxECkkptWPHjtGsWTO8vb2Z\nOXNmkZ2bj4vJkycXeY56W2hoKKtWrSrxmPb29ixbtoxx48YZG3pWrVrF//zP/zxouSLyGNFyq/zi\nXbhwgQsXLtz1nJOTE15eXj9zRWVLy60i908zycecy4Liv5wu98tsE08B8GTd413We7cRkVu0u1VE\nRMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSE\nQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJERMSEQlJE\nRMSEQlJERMSEQlJERMREhbIuQIqX+5p3WZcgvzA5OTllXYJIuaGZpIiIiAmFpIiIiAmFpIiIiAmF\npIiIiAmFpIiIiAmFpIiIiAmFpEgJxcXFERUVVdZliMjPQCEpUkITJ05k7ty592yXnp6Oi4sL58+f\nB+DIkSO4uLgYP3Xr1iUiIoKMjIxS13L9+nVGjhxJgwYN8PLyIjo6mhMnTpR6PBEpTCEpUkLVq1fH\nxcWl1P1Xr15NdnY2H330EdWqVeOVV17hu+++K9VYo0aNYu3atcybN4/169dz6dIloqKiuHnzZqnr\nE5H/UEiKlNCdy63bt2/n5ZdfxtvbGx8fH1q3bs2+ffuK7f/000/j6elJkyZNmDp1KleuXOGf//xn\nieu4ePEiixcvZsKECbz00kv4+/szd+5c9u7dW6rxRKQohaRIKeXn59O9e3dCQkLIyMhg06ZNxMXF\n4eDgcN9jODk5AbeWTQEmT56Mt7d3sT+fffYZAHv27OHGjRu0bt3aGK927dpYLBZ27tz5EK9U5Mml\n390qUkqXLl3i4sWLtG3blvr16wPg5+d33/0vX77MhAkTcHBwwGq1AtC7d286depUbL9atWoBcObM\nGRwcHKhRo0ah8+7u7pw5c6YklyIiJhSSIqXk6upK9+7d6dy5My+++CItW7akY8eO1KlTp9h+v/3t\nb7G3t+fKlSvUrFmTWbNm0bhxY2NMV1fXn6N8EbkPWm4VeQCzZs1i06ZNvPDCC3z88ccEBgayefPm\nYvu8++67ZGRkcPDgQfbv31/o6yQlWW718PDg5s2bxu7Z286ePYuHh8fDv1iRJ5BmkiIP6LnnnuO5\n555j6NChdOnShaVLlxIeHm7a3tvb21ie/W8lWW719/enYsWKbN26la5duwJw4sQJsrOzCQ4OLuXV\niMidFJIipfTdd9+xcOFCIiIiqFWrFt999x179+6ld+/epR6zJMut1atXp2fPnowfPx53d3dcXV0Z\nM2YMjRs3plWrVqWuQUT+QyEpUkrOzs58++23vPrqq5w/fx4PDw+6du3K0KFDf7YakpKScHBw4LXX\nXuPatWu0bNmSOXPmlGiHrYiYs8vNzS0o6yJE5OeTk5ODr69vWZchUi5o446IiIgJhaSIiIgJhaSI\niIgJhaSIiIgJ7W4t51wW6L9FkpLZZS3rCkTKD80kRURETCgkRURETCgkRURETCgkRURETCgkRURE\nTCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgk\nRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETFQo6wLkweS+5l3WJUg5k5OT\n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\n9rRs2ZK//e1vxlJpbGwsgwcPZvz48YSGhvLRRx+xaNEi0yXQh+3pp5+mX79+bN26lR07djzUsefP\nn0/Lli3p27cvAK+88gotW7Zk/fr1RpvDhw8XmuHfDr0lS5bQokULli1bxvz582nevLnR5n//939J\nSkoiOTmZsLAwPv/8c1asWIGPj89DrV/kSWWXm5v78z9kEpEyk5OTg6+vb1mXIVIuaCYpIiJiQiEp\nD018fLzpl+3j4+PLujwRkRLTcqs8NGfPni20q/ZOVatWLfKldykbWm4VuX/a3foL5LLgxL0bPTKO\nJsfzgLKsS27bZS3rCkTKDy23ioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiI\nmFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImFBI\nioiImFBIioiImFBIioiImFBIioiImFBIioiImFBIioiImKhQ1gXIw5f7mndZlyCPsZycnLIuQaTc\n0ExSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRACIjIxk5MiRZV3GI+Ht7c37\n779/z3ZHjhzBxcWF3bt3/wxVSXmgkBQRKYH09HRcXFw4f/58oeOPy4eMY8eOERUVhZeXFw0aNOD1\n118nLy+vrMsqt/TLBETkFyEvL49KlSqVdRll6ubNm0RFReHq6sr69eu5cOECcXFxFBQUkJycXNbl\nlUuaSYrIXW3btg0fHx/mz58PQFpaGsHBwXh6ehIQEMDMmTOx2WwADBw4kKioqEL9bTYbTZo0YcaM\nGWzatInatWuTn58PwKFDh3BxcSE+Pt5on5iYSMeOHY3X27dvJzw8HE9PT3x9fRk1alShGVFkZCTD\nhg1j7NixNGzYkDZt2hhjR0ZG4unpSfPmzdmwYUOJr/3o0aP87ne/o1atWgQHB7N161bg1nJs+/bt\nAWjYsCEuLi7ExcURFxfH9u3beffdd3FxccHFxYUjR44Ys84NGzZgtVrx9PTkxRdfZM+ePcZ7Xbx4\nkX79+vHMM8/g6elJs2bNmDVrVolrBtiyZQv79+9n7ty5+Pv789JLL5GQkMCiRYv48ccfSzXmk04z\nSREpYs2aNQwaNIhp06bRqVMnUlNT+ctf/sKkSZNo1qwZ+/fvZ8iQIVSsWJF+/frRq1cvIiIiOHXq\n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\nQYPYv38/W7duJSEhgV69epV4Jvuvf/2LKVOmcPDgQVJTU1m2bBkDBgwwzt/+vmNxP7e1bt2aRo0a\nERsby1dffcU///lPxo0bR0xMDNWqVStRXSJydwpJuav69euzbt06Nm3axNChQ+nZsyczZsxg+fLl\nWK1WIiIiSE1NpW7duoX6hYWF4eXlhdVqpV69ekXGtVqt5OfnG4Ho5OREQEAAjo6OxvNIuBUWK1eu\nJCsri7CwMAYNGkTnzp0ZN25csXXb29uTlpaGzWbj5ZdfJjY2lhEjRuDo6Hjf13748OFCu3QBWrRo\nwbPPPkv79u3p0aMHYWFhRYL0fgwYMIC9e/fSsmVLEhMTGT16dKGvvZSEg4MDy5cvx9nZmbZt2/La\na6/Rvn17EhMTSzWeiBRll5ubW7KHJiLFuHr1Ko0aNWLSpEm88sorZV3OQxEXF8cPP/zA8uXLH2ic\n5557jn79+jF48OCHVFnp5OTk4OvrW6Y1iJQXeiYpD4XNZuP8+fPMmTOHp556ik6dOpV1SSIiD0wh\nKQ/FsWPHaNasGd7e3sycObPITs/HxeTJk4s8R70tNDSUVatW/cwVicjjTMut8kS5cOECFy5cuOs5\nJyenJ+J7ilpuFbl/mknKE8FlwYk7Xplt4ikATpic++XYZb13GxG5RbtbRURETCgkRURETCgkRURE\nTCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgk\nRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURETCgkRURE\nTFQo6wJEfg65r3mXdQmPjZycnLIuQaTc0ExSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJS\nRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETEhEJSRETE\nhEJSRETEhF1ubm5BWRchIiLyONJMUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRC\nUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRE\nxIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRC\nUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRE\nxIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExIRCUkRExMT/ByNRkaUvsfbyAAAAAElFTkSu\nQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "explain_instance(data.query('phishing == 0').sample(1, random_state=1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conclusion\n", "\n", "With LIME we can actually understand how the classifier is making predictions without having to see the millions of parameters that the model has. In the first example, we’re looking at phishing URL’s from Phishtank, and see why the classifier is assigning both a very high probability of phish. On the other hand, we look at a ham URL, we see that the URL does not contain suspicious words, the length of the subdomain is short and it is not an IP. These indicators are the ones that the classifer uses in order to give this URL a low phishing probability.\n", "\n", "\n", "This method presents a very compelling paradigm for producing example-based explanations of complex classifiers which can truly be useful in building trust in specific predictions and in selecting and tuning models without deep ML expertise. I have worked on several projects in the past which eschewed advanced ML algorithms due to the need for explainability. The type of technique explored here point towards a path where we can utilize the power of complex predictive models while still providing useful explanations." ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 2 }