Kaggle: Credit risk (Model: Decision Tree)

A commonly used model for exploring classification problems is the decision tree. A detailed explanation is given in the post on What are decision trees and CARTS?.

Decision trees are the building blocks for random forests and gradient boosted trees

Loading in required modules

In [2]:
# importing all system modules
import os
import sys
import warnings
from pathlib import Path
if sys.platform == 'linux':
    sys.path.append('/home/randlow/github/blog/listings/machine-learning/') # linux
elif sys.platform == 'win32':
    sys.path.append('\\Users\\randl\\github\\blog2\\listings\\machine-learning\\') # win32

# importing data science modules
import pandas as pd
import numpy as np
import sklearn
import scipy as sp
import pickleshare

# importing graphics modules
import matplotlib.pyplot as plt
import seaborn as sns

# importing personal data science modules
import rand_eda as eda

Loading pickled dataframes

To see how the below dataframes were obtained see the post on the Kaggle: Credit risk (Feature Engineering)

In [3]:
home = str(Path.home())
if sys.platform == 'linux':
    inputDir = "/datasets/kaggle/home-credit-default-risk" # linux
elif sys.platform == 'win32':
    inputDir = "\datasets\kaggle\home-credit-default-risk" # windows

storeDir = home+inputDir+'/pickleshare'

db = pickleshare.PickleShareDB(storeDir)

df_app_test_align = db['df_app_test_align'] 
df_app_train_align = db['df_app_train_align'] 
#df_app_train_align_expert  = db['df_app_train_align_expert'] 
#df_app_test_align_expert = db['df_app_test_align_expert'] 
#df_app_train_poly_align = db['df_app_train_poly_align']
#df_app_test_poly_align = db['df_app_test_poly_align'] 
['df_app_test_align', 'df_app_train_align', 'df_app_train_corr_target', 'df_app_train_align_expert', 'df_app_test_align_expert', 'df_app_train_poly_align', 'df_app_test_poly_align']

Selection of feature set for model training & testing

Assign which ever datasets you want to train and test. This is because as part of feature engineering, you will often build new and different feature datasets and would like to test each one out to evaluate whether it improves model performance.

As the imputer is being fitted on the training data and used to transform both the training and test datasets, the training data needs to have the same number of features as the test dataset. This means that the TARGET column must be removed from the training dataset, and stored in train_labels for use later.

In [4]:
train = df_app_train_align.copy()
test = df_app_test_align.copy()

train_labels = train.pop('TARGET')
feat_names = list(train.columns)

Feature set preprocessing

In [5]:
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(missing_values=np.nan,strategy='median')

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range= (0,1))

We fit the imputer and scaler on the training data, and perform the imputer and scaling transformations on both the training and test datasets.

Scikit-learn models only accept arrays. So the imputer and scalers can accept DataFrames as inputs and they output the train and test variables as arrays for use into Scikit-Learn's machine learning models.

In [6]:
train = imputer.transform(train)
test = imputer.transform(test)

train = scaler.transform(train)
test = scaler.transform(test)

Model implementation (Decision Tree)

In [7]:
from sklearn import tree
from sklearn.model_selection import train_test_split

dtree = tree.DecisionTreeClassifier(random_state=50,max_depth=5)
dtree = dtree.fit(train,train_labels)

Drawing the decision tree

  • export_graphviz generates the decision tree classifier into a dot file.
  • graphviz.Source().render() accepts a dot file and renders it into the specified format.
  • Image() displays it in the JupyterNotebook
In [8]:
import graphviz
from IPython.display import Image
dot_data = tree.export_graphviz(dtree,out_file=None,
                    filled=True, rounded=True,
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-8-8b7c3c3ed8dc> in <module>
----> 1 import graphviz
      2 from IPython.display import Image
      3 dot_data = tree.export_graphviz(dtree,out_file=None,
      4                     filled=True, rounded=True,
      5                     special_characters=True,

ModuleNotFoundError: No module named 'graphviz'

We apply our fitted decision tree to predict the TARGET outcomes from the test dataset

In [9]:
dtree_pred = dtree.predict_proba(test)[:,1]

Kaggle submission

We create the submission dataframe as per the Kaggle home-credit-default-risk competition guidelines

In [10]:
submit = pd.DataFrame()
submit['SK_ID_CURR'] = df_app_test_align.index
submit['TARGET'] = dtree_pred
0      100001  0.079853
1      100005  0.103296
2      100013  0.022893
3      100028  0.034714
4      100038  0.088519
(48744, 2)

Submit the csv file to Kaggle for scoring

In [11]:
!kaggle competitions submit -c home-credit-default-risk -f decision-tree-home-loan-credit-risk.csv -m 'submitted'
100%|██████████████████████████████████████| 1.25M/1.25M [00:00<00:00, 1.43MB/s]
Successfully submitted to Home Credit Default Risk

We review our decision tree scores from Kaggle and find that there is a slight improvement to 0.697 compared to 0.662 based upon the logit model (publicScore). We will try other featured engineering datasets and other more sophisticaed machine learning models in the next posts.

In [12]:
!kaggle competitions submissions -c home-credit-default-risk
fileName                                 date                 description  status    publicScore  privateScore  
---------------------------------------  -------------------  -----------  --------  -----------  ------------  
decision-tree-home-loan-credit-risk.csv  2019-02-23 17:11:25  submitted    complete  0.69792      0.68776       
lightgbm-home-loan-credit-risk.csv       2019-02-19 04:16:44  submitted    complete  0.74158      0.74351       
random-forest-home-loan-credit-risk.csv  2019-02-19 04:15:01  submitted    complete  0.74158      0.74351       
random-forest-home-loan-credit-risk.csv  2019-02-11 17:31:03  submitted    complete  0.68694      0.68886       
random-forest-home-loan-credit-risk.csv  2019-02-11 05:24:55  submitted    complete  0.68694      0.68886       
random-forest-home-loan-credit-risk.csv  2019-02-11 05:10:40  submitted    complete  0.68694      0.68886       
logit-home-loan-credit-risk.csv          2019-02-11 04:52:51  submitted    complete  0.66223      0.67583       
random-forest-home-loan-credit-risk.csv  2019-02-11 04:44:50  submitted    complete  0.68694      0.68886       
logit-home-loan-credit-risk.csv          2019-02-08 04:08:33  submitted    complete  0.66223      0.67583       

Converting iPython notebook to Python code

This allows us to run the code in Spyder.

In [13]:
!jupyter nbconvert ml_kaggle-home-loan-credit-risk-model-decision-tree.ipynb --output-dir='~/github/blog2/listings/machine-learning/' --to python
[NbConvertApp] WARNING | pattern 'ml_kaggle-home-loan-credit-risk-model-decision-tree.ipynb' matched no files
This application is used to convert notebook files (*.ipynb) to various other



Arguments that take values are actually convenience aliases to full
Configurables, whose aliases are listed on the help line. For more information
on full configurables, see '--help-all'.

    set log level to logging.DEBUG (maximize logging output)
    generate default config file
    Answer yes to any questions instead of prompting.
    Execute the notebook prior to export.
    Continue notebook execution even if one of the cells throws an error and include the error message in the cell output (the default behaviour is to abort conversion). This flag is only relevant if '--execute' was specified, too.
    read a single notebook file from stdin. Write the resulting notebook with default basename 'notebook.*'
    Write notebook output to stdout instead of files.
    Run nbconvert in place, overwriting the existing notebook (only 
    relevant when converting to notebook format)
    Clear output of current file and save in place, 
    overwriting the existing notebook.
    Exclude input and output prompts from converted document.
    Exclude input cells and output prompts from converted document. 
    This mode is ideal for generating code-free reports.
--log-level=<Enum> (Application.log_level)
    Default: 30
    Choices: (0, 10, 20, 30, 40, 50, 'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL')
    Set the log level by value or name.
--config=<Unicode> (JupyterApp.config_file)
    Default: ''
    Full path of a config file.
--to=<Unicode> (NbConvertApp.export_format)
    Default: 'html'
    The export format to be used, either one of the built-in formats, or a
    dotted object name that represents the import path for an `Exporter` class
--template=<Unicode> (TemplateExporter.template_file)
    Default: ''
    Name of the template file to use
--writer=<DottedObjectName> (NbConvertApp.writer_class)
    Default: 'FilesWriter'
    Writer class used to write the  results of the conversion
--post=<DottedOrNone> (NbConvertApp.postprocessor_class)
    Default: ''
    PostProcessor class used to write the results of the conversion
--output=<Unicode> (NbConvertApp.output_base)
    Default: ''
    overwrite base name use for output files. can only be used when converting
    one notebook at a time.
--output-dir=<Unicode> (FilesWriter.build_directory)
    Default: ''
    Directory to write output(s) to. Defaults to output to the directory of each
    notebook. To recover previous default behaviour (outputting to the current
    working directory) use . as the flag value.
--reveal-prefix=<Unicode> (SlidesExporter.reveal_url_prefix)
    Default: ''
    The URL prefix for reveal.js (version 3.x). This defaults to the reveal CDN,
    but can be any url pointing to a copy  of reveal.js.
    For speaker notes to work, this must be a relative path to a local  copy of
    reveal.js: e.g., "reveal.js".
    If a relative path is given, it must be a subdirectory of the current
    directory (from which the server is run).
    See the usage documentation
    slideshow) for more details.
--nbformat=<Enum> (NotebookExporter.nbformat_version)
    Default: 4
    Choices: [1, 2, 3, 4]
    The nbformat version to write. Use this to downgrade notebooks.

To see all available configurables, use `--help-all`


    The simplest way to use nbconvert is
    > jupyter nbconvert mynotebook.ipynb
    which will convert mynotebook.ipynb to the default format (probably HTML).
    You can specify the export format with `--to`.
    Options include ['asciidoc', 'custom', 'html', 'latex', 'markdown', 'notebook', 'pdf', 'python', 'rst', 'script', 'slides']
    > jupyter nbconvert --to latex mynotebook.ipynb
    Both HTML and LaTeX support multiple output templates. LaTeX includes
    'base', 'article' and 'report'.  HTML includes 'basic' and 'full'. You
    can specify the flavor of the format used.
    > jupyter nbconvert --to html --template basic mynotebook.ipynb
    You can also pipe the output to stdout, rather than a file
    > jupyter nbconvert mynotebook.ipynb --stdout
    PDF is generated via latex
    > jupyter nbconvert mynotebook.ipynb --to pdf
    You can get (and serve) a Reveal.js-powered slideshow
    > jupyter nbconvert myslides.ipynb --to slides --post serve
    Multiple notebooks can be given at the command line in a couple of 
    different ways:
    > jupyter nbconvert notebook*.ipynb
    > jupyter nbconvert notebook1.ipynb notebook2.ipynb
    or you can specify the notebooks list in a config file, containing::
        c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
    > jupyter nbconvert --config mycfg.py

In [ ]:


Comments powered by Disqus