├── Chapter06 ├── datasets │ └── dataset-download.txt └── sources │ ├── Eigenvectors & Eigenvalues.ipynb │ └── Facial Recognition.ipynb ├── Chapter02 └── sources │ ├── matplot-ex1.py │ ├── numpy-ex1.py │ ├── numpy-ex2.py │ ├── tensorflow-session.txt │ ├── pandas-ex1.py │ ├── numpy-ex3.py │ ├── scikit-ex1.py │ ├── pefile-ex1.py │ └── Ch02 Examples.ipynb ├── Chapter05 ├── sources │ ├── gaussian_anomaly_detection.pyc │ └── Network Anomaly Detection.ipynb └── datasets │ └── network-logs.csv ├── Chapter04 └── sources │ ├── hidden_markov_example.py │ ├── extract_artifacts.py │ ├── Random Forest Malware Classifier.ipynb │ ├── K-means malware clustering.ipynb │ └── Decision Tree Malware Detector.ipynb ├── Chapter07 ├── datasets │ └── Readme.txt └── ch07-sources.txt ├── LICENSE ├── Chapter10 ├── missing-values.py └── cross-validation-model-optimization.py ├── Chapter03 ├── datasets │ ├── sms_spam_perceptron.csv │ └── sms_spam_svm.csv └── sources │ ├── Linear Regression.ipynb │ ├── defs.py │ ├── Logistic Regression Phishing Detector.ipynb │ ├── Decision Tree Phishing Detector.ipynb │ ├── Bayesian Spam Detector with Nltk.ipynb │ ├── Perceptron.ipynb │ └── SVM.ipynb ├── Chapter09 └── CH09-examples.txt ├── README.md ├── Chapter08 ├── facenet_fgsm.py ├── generative_adversarial_network.py └── MalGAN_v2.py └── Chapter01 └── datasets └── clustering.csv /Chapter06/datasets/dataset-download.txt: -------------------------------------------------------------------------------- 1 | Keystroke Dynamics - Benchmark Data Set: 2 | https://www.cs.cmu.edu/~keystroke/DSL-StrongPasswordData.csv 3 | -------------------------------------------------------------------------------- /Chapter02/sources/matplot-ex1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import matplotlib.pyplot as plt 4 | 5 | plt.plot(np.arange(15), np.arange(15)) 6 | 7 | plt.show() 8 | 9 | -------------------------------------------------------------------------------- /Chapter05/sources/gaussian_anomaly_detection.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Hands-On-Artificial-Intelligence-for-Cybersecurity/HEAD/Chapter05/sources/gaussian_anomaly_detection.pyc -------------------------------------------------------------------------------- /Chapter02/sources/numpy-ex1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np_array = np.array( [0, 1, 2, 3] ) 4 | 5 | # Creating an array with ten elements initialized as zero 6 | 7 | np_zero_array = np.zeros(10) 8 | 9 | -------------------------------------------------------------------------------- /Chapter02/sources/numpy-ex2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([-8, 15]) 4 | 5 | X = np.array([[1, 5], 6 | [3, 4], 7 | [2, 3]]) 8 | 9 | y = np.dot(X, a) 10 | -------------------------------------------------------------------------------- /Chapter02/sources/tensorflow-session.txt: -------------------------------------------------------------------------------- 1 | activate py35 2 | 3 | python 4 | 5 | >>> import tensorflow as tf 6 | 7 | >>> hello = tf.constant('Hello, TensorFlow!') 8 | 9 | >>> sess = tf.Session() 10 | 11 | >>> print(sess.run(hello)) 12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter02/sources/pandas-ex1.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from sklearn import datasets 4 | 5 | 6 | iris = datasets.load_iris() 7 | 8 | iris_df = pd.DataFrame(iris.data, columns = iris.feature_names) 9 | 10 | iris_df.head() 11 | 12 | iris_df.describe() 13 | 14 | -------------------------------------------------------------------------------- /Chapter02/sources/numpy-ex3.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def predict(data, w): 4 | return data.dot(w) 5 | 6 | 7 | # w is the vector of weights 8 | w = np.array([0.1, 0.2, 0.3]) 9 | 10 | # matrices as input datasets 11 | data1 = np.array([0.3, 1.5, 2.8]) 12 | 13 | data2 = np.array([0.5, 0.4, 0.9]) 14 | 15 | data3 = np.array([2.3, 3.1, 0.5]) 16 | 17 | 18 | data_in = np.array([data1[0],data2[0],data3[0]]) 19 | 20 | print('Predicted value: $%.2f' % predict(data_in, w) ) 21 | 22 | -------------------------------------------------------------------------------- /Chapter04/sources/hidden_markov_example.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from hidden_markov import hmm 3 | 4 | ob_types = ('W','N' ) 5 | 6 | states = ('L', 'M') 7 | 8 | observations = ('W','W','W','N') 9 | 10 | start = np.matrix('0.1 0.9') 11 | transition = np.matrix('0.7 0.3 ; 0.1 0.9') 12 | emission = np.matrix('0.2 0.8 ; 0.4 0.6') 13 | 14 | _hmm = hmm(states,ob_types,start,transition,emission) 15 | 16 | print("Forward algorithm: ") 17 | print ( _hmm.forward_algo(observations) ) 18 | 19 | print("\nViterbi algorithm: ") 20 | print( _hmm.viterbi(observations) ) 21 | 22 | -------------------------------------------------------------------------------- /Chapter02/sources/scikit-ex1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from sklearn.linear_model import LinearRegression 4 | 5 | # X is a matrix that represents the training dataset 6 | 7 | # y is a vector of weights, to be associated with input dataset 8 | 9 | X = np.array([[3], [5], [7], [9], [11]]).reshape(-1, 1) 10 | 11 | y = [8.0, 9.1, 10.3, 11.4, 12.6] 12 | 13 | 14 | lreg_model = LinearRegression() 15 | 16 | 17 | lreg_model.fit(X, y) 18 | 19 | 20 | # New data (unseen before) 21 | 22 | new_data = np.array([[13]]) 23 | 24 | 25 | print('Model Prediction for new data: $%.2f' % lreg_model.predict(new_data)[0] ) 26 | 27 | -------------------------------------------------------------------------------- /Chapter07/datasets/Readme.txt: -------------------------------------------------------------------------------- 1 | Download the 'creditcard' dataset in .csv format from the following link: 2 | https://www.openml.org/data/get_csv/1673544/phpKo8OWT 3 | 4 | Dataset License: https://www.openml.org/d/1597 5 | (PUBLIC DOMAIN: https://creativecommons.org/publicdomain/mark/1.0/) 6 | 7 | Dataset Credits: 8 | Author: Andrea Dal Pozzolo, Olivier Caelen and Gianluca Bontempi 9 | Source: Credit card fraud detection - Date 25th of June 2015 10 | Please cite: Andrea Dal Pozzolo, Olivier Caelen, Reid A. Johnson and Gianluca Bontempi. 11 | Calibrating Probability with Undersampling for Unbalanced Classification. 12 | In Symposium on Computational Intelligence and Data Mining (CIDM), IEEE, 2015 13 | -------------------------------------------------------------------------------- /Chapter02/sources/pefile-ex1.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pefile 4 | 5 | 6 | notepad = pefile.PE("notepad.exe", fast_load=True) 7 | 8 | 9 | dbgRVA = notepad.OPTIONAL_HEADER.DATA_DIRECTORY[6].VirtualAddress 10 | 11 | imgver = notepad.OPTIONAL_HEADER.MajorImageVersion 12 | 13 | expRVA = notepad.OPTIONAL_HEADER.DATA_DIRECTORY[0].VirtualAddress 14 | 15 | iat = notepad.OPTIONAL_HEADER.DATA_DIRECTORY[12].VirtualAddress 16 | 17 | sections = notepad.FILE_HEADER.NumberOfSections 18 | 19 | dll = notepad.OPTIONAL_HEADER.DllCharacteristics 20 | 21 | 22 | print("Notepad PE info: \n") 23 | 24 | print ("Debug RVA: " + dbgRVA) 25 | 26 | print ("\nImage Version: " + imgver) 27 | 28 | print ("\nExport RVA: " + expRVA) 29 | 30 | print ("\nImport Address Table: " + iat) 31 | 32 | print ("\nNumber of Sections: " + sections) 33 | 34 | print ("\nDynamic linking libraries: " + dll) 35 | 36 | -------------------------------------------------------------------------------- /Chapter04/sources/extract_artifacts.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pefile 3 | import glob 4 | 5 | csv = file('MalwareArtifacts.csv','w') 6 | 7 | files = glob.glob('c:\\MalwareSamples\\*.exe') 8 | 9 | csv.write("AddressOfEntryPoint,MajorLinkerVersion,MajorImageVersion, 10 | MajorOperatingSystemVersion,,DllCharacteristics,SizeOfStackReserve, 11 | NumberOfSections,ResourceSize,\n") 12 | 13 | for file in files: 14 | suspect_pe = pefile.PE(file) 15 | 16 | csv.write( str(suspect_pe.OPTIONAL_HEADER.AddressOfEntryPoint) + ',') 17 | csv.write( str(suspect_pe.OPTIONAL_HEADER.MajorLinkerVersion) + ',') 18 | csv.write( str(suspect_pe.OPTIONAL_HEADER.MajorImageVersion) + ',') 19 | csv.write( str(suspect_pe.OPTIONAL_HEADER.MajorOperatingSystemVersion) + ',') 20 | csv.write( str(suspect_pe.OPTIONAL_HEADER.DllCharacteristics) + ',') 21 | csv.write( str(suspect_pe.OPTIONAL_HEADER.SizeOfStackReserve) + ',') 22 | csv.write( str(suspect_pe.FILE_HEADER.NumberOfSections) + ',') 23 | csv.write( str(suspect_pe.OPTIONAL_HEADER.DATA_DIRECTORY[2].Size) + "\n") 24 | 25 | csv.close() 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter10/missing-values.py: -------------------------------------------------------------------------------- 1 | """ 2 | Univariate missing value imputation with SimpleImputer class 3 | 4 | Code readapted from Scikit-Learn documentation 5 | """ 6 | 7 | import numpy as np 8 | from sklearn.impute import SimpleImputer 9 | 10 | imp = SimpleImputer(missing_values=np.nan, strategy='mean') 11 | 12 | imp.fit([[1, 2], [np.nan, 3], [7, 6]]) 13 | 14 | SimpleImputer(add_indicator=False, copy=True, fill_value=None, 15 | missing_values=nan, strategy='mean', verbose=0) 16 | 17 | X = [[np.nan, 2], [6, np.nan], [7, 6]] 18 | 19 | imp.transform(X) 20 | 21 | 22 | """ 23 | Multivariate missing value imputation with IterativeImputer class 24 | 25 | Code readapted from Scikit-Learn documentation 26 | """ 27 | 28 | import numpy as np 29 | from sklearn.experimental import enable_iterative_imputer 30 | from sklearn.impute import IterativeImputer 31 | 32 | imp = IterativeImputer(max_iter=10, random_state=0) 33 | imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]]) 34 | 35 | IterativeImputer(add_indicator=False, estimator=None, 36 | imputation_order='ascending', initial_strategy='mean', 37 | max_iter=10, max_value=None, min_value=None, 38 | missing_values=nan, n_nearest_features=None, 39 | random_state=0, sample_posterior=False, tol=0.001, 40 | verbose=0) 41 | 42 | X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]] 43 | 44 | np.round(imp.transform(X_test)) 45 | 46 | -------------------------------------------------------------------------------- /Chapter03/datasets/sms_spam_perceptron.csv: -------------------------------------------------------------------------------- 1 | "type","sex","buy" 2 | "ham","0","1" 3 | "ham","0","1" 4 | "ham","1","1" 5 | "spam","1","0" 6 | "ham","0","1" 7 | "spam","1","0" 8 | "ham","0","1" 9 | "ham","0","1" 10 | "spam","2","1" 11 | "ham","0","1" 12 | "ham","0","1" 13 | "ham","0","1" 14 | "ham","0","1" 15 | "ham","0","1" 16 | "spam","1","0" 17 | "ham","0","1" 18 | "ham","0","2" 19 | "ham","0","1" 20 | "spam","1","2" 21 | "ham","0","1" 22 | "spam","1","0" 23 | "ham","0","1" 24 | "spam","1","0" 25 | "ham","0","1" 26 | "spam","2","0" 27 | "ham","0","1" 28 | "spam","1","0" 29 | "ham","0","2" 30 | "spam","1","0" 31 | "ham","0","2" 32 | "ham","0","1" 33 | "ham","0","1" 34 | "ham","1","0" 35 | "ham","0","1" 36 | "spam","1","0" 37 | "ham","0","1" 38 | "ham","0","1" 39 | "ham","0","1" 40 | "spam","1","0" 41 | "ham","0","1" 42 | "ham","1","0" 43 | "ham","0","1" 44 | "ham","0","1" 45 | "ham","0","1" 46 | "spam","1","0" 47 | "ham","0","1" 48 | "ham","0","1" 49 | "spam","1","0" 50 | "spam","1","0" 51 | "spam","1","0" 52 | "ham","1","0" 53 | "ham","0","2" 54 | "ham","0","1" 55 | "ham","0","1" 56 | "ham","1","0" 57 | "ham","0","1" 58 | "ham","0","1" 59 | "spam","1","0" 60 | "ham","0","1" 61 | "ham","0","1" 62 | "ham","1","0" 63 | "spam","2","0" 64 | "ham","1","0" 65 | "ham","1","0" 66 | "ham","0","1" 67 | "ham","0","1" 68 | "ham","0","1" 69 | "ham","1","0" 70 | "spam","1","0" 71 | "ham","0","1" 72 | "ham","1","0" 73 | "ham","0","1" 74 | "ham","0","2" 75 | "ham","0","1" 76 | "ham","1","0" 77 | "spam","1","0" 78 | "ham","0","1" 79 | "ham","0","1" 80 | "ham","0","1" 81 | "ham","0","1" 82 | "ham","0","1" 83 | "ham","1","0" 84 | "spam","2","0" 85 | "ham","0","3" 86 | "spam","1","0" 87 | "ham","0","1" 88 | "spam","1","0" 89 | "ham","1","0" 90 | "ham","0","1" 91 | "ham","0","1" 92 | "ham","0","1" 93 | "ham","0","1" 94 | "ham","0","1" 95 | "ham","0","2" 96 | "ham","0","1" 97 | "ham","0","1" 98 | "ham","0","1" 99 | "spam","1","0" 100 | "ham","0","1" 101 | -------------------------------------------------------------------------------- /Chapter03/sources/Linear Regression.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-02-20 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.16.1\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": {}, 36 | "outputs": [ 37 | { 38 | "name": "stdout", 39 | "output_type": "stream", 40 | "text": [ 41 | "0.5609580848733504\n" 42 | ] 43 | } 44 | ], 45 | "source": [ 46 | "import pandas as pd\n", 47 | "import numpy as np\n", 48 | "\n", 49 | "df = pd.read_csv('../datasets/sms_spam_perceptron.csv')\n", 50 | "\n", 51 | "X = df.iloc[:, [1, 2]].values\n", 52 | "\n", 53 | "y = df.iloc[:, 0].values\n", 54 | "y = np.where(y == 'spam', -1, 1)\n", 55 | "\n", 56 | "from sklearn.linear_model import LinearRegression\n", 57 | "linear_regression = LinearRegression()\n", 58 | "linear_regression.fit(X,y)\n", 59 | "\n", 60 | "print (linear_regression.score(X,y))" 61 | ] 62 | } 63 | ], 64 | "metadata": { 65 | "kernelspec": { 66 | "display_name": "Py35", 67 | "language": "python", 68 | "name": "py35" 69 | }, 70 | "language_info": { 71 | "codemirror_mode": { 72 | "name": "ipython", 73 | "version": 3 74 | }, 75 | "file_extension": ".py", 76 | "mimetype": "text/x-python", 77 | "name": "python", 78 | "nbconvert_exporter": "python", 79 | "pygments_lexer": "ipython3", 80 | "version": "3.5.4" 81 | } 82 | }, 83 | "nbformat": 4, 84 | "nbformat_minor": 2 85 | } 86 | -------------------------------------------------------------------------------- /Chapter03/sources/defs.py: -------------------------------------------------------------------------------- 1 | from textblob import TextBlob 2 | 3 | def get_tokens(msg): 4 | return TextBlob(str(msg)).words 5 | 6 | def get_lemmas(msg): 7 | lemmas = [] 8 | words = get_tokens(msg) 9 | 10 | for word in words: 11 | lemmas.append(word.lemma) 12 | 13 | return lemmas 14 | 15 | 16 | # Thanks to Sebastian Raschka for 'plot_decision_regions' 17 | # https://github.com/rasbt/python-machine-learning-book 18 | 19 | from matplotlib.colors import ListedColormap 20 | import matplotlib.pyplot as plt 21 | import numpy as np 22 | import warnings 23 | 24 | def versiontuple(v): 25 | return tuple(map(int, (v.split(".")))) 26 | 27 | def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02): 28 | 29 | # setup marker generator and color map 30 | markers = ('s', 'x', 'o', '^', 'v') 31 | colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') 32 | cmap = ListedColormap(colors[:len(np.unique(y))]) 33 | 34 | # plot the decision surface 35 | x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 36 | x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 37 | xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), 38 | np.arange(x2_min, x2_max, resolution)) 39 | Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) 40 | Z = Z.reshape(xx1.shape) 41 | plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap) 42 | plt.xlim(xx1.min(), xx1.max()) 43 | plt.ylim(xx2.min(), xx2.max()) 44 | 45 | for idx, cl in enumerate(np.unique(y)): 46 | plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], 47 | alpha=0.8, c=cmap(idx), 48 | marker=markers[idx], label=cl) 49 | 50 | # highlight test samples 51 | if test_idx: 52 | # plot all samples 53 | if not versiontuple(np.__version__) >= versiontuple('1.9.0'): 54 | X_test, y_test = X[list(test_idx), :], y[list(test_idx)] 55 | warnings.warn('Please update to NumPy 1.9.0 or newer') 56 | else: 57 | X_test, y_test = X[test_idx, :], y[test_idx] 58 | 59 | plt.scatter(X_test[:, 0], 60 | X_test[:, 1], 61 | c='', 62 | alpha=1.0, 63 | linewidths=1, 64 | marker='o', 65 | s=55, label='test set') 66 | 67 | -------------------------------------------------------------------------------- /Chapter03/datasets/sms_spam_svm.csv: -------------------------------------------------------------------------------- 1 | type,suspect,neutral 2 | ham,1,3 3 | ham,49,30 4 | spam,47,32 5 | ham,46,31 6 | ham,0,36 7 | spam,4,39 8 | ham,46,34 9 | ham,0,34 10 | spam,44,29 11 | spam,49,31 12 | ham,4,37 13 | spam,48,34 14 | spam,48,30 15 | ham,43,30 16 | ham,8,40 17 | spam,7,44 18 | ham,4,39 19 | ham,1,3 20 | ham,7,38 21 | spam,1,38 22 | ham,4,34 23 | ham,1,37 24 | ham,46,36 25 | ham,1,33 26 | ham,48,34 27 | ham,0,30 28 | ham,0,34 29 | ham,2,3 30 | ham,2,34 31 | ham,47,32 32 | ham,48,31 33 | ham,4,34 34 | ham,2,41 35 | ham,0,42 36 | spam,49,31 37 | ham,0,32 38 | ham,0,3 39 | ham,49,36 40 | ham,44,30 41 | ham,1,34 42 | ham,0,3 43 | ham,4,23 44 | spam,44,32 45 | ham,0,3 46 | ham,1,38 47 | ham,48,30 48 | ham,1,38 49 | ham,46,32 50 | ham,3,37 51 | ham,0,33 52 | ham,70,32 53 | ham,64,32 54 | ham,69,31 55 | ham,0,23 56 | spam,6,28 57 | ham,7,28 58 | spam,63,33 59 | ham,49,24 60 | ham,66,29 61 | ham,2,27 62 | ham,0,20 63 | ham,9,30 64 | ham,60,22 65 | ham,61,29 66 | ham,6,29 67 | spam,67,31 68 | ham,6,30 69 | spam,8,27 70 | spam,62,22 71 | ham,6,2 72 | ham,9,32 73 | ham,61,28 74 | ham,63,2 75 | ham,61,28 76 | ham,64,29 77 | ham,66,30 78 | ham,68,28 79 | ham,67,30 80 | ham,60,29 81 | ham,7,26 82 | ham,0,24 83 | ham,0,24 84 | ham,8,27 85 | ham,60,27 86 | ham,4,30 87 | ham,60,34 88 | ham,67,31 89 | ham,63,23 90 | ham,6,30 91 | ham,0,2 92 | ham,0,26 93 | ham,61,30 94 | ham,8,26 95 | spam,0,23 96 | ham,6,27 97 | spam,7,30 98 | ham,7,29 99 | ham,62,29 100 | ham,1,2 101 | ham,7,28 102 | ham,63,33 103 | ham,8,27 104 | ham,71,30 105 | ham,63,29 106 | ham,6,30 107 | ham,76,30 108 | ham,49,2 109 | ham,73,29 110 | ham,67,2 111 | ham,72,36 112 | ham,6,32 113 | ham,64,27 114 | ham,68,30 115 | ham,7,2 116 | spam,8,28 117 | ham,64,32 118 | ham,6,30 119 | spam,77,38 120 | ham,77,26 121 | ham,60,22 122 | spam,69,32 123 | spam,6,28 124 | ham,77,28 125 | spam,63,27 126 | ham,67,33 127 | ham,72,32 128 | ham,62,28 129 | ham,61,30 130 | ham,64,28 131 | ham,72,30 132 | ham,74,28 133 | ham,79,38 134 | ham,64,28 135 | ham,63,28 136 | spam,61,26 137 | spam,77,30 138 | ham,63,34 139 | ham,64,31 140 | ham,60,30 141 | spam,69,31 142 | ham,67,31 143 | ham,69,31 144 | ham,8,27 145 | ham,68,32 146 | ham,67,33 147 | ham,67,30 148 | ham,63,2 149 | spam,6,30 150 | ham,62,34 151 | ham,9,30 152 | -------------------------------------------------------------------------------- /Chapter10/cross-validation-model-optimization.py: -------------------------------------------------------------------------------- 1 | """ 2 | Readapted from the original source code available at: 3 | https://scikit-learn.org/stable/auto_examples/model_selection/plot_grid_search_digits.html 4 | 5 | Original code released under BSD License. 6 | """ 7 | 8 | from sklearn import datasets 9 | from sklearn.model_selection import train_test_split 10 | from sklearn.model_selection import GridSearchCV 11 | from sklearn.metrics import classification_report 12 | from sklearn.svm import SVC 13 | 14 | # Loading the Digits dataset 15 | digits = datasets.load_digits() 16 | 17 | n_samples = len(digits.images) 18 | X = digits.images.reshape((n_samples, -1)) 19 | y = digits.target 20 | 21 | 22 | # Split the dataset in two equal parts 23 | X_train, X_test, y_train, y_test = train_test_split( 24 | X, y, test_size=0.5, random_state=0) 25 | 26 | 27 | # Set the parameters by cross-validation 28 | tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4], 29 | 'C': [1, 10, 100, 1000]}, 30 | {'kernel': ['linear'], 'C': [1, 10, 100, 1000]}] 31 | 32 | 33 | print("# Tuning hyper-parameters for precision") 34 | print() 35 | 36 | clf = GridSearchCV(SVC(), tuned_parameters, cv=5, 37 | scoring='precision') 38 | 39 | clf.fit(X_train, y_train) 40 | 41 | print("Best parameters set found on development set:") 42 | print() 43 | print(clf.best_params_) 44 | print() 45 | print("Grid scores on development set:") 46 | print() 47 | means = clf.cv_results_['mean_test_score'] 48 | stds = clf.cv_results_['std_test_score'] 49 | 50 | for mean, std, params in zip(means, stds, clf.cv_results_['params']): 51 | print("%0.3f (+/-%0.03f) for %r" % (mean, std * 2, params)) 52 | 53 | print() 54 | print("Detailed classification report:") 55 | print() 56 | print("The model is trained on the full development set.") 57 | print("The scores are computed on the full evaluation set.") 58 | print() 59 | y_true, y_pred = y_test, clf.predict(X_test) 60 | print(classification_report(y_true, y_pred)) 61 | print() 62 | 63 | print("# Tuning hyper-parameters for recall") 64 | print() 65 | 66 | clf = GridSearchCV(SVC(), tuned_parameters, cv=5, 67 | scoring='recall') 68 | 69 | clf.fit(X_train, y_train) 70 | 71 | print("Best parameters set found on development set:") 72 | print() 73 | print(clf.best_params_) 74 | print() 75 | print("Grid scores on development set:") 76 | print() 77 | means = clf.cv_results_['mean_test_score'] 78 | stds = clf.cv_results_['std_test_score'] 79 | 80 | for mean, std, params in zip(means, stds, clf.cv_results_['params']): 81 | print("%0.3f (+/-%0.03f) for %r" % (mean, std * 2, params)) 82 | 83 | print() 84 | print("Detailed classification report:") 85 | print() 86 | print("The model is trained on the full development set.") 87 | print("The scores are computed on the full evaluation set.") 88 | print() 89 | y_true, y_pred = y_test, clf.predict(X_test) 90 | print(classification_report(y_true, y_pred)) 91 | print() 92 | 93 | -------------------------------------------------------------------------------- /Chapter06/sources/Eigenvectors & Eigenvalues.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-04-17 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.15.2\n", 19 | "pandas 0.23.4\n", 20 | "matplotlib 2.2.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line\n", 30 | "import warnings \n", 31 | "warnings.simplefilter('ignore')" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stdout", 41 | "output_type": "stream", 42 | "text": [ 43 | "[[7.30333333 7.69166667 7.19166667]\n", 44 | " [7.69166667 8.12333333 7.54333333]\n", 45 | " [7.19166667 7.54333333 7.12333333]]\n" 46 | ] 47 | } 48 | ], 49 | "source": [ 50 | "import numpy as np\n", 51 | "\n", 52 | "X = np.array([\n", 53 | " [3, 0.1, -2.4],\n", 54 | " [3.1, 0.3, -2.6],\n", 55 | " [3.4, 0.2, -1.9],\n", 56 | "])\n", 57 | "\n", 58 | "print(np.cov(X).T)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 5, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "Eigenvaules: [-1.99999996 -2.00000004]\n", 71 | "Eigenvectors: [[0.70710678 0.70710678]\n", 72 | " [0.70710678 0.70710678]]\n" 73 | ] 74 | } 75 | ], 76 | "source": [ 77 | "\"\"\"\n", 78 | " __ __ \n", 79 | " | | \n", 80 | " | 2 -4 | \n", 81 | "A = | | \n", 82 | " | 4 -6 | \n", 83 | " |__ __| \n", 84 | " \n", 85 | "\n", 86 | "\"\"\"\n", 87 | "\n", 88 | "\n", 89 | "import numpy as np\n", 90 | "eigenvaules, eigenvectors = np.linalg.eig(np.array([[2, -4], [4, -6]]))\n", 91 | "\n", 92 | "print(\"Eigenvaules:\", eigenvaules)\n", 93 | "print(\"Eigenvectors:\", eigenvectors)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": { 100 | "collapsed": true 101 | }, 102 | "outputs": [], 103 | "source": [] 104 | } 105 | ], 106 | "metadata": { 107 | "kernelspec": { 108 | "display_name": "Py35", 109 | "language": "python", 110 | "name": "py35" 111 | }, 112 | "language_info": { 113 | "codemirror_mode": { 114 | "name": "ipython", 115 | "version": 3 116 | }, 117 | "file_extension": ".py", 118 | "mimetype": "text/x-python", 119 | "name": "python", 120 | "nbconvert_exporter": "python", 121 | "pygments_lexer": "ipython3", 122 | "version": "3.5.4" 123 | } 124 | }, 125 | "nbformat": 4, 126 | "nbformat_minor": 2 127 | } 128 | -------------------------------------------------------------------------------- /Chapter06/sources/Facial Recognition.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-04-17 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.15.2\n", 19 | "pandas 0.23.4\n", 20 | "matplotlib 2.2.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line\n", 30 | "import warnings \n", 31 | "warnings.simplefilter('ignore')" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stdout", 41 | "output_type": "stream", 42 | "text": [ 43 | " precision recall f1-score support\n", 44 | "\n", 45 | " Colin Powell 0.92 0.89 0.90 79\n", 46 | "George W Bush 0.94 0.96 0.95 151\n", 47 | "\n", 48 | " micro avg 0.93 0.93 0.93 230\n", 49 | " macro avg 0.93 0.92 0.93 230\n", 50 | " weighted avg 0.93 0.93 0.93 230\n", 51 | "\n" 52 | ] 53 | } 54 | ], 55 | "source": [ 56 | "from sklearn.datasets import fetch_lfw_people\n", 57 | "from sklearn.decomposition import PCA\n", 58 | "from sklearn.neural_network import MLPClassifier\n", 59 | "from sklearn.model_selection import train_test_split\n", 60 | "from sklearn.metrics import classification_report\n", 61 | "\n", 62 | "\n", 63 | "lfw = fetch_lfw_people(min_faces_per_person=150)\n", 64 | "\n", 65 | "X_data = lfw.data\n", 66 | "y_target = lfw.target\n", 67 | "names = lfw.target_names\n", 68 | "\n", 69 | "X_train, X_test, y_train, y_test = train_test_split(X_data, y_target, test_size=0.3)\n", 70 | "\n", 71 | "\n", 72 | "pca = PCA(n_components=150, whiten=True)\n", 73 | "pca.fit(X_train)\n", 74 | "\n", 75 | "pca_train = pca.transform(X_train)\n", 76 | "pca_test = pca.transform(X_test)\n", 77 | "\n", 78 | "\n", 79 | "mlpc = MLPClassifier()\n", 80 | "mlpc.fit(pca_train, y_train)\n", 81 | "\n", 82 | "y_pred = mlpc.predict(pca_test)\n", 83 | "print(classification_report(y_test, y_pred, target_names=names))\n" 84 | ] 85 | } 86 | ], 87 | "metadata": { 88 | "kernelspec": { 89 | "display_name": "Py35", 90 | "language": "python", 91 | "name": "py35" 92 | }, 93 | "language_info": { 94 | "codemirror_mode": { 95 | "name": "ipython", 96 | "version": 3 97 | }, 98 | "file_extension": ".py", 99 | "mimetype": "text/x-python", 100 | "name": "python", 101 | "nbconvert_exporter": "python", 102 | "pygments_lexer": "ipython3", 103 | "version": "3.5.4" 104 | } 105 | }, 106 | "nbformat": 4, 107 | "nbformat_minor": 2 108 | } 109 | -------------------------------------------------------------------------------- /Chapter04/sources/Random Forest Malware Classifier.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-03-15 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.15.2\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.2.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import pandas as pd\n", 41 | "import numpy as np\n", 42 | "from sklearn import *\n", 43 | "\n", 44 | "import warnings \n", 45 | "warnings.simplefilter('ignore')" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 3, 51 | "metadata": { 52 | "collapsed": true 53 | }, 54 | "outputs": [], 55 | "source": [ 56 | "malware_dataset = pd.read_csv('../datasets/MalwareArtifacts.csv', delimiter=',')\n", 57 | "# Extacting artifacts samples fields \"AddressOfEntryPoint\" and \"DllCharacteristics\"\n", 58 | "samples = malware_dataset.iloc[:, [0,4]].values\n", 59 | "targets = malware_dataset.iloc[:, 8].values" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 4, 65 | "metadata": { 66 | "collapsed": true 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "from sklearn.model_selection import train_test_split\n", 71 | "\n", 72 | "training_samples, testing_samples, training_targets, testing_targets = train_test_split(samples, targets, test_size=0.2)\n" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 5, 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "name": "stdout", 82 | "output_type": "stream", 83 | "text": [ 84 | "Random Forest Classifier accuracy: 96.46142701919594\n" 85 | ] 86 | } 87 | ], 88 | "source": [ 89 | "rfc = ensemble.RandomForestClassifier(n_estimators=50)\n", 90 | "rfc.fit(training_samples, training_targets)\n", 91 | "accuracy = rfc.score(testing_samples, testing_targets)\n", 92 | "\n", 93 | "print(\"Random Forest Classifier accuracy: \" + str(accuracy*100) )" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": { 100 | "collapsed": true 101 | }, 102 | "outputs": [], 103 | "source": [] 104 | } 105 | ], 106 | "metadata": { 107 | "kernelspec": { 108 | "display_name": "Py35", 109 | "language": "python", 110 | "name": "py35" 111 | }, 112 | "language_info": { 113 | "codemirror_mode": { 114 | "name": "ipython", 115 | "version": 3 116 | }, 117 | "file_extension": ".py", 118 | "mimetype": "text/x-python", 119 | "name": "python", 120 | "nbconvert_exporter": "python", 121 | "pygments_lexer": "ipython3", 122 | "version": "3.5.4" 123 | } 124 | }, 125 | "nbformat": 4, 126 | "nbformat_minor": 2 127 | } 128 | -------------------------------------------------------------------------------- /Chapter04/sources/K-means malware clustering.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-03-15 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.15.2\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.2.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import numpy as np \n", 41 | "import pandas as pd \n", 42 | "import matplotlib.pyplot as plt \n", 43 | " \n", 44 | "from sklearn.cluster import KMeans \n", 45 | "from sklearn.metrics import silhouette_score \n", 46 | "\n", 47 | "import warnings \n", 48 | "warnings.simplefilter('ignore')" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 3, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "malware_dataset = pd.read_csv('../datasets/MalwareArtifacts.csv', delimiter=',')\n", 58 | "# Extacting artifacts samples fields 'MajorLinkerVersion,MajorImageVersion,MajorOperatingSystemVersion,DllCharacteristics'\n", 59 | "samples = malware_dataset.iloc[:, [1,2,3,4]].values\n", 60 | "targets = malware_dataset.iloc[:, 8].values" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 4, 66 | "metadata": {}, 67 | "outputs": [ 68 | { 69 | "name": "stdout", 70 | "output_type": "stream", 71 | "text": [ 72 | "K-means labels: [0 0 0 ... 0 1 0]\n", 73 | "\n", 74 | "K-means Clustering Results:\n", 75 | "\n", 76 | " Predicted 0 1\n", 77 | "Observed \n", 78 | "0 83419 13107\n", 79 | "1 7995 32923\n", 80 | "\n", 81 | "Silhouette coefficient: 0.975\n" 82 | ] 83 | } 84 | ], 85 | "source": [ 86 | "k_means = KMeans(n_clusters=2,max_iter=300)\n", 87 | "k_means.fit(samples) \n", 88 | "\n", 89 | "print(\"K-means labels: \" + str(k_means.labels_))\n", 90 | "print (\"\\nK-means Clustering Results:\\n\\n\", pd.crosstab(targets, k_means.labels_,rownames = [\"Observed\"],colnames = [\"Predicted\"]) ) \n", 91 | "print (\"\\nSilhouette coefficient: %0.3f\" % silhouette_score(samples, k_means.labels_, metric='euclidean')) " 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": true 99 | }, 100 | "outputs": [], 101 | "source": [] 102 | } 103 | ], 104 | "metadata": { 105 | "kernelspec": { 106 | "display_name": "Py35", 107 | "language": "python", 108 | "name": "py35" 109 | }, 110 | "language_info": { 111 | "codemirror_mode": { 112 | "name": "ipython", 113 | "version": 3 114 | }, 115 | "file_extension": ".py", 116 | "mimetype": "text/x-python", 117 | "name": "python", 118 | "nbconvert_exporter": "python", 119 | "pygments_lexer": "ipython3", 120 | "version": "3.5.4" 121 | } 122 | }, 123 | "nbformat": 4, 124 | "nbformat_minor": 2 125 | } 126 | -------------------------------------------------------------------------------- /Chapter07/ch07-sources.txt: -------------------------------------------------------------------------------- 1 | Rule-based IDPS: 2 | 3 | IF amount > $1,000 AND buying_frequency > historical_buying_frequency THEN fraud_likelihood = 90% 4 | 5 | IF distance(new_transaction, last_transaction) > 1000 km AND time_range < 30 min THEN block_transaction 6 | 7 | 8 | ------------- 9 | 10 | Bagging Classifier example: 11 | 12 | from sklearn.tree import DecisionTreeClassifier 13 | 14 | from sklearn.ensemble import BaggingClassifier 15 | 16 | bagging = BaggingClassifier( 17 | DecisionTreeClassifier(), 18 | n_estimators=300, 19 | max_samples=100, 20 | bootstrap=True 21 | ) 22 | 23 | 24 | -------------- 25 | 26 | Boosting with AdaBoost example: 27 | 28 | from sklearn.tree import DecisionTreeClassifier 29 | 30 | from sklearn.ensemble import AdaBoostClassifier 31 | 32 | 33 | adaboost = AdaBoostClassifier( 34 | DecisionTreeClassifier(), 35 | n_estimators=300 36 | ) 37 | 38 | 39 | ---------------- 40 | 41 | Gradient Boosting Classifier example: 42 | 43 | from sklearn.ensemble import GradientBoostingClassifier 44 | 45 | gradient_boost = GradientBoostingClassifier( 46 | max_depth=2, 47 | n_estimators=100, 48 | learning_rate=1.0, 49 | warm_start=True 50 | ) 51 | 52 | 53 | ----------------- 54 | 55 | eXtreme Gradient Boosting (Xgboost) Classifier example: 56 | 57 | from xgboost.sklearn import XGBClassifier 58 | 59 | xgb_model = XGBClassifier() 60 | 61 | 62 | ----------------- 63 | 64 | Under-sampling with RandomUnderSampler: 65 | 66 | # From the Imbalanced-Learn library documentation: 67 | # https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.RandomUnderSampler.html 68 | 69 | from collections import Counter 70 | from sklearn.datasets import make_classification 71 | from imblearn.under_sampling import RandomUnderSampler 72 | 73 | X, y = make_classification(n_classes=2, class_sep=2, 74 | weights=[0.1, 0.9], n_informative=3, n_redundant=1, flip_y=0, 75 | n_features=20, n_clusters_per_class=1, n_samples=1000, random_state=10) 76 | print('Original dataset shape %s' % Counter(y)) 77 | 78 | rus = RandomUnderSampler(random_state=42) 79 | X_res, y_res = rus.fit_resample(X, y) 80 | print('Resampled dataset shape %s' % Counter(y_res)) 81 | 82 | 83 | Over-sampling with SMOTE: 84 | 85 | # From the Imbalanced-Learn library documentation: 86 | # https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.over_sampling.SMOTE.html 87 | 88 | from collections import Counter 89 | from sklearn.datasets import make_classification 90 | from imblearn.over_sampling import SMOTE 91 | 92 | X, y = make_classification(n_classes=2, class_sep=2, 93 | weights=[0.1, 0.9], n_informative=3, n_redundant=1, flip_y=0, 94 | n_features=20, n_clusters_per_class=1, n_samples=1000, 95 | random_state=10) 96 | 97 | print('Original dataset shape %s' % Counter(y)) 98 | Original dataset shape Counter({1: 900, 0: 100}) 99 | 100 | sm = SMOTE(random_state=42) 101 | X_res, y_res = sm.fit_resample(X, y) 102 | print('Resampled dataset shape %s' % Counter(y_res)) 103 | Resampled dataset shape Counter({0: 900, 1: 900}) 104 | 105 | 106 | 107 | ----------------- 108 | 109 | IBM Fraud Detection notebook available at: 110 | https://github.com/IBM/xgboost-smote-detect-fraud/blob/master/notebook/Fraud_Detection.ipynb 111 | (Source code Released under apache version 2 license: http://www.apache.org/licenses/LICENSE-2.0.txt) 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Chapter09/CH09-examples.txt: -------------------------------------------------------------------------------- 1 | # Min-Max Scaler 2 | 3 | from sklearn import preprocessing 4 | 5 | import numpy as np 6 | 7 | raw_data = np.array([ 8 | 9 | [ 2., -3., 4.], 10 | 11 | [ 5., 0., 1.], 12 | 13 | [ 4., 0., -2.]]) 14 | 15 | min_max_scaler = preprocessing.MinMaxScaler() 16 | 17 | scaled_data = min_max_scaler.fit_transform(raw_data) 18 | 19 | 20 | # Standard Scaler 21 | 22 | from sklearn import preprocessing 23 | 24 | import numpy as np 25 | 26 | raw_data = np.array([ 27 | 28 | [ 2., -3., 4.], 29 | 30 | [ 5., 0., 1.], 31 | 32 | [ 4., 0., -2.]]) 33 | 34 | std_scaler = preprocessing.StandardScaler().fit(raw_data) 35 | 36 | std_scaler.transform(raw_data) 37 | 38 | test_data = [[-3., 1., 2.]] 39 | 40 | std_scaler.transform(test_data) 41 | 42 | 43 | # Power Transformation 44 | 45 | from sklearn import preprocessing 46 | 47 | import numpy as np 48 | 49 | pt = preprocessing.PowerTransformer(method='box-cox', standardize=False) 50 | 51 | X_lognormal = np.random.RandomState(616).lognormal(size=(3, 3)) 52 | 53 | pt.fit_transform(X_lognormal) 54 | 55 | 56 | # Ordinal Encoding 57 | 58 | from sklearn import preprocessing 59 | 60 | ord_enc = preprocessing.OrdinalEncoder() 61 | 62 | cat_data = [['Developer', 'Remote Working', 'Windows'], ['Sysadmin', 'Onsite Working', 'Linux']] 63 | 64 | ord_enc.fit(cat_data) 65 | 66 | ord_enc.transform([['Developer', 'Onsite Working', 'Linux']]) 67 | 68 | 69 | # One-Hot Encoding 70 | 71 | from sklearn import preprocessing 72 | 73 | one_hot_enc = preprocessing.OneHotEncoder() 74 | 75 | cat_data = [['Developer', 'Remote Working', 'Windows'], ['Sysadmin', 'Onsite Working', 'Linux']] 76 | 77 | one_hot_enc.fit(cat_data) 78 | 79 | one_hot_enc.transform([['Developer', 'Onsite Working', 'Linux']]) 80 | 81 | 82 | # ROC Metrics Examples 83 | 84 | import numpy as np 85 | 86 | from sklearn import metrics 87 | from sklearn.metrics import precision_recall_curve 88 | from sklearn.metrics import average_precision_score 89 | 90 | y_true = np.array([0, 1, 1, 1]) 91 | y_pred = np.array([0.2, 0.7, 0.65, 0.9]) 92 | 93 | prec, rec, thres = precision_recall_curve(y_true, y_pred) 94 | 95 | average_precision_score(y_true, y_pred) 96 | 97 | metrics.precision_score(y_true, y_pred) 98 | 99 | metrics.recall_score(y_true, y_pred) 100 | 101 | metrics.f1_score(y_true, y_pred) 102 | 103 | 104 | # ROC curve Example 105 | 106 | import numpy as np 107 | from sklearn.metrics import roc_curve 108 | 109 | y_true = np.array([0, 1, 1, 1]) 110 | y_pred = np.array([0.2, 0.7, 0.65, 0.9]) 111 | 112 | FPR, TPR, THR = roc_curve(y_true, y_pred) 113 | 114 | 115 | # AUC score Example 116 | 117 | import numpy as np 118 | from sklearn.metrics import roc_auc_score 119 | 120 | y_true = np.array([0, 1, 1, 1]) 121 | y_pred = np.array([0.2, 0.7, 0.65, 0.9]) 122 | 123 | roc_auc_score(y_true, y_pred) 124 | 125 | 126 | # Brier score Example 127 | 128 | import numpy as np 129 | from sklearn.metrics import brier_score_loss 130 | 131 | y_true = np.array([0, 1, 1, 1]) 132 | y_cats = np.array(["fraud", "legit", "legit", "legit"]) 133 | 134 | y_prob = np.array([0.2, 0.7, 0.9, 0.3]) 135 | y_pred = np.array([1, 1, 1, 0]) 136 | 137 | brier_score_loss(y_true, y_prob) 138 | 139 | brier_score_loss(y_cats, y_prob, pos_label="legit") 140 | 141 | brier_score_loss(y_true, y_prob > 0.5) 142 | 143 | 144 | # Splitting samples into training and testing subsets 145 | 146 | from sklearn.model_selection import train_test_split 147 | 148 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) 149 | 150 | 151 | # Learning curve example 152 | 153 | from sklearn.model_selection import learning_curve 154 | 155 | from sklearn.svm import SVC 156 | 157 | _sizes = [ 60, 80, 100] 158 | 159 | train_sizes, train_scores, valid_scores = learning_curve(SVC(), X, y, train_sizes=_sizes) 160 | 161 | 162 | # K-folds Cross Validation example 163 | 164 | import numpy as np 165 | from sklearn.model_selection import KFold 166 | 167 | X = np.array([[1., 0.], [2., 1.], [-2., -1.], [3., 2.]]) 168 | y = np.array([0, 1, 0, 1]) 169 | 170 | k_folds = KFold(n_splits=2) 171 | 172 | for train, test in k_folds.split(X): 173 | print("%s %s" % (train, test)) 174 | 175 | [2 0] [3 1] 176 | [3 1] [2 0] 177 | 178 | X_train, X_test, y_train, y_test = X[train], X[test], y[train], y[test] 179 | 180 | 181 | -------------------------------------------------------------------------------- /Chapter03/sources/Logistic Regression Phishing Detector.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-02-19 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.16.1\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import pandas as pd\n", 41 | "import numpy as np\n", 42 | "from sklearn import *\n", 43 | "from sklearn.linear_model import LogisticRegression\n", 44 | "from sklearn.metrics import accuracy_score\n", 45 | "import warnings \n", 46 | "warnings.simplefilter('ignore')\n" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 3, 52 | "metadata": { 53 | "collapsed": true 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "phishing_dataset = np.genfromtxt('../datasets/phishing_dataset.csv', delimiter=',', dtype=np.int32)\n", 58 | "samples = phishing_dataset[:,:-1]\n", 59 | "targets = phishing_dataset[:, -1]" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 4, 65 | "metadata": { 66 | "collapsed": true 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "from sklearn.model_selection import train_test_split\n", 71 | "\n", 72 | "training_samples, testing_samples, training_targets, testing_targets = train_test_split(\n", 73 | " samples, targets, test_size=0.2, random_state=0)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 5, 79 | "metadata": { 80 | "collapsed": true 81 | }, 82 | "outputs": [], 83 | "source": [ 84 | "log_classifier = LogisticRegression()" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": 6, 90 | "metadata": {}, 91 | "outputs": [ 92 | { 93 | "data": { 94 | "text/plain": [ 95 | "LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n", 96 | " intercept_scaling=1, max_iter=100, multi_class='warn',\n", 97 | " n_jobs=None, penalty='l2', random_state=None, solver='warn',\n", 98 | " tol=0.0001, verbose=0, warm_start=False)" 99 | ] 100 | }, 101 | "execution_count": 6, 102 | "metadata": {}, 103 | "output_type": "execute_result" 104 | } 105 | ], 106 | "source": [ 107 | "log_classifier.fit(training_samples, training_targets)" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 7, 113 | "metadata": { 114 | "collapsed": true 115 | }, 116 | "outputs": [], 117 | "source": [ 118 | "predictions = log_classifier.predict(testing_samples)" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 8, 124 | "metadata": {}, 125 | "outputs": [ 126 | { 127 | "name": "stdout", 128 | "output_type": "stream", 129 | "text": [ 130 | "Logistic Regression accuracy: 91.72320217096338\n" 131 | ] 132 | } 133 | ], 134 | "source": [ 135 | "accuracy = 100.0 * accuracy_score(testing_targets, predictions)\n", 136 | "print (\"Logistic Regression accuracy: \" + str(accuracy))" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": { 143 | "collapsed": true 144 | }, 145 | "outputs": [], 146 | "source": [] 147 | } 148 | ], 149 | "metadata": { 150 | "kernelspec": { 151 | "display_name": "Py35", 152 | "language": "python", 153 | "name": "py35" 154 | }, 155 | "language_info": { 156 | "codemirror_mode": { 157 | "name": "ipython", 158 | "version": 3 159 | }, 160 | "file_extension": ".py", 161 | "mimetype": "text/x-python", 162 | "name": "python", 163 | "nbconvert_exporter": "python", 164 | "pygments_lexer": "ipython3", 165 | "version": "3.5.4" 166 | } 167 | }, 168 | "nbformat": 4, 169 | "nbformat_minor": 2 170 | } 171 | -------------------------------------------------------------------------------- /Chapter03/sources/Decision Tree Phishing Detector.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-02-19 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.16.1\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import pandas as pd\n", 41 | "import numpy as np\n", 42 | "from sklearn import *\n", 43 | "from sklearn.linear_model import LogisticRegression\n", 44 | "from sklearn.metrics import accuracy_score\n", 45 | "import warnings \n", 46 | "warnings.simplefilter('ignore')" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 3, 52 | "metadata": { 53 | "collapsed": true 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "phishing_dataset = np.genfromtxt('../datasets/phishing_dataset.csv', delimiter=',', dtype=np.int32)\n", 58 | "samples = phishing_dataset[:,:-1]\n", 59 | "targets = phishing_dataset[:, -1]" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 4, 65 | "metadata": { 66 | "collapsed": true 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "from sklearn.model_selection import train_test_split\n", 71 | "\n", 72 | "training_samples, testing_samples, training_targets, testing_targets = train_test_split(\n", 73 | " samples, targets, test_size=0.2, random_state=0)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 5, 79 | "metadata": { 80 | "collapsed": true 81 | }, 82 | "outputs": [], 83 | "source": [ 84 | "from sklearn import tree\n", 85 | "tree_classifier = tree.DecisionTreeClassifier()" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 6, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,\n", 97 | " max_features=None, max_leaf_nodes=None,\n", 98 | " min_impurity_decrease=0.0, min_impurity_split=None,\n", 99 | " min_samples_leaf=1, min_samples_split=2,\n", 100 | " min_weight_fraction_leaf=0.0, presort=False, random_state=None,\n", 101 | " splitter='best')" 102 | ] 103 | }, 104 | "execution_count": 6, 105 | "metadata": {}, 106 | "output_type": "execute_result" 107 | } 108 | ], 109 | "source": [ 110 | "tree_classifier.fit(training_samples, training_targets)" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 7, 116 | "metadata": { 117 | "collapsed": true 118 | }, 119 | "outputs": [], 120 | "source": [ 121 | "predictions = tree_classifier.predict(testing_samples)" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 8, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stdout", 131 | "output_type": "stream", 132 | "text": [ 133 | "Decision Tree accuracy: 96.29127091813659\n" 134 | ] 135 | } 136 | ], 137 | "source": [ 138 | "accuracy = 100.0 * accuracy_score(testing_targets, predictions)\n", 139 | "print (\"Decision Tree accuracy: \" + str(accuracy))" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": { 146 | "collapsed": true 147 | }, 148 | "outputs": [], 149 | "source": [] 150 | } 151 | ], 152 | "metadata": { 153 | "kernelspec": { 154 | "display_name": "Py35", 155 | "language": "python", 156 | "name": "py35" 157 | }, 158 | "language_info": { 159 | "codemirror_mode": { 160 | "name": "ipython", 161 | "version": 3 162 | }, 163 | "file_extension": ".py", 164 | "mimetype": "text/x-python", 165 | "name": "python", 166 | "nbconvert_exporter": "python", 167 | "pygments_lexer": "ipython3", 168 | "version": "3.5.4" 169 | } 170 | }, 171 | "nbformat": 4, 172 | "nbformat_minor": 2 173 | } 174 | -------------------------------------------------------------------------------- /Chapter04/sources/Decision Tree Malware Detector.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-03-15 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.15.2\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.2.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import pandas as pd\n", 41 | "import numpy as np\n", 42 | "from sklearn import *\n", 43 | "\n", 44 | "from sklearn.metrics import accuracy_score\n", 45 | "import warnings \n", 46 | "warnings.simplefilter('ignore')" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 3, 52 | "metadata": { 53 | "collapsed": true 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "malware_dataset = pd.read_csv('../datasets/MalwareArtifacts.csv', delimiter=',')\n", 58 | "# Extacting artifacts samples fields \"AddressOfEntryPoint\" and \"DllCharacteristics\"\n", 59 | "samples = malware_dataset.iloc[:, [0, 4]].values\n", 60 | "targets = malware_dataset.iloc[:, 8].values" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 4, 66 | "metadata": { 67 | "collapsed": true 68 | }, 69 | "outputs": [], 70 | "source": [ 71 | "from sklearn.model_selection import train_test_split\n", 72 | "\n", 73 | "training_samples, testing_samples, training_targets, testing_targets = train_test_split(\n", 74 | " samples, targets, test_size=0.2, random_state=0)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 5, 80 | "metadata": { 81 | "collapsed": true 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "from sklearn import tree\n", 86 | "tree_classifier = tree.DecisionTreeClassifier()" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 6, 92 | "metadata": {}, 93 | "outputs": [ 94 | { 95 | "data": { 96 | "text/plain": [ 97 | "DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,\n", 98 | " max_features=None, max_leaf_nodes=None,\n", 99 | " min_impurity_decrease=0.0, min_impurity_split=None,\n", 100 | " min_samples_leaf=1, min_samples_split=2,\n", 101 | " min_weight_fraction_leaf=0.0, presort=False, random_state=None,\n", 102 | " splitter='best')" 103 | ] 104 | }, 105 | "execution_count": 6, 106 | "metadata": {}, 107 | "output_type": "execute_result" 108 | } 109 | ], 110 | "source": [ 111 | "tree_classifier.fit(training_samples, training_targets)" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 7, 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "outputs": [], 121 | "source": [ 122 | "predictions = tree_classifier.predict(testing_samples)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 8, 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "name": "stdout", 132 | "output_type": "stream", 133 | "text": [ 134 | "Decision Tree accuracy: 96.25860195581312\n" 135 | ] 136 | } 137 | ], 138 | "source": [ 139 | "accuracy = 100.0 * accuracy_score(testing_targets, predictions)\n", 140 | "print (\"Decision Tree accuracy: \" + str(accuracy))" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "collapsed": true 148 | }, 149 | "outputs": [], 150 | "source": [] 151 | } 152 | ], 153 | "metadata": { 154 | "kernelspec": { 155 | "display_name": "Py35", 156 | "language": "python", 157 | "name": "py35" 158 | }, 159 | "language_info": { 160 | "codemirror_mode": { 161 | "name": "ipython", 162 | "version": 3 163 | }, 164 | "file_extension": ".py", 165 | "mimetype": "text/x-python", 166 | "name": "python", 167 | "nbconvert_exporter": "python", 168 | "pygments_lexer": "ipython3", 169 | "version": "3.5.4" 170 | } 171 | }, 172 | "nbformat": 4, 173 | "nbformat_minor": 2 174 | } 175 | -------------------------------------------------------------------------------- /Chapter05/sources/Network Anomaly Detection.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-04-02 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.15.2\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.2.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line\n", 30 | "import warnings \n", 31 | "warnings.simplefilter('ignore')" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": { 38 | "collapsed": true 39 | }, 40 | "outputs": [], 41 | "source": [ 42 | "import numpy as np\n", 43 | "import pandas as pd\n", 44 | "\n", 45 | "from sklearn.linear_model import *\n", 46 | "from sklearn.tree import *\n", 47 | "from sklearn.naive_bayes import *\n", 48 | "from sklearn.neighbors import *\n", 49 | "from sklearn.metrics import accuracy_score\n", 50 | "\n", 51 | "from sklearn.model_selection import train_test_split\n", 52 | "\n", 53 | "import matplotlib.pyplot as plt\n", 54 | "%matplotlib inline\n", 55 | "\n", 56 | "# Load the data.\n", 57 | "dataset = pd.read_csv('../datasets/network-logs.csv')" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 3, 63 | "metadata": { 64 | "collapsed": true 65 | }, 66 | "outputs": [], 67 | "source": [ 68 | "samples = dataset.iloc[:, [1, 2]].values\n", 69 | "targets = dataset['ANOMALY'].values" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 4, 75 | "metadata": { 76 | "collapsed": true 77 | }, 78 | "outputs": [], 79 | "source": [ 80 | "training_samples, testing_samples, training_targets, testing_targets = train_test_split(\n", 81 | " samples, targets, test_size=0.3, random_state=0)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 5, 87 | "metadata": {}, 88 | "outputs": [ 89 | { 90 | "name": "stdout", 91 | "output_type": "stream", 92 | "text": [ 93 | "K-Nearest Neighbours accuracy: 95.90163934426229\n" 94 | ] 95 | } 96 | ], 97 | "source": [ 98 | "# k-Nearest Neighbors model\n", 99 | "knc = KNeighborsClassifier(n_neighbors=2)\n", 100 | "knc.fit(training_samples,training_targets)\n", 101 | "knc_prediction = knc.predict(testing_samples)\n", 102 | "knc_accuracy = 100.0 * accuracy_score(testing_targets, knc_prediction)\n", 103 | "print (\"K-Nearest Neighbours accuracy: \" + str(knc_accuracy))" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 6, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "Decision Tree accuracy: 96.72131147540983\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "# Decision tree model\n", 121 | "dtc = DecisionTreeClassifier(random_state=0)\n", 122 | "dtc.fit(training_samples,training_targets)\n", 123 | "dtc_prediction = dtc.predict(testing_samples)\n", 124 | "dtc_accuracy = 100.0 * accuracy_score(testing_targets, dtc_prediction)\n", 125 | "print (\"Decision Tree accuracy: \" + str(dtc_accuracy))" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 7, 131 | "metadata": {}, 132 | "outputs": [ 133 | { 134 | "name": "stdout", 135 | "output_type": "stream", 136 | "text": [ 137 | "Gaussian Naive Bayes accuracy: 98.36065573770492\n" 138 | ] 139 | } 140 | ], 141 | "source": [ 142 | "# Gaussian Naive Bayes model\n", 143 | "gnb = GaussianNB()\n", 144 | "gnb.fit(training_samples,training_targets)\n", 145 | "gnb_prediction = gnb.predict(testing_samples)\n", 146 | "gnb_accuracy = 100.0 * accuracy_score(testing_targets, gnb_prediction)\n", 147 | "print (\"Gaussian Naive Bayes accuracy: \" + str(gnb_accuracy))" 148 | ] 149 | } 150 | ], 151 | "metadata": { 152 | "kernelspec": { 153 | "display_name": "Py35", 154 | "language": "python", 155 | "name": "py35" 156 | }, 157 | "language_info": { 158 | "codemirror_mode": { 159 | "name": "ipython", 160 | "version": 3 161 | }, 162 | "file_extension": ".py", 163 | "mimetype": "text/x-python", 164 | "name": "python", 165 | "nbconvert_exporter": "python", 166 | "pygments_lexer": "ipython3", 167 | "version": "3.5.4" 168 | } 169 | }, 170 | "nbformat": 4, 171 | "nbformat_minor": 2 172 | } 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Hands-On Artificial Intelligence for Cybersecurity 5 | 6 | Hands-On Artificial Intelligence for Cybersecurity 7 | 8 | This is the code repository for [Hands-On Artificial Intelligence for Cybersecurity](https://www.packtpub.com/in/data/hands-on-artificial-intelligence-for-cybersecurity?utm_source=github&utm_medium=repository&utm_campaign=9781789804027), published by Packt. 9 | 10 | **Implement smart AI systems for preventing cyber attacks and detecting threats and network anomalies** 11 | 12 | ## What is this book about? 13 | If you wish to design smart, threat-proof cybersecurity systems using trending AI tools and techniques, then this book is for you. With this book, you will learn to develop intelligent systems that can detect suspicious patterns and attacks, thereby allowing you to protect your network and corporate assets. 14 | 15 | This book covers the following exciting features: 16 | * Detect email threats such as spamming and phishing using AI 17 | * Categorize APT, zero-days, and polymorphic malware samples 18 | * Overcome antivirus limits in threat detection 19 | * Predict network intrusions and detect anomalies with machine learning 20 | * Verify the strength of biometric authentication procedures with deep learning 21 | 22 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1789804027) today! 23 | 24 | https://www.packtpub.com/ 25 | 26 | ## Instructions and Navigations 27 | All of the code is organized into folders. For example, 28 | 29 | The code will look like the following: 30 | ``` 31 | In [ ]: 32 | from sklearn.decomposition import PCA 33 | 34 | pca = PCA(n_components=2) 35 | pca.fit(X_data) 36 | X_2D = pca.transform(X_data) 37 | data_df['PCA1'] = X_2D[:, 0] 38 | data_df['PCA2'] = X_2D[:, 1] 39 | ``` 40 | 41 | **Following is what you need for this book:** 42 | If you’re a cybersecurity professional or ethical hacker who wants to build intelligent systems using the power of machine learning and AI, you’ll find this book useful. Familiarity with cybersecurity concepts and knowledge of Python programming is essential to get the most out of this book. 43 | 44 | With the following software and hardware list you can run all code files present in the book (Chapter 1-11). 45 | 46 | ### Software and Hardware List 47 | 48 | | Chapter | Software required | OS required | 49 | | -------- | ------------------------------------------------------| -----------------------------------| 50 | | 1-10 | Python 3.7, Jupyter Notebook | Windows, Mac OS X, and Linux (Any) | 51 | | 7 | Python 3.7, Jupyter Notebook, IBM Watson | Windows, Mac OS X, and Linux (Any) | 52 | 53 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](https://static.packt-cdn.com/downloads/9781789804027_ColorImages.pdf). 54 | 55 | 56 | ### Related products 57 | * Hands-On Machine Learning for Cybersecurity [[Packt]](https://www.packtpub.com/in/big-data-and-business-intelligence/hands-machine-learning-cybersecurity?utm_source=github&utm_medium=repository&utm_campaign=9781788992282) [[Amazon]](https://www.amazon.com/dp/B07FNVYSN3) 58 | 59 | * Hands-On Cybersecurity with Blockchain [[Packt]](https://www.packtpub.com/networking-and-servers/hands-cybersecurity-blockchain?utm_source=github&utm_medium=repository&utm_campaign=9781788990189) [[Amazon]](https://www.amazon.com/dp/B07DTB3SLX) 60 | 61 | ## Errata 62 | * Page 37 (line 2): **conda update –all** _should be_ **conda update ––all** 63 | 64 | ## Get to Know the Author 65 | **Alessandro Parisi** 66 | has been an IT professional for over 20 years, acquiring significant experience as a security data scientist, and as an AI cybersecurity and blockchain specialist. He has experience of operating within organizational and decisional contexts characterized by high complexity. Over the years, he has helped companies to adopt AI and blockchain DLT technologies as strategic tools in protecting sensitive corporate assets. He holds an MSc in economics and statistics. 67 | 68 | 69 | ### Suggestions and Feedback 70 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSdy7dATC6QmEL81FIUuymZ0Wy9vH1jHkvpY57OiMeKGqib_Ow/viewform) if you have any feedback or suggestions. 71 | ### Download a free PDF 72 | 73 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
74 |

https://packt.link/free-ebook/9781789804027

-------------------------------------------------------------------------------- /Chapter08/facenet_fgsm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script name: facenet_fgsm.py 3 | Reproduced for reader's convenience from the original code available at: 4 | https://github.com/tensorflow/cleverhans/blob/master/examples/facenet_adversarial_faces/facenet_fgsm.py 5 | Released under MIT LICENSE: 6 | https://github.com/tensorflow/cleverhans/blob/master/LICENSE 7 | """ 8 | 9 | import facenet 10 | 11 | import tensorflow as tf 12 | import numpy as np 13 | from cleverhans.model import Model 14 | from cleverhans.attacks import FastGradientMethod 15 | 16 | import set_loader 17 | 18 | 19 | class InceptionResnetV1Model(Model): 20 | model_path = "models/facenet/20170512-110547/20170512-110547.pb" 21 | 22 | def __init__(self): 23 | super(InceptionResnetV1Model, self).__init__(scope='model') 24 | 25 | # Load Facenet CNN 26 | facenet.load_model(self.model_path) 27 | # Save input and output tensors references 28 | graph = tf.get_default_graph() 29 | self.face_input = graph.get_tensor_by_name("input:0") 30 | self.embedding_output = graph.get_tensor_by_name("embeddings:0") 31 | 32 | def convert_to_classifier(self): 33 | # Create victim_embedding placeholder 34 | self.victim_embedding_input = tf.placeholder( 35 | tf.float32, 36 | shape=(None, 128)) 37 | 38 | # Squared Euclidean Distance between embeddings 39 | distance = tf.reduce_sum( 40 | tf.square(self.embedding_output - self.victim_embedding_input), 41 | axis=1) 42 | 43 | # Convert distance to a softmax vector 44 | # 0.99 out of 4 is the distance threshold for the Facenet CNN 45 | threshold = 0.99 46 | score = tf.where( 47 | distance > threshold, 48 | 0.5 + ((distance - threshold) * 0.5) / (4.0 - threshold), 49 | 0.5 * distance / threshold) 50 | reverse_score = 1.0 - score 51 | self.softmax_output = tf.transpose(tf.stack([reverse_score, score])) 52 | 53 | # Save softmax layer 54 | self.layer_names = [] 55 | self.layers = [] 56 | self.layers.append(self.softmax_output) 57 | self.layer_names.append('probs') 58 | 59 | def fprop(self, x, set_ref=False): 60 | return dict(zip(self.layer_names, self.layers)) 61 | 62 | 63 | with tf.Graph().as_default(): 64 | with tf.Session() as sess: 65 | # Load model 66 | model = InceptionResnetV1Model() 67 | # Convert to classifier 68 | model.convert_to_classifier() 69 | 70 | # Load pairs of faces and their labels in one-hot encoding 71 | faces1, faces2, labels = set_loader.load_testset(1000) 72 | 73 | # Create victims' embeddings using Facenet itself 74 | graph = tf.get_default_graph() 75 | phase_train_placeholder = graph.get_tensor_by_name("phase_train:0") 76 | feed_dict = {model.face_input: faces2, 77 | phase_train_placeholder: False} 78 | victims_embeddings = sess.run( 79 | model.embedding_output, feed_dict=feed_dict) 80 | 81 | # Define FGSM for the model 82 | steps = 1 83 | eps = 0.01 84 | alpha = eps / steps 85 | fgsm = FastGradientMethod(model) 86 | fgsm_params = {'eps': alpha, 87 | 'clip_min': 0., 88 | 'clip_max': 1.} 89 | adv_x = fgsm.generate(model.face_input, **fgsm_params) 90 | 91 | # Run FGSM 92 | adv = faces1 93 | for i in range(steps): 94 | print("FGSM step " + str(i + 1)) 95 | feed_dict = {model.face_input: adv, 96 | model.victim_embedding_input: victims_embeddings, 97 | phase_train_placeholder: False} 98 | adv = sess.run(adv_x, feed_dict=feed_dict) 99 | 100 | # Test accuracy of the model 101 | batch_size = graph.get_tensor_by_name("batch_size:0") 102 | 103 | feed_dict = {model.face_input: faces1, 104 | model.victim_embedding_input: victims_embeddings, 105 | phase_train_placeholder: False, 106 | batch_size: 64} 107 | real_labels = sess.run(model.softmax_output, feed_dict=feed_dict) 108 | 109 | accuracy = np.mean( 110 | (np.argmax(labels, axis=-1)) == (np.argmax(real_labels, axis=-1)) 111 | ) 112 | print('Accuracy: ' + str(accuracy * 100) + '%') 113 | 114 | # Test accuracy against adversarial examples 115 | feed_dict = {model.face_input: adv, 116 | model.victim_embedding_input: victims_embeddings, 117 | phase_train_placeholder: False, 118 | batch_size: 64} 119 | adversarial_labels = sess.run( 120 | model.softmax_output, feed_dict=feed_dict) 121 | 122 | same_faces_index = np.where((np.argmax(labels, axis=-1) == 0)) 123 | different_faces_index = np.where((np.argmax(labels, axis=-1) == 1)) 124 | 125 | accuracy = np.mean( 126 | (np.argmax(labels[same_faces_index], axis=-1)) == 127 | (np.argmax(adversarial_labels[same_faces_index], axis=-1)) 128 | ) 129 | print('Accuracy against adversarial examples for ' 130 | + 'same person faces (dodging): ' 131 | + str(accuracy * 100) 132 | + '%') 133 | 134 | accuracy = np.mean( 135 | (np.argmax(labels[different_faces_index], axis=-1)) == ( 136 | np.argmax(adversarial_labels[different_faces_index], axis=-1)) 137 | ) 138 | print('Accuracy against adversarial examples for ' 139 | + 'different people faces (impersonation): ' 140 | + str(accuracy * 100) 141 | + '%') 142 | 143 | -------------------------------------------------------------------------------- /Chapter03/sources/Bayesian Spam Detector with Nltk.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-02-20 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.16.1\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import matplotlib.pyplot as plt\n", 41 | "import csv\n", 42 | "from textblob import TextBlob\n", 43 | "import pandas\n", 44 | "import sklearn\n", 45 | "import numpy as np\n", 46 | "\n", 47 | "import nltk\n", 48 | "# nltk.download('popular')\n", 49 | "# nltk.download('punkt')\n", 50 | "# nltk.download('averaged_perceptron_tagger')\n", 51 | "# nltk.download('wordnet')\n", 52 | "\n", 53 | "from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer\n", 54 | "from sklearn.naive_bayes import MultinomialNB\n", 55 | "from sklearn.metrics import classification_report, accuracy_score\n", 56 | "from sklearn.model_selection import train_test_split \n", 57 | "\n", 58 | "from defs import get_tokens\n", 59 | "from defs import get_lemmas" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 3, 65 | "metadata": { 66 | "collapsed": true 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "sms = pandas.read_csv('../datasets/sms_spam_no_header.csv', sep=',', names=[\"type\", \"text\"])" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 4, 76 | "metadata": { 77 | "collapsed": true 78 | }, 79 | "outputs": [], 80 | "source": [ 81 | "text_train, text_test, type_train, type_test = train_test_split(sms['text'], sms['type'], test_size=0.3)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 5, 87 | "metadata": { 88 | "collapsed": true 89 | }, 90 | "outputs": [], 91 | "source": [ 92 | "bow = CountVectorizer(analyzer=get_lemmas).fit(text_train)" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 6, 98 | "metadata": { 99 | "collapsed": true 100 | }, 101 | "outputs": [], 102 | "source": [ 103 | "sms_bow = bow.transform(text_train)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 7, 109 | "metadata": { 110 | "collapsed": true 111 | }, 112 | "outputs": [], 113 | "source": [ 114 | "tfidf = TfidfTransformer().fit(sms_bow)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 8, 120 | "metadata": { 121 | "collapsed": true 122 | }, 123 | "outputs": [], 124 | "source": [ 125 | "sms_tfidf = tfidf.transform(sms_bow)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 9, 131 | "metadata": { 132 | "collapsed": true 133 | }, 134 | "outputs": [], 135 | "source": [ 136 | "spam_detector = MultinomialNB().fit(sms_tfidf, type_train)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 10, 142 | "metadata": {}, 143 | "outputs": [ 144 | { 145 | "name": "stdout", 146 | "output_type": "stream", 147 | "text": [ 148 | "predicted: ham\n", 149 | "expected: ham\n" 150 | ] 151 | } 152 | ], 153 | "source": [ 154 | "msg = sms['text'][25]\n", 155 | "msg_bow = bow.transform([msg])\n", 156 | "msg_tfidf = tfidf.transform(msg_bow)\n", 157 | "\n", 158 | "print ('predicted:', spam_detector.predict(msg_tfidf)[0])\n", 159 | "print ('expected:', sms.type[25])" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 11, 165 | "metadata": { 166 | "collapsed": true 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "predictions = spam_detector.predict(sms_tfidf)" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 12, 176 | "metadata": {}, 177 | "outputs": [ 178 | { 179 | "name": "stdout", 180 | "output_type": "stream", 181 | "text": [ 182 | "accuracy 0.789797487823635\n" 183 | ] 184 | } 185 | ], 186 | "source": [ 187 | "print ('accuracy', accuracy_score(sms['type'][:len(predictions)], predictions))" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": 13, 193 | "metadata": {}, 194 | "outputs": [ 195 | { 196 | "name": "stdout", 197 | "output_type": "stream", 198 | "text": [ 199 | " precision recall f1-score support\n", 200 | "\n", 201 | " ham 0.87 0.90 0.88 3382\n", 202 | " spam 0.13 0.10 0.11 519\n", 203 | "\n", 204 | " micro avg 0.79 0.79 0.79 3901\n", 205 | " macro avg 0.50 0.50 0.50 3901\n", 206 | "weighted avg 0.77 0.79 0.78 3901\n", 207 | "\n" 208 | ] 209 | } 210 | ], 211 | "source": [ 212 | "print (classification_report(sms['type'][:len(predictions)], predictions))" 213 | ] 214 | } 215 | ], 216 | "metadata": { 217 | "kernelspec": { 218 | "display_name": "Py35", 219 | "language": "python", 220 | "name": "py35" 221 | }, 222 | "language_info": { 223 | "codemirror_mode": { 224 | "name": "ipython", 225 | "version": 3 226 | }, 227 | "file_extension": ".py", 228 | "mimetype": "text/x-python", 229 | "name": "python", 230 | "nbconvert_exporter": "python", 231 | "pygments_lexer": "ipython3", 232 | "version": "3.5.4" 233 | } 234 | }, 235 | "nbformat": 4, 236 | "nbformat_minor": 2 237 | } 238 | -------------------------------------------------------------------------------- /Chapter08/generative_adversarial_network.py: -------------------------------------------------------------------------------- 1 | """ 2 | Code adapted from the original available at the link: 3 | https://github.com/eriklindernoren/ML-From-Scratch/blob/master/mlfromscratch/unsupervised_learning/generative_adversarial_network.py 4 | MIT License: https://github.com/eriklindernoren/ML-From-Scratch/blob/master/LICENSE 5 | """ 6 | 7 | from __future__ import print_function, division 8 | from sklearn import datasets 9 | import math 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import progressbar 13 | 14 | # from sklearn.datasets import fetch_mldata 15 | from sklearn.datasets import fetch_openml 16 | from mlxtend.data import loadlocal_mnist 17 | 18 | from mlfromscratch.deep_learning.optimizers import Adam 19 | from mlfromscratch.deep_learning.loss_functions import CrossEntropy 20 | from mlfromscratch.deep_learning.layers import Dense, Dropout, Flatten, Activation, Reshape, BatchNormalization 21 | from mlfromscratch.deep_learning import NeuralNetwork 22 | 23 | """ 24 | def sort_by_target(mnist): 25 | reorder_train = np.array(sorted([(target, i) for i, target in enumerate(mnist.target[:60000])]))[:, 1] 26 | reorder_test = np.array(sorted([(target, i) for i, target in enumerate(mnist.target[60000:])]))[:, 1] 27 | mnist.data[:60000] = mnist.data[reorder_train] 28 | mnist.target[:60000] = mnist.target[reorder_train] 29 | mnist.data[60000:] = mnist.data[reorder_test + 60000] 30 | mnist.target[60000:] = mnist.target[reorder_test + 60000] 31 | """ 32 | 33 | class GAN(): 34 | """A Generative Adversarial Network with deep fully-connected neural nets as 35 | Generator and Discriminator. 36 | 37 | Training Data: MNIST Handwritten Digits (28x28 images) 38 | """ 39 | def __init__(self): 40 | self.img_rows = 28 41 | self.img_cols = 28 42 | self.img_dim = self.img_rows * self.img_cols 43 | self.latent_dim = 100 44 | 45 | optimizer = Adam(learning_rate=0.0002, b1=0.5) 46 | loss_function = CrossEntropy 47 | 48 | # Build the discriminator 49 | self.discriminator = self.build_discriminator(optimizer, loss_function) 50 | 51 | # Build the generator 52 | self.generator = self.build_generator(optimizer, loss_function) 53 | 54 | # Build the combined model 55 | self.combined = NeuralNetwork(optimizer=optimizer, loss=loss_function) 56 | self.combined.layers.extend(self.generator.layers) 57 | self.combined.layers.extend(self.discriminator.layers) 58 | 59 | print () 60 | self.generator.summary(name="Generator") 61 | self.discriminator.summary(name="Discriminator") 62 | 63 | def build_generator(self, optimizer, loss_function): 64 | 65 | model = NeuralNetwork(optimizer=optimizer, loss=loss_function) 66 | 67 | model.add(Dense(256, input_shape=(self.latent_dim,))) 68 | model.add(Activation('leaky_relu')) 69 | model.add(BatchNormalization(momentum=0.8)) 70 | model.add(Dense(512)) 71 | model.add(Activation('leaky_relu')) 72 | model.add(BatchNormalization(momentum=0.8)) 73 | model.add(Dense(1024)) 74 | model.add(Activation('leaky_relu')) 75 | model.add(BatchNormalization(momentum=0.8)) 76 | model.add(Dense(self.img_dim)) 77 | model.add(Activation('tanh')) 78 | 79 | return model 80 | 81 | def build_discriminator(self, optimizer, loss_function): 82 | 83 | model = NeuralNetwork(optimizer=optimizer, loss=loss_function) 84 | 85 | model.add(Dense(512, input_shape=(self.img_dim,))) 86 | model.add(Activation('leaky_relu')) 87 | model.add(Dropout(0.5)) 88 | model.add(Dense(256)) 89 | model.add(Activation('leaky_relu')) 90 | model.add(Dropout(0.5)) 91 | model.add(Dense(2)) 92 | model.add(Activation('softmax')) 93 | 94 | return model 95 | 96 | def train(self, n_epochs, batch_size=128, save_interval=50): 97 | 98 | # mnist = fetch_mldata('MNIST original') 99 | 100 | """ 101 | mnist = fetch_openml('mnist_784', version=1, cache=False) 102 | mnist.target = mnist.target.astype(np.int8) # fetch_openml() returns targets as strings 103 | sort_by_target(mnist) # fetch_openml() returns an unsorted dataset 104 | 105 | X = mnist.data 106 | y = mnist.target 107 | """ 108 | 109 | X, y = loadlocal_mnist(images_path='./MNIST/train-images.idx3-ubyte', labels_path='./MNIST/train-labels.idx1-ubyte') 110 | 111 | 112 | # Rescale [-1, 1] 113 | X = (X.astype(np.float32) - 127.5) / 127.5 114 | 115 | half_batch = int(batch_size / 2) 116 | 117 | for epoch in range(n_epochs): 118 | 119 | # --------------------- 120 | # Train Discriminator 121 | # --------------------- 122 | 123 | self.discriminator.set_trainable(True) 124 | 125 | # Select a random half batch of images 126 | idx = np.random.randint(0, X.shape[0], half_batch) 127 | imgs = X[idx] 128 | 129 | # Sample noise to use as generator input 130 | noise = np.random.normal(0, 1, (half_batch, self.latent_dim)) 131 | 132 | # Generate a half batch of images 133 | gen_imgs = self.generator.predict(noise) 134 | 135 | # Valid = [1, 0], Fake = [0, 1] 136 | valid = np.concatenate((np.ones((half_batch, 1)), np.zeros((half_batch, 1))), axis=1) 137 | fake = np.concatenate((np.zeros((half_batch, 1)), np.ones((half_batch, 1))), axis=1) 138 | 139 | # Train the discriminator 140 | d_loss_real, d_acc_real = self.discriminator.train_on_batch(imgs, valid) 141 | d_loss_fake, d_acc_fake = self.discriminator.train_on_batch(gen_imgs, fake) 142 | d_loss = 0.5 * (d_loss_real + d_loss_fake) 143 | d_acc = 0.5 * (d_acc_real + d_acc_fake) 144 | 145 | 146 | # --------------------- 147 | # Train Generator 148 | # --------------------- 149 | 150 | # We only want to train the generator for the combined model 151 | self.discriminator.set_trainable(False) 152 | 153 | # Sample noise and use as generator input 154 | noise = np.random.normal(0, 1, (batch_size, self.latent_dim)) 155 | 156 | # The generator wants the discriminator to label the generated samples as valid 157 | valid = np.concatenate((np.ones((batch_size, 1)), np.zeros((batch_size, 1))), axis=1) 158 | 159 | # Train the generator 160 | g_loss, g_acc = self.combined.train_on_batch(noise, valid) 161 | 162 | # Display the progress 163 | print ("%d [D loss: %f, acc: %.2f%%] [G loss: %f, acc: %.2f%%]" % (epoch, d_loss, 100*d_acc, g_loss, 100*g_acc)) 164 | 165 | # If at save interval => save generated image samples 166 | if epoch % save_interval == 0: 167 | self.save_imgs(epoch) 168 | 169 | def save_imgs(self, epoch): 170 | r, c = 5, 5 # Grid size 171 | noise = np.random.normal(0, 1, (r * c, self.latent_dim)) 172 | # Generate images and reshape to image shape 173 | gen_imgs = self.generator.predict(noise).reshape((-1, self.img_rows, self.img_cols)) 174 | 175 | # Rescale images 0 - 1 176 | gen_imgs = 0.5 * gen_imgs + 0.5 177 | 178 | fig, axs = plt.subplots(r, c) 179 | plt.suptitle("Generative Adversarial Network") 180 | cnt = 0 181 | for i in range(r): 182 | for j in range(c): 183 | axs[i,j].imshow(gen_imgs[cnt,:,:], cmap='gray') 184 | axs[i,j].axis('off') 185 | cnt += 1 186 | fig.savefig("mnist_%d.png" % epoch) 187 | plt.close() 188 | 189 | 190 | if __name__ == '__main__': 191 | gan = GAN() 192 | gan.train(n_epochs=200000, batch_size=64, save_interval=400) 193 | 194 | 195 | -------------------------------------------------------------------------------- /Chapter08/MalGAN_v2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script name: MalGAN_v2.py 3 | Reproduced for reader's convenience from the original code available at: 4 | https://github.com/yanminglai/Malware-GAN/blob/master/MalGAN_v2.py 5 | Released under GPL 3.0 LICENSE: https://github.com/yanminglai/Malware-GAN/blob/master/LICENSE 6 | """ 7 | 8 | from keras.layers import Input, Dense, Activation 9 | from keras.layers.merge import Maximum, Concatenate 10 | from keras.models import Model 11 | from keras.optimizers import Adam 12 | from numpy.lib import format 13 | from sklearn.ensemble import RandomForestClassifier 14 | from sklearn import linear_model, svm 15 | from sklearn.model_selection import train_test_split 16 | import matplotlib.pyplot as plt 17 | from load_data import * 18 | import numpy as np 19 | 20 | class MalGAN(): 21 | def __init__(self): 22 | self.apifeature_dims = 74 23 | self.z_dims = 10 24 | self.hide_layers = 256 25 | self.generator_layers = [self.apifeature_dims+self.z_dims, self.hide_layers, self.apifeature_dims] 26 | self.substitute_detector_layers = [self.apifeature_dims, self.hide_layers, 1] 27 | self.blackbox = 'RF' 28 | optimizer = Adam(lr=0.001) 29 | 30 | # Build and Train blackbox_detector 31 | self.blackbox_detector = self.build_blackbox_detector() 32 | 33 | # Build and compile the substitute_detector 34 | self.substitute_detector = self.build_substitute_detector() 35 | self.substitute_detector.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy']) 36 | 37 | # Build the generator 38 | self.generator = self.build_generator() 39 | 40 | # The generator takes malware and noise as input and generates adversarial malware examples 41 | example = Input(shape=(self.apifeature_dims,)) 42 | noise = Input(shape=(self.z_dims,)) 43 | input = [example, noise] 44 | malware_examples = self.generator(input) 45 | 46 | # For the combined model we will only train the generator 47 | self.substitute_detector.trainable = False 48 | 49 | # The discriminator takes generated images as input and determines validity 50 | validity = self.substitute_detector(malware_examples) 51 | 52 | # The combined model (stacked generator and substitute_detector) 53 | # Trains the generator to fool the discriminator 54 | self.combined = Model(input, validity) 55 | self.combined.compile(loss='binary_crossentropy', optimizer=optimizer) 56 | 57 | def build_blackbox_detector(self): 58 | 59 | if self.blackbox is 'RF': 60 | blackbox_detector = RandomForestClassifier(n_estimators=50, max_depth=5, random_state=1) 61 | return blackbox_detector 62 | 63 | def build_generator(self): 64 | 65 | example = Input(shape=(self.apifeature_dims,)) 66 | noise = Input(shape=(self.z_dims,)) 67 | x = Concatenate(axis=1)([example, noise]) 68 | for dim in self.generator_layers[1:]: 69 | x = Dense(dim)(x) 70 | x = Activation(activation='sigmoid')(x) 71 | x = Maximum()([example, x]) 72 | generator = Model([example, noise], x, name='generator') 73 | generator.summary() 74 | return generator 75 | 76 | def build_substitute_detector(self): 77 | 78 | input = Input(shape=(self.substitute_detector_layers[0],)) 79 | x = input 80 | for dim in self.substitute_detector_layers[1:]: 81 | x = Dense(dim)(x) 82 | x = Activation(activation='sigmoid')(x) 83 | substitute_detector = Model(input, x, name='substitute_detector') 84 | substitute_detector.summary() 85 | return substitute_detector 86 | 87 | def load_data(self, filename): 88 | 89 | data = load(filename) 90 | xmal, ymal, xben, yben = data['xmal'], data['ymal'], data['xben'], data['yben'] 91 | # np.savez('mydata.npz', xmal=xmal, ymal=ymal, xben=xben, yben=yben, 92 | # xmal_=xmal, ymal_=ymal, xben_=xmal, yben_=ymal, t=8) 93 | return (xmal, ymal), (xben, yben) 94 | 95 | def train(self, epochs, batch_size=32): 96 | 97 | # Load the dataset 98 | (xmal, ymal), (xben, yben) = self.load_data('mydata.npz') 99 | xtrain_mal, xtest_mal, ytrain_mal, ytest_mal = train_test_split(xmal, ymal, test_size=0.20) 100 | xtrain_ben, xtest_ben, ytrain_ben, ytest_ben = train_test_split(xben, yben, test_size=0.20) 101 | 102 | # Train blackbox_detctor 103 | self.blackbox_detector.fit(np.concatenate([xmal, xben]), 104 | np.concatenate([ymal, yben])) 105 | 106 | ytrain_ben_blackbox = self.blackbox_detector.predict(xtrain_ben) 107 | Original_Train_TPR = self.blackbox_detector.score(xtrain_mal, ytrain_mal) 108 | Original_Test_TPR = self.blackbox_detector.score(xtest_mal, ytest_mal) 109 | Train_TPR, Test_TPR = [Original_Train_TPR], [Original_Test_TPR] 110 | best_TPR = 1.0 111 | for epoch in range(epochs): 112 | 113 | for step in range(xtrain_mal.shape[0] // batch_size): 114 | # --------------------- 115 | # Train substitute_detector 116 | # --------------------- 117 | 118 | # Select a random batch of malware examples 119 | idx = np.random.randint(0, xtrain_mal.shape[0], batch_size) 120 | xmal_batch = xtrain_mal[idx] 121 | noise = np.random.uniform(0, 1, (batch_size, self.z_dims)) #noise as random uniform 122 | idx = np.random.randint(0, xmal_batch.shape[0], batch_size) 123 | xben_batch = xtrain_ben[idx] 124 | yben_batch = ytrain_ben_blackbox[idx] 125 | 126 | # Generate a batch of new malware examples 127 | gen_examples = self.generator.predict([xmal_batch, noise]) 128 | ymal_batch = self.blackbox_detector.predict(np.ones(gen_examples.shape)*(gen_examples > 0.5)) 129 | 130 | # Train the substitute_detector 131 | d_loss_real = self.substitute_detector.train_on_batch(gen_examples, ymal_batch) 132 | d_loss_fake = self.substitute_detector.train_on_batch(xben_batch, yben_batch) 133 | d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) 134 | 135 | # --------------------- 136 | # Train Generator 137 | # --------------------- 138 | 139 | idx = np.random.randint(0, xtrain_mal.shape[0], batch_size) 140 | xmal_batch = xtrain_mal[idx] 141 | noise = np.random.uniform(0, 1, (batch_size, self.z_dims)) 142 | 143 | # Train the generator 144 | g_loss = self.combined.train_on_batch([xmal_batch, noise], np.zeros((batch_size, 1))) 145 | 146 | # Compute Train TPR 147 | noise = np.random.uniform(0, 1, (xtrain_mal.shape[0], self.z_dims)) 148 | gen_examples = self.generator.predict([xtrain_mal, noise]) 149 | TPR = self.blackbox_detector.score(np.ones(gen_examples.shape) * (gen_examples > 0.5), ytrain_mal) 150 | Train_TPR.append(TPR) 151 | 152 | # Compute Test TPR 153 | noise = np.random.uniform(0, 1, (xtest_mal.shape[0], self.z_dims)) 154 | gen_examples = self.generator.predict([xtest_mal, noise]) 155 | TPR = self.blackbox_detector.score(np.ones(gen_examples.shape) * (gen_examples > 0.5), ytest_mal) 156 | Test_TPR.append(TPR) 157 | 158 | # Save best model 159 | if TPR < best_TPR: 160 | self.combined.save_weights('saves/malgan.h5') 161 | best_TPR = TPR 162 | 163 | # Plot the progress 164 | print("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss)) 165 | 166 | print('Original_Train_TPR: {0}, Adver_Train_TPR: {1}'.format(Original_Train_TPR, Train_TPR[-1])) 167 | print('Original_Test_TPR: {0}, Adver_Test_TPR: {1}'.format(Original_Test_TPR, Test_TPR[-1])) 168 | 169 | # Plot TPR 170 | plt.figure() 171 | plt.plot(range(len(Train_TPR)), Train_TPR, c='r', label='Training Set', linewidth=2) 172 | plt.plot(range(len(Test_TPR)), Test_TPR, c='g', linestyle='--', label='Validation Set', linewidth=2) 173 | plt.xlabel('Epoch') 174 | plt.ylabel('TPR') 175 | plt.legend() 176 | plt.savefig('saves/Epoch_TPR.png') 177 | plt.show() 178 | 179 | if __name__ == '__main__': 180 | malgan = MalGAN() 181 | malgan.train(epochs=50, batch_size=64) 182 | 183 | -------------------------------------------------------------------------------- /Chapter01/datasets/clustering.csv: -------------------------------------------------------------------------------- 1 | 178,13,class_0,class_1,class_2 2 | 14.23,1.71,2.43,15.6,127,2.8,3.06,0.28,2.29,5.64,1.04,3.92,1065,0 3 | 13.2,1.78,2.14,11.2,100,2.65,2.76,0.26,1.28,4.38,1.05,3.4,1050,0 4 | 13.16,2.36,2.67,18.6,101,2.8,3.24,0.3,2.81,5.68,1.03,3.17,1185,0 5 | 14.37,1.95,2.5,16.8,113,3.85,3.49,0.24,2.18,7.8,0.86,3.45,1480,0 6 | 13.24,2.59,2.87,21,118,2.8,2.69,0.39,1.82,4.32,1.04,2.93,735,0 7 | 14.2,1.76,2.45,15.2,112,3.27,3.39,0.34,1.97,6.75,1.05,2.85,1450,0 8 | 14.39,1.87,2.45,14.6,96,2.5,2.52,0.3,1.98,5.25,1.02,3.58,1290,0 9 | 14.06,2.15,2.61,17.6,121,2.6,2.51,0.31,1.25,5.05,1.06,3.58,1295,0 10 | 14.83,1.64,2.17,14,97,2.8,2.98,0.29,1.98,5.2,1.08,2.85,1045,0 11 | 13.86,1.35,2.27,16,98,2.98,3.15,0.22,1.85,7.22,1.01,3.55,1045,0 12 | 14.1,2.16,2.3,18,105,2.95,3.32,0.22,2.38,5.75,1.25,3.17,1510,0 13 | 14.12,1.48,2.32,16.8,95,2.2,2.43,0.26,1.57,5,1.17,2.82,1280,0 14 | 13.75,1.73,2.41,16,89,2.6,2.76,0.29,1.81,5.6,1.15,2.9,1320,0 15 | 14.75,1.73,2.39,11.4,91,3.1,3.69,0.43,2.81,5.4,1.25,2.73,1150,0 16 | 14.38,1.87,2.38,12,102,3.3,3.64,0.29,2.96,7.5,1.2,3,1547,0 17 | 13.63,1.81,2.7,17.2,112,2.85,2.91,0.3,1.46,7.3,1.28,2.88,1310,0 18 | 14.3,1.92,2.72,20,120,2.8,3.14,0.33,1.97,6.2,1.07,2.65,1280,0 19 | 13.83,1.57,2.62,20,115,2.95,3.4,0.4,1.72,6.6,1.13,2.57,1130,0 20 | 14.19,1.59,2.48,16.5,108,3.3,3.93,0.32,1.86,8.7,1.23,2.82,1680,0 21 | 13.64,3.1,2.56,15.2,116,2.7,3.03,0.17,1.66,5.1,0.96,3.36,845,0 22 | 14.06,1.63,2.28,16,126,3,3.17,0.24,2.1,5.65,1.09,3.71,780,0 23 | 12.93,3.8,2.65,18.6,102,2.41,2.41,0.25,1.98,4.5,1.03,3.52,770,0 24 | 13.71,1.86,2.36,16.6,101,2.61,2.88,0.27,1.69,3.8,1.11,4,1035,0 25 | 12.85,1.6,2.52,17.8,95,2.48,2.37,0.26,1.46,3.93,1.09,3.63,1015,0 26 | 13.5,1.81,2.61,20,96,2.53,2.61,0.28,1.66,3.52,1.12,3.82,845,0 27 | 13.05,2.05,3.22,25,124,2.63,2.68,0.47,1.92,3.58,1.13,3.2,830,0 28 | 13.39,1.77,2.62,16.1,93,2.85,2.94,0.34,1.45,4.8,0.92,3.22,1195,0 29 | 13.3,1.72,2.14,17,94,2.4,2.19,0.27,1.35,3.95,1.02,2.77,1285,0 30 | 13.87,1.9,2.8,19.4,107,2.95,2.97,0.37,1.76,4.5,1.25,3.4,915,0 31 | 14.02,1.68,2.21,16,96,2.65,2.33,0.26,1.98,4.7,1.04,3.59,1035,0 32 | 13.73,1.5,2.7,22.5,101,3,3.25,0.29,2.38,5.7,1.19,2.71,1285,0 33 | 13.58,1.66,2.36,19.1,106,2.86,3.19,0.22,1.95,6.9,1.09,2.88,1515,0 34 | 13.68,1.83,2.36,17.2,104,2.42,2.69,0.42,1.97,3.84,1.23,2.87,990,0 35 | 13.76,1.53,2.7,19.5,132,2.95,2.74,0.5,1.35,5.4,1.25,3,1235,0 36 | 13.51,1.8,2.65,19,110,2.35,2.53,0.29,1.54,4.2,1.1,2.87,1095,0 37 | 13.48,1.81,2.41,20.5,100,2.7,2.98,0.26,1.86,5.1,1.04,3.47,920,0 38 | 13.28,1.64,2.84,15.5,110,2.6,2.68,0.34,1.36,4.6,1.09,2.78,880,0 39 | 13.05,1.65,2.55,18,98,2.45,2.43,0.29,1.44,4.25,1.12,2.51,1105,0 40 | 13.07,1.5,2.1,15.5,98,2.4,2.64,0.28,1.37,3.7,1.18,2.69,1020,0 41 | 14.22,3.99,2.51,13.2,128,3,3.04,0.2,2.08,5.1,0.89,3.53,760,0 42 | 13.56,1.71,2.31,16.2,117,3.15,3.29,0.34,2.34,6.13,0.95,3.38,795,0 43 | 13.41,3.84,2.12,18.8,90,2.45,2.68,0.27,1.48,4.28,0.91,3,1035,0 44 | 13.88,1.89,2.59,15,101,3.25,3.56,0.17,1.7,5.43,0.88,3.56,1095,0 45 | 13.24,3.98,2.29,17.5,103,2.64,2.63,0.32,1.66,4.36,0.82,3,680,0 46 | 13.05,1.77,2.1,17,107,3,3,0.28,2.03,5.04,0.88,3.35,885,0 47 | 14.21,4.04,2.44,18.9,111,2.85,2.65,0.3,1.25,5.24,0.87,3.33,1080,0 48 | 14.38,3.59,2.28,16,102,3.25,3.17,0.27,2.19,4.9,1.04,3.44,1065,0 49 | 13.9,1.68,2.12,16,101,3.1,3.39,0.21,2.14,6.1,0.91,3.33,985,0 50 | 14.1,2.02,2.4,18.8,103,2.75,2.92,0.32,2.38,6.2,1.07,2.75,1060,0 51 | 13.94,1.73,2.27,17.4,108,2.88,3.54,0.32,2.08,8.9,1.12,3.1,1260,0 52 | 13.05,1.73,2.04,12.4,92,2.72,3.27,0.17,2.91,7.2,1.12,2.91,1150,0 53 | 13.83,1.65,2.6,17.2,94,2.45,2.99,0.22,2.29,5.6,1.24,3.37,1265,0 54 | 13.82,1.75,2.42,14,111,3.88,3.74,0.32,1.87,7.05,1.01,3.26,1190,0 55 | 13.77,1.9,2.68,17.1,115,3,2.79,0.39,1.68,6.3,1.13,2.93,1375,0 56 | 13.74,1.67,2.25,16.4,118,2.6,2.9,0.21,1.62,5.85,0.92,3.2,1060,0 57 | 13.56,1.73,2.46,20.5,116,2.96,2.78,0.2,2.45,6.25,0.98,3.03,1120,0 58 | 14.22,1.7,2.3,16.3,118,3.2,3,0.26,2.03,6.38,0.94,3.31,970,0 59 | 13.29,1.97,2.68,16.8,102,3,3.23,0.31,1.66,6,1.07,2.84,1270,0 60 | 13.72,1.43,2.5,16.7,108,3.4,3.67,0.19,2.04,6.8,0.89,2.87,1285,0 61 | 12.37,0.94,1.36,10.6,88,1.98,0.57,0.28,0.42,1.95,1.05,1.82,520,1 62 | 12.33,1.1,2.28,16,101,2.05,1.09,0.63,0.41,3.27,1.25,1.67,680,1 63 | 12.64,1.36,2.02,16.8,100,2.02,1.41,0.53,0.62,5.75,0.98,1.59,450,1 64 | 13.67,1.25,1.92,18,94,2.1,1.79,0.32,0.73,3.8,1.23,2.46,630,1 65 | 12.37,1.13,2.16,19,87,3.5,3.1,0.19,1.87,4.45,1.22,2.87,420,1 66 | 12.17,1.45,2.53,19,104,1.89,1.75,0.45,1.03,2.95,1.45,2.23,355,1 67 | 12.37,1.21,2.56,18.1,98,2.42,2.65,0.37,2.08,4.6,1.19,2.3,678,1 68 | 13.11,1.01,1.7,15,78,2.98,3.18,0.26,2.28,5.3,1.12,3.18,502,1 69 | 12.37,1.17,1.92,19.6,78,2.11,2,0.27,1.04,4.68,1.12,3.48,510,1 70 | 13.34,0.94,2.36,17,110,2.53,1.3,0.55,0.42,3.17,1.02,1.93,750,1 71 | 12.21,1.19,1.75,16.8,151,1.85,1.28,0.14,2.5,2.85,1.28,3.07,718,1 72 | 12.29,1.61,2.21,20.4,103,1.1,1.02,0.37,1.46,3.05,0.906,1.82,870,1 73 | 13.86,1.51,2.67,25,86,2.95,2.86,0.21,1.87,3.38,1.36,3.16,410,1 74 | 13.49,1.66,2.24,24,87,1.88,1.84,0.27,1.03,3.74,0.98,2.78,472,1 75 | 12.99,1.67,2.6,30,139,3.3,2.89,0.21,1.96,3.35,1.31,3.5,985,1 76 | 11.96,1.09,2.3,21,101,3.38,2.14,0.13,1.65,3.21,0.99,3.13,886,1 77 | 11.66,1.88,1.92,16,97,1.61,1.57,0.34,1.15,3.8,1.23,2.14,428,1 78 | 13.03,0.9,1.71,16,86,1.95,2.03,0.24,1.46,4.6,1.19,2.48,392,1 79 | 11.84,2.89,2.23,18,112,1.72,1.32,0.43,0.95,2.65,0.96,2.52,500,1 80 | 12.33,0.99,1.95,14.8,136,1.9,1.85,0.35,2.76,3.4,1.06,2.31,750,1 81 | 12.7,3.87,2.4,23,101,2.83,2.55,0.43,1.95,2.57,1.19,3.13,463,1 82 | 12,0.92,2,19,86,2.42,2.26,0.3,1.43,2.5,1.38,3.12,278,1 83 | 12.72,1.81,2.2,18.8,86,2.2,2.53,0.26,1.77,3.9,1.16,3.14,714,1 84 | 12.08,1.13,2.51,24,78,2,1.58,0.4,1.4,2.2,1.31,2.72,630,1 85 | 13.05,3.86,2.32,22.5,85,1.65,1.59,0.61,1.62,4.8,0.84,2.01,515,1 86 | 11.84,0.89,2.58,18,94,2.2,2.21,0.22,2.35,3.05,0.79,3.08,520,1 87 | 12.67,0.98,2.24,18,99,2.2,1.94,0.3,1.46,2.62,1.23,3.16,450,1 88 | 12.16,1.61,2.31,22.8,90,1.78,1.69,0.43,1.56,2.45,1.33,2.26,495,1 89 | 11.65,1.67,2.62,26,88,1.92,1.61,0.4,1.34,2.6,1.36,3.21,562,1 90 | 11.64,2.06,2.46,21.6,84,1.95,1.69,0.48,1.35,2.8,1,2.75,680,1 91 | 12.08,1.33,2.3,23.6,70,2.2,1.59,0.42,1.38,1.74,1.07,3.21,625,1 92 | 12.08,1.83,2.32,18.5,81,1.6,1.5,0.52,1.64,2.4,1.08,2.27,480,1 93 | 12,1.51,2.42,22,86,1.45,1.25,0.5,1.63,3.6,1.05,2.65,450,1 94 | 12.69,1.53,2.26,20.7,80,1.38,1.46,0.58,1.62,3.05,0.96,2.06,495,1 95 | 12.29,2.83,2.22,18,88,2.45,2.25,0.25,1.99,2.15,1.15,3.3,290,1 96 | 11.62,1.99,2.28,18,98,3.02,2.26,0.17,1.35,3.25,1.16,2.96,345,1 97 | 12.47,1.52,2.2,19,162,2.5,2.27,0.32,3.28,2.6,1.16,2.63,937,1 98 | 11.81,2.12,2.74,21.5,134,1.6,0.99,0.14,1.56,2.5,0.95,2.26,625,1 99 | 12.29,1.41,1.98,16,85,2.55,2.5,0.29,1.77,2.9,1.23,2.74,428,1 100 | 12.37,1.07,2.1,18.5,88,3.52,3.75,0.24,1.95,4.5,1.04,2.77,660,1 101 | 12.29,3.17,2.21,18,88,2.85,2.99,0.45,2.81,2.3,1.42,2.83,406,1 102 | 12.08,2.08,1.7,17.5,97,2.23,2.17,0.26,1.4,3.3,1.27,2.96,710,1 103 | 12.6,1.34,1.9,18.5,88,1.45,1.36,0.29,1.35,2.45,1.04,2.77,562,1 104 | 12.34,2.45,2.46,21,98,2.56,2.11,0.34,1.31,2.8,0.8,3.38,438,1 105 | 11.82,1.72,1.88,19.5,86,2.5,1.64,0.37,1.42,2.06,0.94,2.44,415,1 106 | 12.51,1.73,1.98,20.5,85,2.2,1.92,0.32,1.48,2.94,1.04,3.57,672,1 107 | 12.42,2.55,2.27,22,90,1.68,1.84,0.66,1.42,2.7,0.86,3.3,315,1 108 | 12.25,1.73,2.12,19,80,1.65,2.03,0.37,1.63,3.4,1,3.17,510,1 109 | 12.72,1.75,2.28,22.5,84,1.38,1.76,0.48,1.63,3.3,0.88,2.42,488,1 110 | 12.22,1.29,1.94,19,92,2.36,2.04,0.39,2.08,2.7,0.86,3.02,312,1 111 | 11.61,1.35,2.7,20,94,2.74,2.92,0.29,2.49,2.65,0.96,3.26,680,1 112 | 11.46,3.74,1.82,19.5,107,3.18,2.58,0.24,3.58,2.9,0.75,2.81,562,1 113 | 12.52,2.43,2.17,21,88,2.55,2.27,0.26,1.22,2,0.9,2.78,325,1 114 | 11.76,2.68,2.92,20,103,1.75,2.03,0.6,1.05,3.8,1.23,2.5,607,1 115 | 11.41,0.74,2.5,21,88,2.48,2.01,0.42,1.44,3.08,1.1,2.31,434,1 116 | 12.08,1.39,2.5,22.5,84,2.56,2.29,0.43,1.04,2.9,0.93,3.19,385,1 117 | 11.03,1.51,2.2,21.5,85,2.46,2.17,0.52,2.01,1.9,1.71,2.87,407,1 118 | 11.82,1.47,1.99,20.8,86,1.98,1.6,0.3,1.53,1.95,0.95,3.33,495,1 119 | 12.42,1.61,2.19,22.5,108,2,2.09,0.34,1.61,2.06,1.06,2.96,345,1 120 | 12.77,3.43,1.98,16,80,1.63,1.25,0.43,0.83,3.4,0.7,2.12,372,1 121 | 12,3.43,2,19,87,2,1.64,0.37,1.87,1.28,0.93,3.05,564,1 122 | 11.45,2.4,2.42,20,96,2.9,2.79,0.32,1.83,3.25,0.8,3.39,625,1 123 | 11.56,2.05,3.23,28.5,119,3.18,5.08,0.47,1.87,6,0.93,3.69,465,1 124 | 12.42,4.43,2.73,26.5,102,2.2,2.13,0.43,1.71,2.08,0.92,3.12,365,1 125 | 13.05,5.8,2.13,21.5,86,2.62,2.65,0.3,2.01,2.6,0.73,3.1,380,1 126 | 11.87,4.31,2.39,21,82,2.86,3.03,0.21,2.91,2.8,0.75,3.64,380,1 127 | 12.07,2.16,2.17,21,85,2.6,2.65,0.37,1.35,2.76,0.86,3.28,378,1 128 | 12.43,1.53,2.29,21.5,86,2.74,3.15,0.39,1.77,3.94,0.69,2.84,352,1 129 | 11.79,2.13,2.78,28.5,92,2.13,2.24,0.58,1.76,3,0.97,2.44,466,1 130 | 12.37,1.63,2.3,24.5,88,2.22,2.45,0.4,1.9,2.12,0.89,2.78,342,1 131 | 12.04,4.3,2.38,22,80,2.1,1.75,0.42,1.35,2.6,0.79,2.57,580,1 132 | 12.86,1.35,2.32,18,122,1.51,1.25,0.21,0.94,4.1,0.76,1.29,630,2 133 | 12.88,2.99,2.4,20,104,1.3,1.22,0.24,0.83,5.4,0.74,1.42,530,2 134 | 12.81,2.31,2.4,24,98,1.15,1.09,0.27,0.83,5.7,0.66,1.36,560,2 135 | 12.7,3.55,2.36,21.5,106,1.7,1.2,0.17,0.84,5,0.78,1.29,600,2 136 | 12.51,1.24,2.25,17.5,85,2,0.58,0.6,1.25,5.45,0.75,1.51,650,2 137 | 12.6,2.46,2.2,18.5,94,1.62,0.66,0.63,0.94,7.1,0.73,1.58,695,2 138 | 12.25,4.72,2.54,21,89,1.38,0.47,0.53,0.8,3.85,0.75,1.27,720,2 139 | 12.53,5.51,2.64,25,96,1.79,0.6,0.63,1.1,5,0.82,1.69,515,2 140 | 13.49,3.59,2.19,19.5,88,1.62,0.48,0.58,0.88,5.7,0.81,1.82,580,2 141 | 12.84,2.96,2.61,24,101,2.32,0.6,0.53,0.81,4.92,0.89,2.15,590,2 142 | 12.93,2.81,2.7,21,96,1.54,0.5,0.53,0.75,4.6,0.77,2.31,600,2 143 | 13.36,2.56,2.35,20,89,1.4,0.5,0.37,0.64,5.6,0.7,2.47,780,2 144 | 13.52,3.17,2.72,23.5,97,1.55,0.52,0.5,0.55,4.35,0.89,2.06,520,2 145 | 13.62,4.95,2.35,20,92,2,0.8,0.47,1.02,4.4,0.91,2.05,550,2 146 | 12.25,3.88,2.2,18.5,112,1.38,0.78,0.29,1.14,8.21,0.65,2,855,2 147 | 13.16,3.57,2.15,21,102,1.5,0.55,0.43,1.3,4,0.6,1.68,830,2 148 | 13.88,5.04,2.23,20,80,0.98,0.34,0.4,0.68,4.9,0.58,1.33,415,2 149 | 12.87,4.61,2.48,21.5,86,1.7,0.65,0.47,0.86,7.65,0.54,1.86,625,2 150 | 13.32,3.24,2.38,21.5,92,1.93,0.76,0.45,1.25,8.42,0.55,1.62,650,2 151 | 13.08,3.9,2.36,21.5,113,1.41,1.39,0.34,1.14,9.4,0.57,1.33,550,2 152 | 13.5,3.12,2.62,24,123,1.4,1.57,0.22,1.25,8.6,0.59,1.3,500,2 153 | 12.79,2.67,2.48,22,112,1.48,1.36,0.24,1.26,10.8,0.48,1.47,480,2 154 | 13.11,1.9,2.75,25.5,116,2.2,1.28,0.26,1.56,7.1,0.61,1.33,425,2 155 | 13.23,3.3,2.28,18.5,98,1.8,0.83,0.61,1.87,10.52,0.56,1.51,675,2 156 | 12.58,1.29,2.1,20,103,1.48,0.58,0.53,1.4,7.6,0.58,1.55,640,2 157 | 13.17,5.19,2.32,22,93,1.74,0.63,0.61,1.55,7.9,0.6,1.48,725,2 158 | 13.84,4.12,2.38,19.5,89,1.8,0.83,0.48,1.56,9.01,0.57,1.64,480,2 159 | 12.45,3.03,2.64,27,97,1.9,0.58,0.63,1.14,7.5,0.67,1.73,880,2 160 | 14.34,1.68,2.7,25,98,2.8,1.31,0.53,2.7,13,0.57,1.96,660,2 161 | 13.48,1.67,2.64,22.5,89,2.6,1.1,0.52,2.29,11.75,0.57,1.78,620,2 162 | 12.36,3.83,2.38,21,88,2.3,0.92,0.5,1.04,7.65,0.56,1.58,520,2 163 | 13.69,3.26,2.54,20,107,1.83,0.56,0.5,0.8,5.88,0.96,1.82,680,2 164 | 12.85,3.27,2.58,22,106,1.65,0.6,0.6,0.96,5.58,0.87,2.11,570,2 165 | 12.96,3.45,2.35,18.5,106,1.39,0.7,0.4,0.94,5.28,0.68,1.75,675,2 166 | 13.78,2.76,2.3,22,90,1.35,0.68,0.41,1.03,9.58,0.7,1.68,615,2 167 | 13.73,4.36,2.26,22.5,88,1.28,0.47,0.52,1.15,6.62,0.78,1.75,520,2 168 | 13.45,3.7,2.6,23,111,1.7,0.92,0.43,1.46,10.68,0.85,1.56,695,2 169 | 12.82,3.37,2.3,19.5,88,1.48,0.66,0.4,0.97,10.26,0.72,1.75,685,2 170 | 13.58,2.58,2.69,24.5,105,1.55,0.84,0.39,1.54,8.66,0.74,1.8,750,2 171 | 13.4,4.6,2.86,25,112,1.98,0.96,0.27,1.11,8.5,0.67,1.92,630,2 172 | 12.2,3.03,2.32,19,96,1.25,0.49,0.4,0.73,5.5,0.66,1.83,510,2 173 | 12.77,2.39,2.28,19.5,86,1.39,0.51,0.48,0.64,9.899999,0.57,1.63,470,2 174 | 14.16,2.51,2.48,20,91,1.68,0.7,0.44,1.24,9.7,0.62,1.71,660,2 175 | 13.71,5.65,2.45,20.5,95,1.68,0.61,0.52,1.06,7.7,0.64,1.74,740,2 176 | 13.4,3.91,2.48,23,102,1.8,0.75,0.43,1.41,7.3,0.7,1.56,750,2 177 | 13.27,4.28,2.26,20,120,1.59,0.69,0.43,1.35,10.2,0.59,1.56,835,2 178 | 13.17,2.59,2.37,20,120,1.65,0.68,0.53,1.46,9.3,0.6,1.62,840,2 179 | 14.13,4.1,2.74,24.5,96,2.05,0.76,0.56,1.35,9.2,0.61,1.6,560,2 180 | -------------------------------------------------------------------------------- /Chapter03/sources/Perceptron.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-02-18 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.16.1\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "# Execute plot() inline without calling show()\n", 39 | "%matplotlib inline\n", 40 | "import warnings\n", 41 | "warnings.simplefilter('ignore')\n", 42 | "\n", 43 | "import pandas as pd\n", 44 | "import numpy as np\n", 45 | "import matplotlib.pyplot as plt\n", 46 | "\n", 47 | "\n", 48 | "df = pd.read_csv('../datasets/sms_spam_perceptron.csv')\n", 49 | "\n", 50 | "y = df.iloc[:, 0].values\n", 51 | "y = np.where(y == 'spam', -1, 1)\n", 52 | "\n", 53 | "X = df.iloc[:, [1, 2]].values" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 3, 59 | "metadata": { 60 | "collapsed": true 61 | }, 62 | "outputs": [], 63 | "source": [ 64 | "from sklearn.model_selection import train_test_split\n", 65 | "\n", 66 | "X_train, X_test, y_train, y_test = train_test_split(\n", 67 | " X, y, test_size=0.3, random_state=0)\n", 68 | "\n" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 4, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "data": { 78 | "text/plain": [ 79 | "Perceptron(alpha=0.0001, class_weight=None, early_stopping=False, eta0=0.1,\n", 80 | " fit_intercept=True, max_iter=40, n_iter=None, n_iter_no_change=5,\n", 81 | " n_jobs=None, penalty=None, random_state=0, shuffle=True, tol=None,\n", 82 | " validation_fraction=0.1, verbose=0, warm_start=False)" 83 | ] 84 | }, 85 | "execution_count": 4, 86 | "metadata": {}, 87 | "output_type": "execute_result" 88 | } 89 | ], 90 | "source": [ 91 | "from sklearn.linear_model import Perceptron\n", 92 | "\n", 93 | "p = Perceptron(max_iter=40, eta0=0.1, random_state=0)\n", 94 | "p.fit(X_train, y_train)" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 5, 100 | "metadata": { 101 | "collapsed": true 102 | }, 103 | "outputs": [], 104 | "source": [ 105 | "y_pred = p.predict(X_test)" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 6, 111 | "metadata": {}, 112 | "outputs": [ 113 | { 114 | "data": { 115 | "image/png": "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\n", 116 | "text/plain": [ 117 | "" 118 | ] 119 | }, 120 | "metadata": {}, 121 | "output_type": "display_data" 122 | } 123 | ], 124 | "source": [ 125 | "# Thanks to Sebastian Raschka for 'plot_decision_regions'\n", 126 | "# https://github.com/rasbt/python-machine-learning-book\n", 127 | "from defs import plot_decision_regions\n", 128 | "\n", 129 | "X_combined = np.vstack((X_train, X_test))\n", 130 | "y_combined = np.hstack((y_train, y_test))\n", 131 | "\n", 132 | "plot_decision_regions(X=X_combined, y=y_combined,\n", 133 | " classifier=p, test_idx=range(-5, 5))\n", 134 | "plt.xlabel('suspect words')\n", 135 | "plt.ylabel('spam or ham')\n", 136 | "plt.legend(loc='upper right')\n", 137 | "\n", 138 | "plt.tight_layout()\n", 139 | "plt.show()" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 7, 145 | "metadata": {}, 146 | "outputs": [ 147 | { 148 | "name": "stdout", 149 | "output_type": "stream", 150 | "text": [ 151 | "Misclassified samples: 3\n", 152 | "Accuracy: 0.90\n" 153 | ] 154 | } 155 | ], 156 | "source": [ 157 | "from sklearn.metrics import accuracy_score\n", 158 | "\n", 159 | "print('Misclassified samples: %d' % (y_test != y_pred).sum())\n", 160 | "print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))" 161 | ] 162 | } 163 | ], 164 | "metadata": { 165 | "kernelspec": { 166 | "display_name": "Py35", 167 | "language": "python", 168 | "name": "py35" 169 | }, 170 | "language_info": { 171 | "codemirror_mode": { 172 | "name": "ipython", 173 | "version": 3 174 | }, 175 | "file_extension": ".py", 176 | "mimetype": "text/x-python", 177 | "name": "python", 178 | "nbconvert_exporter": "python", 179 | "pygments_lexer": "ipython3", 180 | "version": "3.5.4" 181 | } 182 | }, 183 | "nbformat": 4, 184 | "nbformat_minor": 2 185 | } 186 | -------------------------------------------------------------------------------- /Chapter05/datasets/network-logs.csv: -------------------------------------------------------------------------------- 1 | REMOTE_PORT,LATENCY,THROUGHPUT,ANOMALY 2 | 21,15.94287532482238,16.20299807446642,0 3 | 20,12.66645094909174,15.8990837351338,1 4 | 80,13.89454962300191,12.95800821585463,0 5 | 21,13.62081291712303,15.45947525058772,0 6 | 21,15.70548484709227,15.33956526603583,0 7 | 23,15.59318972857327,15.61238105671215,0 8 | 21,15.48906754712418,15.64087368177291,0 9 | 80,15.52704801171451,15.63568031226173,0 10 | 21,14.07506707358789,15.76531532927648,0 11 | 53,12.95364954381841,15.82328512087584,0 12 | 20,12.88787444214799,15.07607810133002,0 13 | 80,16.02178960565569,16.25746991816081,0 14 | 80,15.9262927071427,16.29725072434191,0 15 | 21,12.46559400363085,15.16321211753596,0 16 | 21,15.08466278107714,15.44192203204038,0 17 | 80,15.53717522545769,15.24224248113181,0 18 | 21,15.22250851601845,15.42386187610343,0 19 | 21,15.51908495978717,14.09871698993444,0 20 | 21,13.11971433616167,15.66081845898369,0 21 | 443,13.04681516870484,15.7411524132184,0 22 | 20,13.4085201853932,13.76326960024047,0 23 | 21,15.19591481245491,15.85318112982812,0 24 | 21,15.91470076531303,16.17425986715807,0 25 | 21,13.5766996051752,15.04284943755652,0 26 | 21,14.02240250750028,13.40646893666083,0 27 | 53,12.82213163903098,15.22318782380161,0 28 | 20,15.6763661470048,15.89169137219994,0 29 | 21,15.94287532482238,16.20299807446642,0 30 | 20,12.66645094909174,15.8990837351338,1 31 | 80,13.89454962300191,12.95800821585463,0 32 | 21,13.62081291712303,15.45947525058772,0 33 | 21,15.70548484709227,15.33956526603583,0 34 | 23,15.59318972857327,15.61238105671215,0 35 | 21,15.48906754712418,15.64087368177291,0 36 | 80,15.52704801171451,15.63568031226173,0 37 | 21,14.07506707358789,15.76531532927648,0 38 | 53,12.95364954381841,15.82328512087584,0 39 | 20,12.88787444214799,15.07607810133002,0 40 | 23,15.5108889424642,15.30465148682366,0 41 | 443,15.16262426407451,15.3938896849634,0 42 | 21,13.260655152992,15.48016214411599,0 43 | 80,15.25273350867239,15.03134360663839,0 44 | 21,12.92124446791387,13.19321540142361,0 45 | 443,13.852431292546,13.33213110580615,0 46 | 21,14.06856800302965,13.19821236714215,0 47 | 21,13.25206981975186,15.36846390294601,0 48 | 21,13.70449633962696,13.21431301976872,0 49 | 21,15.5087472134072,15.46051652161006,0 50 | 80,15.69042695638351,16.48168851978138,0 51 | 21,12.95598191982515,12.43703005897334,0 52 | 80,13.59312604041728,15.84189902611636,0 53 | 21,15.12874638631439,17.14981222613881,0 54 | 21,15.26705036670259,15.67551973639503,0 55 | 21,15.6614505451442,15.70146451457414,0 56 | 21,15.33962672797097,15.49202297710026,0 57 | 21,15.2761765458781,15.70590693250814,0 58 | 20,15.86049072335336,15.59000779027686,0 59 | 20,15.71651844926282,15.73369667477785,0 60 | 443,13.83454699853918,16.17138034441191,0 61 | 21,16.00076179182642,15.69232970320203,0 62 | 80,15.12702715242892,15.91462774747984,0 63 | 21,13.84578546855034,15.34139348861173,0 64 | 21,15.41426110064101,16.24243182463628,1 65 | 21,13.25273726696165,15.00861363933526,0 66 | 20,13.66840226015763,15.35886035673854,0 67 | 443,13.77534773921765,15.73808512203812,0 68 | 21,15.12582342640922,15.92980922624493,0 69 | 21,15.54724604324321,15.6333944514067,0 70 | 21,14.04258077112493,15.53622696521789,0 71 | 21,15.12648161131633,15.34467591276852,0 72 | 443,15.26324658304056,15.89556918087115,0 73 | 80,15.77324331862399,15.25299473774317,0 74 | 23,15.20969933686442,16.14572569071713,0 75 | 21,15.10414479623351,15.1605045637764,0 76 | 21,15.89828286381979,15.62105187028486,0 77 | 21,13.47473582792461,15.59307141917535,0 78 | 80,13.77637601475249,15.99194426684731,0 79 | 21,12.82770875129005,15.67136906874635,0 80 | 21,13.67165486007913,15.11954159126301,0 81 | 21,15.38704283906103,15.56936935237784,0 82 | 21,15.54320933642332,15.51543150058866,0 83 | 21,13.85306094119846,15.60672436869602,0 84 | 21,13.62525245784644,15.45209462876985,0 85 | 20,15.0157784412311,15.91664093008973,0 86 | 21,13.83645753449745,15.24940725360926,0 87 | 21,15.22694438547307,15.3479843622948,0 88 | 80,13.23742625416296,15.61058751286003,0 89 | 21,13.38482919115422,15.7331933025011,0 90 | 80,13.87130103241151,15.97399468636979,0 91 | 80,13.74951530855867,15.26803135994583,0 92 | 21,15.69914333094722,16.05595814533895,0 93 | 21,15.80580490719942,15.33258926354469,0 94 | 21,15.17222942648117,16.70624397729834,0 95 | 21,11.24915511828765,15.13295896107001,0 96 | 21,13.88773906521638,15.48548132472444,0 97 | 21,15.3258701791002,16.58524064023295,0 98 | 443,12.97517063349011,15.1505677140184,0 99 | 21,15.07427780835002,17.21973519125371,0 100 | 21,15.1620256369139,17.83351945487566,0 101 | 21,12.23970014041095,15.72866833837743,0 102 | 21,15.82555960703615,15.94500684833057,0 103 | 80,13.09763368416417,16.23036500469445,0 104 | 21,13.85758877756093,15.03526838191721,0 105 | 443,12.39445846815594,15.64448216946588,0 106 | 21,15.32186557845068,15.52890629439163,0 107 | 80,15.82965092460402,15.71619455432355,0 108 | 21,15.80177302202355,16.01808914480403,0 109 | 80,15.69751200330076,15.11198748714029,0 110 | 20,15.70598656653535,16.46040295414171,0 111 | 443,13.59156859810395,15.91975097196414,0 112 | 80,12.29984538869378,15.77119467910275,0 113 | 21,13.3990474777037,16.11912910518291,0 114 | 80,15.13112869806696,15.90031130320181,0 115 | 21,15.38581197702793,15.71453967469415,0 116 | 23,15.45487421920634,15.4404224240544,0 117 | 21,15.52502523459987,16.78653607805479,0 118 | 21,15.31499528329094,15.56835427536349,0 119 | 21,15.03034873517879,15.6633618769716,0 120 | 21,15.42312994571211,15.94109334872472,0 121 | 21,13.63615118835241,15.96411634434718,0 122 | 21,15.53477942776931,13.35611764012331,0 123 | 80,15.61566223678644,14.04241034694619,0 124 | 21,13.08085544352481,15.0284594118694,0 125 | 21,15.93928677902786,15.54933745884242,0 126 | 20,16.0271266262212,15.70965830468461,0 127 | 80,15.31925037139242,15.11762658185582,0 128 | 23,15.86153307492049,15.28458412390706,0 129 | 20,15.01432032507764,16.77971266133154,0 130 | 21,13.40765469906171,15.60041190939531,0 131 | 80,13.0795973186072,15.19389917316378,0 132 | 20,12.68820688788819,13.70109597020173,0 133 | 21,15.19232756586644,15.36498178724437,0 134 | 21,15.86589365075524,15.47138789706538,0 135 | 21,13.39350297747264,15.34389892642248,0 136 | 21,13.58659142682796,15.39148496395445,0 137 | 21,13.10219289551651,15.3760326021477,0 138 | 21,15.54176555566262,16.37233995317341,0 139 | 80,15.25602703003231,15.0423494965284,0 140 | 20,16.16754760471493,16.36145253974863,0 141 | 23,13.63292362573135,13.62886893815872,0 142 | 21,15.65349334618363,15.97649220824924,0 143 | 21,12.61911799757794,16.77214314245786,0 144 | 80,13.03427729514449,15.25689090988086,0 145 | 80,10.85940051666349,15.47914434225415,0 146 | 20,12.93486070587027,15.60746677979927,0 147 | 21,14.0922676551586,15.96212808248882,0 148 | 21,12.57248704338531,15.1972734968139,0 149 | 80,15.68266703007037,16.22123922102406,0 150 | 23,13.2125815156299,15.3518273677709,0 151 | 80,13.89975002194823,15.52445650352669,0 152 | 20,13.4662664096024,13.65765529406475,0 153 | 20,13.13166385488746,15.79882584075226,0 154 | 21,15.35439254719252,15.02329268379058,0 155 | 21,13.55329410888779,13.73218768633878,0 156 | 21,12.89628429130503,15.80983707085099,0 157 | 80,15.37264883162727,15.95148191190331,0 158 | 23,13.58869050224715,15.19778174710474,0 159 | 80,12.26002251889708,15.61364103922988,0 160 | 80,13.66602493759934,16.44517365387813,0 161 | 20,15.34554567080519,15.44883765222099,0 162 | 21,15.60667497581217,15.77655361118647,0 163 | 21,14.04369523977195,16.57440586446113,0 164 | 53,15.04899502017924,15.39078838248393,0 165 | 21,15.06857464220482,15.62364257375797,0 166 | 21,15.88890082127304,16.33705609429303,0 167 | 80,14.07601419894874,15.84206442894244,0 168 | 443,10.88221341356124,13.46166188373757,0 169 | 21,14.00920312008345,15.97657577218348,0 170 | 23,12.36776146202978,15.14204982137499,0 171 | 443,15.15765639256333,15.51933856946829,0 172 | 53,15.3376951724287,15.23319145087297,0 173 | 21,13.55057689653119,15.73044061233337,0 174 | 21,13.57918656724497,15.47264441338775,0 175 | 80,15.24479089854792,15.0850911865811,0 176 | 21,15.33086296717245,15.71142599198902,0 177 | 80,15.91714892779239,15.15651432878437,0 178 | 21,13.85421253890297,15.32125758133508,0 179 | 21,15.08736591098981,15.30728373787297,0 180 | 20,12.63610997338858,15.65066101888946,0 181 | 21,15.36282756033598,13.87195409310256,0 182 | 21,15.50066606012271,15.61759024545319,0 183 | 21,14.06984547008964,16.17341605305203,0 184 | 21,15.13133128099397,15.28924849061305,0 185 | 23,15.15300231315136,15.01362830007739,0 186 | 20,13.31011939341444,15.39060274697614,0 187 | 21,15.25712172586539,15.29705004451436,0 188 | 443,13.71613134707139,13.52733470384027,0 189 | 21,15.70094057818437,15.99611428697285,0 190 | 21,12.87853442397187,13.20174479842375,0 191 | 23,13.69916365173765,15.41800069841461,0 192 | 22,15.01609081001448,15.82165925226776,0 193 | 80,15.5899650464961,16.38090675134464,0 194 | 443,15.00784342040606,15.50954333819685,0 195 | 21,15.05950746445452,13.75788684204651,0 196 | 21,15.46114683681014,13.34425721343066,0 197 | 21,15.64474777063343,15.03905866347516,0 198 | 21,13.85478898285457,15.86614260965412,0 199 | 23,15.2814175097121,15.02340696081207,0 200 | 21,15.93304554162803,15.32639552072927,0 201 | 80,13.38943515399727,15.36513422537798,0 202 | 21,15.14088666467278,14.07440554314796,0 203 | 21,15.84487049785213,15.01695105963744,0 204 | 20,12.70489590338878,15.27293037161499,0 205 | 21,15.95353525235777,15.73218902472499,0 206 | 80,15.28114117782965,15.61262377516035,0 207 | 21,13.06799073973982,15.83286345035982,0 208 | 21,13.60279699846308,12.20295198971654,0 209 | 80,12.68816488185228,15.70141680713469,0 210 | 20,13.88291727981215,15.11808370066965,0 211 | 21,15.016482216113,15.33509982485053,0 212 | 80,15.36576550135049,15.82610475260424,0 213 | 21,13.57764756126836,15.88045533202498,0 214 | 80,13.3918924208501,15.34497756139911,0 215 | 80,13.69362090262048,15.92189939882443,0 216 | 443,13.7693080678919,16.51310530416839,0 217 | 20,13.44404345182867,15.07922662749323,0 218 | 443,15.0317928593353,15.40986664465888,0 219 | 80,13.70946840229293,15.58676798397279,0 220 | 80,16.50656640573653,15.22029747467542,0 221 | 21,12.20423230665472,15.32106064914233,0 222 | 80,15.8819298948981,16.36162230554352,0 223 | 53,15.15030999546341,15.14972042192441,0 224 | 21,11.78759609450762,15.55034168613148,0 225 | 23,12.88388298331717,15.57250347912669,0 226 | 21,13.62023705917705,16.42369250161395,0 227 | 21,15.53049363223479,15.44664319460541,0 228 | 21,12.64616608049998,15.10838775257841,0 229 | 80,15.54763373107359,16.43238820991158,0 230 | 20,15.4007699774828,15.21258204276164,0 231 | 21,15.21058389990948,15.93547994178749,0 232 | 443,15.06173440367518,15.11740665636805,0 233 | 23,15.86214589875373,15.70177771082854,0 234 | 20,15.40451989437227,15.34490711864667,0 235 | 21,13.79430574831448,15.68727111247282,0 236 | 21,15.63390271757003,16.30082803685785,0 237 | 21,12.45687580804446,15.54617986485219,0 238 | 443,14.09759772841731,16.73594542008409,0 239 | 443,12.93253733568772,12.62389976814524,0 240 | 80,13.70345190616539,15.71480993356161,0 241 | 443,13.12395594125503,15.44848980937747,0 242 | 21,13.70691009423219,15.09233539217894,0 243 | 21,13.02489337092878,15.25050251544228,0 244 | 21,15.53425534561566,15.76596516545384,0 245 | 21,13.25186260458783,16.3225231885698,0 246 | 21,13.23657554891477,15.33696609589177,0 247 | 80,12.1297131595538,12.66688846478064,0 248 | 80,15.3808873556303,16.03087164666765,0 249 | 80,15.89239721601976,15.52399453253037,0 250 | 21,13.75107909980303,13.64320737566979,0 251 | 21,13.35730012174231,13.42431786138274,0 252 | 21,13.08559089708043,15.86775905977197,0 253 | 21,13.6117330216296,15.86806413838196,0 254 | 21,15.1776173709485,14.04354188009321,0 255 | 80,14.04456588767872,15.28746897631645,0 256 | 21,13.22531906267953,14.0598546965538,0 257 | 21,14.04151500958564,15.76023193066396,0 258 | 21,15.39066478902675,15.71412823472551,0 259 | 21,13.17642606705518,13.67395694240669,0 260 | 21,13.38689005901117,15.66536821990745,0 261 | 20,15.15888821036137,15.78211270885843,0 262 | 80,15.55599224830758,15.04946255637684,0 263 | 21,15.62692885570043,15.29592015439668,0 264 | 21,13.28624407169681,15.6581260669439,0 265 | 20,13.7054823515179,15.1716943145893,0 266 | 80,15.3109896419094,16.25419059506493,0 267 | 80,13.53597112272297,15.77020127180871,0 268 | 21,15.80103055297733,13.70813140471321,0 269 | 80,13.77274485542839,15.64955360893938,0 270 | 21,13.76510156692244,15.02311286948475,0 271 | 80,15.05349835921094,14.03946896423697,0 272 | 21,15.30905390162218,16.04190604522437,0 273 | 80,13.15523771144825,16.9212211680188,0 274 | 21,12.69940390796505,14.09916733869651,0 275 | 80,15.3679922537568,16.75782353966251,0 276 | 20,13.2632541853177,15.09898705600851,0 277 | 80,11.91253508924009,15.61325734486844,0 278 | 21,13.37000592461161,15.16268143261131,0 279 | 21,15.99450697482097,15.4532938283601,0 280 | 21,14.04764860588238,13.77083846575649,0 281 | 21,15.96982662482653,15.59222552688896,0 282 | 80,15.75068711060737,15.46889187883478,0 283 | 22,13.33027919659259,15.34699591207669,0 284 | 21,13.05002153442813,15.68726188711367,0 285 | 80,13.77642646984253,15.23618563920568,0 286 | 21,15.17426585206286,15.5095749119089,0 287 | 21,15.21251759323552,15.08270517066944,0 288 | 21,13.82089482923982,15.61146315929325,0 289 | 21,15.12355955034152,15.95509753853501,0 290 | 20,15.54752171050364,15.85861945287413,0 291 | 21,15.09944359402792,16.03131199865159,0 292 | 80,15.57730180008498,15.25667659137451,0 293 | 20,15.52331832390665,15.2300499886642,0 294 | 21,15.30044704017983,15.26643299159799,0 295 | 21,15.55839285912062,15.48691913661183,0 296 | 21,15.22494186934392,15.86117827216267,0 297 | 80,12.04029344338111,13.34483350304919,0 298 | 80,13.07931049306772,9.347878119065356,1 299 | 21,21.7271340215587,4.126232224310076,1 300 | 21,12.4766288158932,15.4593696654036,1 301 | 21,19.5825727723877,10.4116189967773,1 302 | 21,23.33986752737173,16.29887355272053,1 303 | 20,18.2611884383863,17.9783089957873,1 304 | 80,4.752612823293772,24.35040724802435,1 305 | 21,15.41426110064101,16.24243182463628,1 306 | 21,13.25273726696165,15.00861363933526,0 307 | 20,13.66840226015763,15.35886035673854,0 308 | 443,13.77534773921765,15.73808512203812,0 309 | 21,15.12582342640922,15.92980922624493,0 310 | 21,15.54724604324321,15.6333944514067,0 311 | 21,14.04258077112493,15.53622696521789,0 312 | 21,15.12648161131633,15.34467591276852,0 313 | 443,15.26324658304056,15.89556918087115,0 314 | 80,15.77324331862399,15.25299473774317,0 315 | 23,15.20969933686442,16.14572569071713,0 316 | 21,15.10414479623351,15.1605045637764,0 317 | 21,15.89828286381979,15.62105187028486,0 318 | 20,13.4085201853932,13.76326960024047,0 319 | 21,15.19591481245491,15.85318112982812,0 320 | 21,15.91470076531303,16.17425986715807,0 321 | 21,13.5766996051752,15.04284943755652,0 322 | 21,14.02240250750028,13.40646893666083,0 323 | 53,12.82213163903098,15.22318782380161,0 324 | 20,15.6763661470048,15.89169137219994,0 325 | 21,15.94287532482238,16.20299807446642,0 326 | 20,12.66645094909174,15.8990837351338,1 327 | 80,13.89454962300191,12.95800821585463,0 328 | 21,13.62081291712303,15.45947525058772,0 329 | 21,15.70548484709227,15.33956526603583,0 330 | 23,15.59318972857327,15.61238105671215,0 331 | 21,15.48906754712418,15.64087368177291,0 332 | 80,15.52704801171451,15.63568031226173,0 333 | 21,14.07506707358789,15.76531532927648,0 334 | 21,12.23970014041095,15.72866833837743,0 335 | 21,15.82555960703615,15.94500684833057,0 336 | 80,13.09763368416417,16.23036500469445,0 337 | 21,13.85758877756093,15.03526838191721,0 338 | 443,12.39445846815594,15.64448216946588,0 339 | 21,15.32186557845068,15.52890629439163,0 340 | 80,15.82965092460402,15.71619455432355,0 341 | 21,15.80177302202355,16.01808914480403,0 342 | 80,15.69751200330076,15.11198748714029,0 343 | 20,15.70598656653535,16.46040295414171,0 344 | 443,13.59156859810395,15.91975097196414,0 345 | 80,12.29984538869378,15.77119467910275,0 346 | 21,13.3990474777037,16.11912910518291,0 347 | 80,15.13112869806696,15.90031130320181,0 348 | 21,15.38581197702793,15.71453967469415,0 349 | 23,15.45487421920634,15.4404224240544,0 350 | 21,15.52502523459987,16.78653607805479,0 351 | 21,15.31499528329094,15.56835427536349,0 352 | 21,15.03034873517879,15.6633618769716,0 353 | 21,15.42312994571211,15.94109334872472,0 354 | 21,13.63615118835241,15.96411634434718,0 355 | 21,15.53477942776931,13.35611764012331,0 356 | 443,15.06146043109355,15.54908874282629,0 357 | 80,13.38988671215899,15.56202141787754,0 358 | 443,13.39350474623341,15.62698794188875,0 359 | 21,14.07900926099814,13.28061494266342,0 360 | 20,14.04791258723419,15.46583828507579,0 361 | 443,14.06176145283657,15.75182421254904,0 362 | 80,15.45899735355037,15.07018562997125,0 363 | 21,15.58476371878708,15.82743423785702,0 364 | 21,12.07427073619131,13.06711089796514,0 365 | 21,13.54912940444922,15.53827676982062,0 366 | 80,13.89625041879221,15.78776303583677,0 367 | 80,15.96991942049244,16.51830493015889,0 368 | 21,15.2557659665841,15.29427277420701,0 369 | 80,15.33425000108006,16.12469988952639,0 370 | 80,15.63504869777692,16.49094476663806,0 371 | 443,13.04681516870484,15.7411524132184,0 372 | 20,13.4085201853932,13.76326960024047,0 373 | 21,15.19591481245491,15.85318112982812,0 374 | 21,15.91470076531303,16.17425986715807,0 375 | 21,13.5766996051752,15.04284943755652,0 376 | 21,14.02240250750028,13.40646893666083,0 377 | 53,12.82213163903098,15.22318782380161,0 378 | 20,15.6763661470048,15.89169137219994,0 379 | 21,15.65349334618363,15.97649220824924,0 380 | 21,12.61911799757794,16.77214314245786,0 381 | 80,13.03427729514449,15.25689090988086,0 382 | 80,10.85940051666349,15.47914434225415,0 383 | 20,12.93486070587027,15.60746677979927,0 384 | 21,14.0922676551586,15.96212808248882,0 385 | 21,12.57248704338531,15.1972734968139,0 386 | 80,15.68266703007037,16.22123922102406,0 387 | 23,13.2125815156299,15.3518273677709,0 388 | 80,13.89975002194823,15.52445650352669,0 389 | 20,13.4662664096024,13.65765529406475,0 390 | 20,13.13166385488746,15.79882584075226,0 391 | 21,15.35439254719252,15.02329268379058,0 392 | 21,13.55329410888779,13.73218768633878,0 393 | 21,12.89628429130503,15.80983707085099,0 394 | 80,15.37264883162727,15.95148191190331,0 395 | 23,13.58869050224715,15.19778174710474,0 396 | 80,12.26002251889708,15.61364103922988,0 397 | 80,13.66602493759934,16.44517365387813,0 398 | 20,15.34554567080519,15.44883765222099,0 399 | 21,15.60667497581217,15.77655361118647,0 400 | 21,14.04369523977195,16.57440586446113,0 401 | 53,15.04899502017924,15.39078838248393,0 402 | 21,15.06857464220482,15.62364257375797,0 403 | 21,15.88890082127304,16.33705609429303,0 404 | 80,14.07601419894874,15.84206442894244,0 405 | 443,10.88221341356124,13.46166188373757,0 406 | 21,14.00920312008345,15.97657577218348,0 407 | -------------------------------------------------------------------------------- /Chapter02/sources/Ch02 Examples.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-01-30 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.13.3\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": {}, 36 | "outputs": [ 37 | { 38 | "data": { 39 | "text/plain": [ 40 | "[]" 41 | ] 42 | }, 43 | "execution_count": 2, 44 | "metadata": {}, 45 | "output_type": "execute_result" 46 | }, 47 | { 48 | "data": { 49 | "image/png": "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\nAElFTkSuQmCC\n", 50 | "text/plain": [ 51 | "" 52 | ] 53 | }, 54 | "metadata": {}, 55 | "output_type": "display_data" 56 | } 57 | ], 58 | "source": [ 59 | "# Execute plot() inline without calling show()\n", 60 | "\n", 61 | "%matplotlib inline\n", 62 | "\n", 63 | "import numpy as np \n", 64 | "\n", 65 | "import matplotlib.pyplot as plt \n", 66 | "\n", 67 | "plt.plot(np.arange(15), np.arange(15))\n" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 3, 73 | "metadata": {}, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "Model Prediction for new data: $13.73\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "import numpy as np \n", 85 | "from sklearn.linear_model import LinearRegression\n", 86 | "\n", 87 | "# X is a matrix that represents the training dataset\n", 88 | "# y is a vector of weights, to be associated with input dataset\n", 89 | "\n", 90 | "X = np.array([[3], [5], [7], [9], [11]]).reshape(-1, 1) \n", 91 | "y = [8.0, 9.1, 10.3, 11.4, 12.6] \n", 92 | "\n", 93 | "lreg_model = LinearRegression() \n", 94 | "lreg_model.fit(X, y) \n", 95 | "\n", 96 | "# New data (unseen before)\n", 97 | "new_data = np.array([[13]]) \n", 98 | "\n", 99 | "print('Model Prediction for new data: $%.2f' % lreg_model.predict(new_data)[0] ) " 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 4, 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "data": { 109 | "text/html": [ 110 | "
\n", 111 | "\n", 124 | "\n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
count150.000000150.000000150.000000150.000000
mean5.8433333.0573333.7580001.199333
std0.8280660.4358661.7652980.762238
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
\n", 193 | "
" 194 | ], 195 | "text/plain": [ 196 | " sepal length (cm) sepal width (cm) petal length (cm) \\\n", 197 | "count 150.000000 150.000000 150.000000 \n", 198 | "mean 5.843333 3.057333 3.758000 \n", 199 | "std 0.828066 0.435866 1.765298 \n", 200 | "min 4.300000 2.000000 1.000000 \n", 201 | "25% 5.100000 2.800000 1.600000 \n", 202 | "50% 5.800000 3.000000 4.350000 \n", 203 | "75% 6.400000 3.300000 5.100000 \n", 204 | "max 7.900000 4.400000 6.900000 \n", 205 | "\n", 206 | " petal width (cm) \n", 207 | "count 150.000000 \n", 208 | "mean 1.199333 \n", 209 | "std 0.762238 \n", 210 | "min 0.100000 \n", 211 | "25% 0.300000 \n", 212 | "50% 1.300000 \n", 213 | "75% 1.800000 \n", 214 | "max 2.500000 " 215 | ] 216 | }, 217 | "execution_count": 4, 218 | "metadata": {}, 219 | "output_type": "execute_result" 220 | } 221 | ], 222 | "source": [ 223 | "import pandas as pd \n", 224 | "from sklearn import datasets\n", 225 | "\n", 226 | "iris = datasets.load_iris()\n", 227 | "iris_df = pd.DataFrame(iris.data, columns = iris.feature_names)\n", 228 | "\n", 229 | "iris_df.head()\n", 230 | "iris_df.describe()" 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": null, 236 | "metadata": { 237 | "collapsed": true 238 | }, 239 | "outputs": [], 240 | "source": [] 241 | } 242 | ], 243 | "metadata": { 244 | "kernelspec": { 245 | "display_name": "Py35", 246 | "language": "python", 247 | "name": "py35" 248 | }, 249 | "language_info": { 250 | "codemirror_mode": { 251 | "name": "ipython", 252 | "version": 3 253 | }, 254 | "file_extension": ".py", 255 | "mimetype": "text/x-python", 256 | "name": "python", 257 | "nbconvert_exporter": "python", 258 | "pygments_lexer": "ipython3", 259 | "version": "3.5.4" 260 | } 261 | }, 262 | "nbformat": 4, 263 | "nbformat_minor": 2 264 | } 265 | -------------------------------------------------------------------------------- /Chapter03/sources/SVM.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Alessandro Parisi \n", 13 | "last updated: 2019-02-18 \n", 14 | "\n", 15 | "CPython 3.5.4\n", 16 | "IPython 6.1.0\n", 17 | "\n", 18 | "numpy 1.16.1\n", 19 | "pandas 0.20.3\n", 20 | "matplotlib 2.0.2\n", 21 | "sklearn 0.20.0\n", 22 | "seaborn 0.8.0\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "%load_ext watermark\n", 28 | "%watermark -a \"Alessandro Parisi\" -u -d -v -p numpy,pandas,matplotlib,sklearn,seaborn\n", 29 | "# to install watermark launch 'pip install watermark' at command line\n", 30 | "import warnings \n", 31 | "warnings.simplefilter('ignore')" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "import pandas as pd\n", 41 | "import numpy as np\n", 42 | "import matplotlib.pyplot as plt \n", 43 | "\n", 44 | "df = pd.read_csv('../datasets/sms_spam_svm.csv')\n", 45 | "\n", 46 | "y = df.iloc[:, 0].values\n", 47 | "y = np.where(y == 'spam', -1, 1)\n", 48 | "\n", 49 | "X = df.iloc[:, [1, 2]].values" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 3, 55 | "metadata": { 56 | "collapsed": true 57 | }, 58 | "outputs": [], 59 | "source": [ 60 | "from sklearn.model_selection import train_test_split\n", 61 | "\n", 62 | "X_train, X_test, y_train, y_test = train_test_split(\n", 63 | " X, y, test_size=0.3, random_state=0)\n", 64 | "\n" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 4, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "from sklearn.svm import SVC\n", 74 | "\n", 75 | "svm = SVC(kernel='linear', C=1.0, random_state=1)\n", 76 | "svm.fit(X_train, y_train)\n", 77 | "\n", 78 | "y_pred = svm.predict(X_test)\n" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 5, 84 | "metadata": {}, 85 | "outputs": [ 86 | { 87 | "data": { 88 | "image/png": "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\nUg4lla8zJhXOuG0IHcq31BtfVdKLp6a7K0wTf6M7pt7GkvIhjG2/mB8Xz2tTZY1SJfaZ+DMbR236\nA3eVX0Rh0S56al2GcGPJDonZyJMmwYwZbjs2ezZMnuy+k03TZtFt9yZ+VDxv32v/u/octhf1oc/t\nVzerRFMub39yag8K4ovBFhZCu3bQq1fd4b+hQ1vfP02QciipfJ0xqdKhfAvVnXvWu8WCVuJvNBqF\nJeVDWFp7HM9Hv0dlx7ZT1iiVRLzMxoL5TJFZFJVv5UDdQLUW8cfa8XGXrzRWMi0Sic8iFoFhw6B9\ne/jqKze8aBE8vXMk29v3pqqT+/6qOvVke/vePL1zZLNKNOX69ifnkiTKyuJLjQweDGPGxJcoScU5\nqCDlUFL5OmNS4Zxp/anu3LPe+OKKrcy73Z3IT/yN7v/Ze/Rqt51NtT33/UbbSlmjVPNvX6JRt9fz\n4Yd1zwdNdvBn6yXbrl2ydQYX9XiqXjX1B7adwX096zIrg5RoCsv2Jy+SJBJLjfiDU2yaVC2rqXIo\nqXydMZmS+BsV4OEe18T9RttKWaNUSyyZNnly/PNBkx380yTbrsWqyCcu+/Li++PGBSnRlMvbn5wK\nUEFKlGR7WZlsozEtkZhspMAF2+6M+42Wlp9riRNNiO1B+SUmOzT22hhVWLgw/vl7qy+mtjZ+XG2t\nG+8XpERTLm9/cipJoqkSJan6l9DSZWWyjca0RLJko6ev2Mzi6hP5l8J1LOn9n/y+4lweKD+b1+UI\nTvcORanCjsum0SW6nYnyQNw8awuL+O97dmXpHWVHNOqSGzZtgsMPd3tSsaStGTNc0lZDe1ILpzxP\n5Z52zOt8ESJwd+XFLNp9Bf3bf85ld3+TRYvgzicn8chnZ/IOR1NQ4ILTIN5mM70Z2YwSTbm+/cmZ\nPaiGSpSkIikiVcvKZBuNSaaqpBfFFVvr3apKesVN5082KmgndKCSw1hDh11buZpZHCmrWKn/yuLF\ndX+8nqj9ITsj3agpKKK2sO5WULM7C+80u0RcAGrfHg47zA0fdpgbjkQaXtejUajc046ltccxvvph\nqjr15I+146miIwdGN6Dq/jj0ZjP/5BucyZ+IRuFM/sQ/+Qa92czIkcm3LW1x+5NTSRKQ2W6oW7qs\nttxVtsl9QZKNYqXD/Cfbr/j0p1xZOLveb7mgZjcPlNakv+Ehk+xzHDKkrg5oQ876eX/GVz/My7uH\n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\nrJAOei0SAAAAAElFTkSuQmCC\n", 89 | "text/plain": [ 90 | "" 91 | ] 92 | }, 93 | "metadata": {}, 94 | "output_type": "display_data" 95 | } 96 | ], 97 | "source": [ 98 | "# Thanks to Sebastian Raschka for 'plot_decision_regions'\n", 99 | "# https://github.com/rasbt/python-machine-learning-book\n", 100 | "from defs import plot_decision_regions\n", 101 | "\n", 102 | "X_combined = np.vstack((X_train, X_test))\n", 103 | "y_combined = np.hstack((y_train, y_test))\n", 104 | "\n", 105 | "plot_decision_regions(X_combined, y_combined,\n", 106 | " classifier=svm, test_idx=range(-15, 15))\n", 107 | "plt.xlabel('suspect words')\n", 108 | "plt.ylabel('spam or ham')\n", 109 | "plt.legend(loc='upper right')\n", 110 | "plt.tight_layout()\n", 111 | "plt.show()" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 6, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "name": "stdout", 121 | "output_type": "stream", 122 | "text": [ 123 | "Misclassified samples: 7\n", 124 | "Accuracy: 0.84\n" 125 | ] 126 | } 127 | ], 128 | "source": [ 129 | "from sklearn.metrics import accuracy_score\n", 130 | "\n", 131 | "print('Misclassified samples: %d' % (y_test != y_pred).sum())\n", 132 | "print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": { 139 | "collapsed": true 140 | }, 141 | "outputs": [], 142 | "source": [] 143 | } 144 | ], 145 | "metadata": { 146 | "kernelspec": { 147 | "display_name": "Py35", 148 | "language": "python", 149 | "name": "py35" 150 | }, 151 | "language_info": { 152 | "codemirror_mode": { 153 | "name": "ipython", 154 | "version": 3 155 | }, 156 | "file_extension": ".py", 157 | "mimetype": "text/x-python", 158 | "name": "python", 159 | "nbconvert_exporter": "python", 160 | "pygments_lexer": "ipython3", 161 | "version": "3.5.4" 162 | } 163 | }, 164 | "nbformat": 4, 165 | "nbformat_minor": 2 166 | } 167 | --------------------------------------------------------------------------------