Cílem tohoto dokumentu je sestavení a ověření referenčního modelu zahájení úvěru pro stávající klienty, a to s horizonty 6 měsíců a 12 měsíců. Model s horizontem 6 měsíců je sestavený podle dat 1. 3. – 29. 8. 2018 a validován na datech 30. 8. 2018 – 28. 2. 2019.
Tento dokument vzniká v rámci podobnostního modelování ke grantu TAČR.
Analýza vychází z dat Equabank za klienty a jejich produkty. Platnost dat je podle poskytovatele od ledna 2015 do konce února 2019, nicméně v datech jsou uvedeny i produkty zahájené i skončené před lednem 2015 (a k nim odpovídající klienti).
Využité tabulky v tomto dokumentu:
Zkratka | Význam |
---|---|
RCA | běžný účet |
RSA | spořicí účet |
RTS | termínovaný vklad |
RCL | spotřebitelský úvěr |
RML | hypotéka |
ROD | kontokorent |
Podobně jako v exploratorní analýze budu za úvěrové produkty považovat jen spotřebitelské úvěry a hypotéky. Kontokorent nebude pro účely další analýzy úvěrový (ani depositní) produkt.
V datech provedu následující úpravy:
Používám dva referenční dny (1. 3. 2018
pro model s 12měsíčním horizontem a pro natrénování modelu se 6měsíčním horizontem; 30. 8. 2018
pro ověření modelu se 6měsíčním horizontem).
V datech je celkem 395 055
klientů, kteří mají celkem 919 707
samostatných (a 33 256
navazujících) retailových produktů.
owner | gender | vek | region | obec | rca | rsa | rts | rod | rcl | rml | typ | doba_vstup | do_uveru | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 16144402 | Z | 25 | 5 | do 10 tis. | 1 | 0 | 0 | 0 | 0 | 0 | Jen běžný účet | 1057 | |
2 | 10063052 | Z | 47 | 6 | do 10 tis. | 1 | 0 | 0 | 0 | 2+ | 0 | Víc úvěrů | 162 | 55 |
3 | 9914206 | M | 55 | 7 | nad 200 tis. | 1 | 0 | 0 | 0 | 0 | 1+ | Ostatní | 2058 | |
4 | 21057752 | Z | 25 | 4 | N/A | 1 | 1 | 0 | 0 | 0 | 0 | Spořič | 164 | |
5 | 15372744 | Z | 36 | 3 | do 10 tis. | 1 | 0 | 0 | 0 | 1 | 0 | Úvěr | 1235 | |
6 | 14174554 | M | 48 | 6 | do 10 tis. | 1 | 2+ | 0 | 0 | 0 | 0 | Spořič plus | 1647 | |
7 | 13744237 | Z | 48 | 5 | 10-40 tis. | 2+ | 1 | 0 | 0 | 0 | 0 | Spořič | 1618 | |
8 | 21723890 | Z | 49 | 7 | do 10 tis. | 1 | 1 | 0 | 1+ | 1 | 0 | Ostatní | 73 | 113 |
9 | 14151536 | Z | 60 | 7 | nad 200 tis. | 1 | 1 | 0 | 0 | 0 | 0 | Spořič | 1654 | |
10 | 15928358 | Z | 28 | 1 | nad 200 tis. | 1 | 1 | 0 | 0 | 0 | 0 | Spořič | 1116 | |
11 | 19821463 | M | 45 | 7 | do 10 tis. | 1 | 0 | 0 | 0 | 0 | 0 | Jen běžný účet | 405 | |
12 | 15148043 | M | 48 | 5 | do 10 tis. | 1 | 1 | 0 | 0 | 2+ | 0 | Víc úvěrů | 2191 | |
13 | 17967126 | Z | 24 | 6 | 10-40 tis. | 1 | 0 | 0 | 0 | 0 | 0 | Jen běžný účet | 825 | |
14 | 18753996 | M | 26 | 7 | 90-200 tis. | 1 | 1 | 0 | 0 | 0 | 0 | Spořič | 640 | |
15 | 18128953 | M | 45 | 2 | 40-90 tis. | 1 | 0 | 0 | 0 | 2+ | 0 | Víc úvěrů | 781 | |
16 | 14277410 | Z | 45 | 5 | do 10 tis. | 1 | 0 | 0 | 0 | 0 | 0 | Jen běžný účet | 1612 | |
17 | 14498938 | Z | 37 | 5 | do 10 tis. | 1 | 1 | 0 | 0 | 0 | 0 | Spořič | 1527 | |
18 | 20337259 | Z | 59 | 4 | do 10 tis. | 2+ | 0 | 0 | 0 | 0 | 0 | Jen běžný účet | 290 | |
19 | 16006908 | M | 22 | 6 | do 10 tis. | 1 | 0 | 0 | 0 | 0 | 0 | Jen běžný účet | 1093 | |
20 | 20211269 | M | 26 | 4 | 40-90 tis. | 1 | 0 | 0 | 0 | 0 | 1+ | Ostatní | 258 |
owner | acc.id | type.id | prod.kat | prod.type | state | start | end | |
---|---|---|---|---|---|---|---|---|
1 | 14917396 | 1969956533 | RCL | Loan | 92 | Open | 2018-01-23 | |
2 | 13485100 | 80112019 | RSA | Deposit | 132 | Open | 2013-09-26 | |
3 | 15840767 | 931669448 | RCL | Loan | 92 | Open | 2016-09-12 | |
4 | 14293597 | 139472523 | RCL | Loan | 92 | Open | 2014-04-07 | |
5 | 10318675 | 56543166 | RSA | Deposit | 131 | Open | 2013-06-07 | |
6 | 19806262 | 1507174231 | ROD | Loan | 130 | Open | 2017-07-20 | |
7 | 9843796 | 82871531 | RSA | Deposit | 132 | Open | 2013-10-07 | |
8 | 14940237 | 268541061 | RCL | Loan | 91 | Closed | 2015-01-27 | 2017-05-30 |
9 | 10096048 | 98747498 | RTS | Deposit | 138 | Closed | 2013-12-04 | 2016-12-03 |
10 | 14687383 | 372937809 | RCL | Loan | 92 | Closed | 2015-06-28 | 2016-07-27 |
11 | 18293316 | 899023403 | RSA | Deposit | 134 | Open | 2016-08-22 | |
12 | 14573106 | 183742065 | RCL | Loan | 92 | Open | 2014-07-28 | |
13 | 15103155 | 263447984 | RCA | Deposit | 86 | Open | 2015-01-16 | |
14 | 10414976 | 81059267 | RSA | Deposit | 131 | Open | 2013-09-30 | |
15 | 18165312 | 848282769 | RCA | Deposit | 86 | Open | 2016-07-20 | |
16 | 10229987 | 51117776 | RCA | Deposit | 86 | Open | 2013-05-24 | |
17 | 20152694 | 1667987710 | RCA | Deposit | 86 | Open | 2017-10-04 | |
18 | 13831280 | 143085649 | RSA | Deposit | 131 | Open | 2014-04-16 | |
19 | 10413132 | 68937625 | RCA | Deposit | 86 | Open | 2013-08-07 | |
20 | 18183866 | 3019064748 | RCL | Loan | 92 | Open | 2018-12-12 |
Vytvořím celkem tři modelovací matice, a to jednu pro model s 12měsíčním horizontem a dvě pro natrénování a ověření modelu se 6měsíčním horizontem. Každá modelovací matice se váže k určitému referenčnímu dnu a budou v ní klienti splňující tyto podmínky:
30
dnů od jejich vstupu do banky;30
dnech neměli aktivní žádný úvěrový produkt.K referenčnímu dnu 1. 3. 2018
je v modelovací matici 221 741
klientů, k referenčnímu dnu 30. 8. 2018
je v modelovací matici 244 710
klientů. Target se v modelovací matici nastaví na TRUE, pokud klient od referenčního dne nejpozději do stanoveného časového horizontu (6 nebo 12 měsíců) zahájil nový úvěrový produkt, jinak bude FALSE.
Průměrné podíly pozitivních targetů v datech:
1. 3. 2018
0.043
1. 3. 2018
0.024
30. 8. 2018
0.024
Analýzu jsem provedl jen pro model s 12měsíčním horizontem s referenčním dnem 1. 3. 2018
, protože je v ní vyšší podíl pozitivních případů. Analogicky by šla provést pro model se 6měsíčním horizontem.
Při sestavení modelu řeším dvě otázky:
Kombinací různých odpovědí na předchozí dvě otázky dostávám u 12měsíčního i u 6měsíčního horizontu celkem čtyři kandidáty na model. U každého kandidáta sestavím nejprve model logistické regrese v daném rámci co nejbohatší a automaticky nechám tento model redukovat. Nakonec ručně ověřím významnost zahrnutých prediktorů a případně ještě některé vyřadím. Následuje ukázka kódu, který toto provede:
model0 = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat + (rca.pocet.pred.kat +
rsa.pocet.pred.kat + rts.pocet.pred.kat + rod.pocet.pred.kat +
rcl.pocet.pred.kat + rml.pocet.pred.kat)^2,
data=d.model, family=binomial())
model1 = step(model0)
drop1(model1, test="Chi")
Redukcí všech čtyř kandidátských modelů dostanu finální modely:
model1 = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat + rsa.pocet.pred.kat + rts.pocet.pred.kat +
rod.pocet.pred.kat + rcl.pocet.pred.kat + rml.pocet.pred.kat +
rsa.pocet.pred.kat:rcl.pocet.pred.kat +
rts.pocet.pred.kat:rcl.pocet.pred.kat +
rts.pocet.pred.kat:rml.pocet.pred.kat +
rod.pocet.pred.kat:rcl.pocet.pred.kat,
data=d.model, family=binomial())
model2 = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat +
rca.pocet.pred.kat + rsa.pocet.pred.kat + rts.pocet.pred.kat +
rod.pocet.pred.kat + rcl.pocet.pred.kat + rml.pocet.pred.kat,
data=d.model, family=binomial())
model3 = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat + prod.kombinace,
data=d.model, family=binomial())
model4 = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat +
prod.kombinace + gender:zip.region + gender:prod.kombinace +
vek.kat:doba.od.vstupu.kat + vek.kat:prod.kombinace +
doba.od.vstupu.kat:prod.kombinace,
data=d.model, family=binomial())
model1.tren = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat +
rca.pocet.pred.kat + rsa.pocet.pred.kat + rts.pocet.pred.kat +
rod.pocet.pred.kat + rcl.pocet.pred.kat + rml.pocet.pred.kat +
rca.pocet.pred.kat:rcl.pocet.pred.kat +
rsa.pocet.pred.kat:rcl.pocet.pred.kat +
rts.pocet.pred.kat:rcl.pocet.pred.kat +
rod.pocet.pred.kat:rcl.pocet.pred.kat,
data=d.model.tren, family=binomial())
model2.tren = glm(target ~ gender + vek.kat + zip.region + city.kat +
doba.od.vstupu.kat +
rsa.pocet.pred.kat + rts.pocet.pred.kat + rod.pocet.pred.kat +
rcl.pocet.pred.kat + rml.pocet.pred.kat,
data=d.model.tren, family=binomial())
model3.tren = glm(target ~ gender + vek.kat + zip.region + city.kat + doba.od.vstupu.kat +
prod.kombinace,
data=d.model.tren, family=binomial())
model4.tren = glm(target ~ gender + vek.kat + zip.region + city.kat + doba.od.vstupu.kat +
prod.kombinace + gender:zip.region + gender:doba.od.vstupu.kat +
gender:prod.kombinace + vek.kat:doba.od.vstupu.kat +
vek.kat:prod.kombinace +
doba.od.vstupu.kat:prod.kombinace,
data=d.model.tren, family=binomial())
Ze statistického pohledu je možné modely pro 12měsíční horizont porovnat podle toho, jak se jim podařilo snížit tzv. deviance (\(-2 * log(Lik)\)) a kolik na to spotřebovaly parametrů.
Snížení deviance | Počet parametrů | |
---|---|---|
Model 12m 1 | 9217 | 38 |
Model 12m 2 | 8927 | 30 |
Model 12m 3 | 8576 | 29 |
Model 12m 4 | 9040 | 126 |
Nejvíce snížil deviance Model 1, a to s mnohem menším počtem potřebných parametrů než druhý model v pořadí (Model 4). Nejmenší snížení je u Modelu 3, ale také s nejnižším počtem použitých parametrů. Modely dále můžeme vzájemně porovnat pomocí statistického testu poměru věrohodností, například takto pro Model 2 a Model3:
anova(model2, model3, test="Chi")
## Analysis of Deviance Table
##
## Model 1: target ~ gender + vek.kat + zip.region + city.kat + doba.od.vstupu.kat +
## rca.pocet.pred.kat + rsa.pocet.pred.kat + rts.pocet.pred.kat +
## rod.pocet.pred.kat + rcl.pocet.pred.kat + rml.pocet.pred.kat
## Model 2: target ~ gender + vek.kat + zip.region + city.kat + doba.od.vstupu.kat +
## prod.kombinace
## Resid. Df Resid. Dev Df Deviance Pr(>Chi)
## 1 221710 69633
## 2 221711 69983 -1 -350.78 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Ze statistického porovnání (tabulka výše a vzájemné porovnání) vychází, že nejsilnější je Model 1, nejslabší Model 3; Model 2 a Model 4 jsou mezi nimi přibližně na stejné úrovni.
Podobně vyhodnotím modely pro 6měsíční horizont.
Snížení deviance | Počet parametrů | |
---|---|---|
Model 6m 1 | 5704 | 40 |
Model 6m 2 | 5462 | 29 |
Model 6m 3 | 5314 | 29 |
Model 6m 4 | 5629 | 130 |
Ze statistického porovnání vychází, že i pro 6měsíční horizont je nejlepší Model 1 a nejhorší Model 3. Model 4 je významně lepší než model 2.
Jak modely s 12měsíčním horizontem, tak model se 6měsíčním horizontem vyhodnotím obvyklou cross-validací s dělením modelovací matice na 10
částí.
## $auc
## [1] 0.7490782
##
## $lift.01
## [1] 8.455466
##
## $lift.05
## [1] 5.513809
##
## $pos.pred
## [1] 0.04292884
##
## $pos.skut
## [1] 0.04292846
## $auc
## [1] 0.7488786
##
## $lift.01
## [1] 8.389491
##
## $lift.05
## [1] 5.408701
##
## $pos.pred
## [1] 0.04292727
##
## $pos.skut
## [1] 0.04292846
## $auc
## [1] 0.7460743
##
## $lift.01
## [1] 6.32545
##
## $lift.05
## [1] 5.254052
##
## $pos.pred
## [1] 0.0429339
##
## $pos.skut
## [1] 0.04292846
## $auc
## [1] 0.7490792
##
## $lift.01
## [1] 6.763907
##
## $lift.05
## [1] 5.282458
##
## $pos.pred
## [1] 0.04292682
##
## $pos.skut
## [1] 0.04292846
Modely 1, 2 a 4 jsou z pohledu AUC rovnocenné. Pro Model 1 znázorním rozdělení predikovaných pravděpodobností u skutečných pozitivních a skutečných negativních případů.
## $auc
## [1] 0.7573665
##
## $lift.01
## [1] 9.548132
##
## $lift.05
## [1] 6.012567
##
## $pos.pred
## [1] 0.02397711
##
## $pos.skut
## [1] 0.02397843
## $auc
## [1] 0.7566113
##
## $lift.01
## [1] 9.40069
##
## $lift.05
## [1] 5.860748
##
## $pos.pred
## [1] 0.02398182
##
## $pos.skut
## [1] 0.02397843
## $auc
## [1] 0.7540842
##
## $lift.01
## [1] 7.148695
##
## $lift.05
## [1] 5.722219
##
## $pos.pred
## [1] 0.02397911
##
## $pos.skut
## [1] 0.02397843
## $auc
## [1] 0.7564593
##
## $lift.01
## [1] 7.28228
##
## $lift.05
## [1] 5.752467
##
## $pos.pred
## [1] 0.02397923
##
## $pos.skut
## [1] 0.02397843
Nejlepší model je Model 1. Znázorním pro něj rozdělení predikovaných pravděpodobností u skutečných pozitivních a skutečných negativních případů.
Modely se 6měsíčním horizontem můžeme vyhodnotit také tak, že modely natrénujeme na datech k referenčnímu dnu 1. 3. 2018
, nasadíme na pozdější data k referenčnímu dnu 30. 8. 2018
jako na validační množinu a porovnáme predikce se skutečností.
## $auc
## [1] 0.7667282
##
## $lift.01
## [1] 10.65122
##
## $lift.05
## [1] 6.397614
##
## $pos.pred
## [1] 0.02510907
##
## $pos.skut
## [1] 0.02436762
## $auc
## [1] 0.7665355
##
## $lift.01
## [1] 10.70777
##
## $lift.05
## [1] 6.345335
##
## $pos.pred
## [1] 0.02521519
##
## $pos.skut
## [1] 0.02436762
## $auc
## [1] 0.7626692
##
## $lift.01
## [1] 7.793609
##
## $lift.05
## [1] 5.967572
##
## $pos.pred
## [1] 0.02489836
##
## $pos.skut
## [1] 0.02436762
## $auc
## [1] 0.7640154
##
## $lift.01
## [1] 7.491152
##
## $lift.05
## [1] 6.034719
##
## $pos.pred
## [1] 0.02517653
##
## $pos.skut
## [1] 0.02436762
Z vyhodnocení na validační množině plyne, že všechny modely si vedly dokonce o něco lépe než při cross-validaci. Nejvyšší AUC mají Model 1 a Model 2.
save(model1, model2, model3, model4, file='propensity-modely.RData')
print(sessionInfo())
## R version 3.6.0 (2019-04-26)
## Platform: x86_64-redhat-linux-gnu (64-bit)
## Running under: CentOS Linux 7 (Core)
##
## Matrix products: default
## BLAS/LAPACK: /usr/lib64/R/lib/libRblas.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
## [4] LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ROCR_1.0-7 gplots_3.0.1.1 magrittr_1.5 forcats_0.4.0 stringr_1.4.0
## [6] dplyr_0.8.3 glue_1.3.1 RPostgres_1.1.1 RColorBrewer_1.1-2 xtable_1.8-4
## [11] data.table_1.12.2
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.2 pillar_1.4.2 compiler_3.6.0 bitops_1.0-6 tools_3.6.0
## [6] zeallot_0.1.0 digest_0.6.20 bit_1.1-14 evaluate_0.14 tibble_2.1.3
## [11] pkgconfig_2.0.2 rlang_0.4.0 DBI_1.0.0 yaml_2.2.0 xfun_0.8
## [16] knitr_1.24 caTools_1.17.1.2 vctrs_0.2.0 gtools_3.8.1 hms_0.5.0
## [21] bit64_0.9-7 tidyselect_0.2.5 R6_2.4.0 rmarkdown_1.14 gdata_2.18.0
## [26] purrr_0.3.2 blob_1.2.0 backports_1.1.4 htmltools_0.3.6 assertthat_0.2.1
## [31] KernSmooth_2.23-15 stringi_1.4.3 crayon_1.3.4