<jupyter_start><jupyter_text>Real Life Case Example Building Insight & Communicating  FrameThe busienss objective in this loan default case is to minimize the loss given default. So we need to define a loss function for our problem.Let us take a simple assumption that we will make 10% of the amount if we make a successful loan, but we will only recover 80% of the loan amount if it defaults - Successful loan = amount * 10%- Default loan  = - amount * 80%<jupyter_code>#Load the libraries
import numpy as np
import pandas as pd
%matplotlib inline
from plotnine import *
import ipywidgets as widgets
from ipywidgets import interact, interactive,fixed, interact_manual, IntSlider<jupyter_output>/Users/amitkaps/miniconda3/lib/python3.6/site-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
  from pandas.core import datetools<jupyter_text>Acquire<jupyter_code>#Load the training dataset
df = pd.read_csv("../data/loan_unbalanced.csv")<jupyter_output><empty_output><jupyter_text>Refine<jupyter_code>df.isnull().sum()
df.years = df.years.fillna(np.mean(df.years))<jupyter_output><empty_output><jupyter_text>Explore<jupyter_code>pd.crosstab(df.default, df.grade)
ggplot(df) + aes('grade', 'default', color='default') + geom_col() + facet_wrap('default')<jupyter_output><empty_output><jupyter_text>Transform<jupyter_code>from sklearn.model_selection import train_test_split
X = df.iloc[:,1:]
y = df.iloc[:,0]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify = y )
df_train = df[df.index.isin(X_train.index)]
df_test = df[df.index.isin(X_test.index)]
df_test.head()
X_test.head()<jupyter_output><empty_output><jupyter_text>Model<jupyter_code>from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib

# read the encoders and the model
grade_encoder = joblib.load("../notebooks/le_grade.pkl")
ownership_encoder = joblib.load("../notebooks/le_ownership.pkl")

def train_model(X,y):
    """Trains a random forest model based on the training data
    """
    X_copy = X.copy()
    
     # encoders the features 
    X_copy['grade_encoded'] = grade_encoder.transform(X_copy.grade)
    X_copy['ownership_encoded'] = ownership_encoder.transform(X_copy.ownership)
    X_t = X_copy[['amount', 'grade_encoded', 'years', 'ownership_encoded', 'income', 'age']]
    
    # Train the model
    from sklearn.ensemble import RandomForestClassifier
    clf = RandomForestClassifier(n_estimators = 100, class_weight= {0: 1, 1: 1000})
    clf = clf.fit(X_t,y)
    
    return clf
    
model = train_model(X_train, y_train)
clf = train_model(X_train, y_train)
def predict_test(X, y, model):
    """Returns the probablity of default for the dataframe based on a model.
    """
    
    X_copy = X.copy()
    df_copy = df.copy()
    
    
    # encoders for 
    X_copy['grade_encoded'] = grade_encoder.transform(X_copy.grade)
    X_copy['ownership_encoded'] = ownership_encoder.transform(X_copy.ownership)
    
    # important to pass the features in the same order as we built the model
    X_t = X_copy[['amount', 'grade_encoded', 'years', 'ownership_encoded', 'income', 'age']]
    
    # probablity for defaulting
    p1 = model.predict_proba(X_t)[:, 1]
    pred_df = pd.DataFrame({"default": np.array(y), "amount": np.array(X.amount), "proba": p1})
    
    # Binning the probability & counts in each bin
    pred_df['proba_bin'] = np.round(pred_df.proba*100, decimals=0)/100
    pred_df['proba_bin_count'] = (pred_df.sort_values(by = ["proba_bin", "default"])
                                        .groupby(['proba_bin'])
                                        .cumcount() + 1)
    
    return pred_df
    
test_out = predict_test(X_test, y_test, clf)
test_out.head()
def get_test_prediction(df, threshold): 
    ''' Code the accuracy based on threshold
    '''
    
    df1 = df.copy()
    
    ## Get class prediction
    df1['pred'] = 0
    df1.loc[df1.proba_bin>=threshold, 'pred'] = 1
    
    ## Make input-ouput code
    df1['pred_class'] = "00"
    df1.loc[(df1.default == 0) & (df1.pred == 1), 'pred_class'] = "01"
    df1.loc[(df1.default == 1) & (df1.pred == 0), 'pred_class'] = "10"
    df1.loc[(df1.default == 1) & (df1.pred == 1), 'pred_class'] = "11"

    return df1
get_test_prediction(test_out, 0.4).head()
def plot_test_prediction(df, threshold):
    df1 = get_test_prediction(df,threshold)
    g = (ggplot(df1) + 
         aes('proba_bin', 'proba_bin_count', fill='pred_class') + 
         geom_tile(color = "white") + scale_fill_manual(['#ca0020','#f4a582','#92c5de','#0571b0']) +
         xlab("threshold") + ylab("count") )
    print(g)
plot_test_prediction(test_out, 0.2)
threshold_widget = widgets.FloatSlider(min=0.0, max=1.0, step=0.01, value=0.2)
interactive(plot_test_prediction, df=fixed(test_out), threshold = threshold_widget)<jupyter_output><empty_output><jupyter_text>InsightLets calculate the loss for the calculation<jupyter_code>def loss(df, threshold):
    df1 = get_test_prediction(df, threshold)
    success = df1.loc[(df1.pred == 0) & (df1.default == 0), 'amount' ].sum() * 0.1
    failure = df1.loc[(df1.pred == 0) & (df1.default == 1), 'amount' ].sum() * -0.8
    loss = success + failure
        
    return loss    
loss(test_out, 0.4)
def plot_loss(df):
    thresh = np.arange(0,1,0.01)
    loss_calc = [loss(test_out, x) for x in thresh]
    df_ = pd.DataFrame({"threshold": thresh, "loss": loss_calc})        
    return df_
lossdf = plot_loss(test_out)
ggplot(lossdf) + aes('threshold', 'loss') + geom_line()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13387210119465917, 'fraction_numerical': 0.02178496134926212, 'mean_word_length': 4.180163785259326, 'pattern_counts': {'":': 5, '<': 28, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '173490', 'license': 'MIT', 'n_tokens_mistral': 2102, 'n_tokens_neox': 2013, 'n_words': 445, 'path': 'credit-risk/notebooks/3-Insight.ipynb', 'repo_name': 'mohamedelkansouli/python_fullstack', 'size': '5692'}