#!/usr/bin/env python # coding: utf-8 # # # # Classification-Master Template # # How do you work through a predictive modeling- Classification or Regression based Machine learning problem end-to-end? # In this jupyter note you will work through a case study classication predictive modeling problem in Python # including each step of the applied machine learning process. # However, this notebook is applicable for Regression based case study as well. The Models, Grid Search and Evaluation Metrics will need to change for the regression based case study. # # ## Content # * [1. Introduction](#0) # * [2. Getting Started - Load Libraries and Dataset](#1) # * [2.1. Load Libraries](#1.1) # * [2.2. Load Dataset](#1.2) # * [3. Exploratory Data Analysis](#2) # * [3.1 Descriptive Statistics](#2.1) # * [3.2. Data Visualisation](#2.2) # * [4. Data Preparation](#3) # * [4.1 Data Cleaning](#3.1) # * [4.2.Handling Categorical Data](#3.2) # * [4.3.Feature Selection](#3.3) # * [4.3.Data Transformation](#3.4) # * [4.3.1 Rescaling ](#3.4.1) # * [4.3.2 Standardization](#3.4.2) # * [4.3.3 Normalization](#3.4.3) # * [5.Evaluate Algorithms and Models](#4) # * [5.1. Train/Test Split](#4.1) # * [5.2. Test Options and Evaluation Metrics](#4.2) # * [5.3. Compare Models and Algorithms](#4.3) # * [5.3.1 Common Classification Models](#4.3.1) # * [5.3.2 Ensemble Models](#4.3.2) # * [5.3.3 Deep Learning Models](#4.3.3) # * [6. Model Tuning and Grid Search](#5) # * [7. Finalize the Model](#6) # * [7.1. Results on test dataset](#6.1) # * [7.1. Variable Intuition/Feature Selection](#6.2) # * [7.3. Save model for later use](#6.3) # # # # 1. Introduction # Our goal in this jupyter notebook is to under the following # - How to work through a predictive modeling problem end-to-end. This notebook is applicable both for regression and classification problems. # - How to use data transforms to improve model performance. # - How to use algorithm tuning to improve model performance. # - How to use ensemble methods and tuning of ensemble methods to improve model performance. # - How to use deep Learning methods. # # The data is a subset of the German Default data (https://archive.ics.uci.edu/ml/datasets/statlog+(german+credit+data) with the following attributes. Age, Sex, Job, Housing, SavingAccounts, CheckingAccount, CreditAmount, Duration, Purpose # - Following models are implemented and checked: # # * Logistic Regression # * Linear Discriminant Analysis # * K Nearest Neighbors # * Decision Tree (CART) # * Support Vector Machine # * Ada Boost # * Gradient Boosting Method # * Random Forest # * Extra Trees # * Neural Network - Shallow # * Deep Neural Network # # # 2. Getting Started- Loading the data and python packages # # ## 2.1. Loading the python packages # In[53]: # Load libraries import numpy as np import pandas as pd from matplotlib import pyplot from pandas import read_csv, set_option from pandas.plotting import scatter_matrix import seaborn as sns from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split, KFold, cross_val_score, GridSearchCV from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.naive_bayes import GaussianNB from sklearn.svm import SVC from sklearn.neural_network import MLPClassifier from sklearn.pipeline import Pipeline from sklearn.ensemble import AdaBoostClassifier, GradientBoostingClassifier, RandomForestClassifier, ExtraTreesClassifier from sklearn.metrics import classification_report, confusion_matrix, accuracy_score #Libraries for Deep Learning Models from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasClassifier from keras.optimizers import SGD #Libraries for Saving the Model from pickle import dump from pickle import load # # ## 2.2. Loading the Data # In[54]: # load dataset dataset = read_csv('german_credit_data.csv') # In[55]: #Diable the warnings import warnings warnings.filterwarnings('ignore') # In[56]: type(dataset) # # # 3. Exploratory Data Analysis # # ## 3.1. Descriptive Statistics # In[57]: # shape dataset.shape # In[58]: # peek at data set_option('display.width', 100) dataset.head(2) # In[59]: # types set_option('display.max_rows', 500) dataset.dtypes # In[60]: # describe data set_option('precision', 3) dataset.describe() # In[61]: # class distribution dataset.groupby('Housing').size() # # ## 3.2. Data Visualization # In[62]: # histograms dataset.hist(sharex=False, sharey=False, xlabelsize=1, ylabelsize=1, figsize=(12,12)) pyplot.show() # In[63]: # density dataset.plot(kind='density', subplots=True, layout=(3,3), sharex=False, legend=True, fontsize=1, figsize=(15,15)) pyplot.show() # In[64]: #Box and Whisker Plots dataset.plot(kind='box', subplots=True, layout=(3,3), sharex=False, sharey=False, figsize=(15,15)) pyplot.show() # In[65]: # correlation correlation = dataset.corr() pyplot.figure(figsize=(15,15)) pyplot.title('Correlation Matrix') sns.heatmap(correlation, vmax=1, square=True,annot=True,cmap='cubehelix') # In[66]: # Scatterplot Matrix from pandas.plotting import scatter_matrix pyplot.figure(figsize=(15,15)) scatter_matrix(dataset,figsize=(12,12)) pyplot.show() # # ## 4. Data Preparation # # ## 4.1. Data Cleaning # Check for the NAs in the rows, either drop them or fill them with the mean of the column # In[67]: #Checking for any null values and removing the null values''' print('Null Values =',dataset.isnull().values.any()) # Given that there are null values drop the rown contianing the null values. # In[68]: # Drop the rows containing NA dataset = dataset.dropna(axis=0) # Fill na with 0 #dataset.fillna('0') #Filling the NAs with the mean of the column. #dataset['col'] = dataset['col'].fillna(dataset['col'].mean()) # # ## 4.2. Handling Categorical Data # In[69]: from sklearn.preprocessing import LabelEncoder lb_make = LabelEncoder() dataset["Sex_Code"] = lb_make.fit_transform(dataset["Sex"]) dataset["Housing_Code"] = lb_make.fit_transform(dataset["Housing"]) dataset["SavingAccount_Code"] = lb_make.fit_transform(dataset["SavingAccounts"].fillna('0')) dataset["CheckingAccount_Code"] = lb_make.fit_transform(dataset["CheckingAccount"].fillna('0')) dataset["Purpose_Code"] = lb_make.fit_transform(dataset["Purpose"]) dataset["Risk_Code"] = lb_make.fit_transform(dataset["Risk"]) dataset[["Sex", "Sex_Code","Housing","Housing_Code","Risk_Code","Risk"]].head(10) # In[70]: #dropping the old features dataset.drop(['Sex','Housing','SavingAccounts','CheckingAccount','Purpose','Risk'],axis=1,inplace=True) # In[71]: dataset.head(5) # # ## 4.3. Feature Selection # Statistical tests can be used to select those features that have the strongest relationship with the output variable.The scikit-learn library provides the SelectKBest class that can be used with a suite of different statistical tests to select a specific number of features. # The example below uses the chi-squared (chi²) statistical test for non-negative features to select 10 of the best features from the Dataset. # In[72]: from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 bestfeatures = SelectKBest(score_func=chi2, k=5) bestfeatures # In[73]: Y= dataset["Risk_Code"] X = dataset.loc[:, dataset.columns != 'Risk_Code'] fit = bestfeatures.fit(X,Y) dfscores = pd.DataFrame(fit.scores_) dfcolumns = pd.DataFrame(X.columns) #concat two dataframes for better visualization featureScores = pd.concat([dfcolumns,dfscores],axis=1) featureScores.columns = ['Specs','Score'] #naming the dataframe columns print(featureScores.nlargest(10,'Score')) #print 10 best features # As it can be seem from the numbers above Credit Amount is the most important feature followed by duration. # # ## 4.4. Data Transformation # # ### 4.4.1. Rescale Data # When your data is comprised of attributes with varying scales, many machine learning algorithms # can benefit from rescaling the attributes to all have the same scale. Often this is referred to # as normalization and attributes are often rescaled into the range between 0 and 1. # In[74]: from sklearn.preprocessing import MinMaxScaler X = dataset.loc[:, dataset.columns != 'Risk_Code'] scaler = MinMaxScaler(feature_range=(0, 1)) rescaledX = pd.DataFrame(scaler.fit_transform(X)) # summarize transformed data rescaledX.head(5) # # ### 4.4.2. Standardize Data # Standardization is a useful technique to transform attributes with a Gaussian distribution and # differing means and standard deviations to a standard Gaussian distribution with a mean of # 0 and a standard deviation of 1. # In[75]: from sklearn.preprocessing import StandardScaler X = dataset.loc[:, dataset.columns != 'Risk_Code'] scaler = StandardScaler().fit(X) StandardisedX = pd.DataFrame(scaler.fit_transform(X)) # summarize transformed data StandardisedX.head(5) # # ### 4.4.1. Normalize Data # Normalizing in scikit-learn refers to rescaling each observation (row) to have a length of 1 (called # a unit norm or a vector with the length of 1 in linear algebra). # In[76]: from sklearn.preprocessing import Normalizer X = dataset.loc[:, dataset.columns != 'Risk_Code'] scaler = Normalizer().fit(X) NormalizedX = pd.DataFrame(scaler.fit_transform(X)) # summarize transformed data NormalizedX.head(5) # # # 5. Evaluate Algorithms and Models # # ## 5.1. Train Test Split # In[77]: # split out validation dataset for the end Y= dataset["Risk_Code"] X = dataset.loc[:, dataset.columns != 'Risk_Code'] scaler = StandardScaler().fit(X) StandardisedX = pd.DataFrame(scaler.fit_transform(X)) validation_size = 0.2 seed = 7 X_train, X_validation, Y_train, Y_validation = train_test_split(X, Y, test_size=validation_size, random_state=seed) # # ## 5.2. Test Options and Evaluation Metrics # # In[78]: # test options for classification num_folds = 10 seed = 7 scoring = 'accuracy' #scoring ='neg_log_loss' #scoring = 'roc_auc' # # ## 5.3. Compare Models and Algorithms # # ### 5.3.1. Common Models # In[79]: # spot check the algorithms models = [] models.append(('LR', LogisticRegression())) models.append(('LDA', LinearDiscriminantAnalysis())) models.append(('KNN', KNeighborsClassifier())) models.append(('CART', DecisionTreeClassifier())) models.append(('NB', GaussianNB())) models.append(('SVM', SVC())) #Neural Network models.append(('NN', MLPClassifier())) # # ### 5.3.2. Ensemble Models # In[80]: #Ensable Models # Boosting methods models.append(('AB', AdaBoostClassifier())) models.append(('GBM', GradientBoostingClassifier())) # Bagging methods models.append(('RF', RandomForestClassifier())) models.append(('ET', ExtraTreesClassifier())) # # ### 5.3.3. Deep Learning Model # In[81]: #Writing the Deep Learning Classifier in case the Deep Learning Flag is Set to True #Set the following Flag to 0 if the Deep LEarning Models Flag has to be enabled EnableDLModelsFlag = 1 if EnableDLModelsFlag == 1 : # Function to create model, required for KerasClassifier def create_model(neurons=12, activation='relu', learn_rate = 0.01, momentum=0): # create model model = Sequential() model.add(Dense(neurons, input_dim=X_train.shape[1], activation=activation)) model.add(Dense(2, activation=activation)) model.add(Dense(1, activation='sigmoid')) # Compile model optimizer = SGD(lr=learn_rate, momentum=momentum) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) return model models.append(('DNN', KerasClassifier(build_fn=create_model, epochs=10, batch_size=10, verbose=1))) # ### K-folds cross validation # In[82]: results = [] names = [] for name, model in models: kfold = KFold(n_splits=num_folds, random_state=seed) cv_results = cross_val_score(model, X_train, Y_train, cv=kfold, scoring=scoring) results.append(cv_results) names.append(name) msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std()) print(msg) # ### Algorithm comparison # In[83]: # compare algorithms fig = pyplot.figure() fig.suptitle('Algorithm Comparison') ax = fig.add_subplot(111) pyplot.boxplot(results) ax.set_xticklabels(names) fig.set_size_inches(15,8) pyplot.show() # # # 6. Model Tuning and Grid Search # Algorithm Tuning: Although some of the models show the most promising options. the grid search for Gradient Bossting Classifier is shown below. # In[84]: # 1. Grid search : Logistic Regression Algorithm ''' penalty : str, ‘l1’, ‘l2’, ‘elasticnet’ or ‘none’, optional (default=’l2’) C : float, optional (default=1.0) Inverse of regularization strength; must be a positive float.Smaller values specify stronger regularization. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) grid={"C":np.logspace(-3,3,7), "penalty":["l1","l2"]}# l1 lasso l2 ridge C= np.logspace(-3,3,7) penalty = ["l1","l2"]# l1 lasso l2 ridge param_grid = dict(C=C,penalty=penalty ) model = LogisticRegression() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[85]: # Grid Search : LDA Algorithm ''' n_components : int, optional (default=None) Number of components for dimensionality reduction. If None, will be set to min(n_classes - 1, n_features). ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) components = [1,3,5,7,9,11,13,15,17,19,600] param_grid = dict(n_components=components) model = LinearDiscriminantAnalysis() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[86]: # Grid Search KNN algorithm tuning ''' n_neighbors : int, optional (default = 5) Number of neighbors to use by default for kneighbors queries. weights : str or callable, optional (default = ‘uniform’) weight function used in prediction. Possible values: ‘uniform’, ‘distance’ ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) neighbors = [1,3,5,7,9,11,13,15,17,19,21] weights = ['uniform', 'distance'] param_grid = dict(n_neighbors=neighbors, weights = weights ) model = KNeighborsClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[87]: # Grid Search : CART Algorithm ''' max_depth : int or None, optional (default=None) The maximum depth of the tree. If None, then nodes are expanded until all leaves are pure or until all leaves contain less than min_samples_split samples. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) max_depth = np.arange(2, 30) param_grid = dict(max_depth=max_depth) model = DecisionTreeClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[88]: # Grid Search : NB algorithm tuning #GaussianNB only accepts priors as an argument so unless you have some priors to set for your model ahead of time #you will have nothing to grid search over. # In[89]: # Grid Search: SVM algorithm tuning ''' C : float, optional (default=1.0) Penalty parameter C of the error term. kernel : string, optional (default=’rbf’) Specifies the kernel type to be used in the algorithm. It must be one of ‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ or a callable. Parameters of SVM are C and kernel. Try a number of kernels with various values of C with less bias and more bias (less than and greater than 1.0 respectively ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) c_values = [0.1, 0.3, 0.5, 0.7, 0.9, 1.0, 1.3, 1.5] kernel_values = ['linear', 'poly', 'rbf'] param_grid = dict(C=c_values, kernel=kernel_values) model = SVC() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[90]: # Grid Search: Ada boost Algorithm Tuning ''' n_estimators : integer, optional (default=50) The maximum number of estimators at which boosting is terminated. In case of perfect fit, the learning procedure is stopped early. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) n_estimators = [10, 100] param_grid = dict(n_estimators=n_estimators) model = AdaBoostClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[91]: # Grid Search: GradientBoosting Tuning ''' n_estimators : int (default=100) The number of boosting stages to perform. Gradient boosting is fairly robust to over-fitting so a large number usually results in better performance. max_depth : integer, optional (default=3) maximum depth of the individual regression estimators. The maximum depth limits the number of nodes in the tree. Tune this parameter for best performance; the best value depends on the interaction of the input variables. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) n_estimators = [20,180] max_depth= [3,5] param_grid = dict(n_estimators=n_estimators, max_depth=max_depth) model = GradientBoostingClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[92]: # Grid Search: Random Forest Classifier ''' n_estimators : int (default=100) The number of boosting stages to perform. Gradient boosting is fairly robust to over-fitting so a large number usually results in better performance. max_depth : integer, optional (default=3) maximum depth of the individual regression estimators. The maximum depth limits the number of nodes in the tree. Tune this parameter for best performance; the best value depends on the interaction of the input variables criterion : string, optional (default=”gini”) The function to measure the quality of a split. Supported criteria are “gini” for the Gini impurity and “entropy” for the information gain. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) n_estimators = [20,80] max_depth= [5,10] criterion = ["gini","entropy"] param_grid = dict(n_estimators=n_estimators, max_depth=max_depth, criterion = criterion ) model = RandomForestClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[93]: # Grid Search: ExtraTreesClassifier() ''' n_estimators : int (default=100) The number of boosting stages to perform. Gradient boosting is fairly robust to over-fitting so a large number usually results in better performance. max_depth : integer, optional (default=3) maximum depth of the individual regression estimators. The maximum depth limits the number of nodes in the tree. Tune this parameter for best performance; the best value depends on the interaction of the input variables criterion : string, optional (default=”gini”) The function to measure the quality of a split. Supported criteria are “gini” for the Gini impurity and “entropy” for the information gain. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) n_estimators = [20,80] max_depth= [5,10] criterion = ["gini","entropy"] param_grid = dict(n_estimators=n_estimators, max_depth=max_depth, criterion = criterion ) model = ExtraTreesClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[94]: # Grid Search : NN algorithm tuning ''' hidden_layer_sizes : tuple, length = n_layers - 2, default (100,) The ith element represents the number of neurons in the ith hidden layer. Other Parameters that can be tuned learning_rate_init : double, optional, default 0.001 The initial learning rate used. It controls the step-size in updating the weights. Only used when solver=’sgd’ or ‘adam’. max_iter : int, optional, default 200 Maximum number of iterations. The solver iterates until convergence (determined by ‘tol’) or this number of iterations. For stochastic solvers (‘sgd’, ‘adam’), note that this determines the number of epochs (how many times each data point will be used), not the number of gradient steps. ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) hidden_layer_sizes=[(20,), (50,), (20,20), (20, 30, 20)] param_grid = dict(hidden_layer_sizes=hidden_layer_sizes) model = MLPClassifier() kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # In[95]: # Grid Search : Deep Neural Network algorithm tuning ''' neurons: int Number of patterns shown to the network before the weights are updated. batch_size: int Number of observation to read at a time and keep in memory. epochs: int Number of times that the entire training dataset is shown to the network during training. activation: The activation function controls the non-linearity of individual neurons and when to fire. learn_rate :int controls how much to update the weight at the end of each batch momentum : int momentum controls how much to let the previous update influence the current weight update ''' scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) #Hyperparameters that can be modified neurons = [1, 5, 10, 15] batch_size = [10, 20, 40, 60, 80, 100] epochs = [10, 50, 100] activation = ['softmax', 'softplus', 'softsign', 'relu', 'tanh', 'sigmoid', 'hard_sigmoid', 'linear'] learn_rate = [0.001, 0.01, 0.1, 0.2, 0.3] momentum = [0.0, 0.2, 0.4, 0.6, 0.8, 0.9] #Changing only Neurons for the sake of simplicity param_grid = dict(neurons=neurons) model = KerasClassifier(build_fn=create_model, epochs=50, batch_size=10, verbose=0) kfold = KFold(n_splits=num_folds, random_state=seed) grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring=scoring, cv=kfold) grid_result = grid.fit(rescaledX, Y_train) #Print Results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] ranks = grid_result.cv_results_['rank_test_score'] for mean, stdev, param, rank in zip(means, stds, params, ranks): print("#%d %f (%f) with: %r" % (rank, mean, stdev, param)) # # # 7. Finalise the Model # Looking at the details above GBM might be worthy of further study, but for now SVM shows a lot of promise as a low complexity and stable model for this problem. # # Finalize Model with best parameters found during tuning step. # # ## 7.1. Results on the Test Dataset # In[96]: # prepare model scaler = StandardScaler().fit(X_train) rescaledX = scaler.transform(X_train) model = GradientBoostingClassifier(n_estimators=20, max_depth=5) # rbf is default kernel model.fit(X_train, Y_train) # In[97]: # estimate accuracy on validation set rescaledValidationX = scaler.transform(X_validation) predictions = model.predict(X_validation) print(accuracy_score(Y_validation, predictions)) print(confusion_matrix(Y_validation, predictions)) print(classification_report(Y_validation, predictions)) # In[98]: predictions # In[99]: Y_validation # # ## 7.2. Variable Intuition/Feature Importance # Looking at the details above GBM might be worthy of further study, but for now SVM shows a lot of promise as a low complexity and stable model for this problem. # Let us look into the Feature Importance of the GBM model # In[100]: import pandas as pd import numpy as np model = GradientBoostingClassifier() model.fit(rescaledX,Y_train) print(model.feature_importances_) #use inbuilt class feature_importances of tree based classifiers #plot graph of feature importances for better visualization feat_importances = pd.Series(model.feature_importances_, index=X.columns) feat_importances.nlargest(10).plot(kind='barh') pyplot.show() # # ## 7.3. Save Model for Later Use # In[101]: # Save Model Using Pickle from pickle import dump from pickle import load # save the model to disk filename = 'finalized_model.sav' dump(model, open(filename, 'wb')) # In[102]: # some time later... # load the model from disk loaded_model = load(open(filename, 'rb')) # estimate accuracy on validation set rescaledValidationX = scaler.transform(X_validation) predictions = model.predict(rescaledValidationX) result = accuracy_score(Y_validation, predictions) print(result)