GithubHelp home page GithubHelp logo

liulinxmu / financial_inclusion_africa Goto Github PK

View Code? Open in Web Editor NEW

This project forked from allisterh/financial_inclusion_africa

0.0 0.0 0.0 602 KB

Analysis of the dataset "Financial Inclusion in Africa"

R 100.00%

financial_inclusion_africa's Introduction

Introdução

Esse repositório contém códigos do desafio Zindi Africa. Aqui, é descrito todo o processo para chegar no resultado final. Os códigos completos do estudo estão no arquivo CaseAnaliseDados.R. Os dados, obtidos de https://zindi.africa/competitions/financial-inclusion-in-africa/data estão na pasta data.

O objetivo é fazer um modelo que identifique quais pessoas possuem conta no banco, correspondente a variável bank_account.

O desafio foi feito na linguagem R e as etapas do processo são:

  • Análise exploratória dos dados
  • Balanceamento de variáveis
  • Modelagem
  • Resultados

Importações

Os pacotes data.table e tidyverse (que inclui dplyr, tidyr e outros) serão utilizados para as operações de data wrangling. Para as visualizações, utilizarei o ggplot2 (incluído no tidyverse) e magick; enquanto que os pacotes caret, pROC e xgboost serão utilizados na parte de machine learning.

Os dados originais estão divididos entre treino e teste, sendo que o teste não contém a variável resposta.

Análise Exploratória dos Dados

names(train)
##  [1] "country"                "year"                   "uniqueid"              
##  [4] "bank_account"           "location_type"          "cellphone_access"      
##  [7] "household_size"         "age_of_respondent"      "gender_of_respondent"  
## [10] "relationship_with_head" "marital_status"         "education_level"       
## [13] "job_type"

A descrição das variáveis está contida no arquivo VariableDefinitions.csv, que são as seguintes:

  • country: País do entrevistado
  • year: Ano da entrevista
  • uniqueid: Identificação única do entrevistado
  • location_type: Tipo da localização, se urbano ou rural
  • cellphone_access: Se o entrevistado tem acesso a celular
  • household_size: Número de pessoas vivendo no domicílio do entrevistado
  • age_of_respondent: Idade do entrevistado
  • gender_of_respondent: Sexo do entrevistado
  • relationship_with_head: Relação do entrevistado com o (a) chefe de família
  • marital_status: Estado civil do entrevistado
  • education_level: Nível de educação do entrevistado
  • job_type: Tipo do emprego do entrevistado

Uma boa maneira de termos um overview do dataset e suas variáveis é simplesmente utilizarmos a função summary, que vai nos dar algumas estatísticas básicas. Antes, iremos transformar algumas variáveis de character para factor. Isso fará sentido para a modelagem, e também para o summary, que irá nos dar algumas estatísticas a mais do que se fosse ainda um character.

cols <- train[, lapply(.SD, function(x) {is.character(x)})]
cols <- setDT(as.data.frame(t(cols)), keep.rownames = T)
cols <- cols[V1==T & rn != 'uniqueid']

train[, (cols$rn) := lapply(.SD, as.factor), .SDcols = cols$rn]

summary(train)
##      country          year        uniqueid         bank_account location_type
##  Kenya   :6068   Min.   :2016   Length:23524       No :20212    Rural:14343  
##  Rwanda  :8735   1st Qu.:2016   Class :character   Yes: 3312    Urban: 9181  
##  Tanzania:6620   Median :2017   Mode  :character                             
##  Uganda  :2101   Mean   :2017                                                
##                  3rd Qu.:2018                                                
##                  Max.   :2018                                                
##                                                                              
##  cellphone_access household_size age_of_respondent gender_of_respondent
##  No : 6070        Min.   : 1.0   Min.   : 16.0     Female:13877        
##  Yes:17454        1st Qu.: 2.0   1st Qu.: 26.0     Male  : 9647        
##                   Median : 3.0   Median : 35.0                         
##                   Mean   : 3.8   Mean   : 38.8                         
##                   3rd Qu.: 5.0   3rd Qu.: 49.0                         
##                   Max.   :21.0   Max.   :100.0                         
##                                                                        
##          relationship_with_head                 marital_status 
##  Child              : 2229      Divorced/Seperated     : 2076  
##  Head of Household  :12831      Dont know              :    8  
##  Other non-relatives:  190      Married/Living together:10749  
##  Other relative     :  668      Single/Never Married   : 7983  
##  Parent             : 1086      Widowed                : 2708  
##  Spouse             : 6520                                     
##                                                                
##                         education_level                       job_type   
##  No formal education            : 4515   Self employed            :6437  
##  Other/Dont know/RTA            :   35   Informally employed      :5597  
##  Primary education              :12791   Farming and Fishing      :5441  
##  Secondary education            : 4223   Remittance Dependent     :2527  
##  Tertiary education             : 1157   Other Income             :1080  
##  Vocational/Specialised training:  803   Formally employed Private:1055  
##                                          (Other)                  :1387

Há um desbalanço na variável resposta. Isso deve ser levado em consideração na hora de treinar o modelo, pois datasets desbalanceados podem influenciar no resultado do modelo.

Os países apresentam taxas diferentes de pessoas com contas bancárias.

Modelagem

O primeiro passo a ser feito é rodar um modelo de machine learning e vermos os resultados iniciais obtidos, para então tomarmos a decisão de que caminho seguir. Como não temos a variável resposta no dataset de teste, iremos criar um dataset de validação a partir do dataset de treino, que ficará de fora do treinamento do nosso modelo, para que possamos avaliar como ele está performando.

O pacote caret tem uma função que facilita o processo de dividir o dataset de maneira distribuida como o dataset original. 75% do dataset original permaneceu no dataset de treino, e 25% ficou separado no de validação.

trainIndex <- createDataPartition(train$bank_account, p = .75, 
                                  list = FALSE, times = 1)

validation <- train[-trainIndex]
train <- train[trainIndex]

y_train <- as.factor(train$bank_account)
y_validation <- as.factor(validation$bank_account)

train <- train[, -'year', with=F]
validation <- validation[, -'year', with=F]

Para treinar nosso primeiro modelo, utilizaremos a metodologia Random Forest, modelo não-paramétrico que se adapta bem a diversos tipos de dataset. Ele utiliza apenas um hiperparâmetro, o mtry. Uma regra de bolso é utilizar a raiz quadrada do número de variáveis do dataset para o mtry. Também utilizaremos o método de Cross Validation.

trcontrol = trainControl( method = "cv",
                          number = 5,  
                          allowParallel = TRUE,
                          verboseIter = TRUE )

mtry <- sqrt(ncol(train[, -'bank_account', with=F]))
tunegrid <- expand.grid(.mtry=mtry)

rf_model <- train(x = train[, -'bank_account', with=F], 
                  y = y_train,
                  trControl = trcontrol,
                  tuneGrid = tunegrid,
                  method = "rf")

Depois de rodarmos o modelo, iremos avaliar a sua performance. Para isso, iremos comparar a acurácia das previsões tanto no treino de teste, quando no de validação, que separamos apenas para isso. Se a performance no treino de validação não for muito inferior a de teste, quer dizer que nosso modelo pode performar bem em dados futuros, não apresentando overfit.

Matriz de Confusão do treino

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    No   Yes
##        No  15060  1081
##        Yes    99  1403
##                                              
##                Accuracy : 0.933              
##                  95% CI : (0.929, 0.937)     
##     No Information Rate : 0.859              
##     P-Value [Acc > NIR] : <0.0000000000000002
##                                              
##                   Kappa : 0.669              
##                                              
##  Mcnemar's Test P-Value : <0.0000000000000002
##                                              
##             Sensitivity : 0.993              
##             Specificity : 0.565              
##          Pos Pred Value : 0.933              
##          Neg Pred Value : 0.934              
##              Prevalence : 0.859              
##          Detection Rate : 0.854              
##    Detection Prevalence : 0.915              
##       Balanced Accuracy : 0.779              
##                                              
##        'Positive' Class : No                 
## 

Matriz de Confusão da validação

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  4917  553
##        Yes  136  275
##                                               
##                Accuracy : 0.883               
##                  95% CI : (0.874, 0.891)      
##     No Information Rate : 0.859               
##     P-Value [Acc > NIR] : 0.0000000522        
##                                               
##                   Kappa : 0.387               
##                                               
##  Mcnemar's Test P-Value : < 0.0000000000000002
##                                               
##             Sensitivity : 0.973               
##             Specificity : 0.332               
##          Pos Pred Value : 0.899               
##          Neg Pred Value : 0.669               
##              Prevalence : 0.859               
##          Detection Rate : 0.836               
##    Detection Prevalence : 0.930               
##       Balanced Accuracy : 0.653               
##                                               
##        'Positive' Class : No                  
## 

No dataset de treino, obtivemos uma acurácia de 0.933, e no de validação 0.883. Se fosse só por essa informação, poderíamos dizer que nosso modelo está performando bem. Porém, pelos valores de especificidade, vemos que o fato de o dataset estar desbalanceado pode estar impactando o resultado de nossas previsões.

Downsamplig

Dessa maneira, utilizaremos o método de Downsampling para obter um dataset que tenha 50% de usuários com conta em banco e 50% de usuários sem conta em banco. Datasets assim tendem a nos dar modelos que capturem melhor as nuances de ambos os valores. Para isso, mais uma vez utilizamos o pacote caret.

Apenas uma linha de comando e temos nosso novo dataset, agora balanceado.

train_ds <- downSample(train, y_train, yname = 'bank_account')
setDT(train_ds)[, .N, bank_account]
##    bank_account    N
## 1:           No 2484
## 2:          Yes 2484

Rodamos novamente o modelo de Random Forest, dessa vez no dataset balanceado o analisamos seus resultados.

y_ds <- train_ds$bank_account
train_ds <- train_ds[, -'bank_account', with=F]

rf_ds_model <- train(x = train_ds, 
                     y = y_ds,
                     trControl = trcontrol,
                     tuneLength = tunegrid,
                     method = "rf")

Matriz de Confusão do treino balanceado

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  2184  375
##        Yes  300 2109
##                                              
##                Accuracy : 0.864              
##                  95% CI : (0.854, 0.874)     
##     No Information Rate : 0.5                
##     P-Value [Acc > NIR] : <0.0000000000000002
##                                              
##                   Kappa : 0.728              
##                                              
##  Mcnemar's Test P-Value : 0.0044             
##                                              
##             Sensitivity : 0.879              
##             Specificity : 0.849              
##          Pos Pred Value : 0.853              
##          Neg Pred Value : 0.875              
##              Prevalence : 0.500              
##          Detection Rate : 0.440              
##    Detection Prevalence : 0.515              
##       Balanced Accuracy : 0.864              
##                                              
##        'Positive' Class : No                 
## 

Matriz de Confusão do modelo com downsampling aplicado na validação

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  3985  207
##        Yes 1068  621
##                                              
##                Accuracy : 0.783              
##                  95% CI : (0.772, 0.794)     
##     No Information Rate : 0.859              
##     P-Value [Acc > NIR] : 1                  
##                                              
##                   Kappa : 0.375              
##                                              
##  Mcnemar's Test P-Value : <0.0000000000000002
##                                              
##             Sensitivity : 0.789              
##             Specificity : 0.750              
##          Pos Pred Value : 0.951              
##          Neg Pred Value : 0.368              
##              Prevalence : 0.859              
##          Detection Rate : 0.678              
##    Detection Prevalence : 0.713              
##       Balanced Accuracy : 0.769              
##                                              
##        'Positive' Class : No                 
## 

Ainda que tenhamos perdido um pouco de acurácia em relação ao modelo original, o novo modelo, feito a partir do dataset balanceado com a tecnica de downsampling, nos dá resultados mais equilibrados, que podemos ver pela Sensibilidade e Especificidade.

Nota: É possível utilizar também o upsampling, que balanceia o dataset com mais observações, copiando observações da variável com menos entradas. Aqui, utilizei apenas o downsampling, mas no script de código completo, faço a avaliação dos dois métodos.

Modelagem

Agora, iremos testar outras metodologias, como o simples GLM e o XGBoost.

GLM

glm_model <- train( x = train_ds, 
                    y = y_ds,
                    trControl = trcontrol,
                    tuneLength = 5,
                    method = "glm")

Matriz de Confusão do GLM no treino balanceado

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  1982  640
##        Yes  502 1844
##                                               
##                Accuracy : 0.77                
##                  95% CI : (0.758, 0.782)      
##     No Information Rate : 0.5                 
##     P-Value [Acc > NIR] : < 0.0000000000000002
##                                               
##                   Kappa : 0.54                
##                                               
##  Mcnemar's Test P-Value : 0.0000503           
##                                               
##             Sensitivity : 0.798               
##             Specificity : 0.742               
##          Pos Pred Value : 0.756               
##          Neg Pred Value : 0.786               
##              Prevalence : 0.500               
##          Detection Rate : 0.399               
##    Detection Prevalence : 0.528               
##       Balanced Accuracy : 0.770               
##                                               
##        'Positive' Class : No                  
## 

Matriz de Confusão do GLM na validação

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  4006  208
##        Yes 1047  620
##                                              
##                Accuracy : 0.787              
##                  95% CI : (0.776, 0.797)     
##     No Information Rate : 0.859              
##     P-Value [Acc > NIR] : 1                  
##                                              
##                   Kappa : 0.38               
##                                              
##  Mcnemar's Test P-Value : <0.0000000000000002
##                                              
##             Sensitivity : 0.793              
##             Specificity : 0.749              
##          Pos Pred Value : 0.951              
##          Neg Pred Value : 0.372              
##              Prevalence : 0.859              
##          Detection Rate : 0.681              
##    Detection Prevalence : 0.717              
##       Balanced Accuracy : 0.771              
##                                              
##        'Positive' Class : No                 
## 

xGBoost

Para rodarmos o modelo de xGBoost, precisamos de algumas transformações antes. O algoritmo do modelo necessita que cada variável categórica esteja como numérica, como se fossem dummies. Assim, usamos o processo chamado One Hot Encoding. O pacote caret nos ajuda mais uma vez.

dmy_train_ds <- dummyVars('~.', data = train_ds)
train_matrix_ds <- data.table(predict(dmy_train_ds, newdata = train_ds))
train_matrix_ds <- train_matrix_ds %>% as.matrix() %>% xgb.DMatrix()


dmy_validation <- dummyVars('~.', data = validation[, -'bank_account', with = F])
validation_matrix <- data.table(predict(dmy_validation, newdata = validation[, -'bank_account', with = F]))
validation_matrix <- validation_matrix %>% as.matrix() %>% xgb.DMatrix()
xgb_model <- train( x = train_matrix_ds, 
                    y = y_ds,
                    trControl = trcontrol,
                    tuneLength = 4,
                    method = "xgbTree")

Matriz de Confusão do xGBoost no treino balanceado

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  2028  522
##        Yes  456 1962
##                                              
##                Accuracy : 0.803              
##                  95% CI : (0.792, 0.814)     
##     No Information Rate : 0.5                
##     P-Value [Acc > NIR] : <0.0000000000000002
##                                              
##                   Kappa : 0.606              
##                                              
##  Mcnemar's Test P-Value : 0.0377             
##                                              
##             Sensitivity : 0.816              
##             Specificity : 0.790              
##          Pos Pred Value : 0.795              
##          Neg Pred Value : 0.811              
##              Prevalence : 0.500              
##          Detection Rate : 0.408              
##    Detection Prevalence : 0.513              
##       Balanced Accuracy : 0.803              
##                                              
##        'Positive' Class : No                 
## 

Matriz de Confusão do xGBoost no treino balanceado

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  3992  202
##        Yes 1061  626
##                                              
##                Accuracy : 0.785              
##                  95% CI : (0.775, 0.796)     
##     No Information Rate : 0.859              
##     P-Value [Acc > NIR] : 1                  
##                                              
##                   Kappa : 0.381              
##                                              
##  Mcnemar's Test P-Value : <0.0000000000000002
##                                              
##             Sensitivity : 0.790              
##             Specificity : 0.756              
##          Pos Pred Value : 0.952              
##          Neg Pred Value : 0.371              
##              Prevalence : 0.859              
##          Detection Rate : 0.679              
##    Detection Prevalence : 0.713              
##       Balanced Accuracy : 0.773              
##                                              
##        'Positive' Class : No                 
## 

Conclusão

Os resultados dos 3 modelos foram bem parecidos, dessa maneira, entendo que temos mais vantagens ao escolhermos o mais simples, no caso o GLM. Isso porque ele nos dá parâmetros, dessa maneira podemos avaliar o impacto de cada variável na previsão. Datasets desbalanceados são bastante frequentes em casos de detecção de fraude ou detecção de câncer, por exemplo. O método de downsampling, utilizado aqui, pode ajudar a corrigir algum viés que esse desbalanço pode produzir nos modelos.

O arquivo SubmissionFile.csv está preenchido com as previsões do teste, no padrão proposto no arquivo original.

financial_inclusion_africa's People

Contributors

mevaldt avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.