<jupyter_start><jupyter_text>Financial Inclusion in Africa  Background InformationFinancial inclusion is the main obstacles to economic and human development in Africa as per studies and research conducted. Only 13.9% of the Adult population is estimated to have access to commercial bank accounts.Acces to a bank account is a contributor to long term economic growth  GOAlPredict which individuals in Kenya,Uganda,Tanzania and Rwanda are most likely to have or use a bank account.   In the process reveal insights into some of the key demographic factors that might drive individuals’ financial outcomes.  Importing essential modules<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import os
import platform
def set_seed(SEED=42):
    np.random.seed = SEED
    os.environ['PYTHONHASHSEED'] = str(SEED)
    
set_seed()
version = platform.python_version()
print("Python : ",version)
print("Pandas : ",pd.__version__)
print("NumPy : ",np.__version__)
print("Seaborn : ",sns.__version__)<jupyter_output>Python :  3.8.3
Pandas :  1.1.1
NumPy :  1.19.0
Seaborn :  0.11.0<jupyter_text>Getting our data<jupyter_code>train = pd.read_csv('datasets/Train_v2.csv')
test = pd.read_csv('datasets/Test_v2.csv')
variable = pd.read_csv('datasets/VariableDefinitions.csv')
Submission = pd.read_csv('datasets/SubmissionFile.csv')<jupyter_output><empty_output><jupyter_text>Visualize and understand our data<jupyter_code>train.head()
train.shape
variable
train.info()
train.bank_account.replace(['Yes','No'],[1,0],inplace = True)
train.head()<jupyter_output><empty_output><jupyter_text>Visualize Categorical values to establish patterns and insights<jupyter_code>a = sns.barplot(x="year",y="bank_account",data=train)
a = a.set_ylabel("bank_account")<jupyter_output><empty_output><jupyter_text>It seems that the probability of having a bank account for an individual in year 2018 is high as compared to other years<jupyter_code>b = sns.barplot(x="location_type",y="bank_account",data=train)
b = b.set_ylabel("bank_account")
c = sns.barplot(x="cellphone_access",y="bank_account",data=train)
c = c.set_ylabel("bank_account")
d = sns.barplot(x="gender_of_respondent",y="bank_account",data=train)
d = d.set_ylabel("bank_account")
d = sns.barplot(x="relationship_with_head",y="bank_account",data=train)
d = d.set_ylabel("bank_account")<jupyter_output><empty_output><jupyter_text>This indicates that the elderly are less likely to have a bank account.It is also clear that if a respondent is the Head of the house, it is more likely for them to have a bank account<jupyter_code>plt.figure(figsize=(16,8))
d = sns.barplot(x="marital_status",y="bank_account",data=train)
d = d.set_ylabel("bank_account")<jupyter_output><empty_output><jupyter_text>Married individuals and those who are not aware where they stand in their relationship are more likely to have a bank account.My assumption is individuals who are not aware of their marital status are most likely to be youths already working and trying to settle<jupyter_code>plt.figure(figsize=(16,8))
d = sns.barplot(x="education_level",y="bank_account",data=train)
d = d.set_ylabel("bank_account")<jupyter_output><empty_output><jupyter_text>Individuals in tertiary and vocational training are most likely to have a bank account<jupyter_code>plt.figure(figsize=(16,8))
d = sns.barplot(x="job_type",y="bank_account",data=train)
d.set_xticklabels(d.get_xticklabels(), rotation=45, horizontalalignment='right')
d = d.set_ylabel("bank_account")<jupyter_output><empty_output><jupyter_text>Individuals sith formal employment are more likely to have a bank account. In summary we can say that an individual in formal employment, Who is the head of the house hold,with a vocation or tertially education, Married or about to get married(Dont Know-- likely in their prime youthful days),urban resident, with phone access, and surveyed in the year 2018 has 95 percent chance of having a bank account  Feature EngineeringWe concatenate the two datasets to achieve uniform feature conversions during thid exercise<jupyter_code>train_len = len(train)
train_test = pd.concat([train,test],axis=0).reset_index(drop=True)
train_test.info()
# Descriptive Analytics
tot_len = len(train_test.columns.tolist())
print('columns present are \n {} \n No of columns is {}'.format(train_test.columns.tolist(),tot_len))
train_test.count() # total number of values per column
leng = len(train_test.describe().keys().tolist())
print("No of numeric features is ", leng)
print("Number of non-numeric features are: ", tot_len-leng)
# visualize unique values in all the categorical features
n = train_test.nunique(axis=0)
print("unique values in each column are: \n", n)<jupyter_output>unique values in each column are: 
 country                       4
year                          3
uniqueid                  12480
bank_account                  2
location_type                 2
cellphone_access              2
household_size               20
age_of_respondent            85
gender_of_respondent          2
relationship_with_head        6
marital_status                5
education_level               6
job_type                     10
dtype: int64<jupyter_text>Categorical features that can be encoded are    * country    * year    * bank_account    * cellphone_access    * gender_of_respondent    * location_type<jupyter_code># Getting Dummies
def getdummies(dataset,col,pref):
    dataset = pd.get_dummies(dataset, columns = col, prefix=pref)
    return dataset
train_test = getdummies(train_test,["country","year","cellphone_access","gender_of_respondent","location_type"],["co","y","ce","g","l"])
train_test.head()
# lets drop the uniqueid since its insignificant
train_test.drop(columns=["uniqueid"],,inplace=True)
def unique_vals(col):
    pd.unique(train_test.col)
# Unique columns in ralationship column
print("relationship with head unique vals",unique_vals(relationship_with_head))
print("marital_status unique vals",unique_vals(marital_status)
print("education_level unique vals",unique_vals(education_level)
print("job_unique vals",unique_vals(job_type)
# Transforming the relationship column
def col_transform(dataset,col,vals,reps): 
        dataset[col].replace(vals,reps,inplace = True)
col_transform(train_test,'relationship_with_head',['Spouse','Head of Household','Other relative','Child','Parent','Other non-relatives'],['S','H','O_R','C','P','N_R'])
# Transform marital_status column
col_transform(train_test,'marital_status',['Married/Living together','Widowed','Single/Never Married','Divorced/Seperated','Dont know'],['M','W','S','D','DN'])
# Transform education_level column
col_transform(train_test,'education_level',['Secondary education','No formal education','Vocational/Specialised training','Primary education','Tertiary education','Other/Dont know/RTA'],['S','N','V','P','T','ODR'])
# Transform job_type column
col_transform(train_test,'job_type',['Self employed', 'Government Dependent',
       'Formally employed Private', 'Informally employed',
       'Formally employed Government', 'Farming and Fishing',
       'Remittance Dependent', 'Other Income',
       'Dont Know/Refuse to answer', 'No Income'],['SE','GD','FEP','IE','FEG','FF','RD','OI','DK','NI'])

# Get dummies of the remaining categorical features
train_test = getdummies(train_test,["relationship_with_head","marital_status","education_level","job_type"],["r","m","e","j"])
train_test.head()
train_test.head()
train_test.head()<jupyter_output><empty_output><jupyter_text>Modelling Models to test    SVC    Decision Tree    AdaBoost    Random Forest    KNN    Logistic regression Other Models That can be used    Extra Trees    Gradient Boosting    Multiple layer perceprton (neural network)    Linear Discriminant Analysis<jupyter_code># obtain back our train and test datasets
train = train_test[:train_len]
testf = train_test[train_len:]
testf.drop(labels=["bank_account"],axis = 1,inplace=True)
## Separate train features and label 

#train["bank_account"] = train["bank_account"].astype(int)

Y_train = train["bank_account"]

X_train = train.drop(labels = ["bank_account"],axis = 1)
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, cross_val_score, StratifiedKFold,train_test_split
from sklearn.metrics import precision_score, recall_score,f1_score,confusion_matrix


sns.set(style='white', context='notebook', palette='deep')<jupyter_output><empty_output><jupyter_text>Evaluating our models with    * Dimension Reduction    * Without Reduction  We start without Reduction  Lets try and Rescale our data to see its effecton overall perfomance<jupyter_code># minimal error before this action is 0.113..Random Forest
from sklearn.preprocessing import MinMaxScaler  
scaler = MinMaxScaler(feature_range=(0, 1))  

X_train_rescaled = scaler.fit_transform(X_train)
testf_rescaled = scaler.fit_transform(testf)
xtrain, xtest, ytrain, ytest = train_test_split(X_train_rescaled, Y_train, train_size=0.65,test_size=0.35, random_state=42)
# Cross validate model with Kfold stratified cross val
kfold = StratifiedKFold(n_splits=10)
# KFold?
# Modeling step To Test differents algorithms 
classifiers = []
classifiers.append(SVC())
classifiers.append(DecisionTreeClassifier())
classifiers.append(AdaBoostClassifier(DecisionTreeClassifier(),learning_rate=0.1))
classifiers.append(RandomForestClassifier())
classifiers.append(KNeighborsClassifier())
classifiers.append(LogisticRegression())

cv_results = []
for classifier in classifiers :
    cv_results.append(cross_val_score(classifier, xtrain, y = ytrain, scoring = "accuracy", cv = kfold, n_jobs=4))

cv_means = []
cv_std = []
for cv_result in cv_results:
    cv_means.append(cv_result.mean())
    cv_std.append(cv_result.std())

#misclassification error
MSE = [1-x for x in cv_means]
#optimal Model
optimal_model_index = MSE.index(min(MSE))
optimal_model = classifiers[optimal_model_index]
print("Optimal Model based on misclassification error Is: ",optimal_model)
print("Minimal Error of our optimal model is:",min(MSE))


cv_res = pd.DataFrame({"CrossValMeans":cv_means,"CrossValerrors": cv_std,"Algorithm":["SVC","DecisionTree","AdaBoost",
"RandomForest","KNeighboors","LogisticRegression"]})

# Visualize the model perfomance
g = sns.barplot("CrossValMeans","Algorithm",data = cv_res, palette="Set3",orient = "h",**{'xerr':cv_std})
g.set_xlabel("Mean Accuracy")
g = g.set_title("Cross validation scores")
# Lets Evaluate Our Best Two models
# In this case LogisticRegression and SVC
optimal_model.fit(xtrain,ytrain)
scores = optimal_model.predict(xtest)
# secod best model is classifiers[4]
classifiers[4].fit(xtrain,ytrain)
scores2 = classifiers[4].predict(xtest)
# Evaluating model perfomance using confusion matrix metrics

print(optimal_model," precision score is : ",precision_score(ytest,scores))
print(optimal_model," Recall score is : ",recall_score(ytest,scores))
print(optimal_model," F1 score is : ",f1_score(ytest,scores))

print(classifiers[4]," Precision score is : ",precision_score(ytest,scores2))
print(classifiers[4]," Recall score is : ",recall_score(ytest,scores2))
print(classifiers[4]," F1 score is : ",f1_score(ytest,scores2))
# confusion matrix
print(optimal_model," Confusion matrix: ")
confusion_matrix(ytest,scores)
print(classifiers[4]," Confusion matrix: ")
confusion_matrix(ytest,scores2)<jupyter_output>KNeighborsClassifier()  Confusion matrix:<jupyter_text>It is Clear that our LogisticRegression model perfoms better than the KneighboursClassifier<jupyter_code>Submission.head()
final_results = list(map(float,optimal_model.predict(testf_rescaled)))
Submission['Bank_account'] = final_results
Submission['uniqueid'] = test['uniqueid'].astype(str) + ' x ' +  test['country'].astype(str)
Submission = Submission[['uniqueid','Bank_account']]
Submission.Bank_account.value_counts()
Submission.to_csv('financial_inclusion2.csv', index=False)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11302271978926572, 'fraction_numerical': 0.008972670398419492, 'mean_word_length': 6.728371501272265, 'pattern_counts': {'":': 3, '<': 50, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '344439', 'license': 'MIT', 'n_tokens_mistral': 3945, 'n_tokens_neox': 3759, 'n_words': 934, 'path': 'Financial_Inclusion/Financial Inclusion-v2.ipynb', 'repo_name': 'tevish321/DataScience', 'size': '12148'}