- This Dataset Contain the information about the bank customer that will take loan.
- Our goal is build a model that will detect weather the customer is eligible for loan or not.
- Data should be present in 2 different files.
- Both conatin same data about bank.
- Both files also contain
-99999values. -99999are the missing values.
Data is present in another folder. Now we can read the data using os.
import os
file_paths = []
data_folder = "Data"
for filename in os.listdir(data_folder):
file_paths.append(os.path.join(os.getcwd(), data_folder, filename))
print(os.path.join(os.getcwd(), data_folder, filename))
df1=pd.read_excel(file_path[0])
df2=pd.read_excel(file_path[1])- Top records
- Shape of data
- Check columns
- Merge based on
common column - Check Datatyes
- Null values
- Duplicates
- Unique Values
- Statistical Summary
- Data1 contain
51336rows and26Column - Data2 contain
51336rows and62Column
- we can see that in
df2most of the columns contain-99999values. - These
-99999are basicallyMissing value.
final_df=df1.merge(df2,how='inner',on='PROSPECTID')final_df.dtypes- As mentioned earlier, both files contain
-99999values, which represent missing values. - Check if the ratio of
-99999values is greater in a specific column and consider removing those columns.
- After removing columns containing more than
10000-99999values, the dataframe has51336rows and79columns. - We will remove only those columns with more than
10000-99999values, but keep in mind that-99999values are also present in columns with fewer than10000occurrences.
- There are two options for handling the remaining missing values:
- We can remove the rows with missing values if the data balance allows it.
- Filling missing values is critical, especially if removing them results in significant data loss.
- After removing rows containing
-99999values, we can retain80%of the data. - We have decided to remove the missing values.
final_df.duplicated().sum()- There are
2unique values inMARITALSTATUSi-e['Married' 'Single'] - There are
7unique values inEDUCATIONi-e['12TH' 'GRADUATE' 'SSC' 'POST-GRADUATE' 'UNDER GRADUATE' 'OTHERS' 'PROFESSIONAL'] - There are
2unique values inGENDERi-e['M' 'F'] - There are
6unique values inlast_prod_enq2i-e['PL' 'ConsumerLoan' 'AL' 'CC' 'others' 'HL'] - There are
6unique values infirst_prod_enq2i-e['PL' 'ConsumerLoan' 'others' 'AL' 'HL' 'CC'] - There are
4unique values inApproved_Flagi-e['P2' 'P1' 'P3' 'P4']
- In statistics, the variance inflation factor (VIF) is a ratio that measures the severity of multicollinearity in regression analysis.
- Multicollinearity occurs when two or more independent variables in a regression model have a linear relationship, which can negatively impact regression results. The VIF measures the number of inflated variances caused by multicollinearity.
- We can apply the
VIFon numerical columns to check the relationship of each column to every other col. - If the 2 or more columns are highly corelated so we can take only one column so that i will reduce the
multicolarnarty. - If we can reduce multicolarty the column will automaticlally reduce.
- we can set the threshold ratio if the variance is greater then treshold we can drop the columns.
- if the variance is less then treshold we can keep the columns.
col_to_kepto=[]
vif_data=final_df[num_col]
column_index=0
for i in range(num_col.shape[0]):
# variance_inflation_factor(dataframe,index)
vif_value=variance_inflation_factor(vif_data,column_index)
print(i,"------->",vif_value)
if(vif_value<=6):
col_to_kept.append(num_col[i])
column_index+=1
else:
vif_data=vif_data.drop(columns=num_col[i])- After applying
variance inflence factorwe can reduce some column now the remaingnumerical column is 40
- It is a hypothesis test in this test we can check the relationship b/w numerical col to target col.
- Target col should be categorical and must contain 3 or greater then 3 categories.
- In our case our target col is
Approved_Flagwhich contain4 classes. - We can set the threshold
0.05if the p_value is greater then0.05we can drop these columns. 0.05threshold are generaly industry standard.
col_to_remaing=[]
for i in col_to_kept:
current_col=final_df[i]
targte_col=final_df[cat_col[-1]]
# Saperat each group for preforming ANOVA
group1=[value for value,group in zip(current_col,targte_col) if group=='P1']
group2=[value for value,group in zip(current_col,targte_col) if group=='P2']
group3=[value for value,group in zip(current_col,targte_col) if group=='P3']
group4=[value for value,group in zip(current_col,targte_col) if group=='P4']
# Perform ANOVA
f_stats,p_value=f_oneway(group1,group2,group3,group4)
print(i,"------>",p_value)
if(p_value<0.05):
col_to_remaing.append(i)- After
ANOVAwe can get only 38 columns.
- These test are generally perform on categorical column.
- Note that target column category should be
>=3. - Now using
chie-squaretest we can check the relationship b/w target col.
drop_col=[]
for i in cat_col[:-1]:
# Perform chie-square
chie,p_value,_,_=chi2_contingency(pd.crosstab(final_df[i],final_df[cat_col[-1]]))
print(i,"----->",p_value)
if(p_value>0.05):
drop_col.append(i)- See that all the columns
p_valueis less the0.05so we can accept all the columns.
- First we can saperate the input and output columns.
- Second we can saperate numerical and categorical columns.
- Third we can build a pipeline for some transformation.
feature=final_df.drop(columns=['Approved_Flag'])
label=final_df['Approved_Flag']from sklearn.preprocessing import LabelEncoder,OneHotEncoder,StandardScaler
lb=LabelEncoder()
label=lb.fit_transform(label)num_col=feature.select_dtypes('number').columns
cat_col=feature.select_dtypes('object').columnsfrom sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(feature,label,test_size=0.2,random_state=43)- we can build a pipeline for numercial column.
- In numerical pipeline we can scale the feature.
- we can build a pipeline for categorical column.
- In categorical pipeline we can encode the categorical column.
num_pipe=Pipeline(steps=[
("impute",SimpleImputer(strategy='median')),
('scale',StandardScaler())
])
num_pipecat_pipe=Pipeline(steps=[
("impute",SimpleImputer(strategy='most_frequent')),
('Encode',OneHotEncoder(drop='first',sparse=False,handle_unknown='ignore'))
])
cat_pipe- In column transformer we can combine al the steps.
transformer=ColumnTransformer(transformers=[
('num_transformer',num_pipe,num_col),
("Encode",cat_pipe,cat_col)
],remainder='passthrough')
transformer- In this we can train different models.
- Those model will give better result we can tune them.
model_dic={
"LogisticRegression":LogisticRegression(),
"RandomForest":RandomForestClassifier(),
"DecessionTree":DecisionTreeClassifier(),
"xgboost":XGBClassifier()
}- Fit models and also calculate the score
results={
"model_name":[],
"score":[],
'train score':[],
"test score":[],
'matrix':[]
}
for model_name,model in model_dic.items():
final=Pipeline(steps=[
("process",transformer),
("model",model)
])
# Fit the model pipe
final.fit(x_train,y_train)
# Prediction
pre=final.predict(x_test)
# Calculate score
score=accuracy_score(y_test,pre)
matrix=confusion_matrix(y_test,pre)
#Cross val score
train_score=cross_val_score(final,x_train,y_train,cv=5,scoring='accuracy')
test_score=cross_val_score(final,x_test,y_test,cv=5,scoring='accuracy')
results['model_name'].append(model_name)
results['score'].append(score)
results['train score'].append(train_score)
results['test score'].append(test_score)
results['matrix'].append(matrix)- We see that
Xgboostgive better result withaccuracy scoreof78now we can fine tune them
param_grid = {
'model__model__colsample_bytree': [0.1, 0.3, 0.5, 0.7, 0.9],
'model__model__learning_rate': [0.001, 0.01, 0.1, 1],
'model__model__max_depth': [3, 5, 8, 10],
'model__model__n_estimators': [10, 50, 100]
}
xgb_boost=XGBClassifier()
pipeline=Pipeline(steps=[
("process",transformer),
('model',xgb_boost)
])
grid_search=GridSearchCV(pipeline,param_grid=param_grid,scoring='accuracy',n_jobs=-1,cv=5)
grid_search.fit(x_train,y_train)grid_search.best_params_
pre=grid_search.predict(x_test)
preaccuracy_score(y_test,pre)confusion_matrix(y_test,pre)- After Hyperparameter Tunning we can get
78%accuracy
- Train score is: 0.7754301083695385
- Test Score is: 0.7669086472192019
