Machine learning
Credit Card Default Prediction
The whole brief is open to read. This lab's datasets come with Premium.
- Company
Capital One- Job positions
- Data ScientistML EngineerData Analyst
- Topics
- ClassificationCredit riskData leakageExpected profitscikit-learn
The scenario
Capital One: Build a model that predicts which credit card applicants will default, decide who to approve, and explain each rejection.
When somebody applies for a Capital One credit card, the company decides whether to approve them, knowing some will stop repaying, which is what defaulting means. A rejected applicant is entitled by law to the main reasons why, which lenders call adverse action reasons, and age cannot be one of them. You're a data scientist on the credit policy team, which wants to approve more applicants without more loss.
Your task
Predict each applicant's chance of defaulting, meaning 90 or more days past due in the first year, set the approval cutoff that makes the most profit, and give reasons for every rejection.
Instructions
- 1Load and clean the applications. Check for repeated records and missing values, and explain how you handled each.
- 2Decide which columns a decision could actually use. Some are filled in only after an account has been opened, and the decision cannot rest on an applicant's age.
- 3Explore how often accounts default, and how that rate moves with the bureau score, balances, recent credit checks and past late payments.
- 4Build a baseline from the bureau score alone, then train and compare at least two models on area under the ROC curve, or AUC, validating on later applications than you trained on.
- 5Choose an approval cutoff from expected profit. An approved account that keeps paying is worth $420 in its first year, and one that defaults costs 55 percent of the credit line the applicant asked for.
- 6For every application you would reject, give the main reasons behind it, ranked, in words the applicant would understand.
- 7Score applications_test.csv and save predictions.csv with the columns application_id, default_probability, decision (approve or decline) and decline_reasons, left empty for approvals.
Datasets
All files come in one download.
applications_train.csv
About 15,000 card applications from January to September 2024, each with how the account went in its first year.
15,207 rows · 21 columns · 1.4 MB
| Column | Type | Description |
|---|---|---|
| application_id | integer | Unique ID of the application. |
| applied_on | date | Date the application was submitted. |
| applicant_age | integer | The applicant's age in years. |
| annual_income_usd | integer | Income the applicant stated, in US dollars. Zero for some retired applicants, who reported no earned income. |
| employment_type | text | salaried, self_employed, contract or retired. |
| employment_years | integer | Years with the current employer. Empty where the applicant left it blank. |
| housing | text | mortgage, rent, own or other. |
| state | text | US state the applicant lives in. |
| zip_median_income_usd | integer | Median household income of the applicant's ZIP code, from census data. |
| bureau_score | integer | Credit bureau score from 300 to 850. Empty for applicants with too little credit history to score. |
| credit_history_months | integer | Months since the applicant's oldest credit account was opened. |
| open_accounts | integer | Credit accounts currently open. |
| total_credit_limit_usd | integer | Total limit across the applicant's existing revolving accounts. |
| revolving_balance_usd | integer | Balance currently carried on those accounts. |
| inquiries_last_6m | integer | Credit checks run on the applicant in the last six months. |
| delinquencies_last_24m | integer | Payments 30 or more days late in the last two years. |
| months_since_last_delinquency | integer | Months since the applicant was last late. Empty means they have never been late. |
| requested_credit_line_usd | integer | Credit line the applicant asked for. |
| assigned_credit_line_usd | integer | Credit line the account was given. Set when the account is opened. |
| first_year_spend_usd | integer | Spend on the account over its first year. |
| ever_90dpd_12m | integer | 1 if the account went 90 or more days past due within twelve months, otherwise 0. This is what you predict. |
Preview the first 5 rowsHide preview
| application_id | applied_on | applicant_age | annual_income_usd | employment_type | employment_years | housing | state | zip_median_income_usd | bureau_score | credit_history_months | open_accounts | total_credit_limit_usd | revolving_balance_usd | inquiries_last_6m | delinquencies_last_24m | months_since_last_delinquency | requested_credit_line_usd | assigned_credit_line_usd | first_year_spend_usd | ever_90dpd_12m |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 700001 | 2024-01-01 | 42 | 65000 | self_employed | 19 | mortgage | FL | 69500 | 619 | 179 | 4 | 24100 | 16912 | 4 | 0 | empty | 12000 | 5300 | 5750 | 1 |
| 700002 | 2024-01-01 | 62 | 20808 | retired | 0 | rent | VA | 50500 | 698 | 299 | 4 | 11900 | 3708 | 4 | 4 | 7 | 12000 | 10500 | 3950 | 0 |
| 700003 | 2024-01-01 | 41 | 73000 | salaried | 3 | own | NY | 97500 | 592 | 144 | 6 | 11900 | 6418 | 2 | 0 | 62 | 12000 | 11700 | 5500 | 0 |
| 700004 | 2024-01-01 | 47 | 117500 | salaried | 15 | own | IL | 112500 | 724 | 267 | 5 | 28500 | 0 | 0 | 0 | empty | 6000 | 5400 | 2950 | 0 |
| 700005 | 2024-01-01 | 42 | 83000 | salaried | 2 | rent | TN | 126000 | 682 | 142 | 3 | 37200 | 30610 | 3 | 0 | 80 | 2500 | 2000 | 900 | 0 |
applications_test.csv
About 5,000 applications from October to December 2024, without the outcome.
5,022 rows · 20 columns · 469 KB
| Column | Type | Description |
|---|---|---|
| application_id | integer | Unique ID of the application. |
| applied_on | date | Date the application was submitted. |
| applicant_age | integer | The applicant's age in years. |
| annual_income_usd | integer | Income the applicant stated, in US dollars. |
| employment_type | text | salaried, self_employed, contract or retired. |
| employment_years | integer | Years with the current employer. Empty where the applicant left it blank. |
| housing | text | mortgage, rent, own or other. |
| state | text | US state the applicant lives in. |
| zip_median_income_usd | integer | Median household income of the applicant's ZIP code, from census data. |
| bureau_score | integer | Credit bureau score from 300 to 850. Empty for applicants with too little credit history to score. |
| credit_history_months | integer | Months since the applicant's oldest credit account was opened. |
| open_accounts | integer | Credit accounts currently open. |
| total_credit_limit_usd | integer | Total limit across the applicant's existing revolving accounts. |
| revolving_balance_usd | integer | Balance currently carried on those accounts. |
| inquiries_last_6m | integer | Credit checks run on the applicant in the last six months. |
| delinquencies_last_24m | integer | Payments 30 or more days late in the last two years. |
| months_since_last_delinquency | integer | Months since the applicant was last late. Empty means they have never been late. |
| requested_credit_line_usd | integer | Credit line the applicant asked for. |
| assigned_credit_line_usd | integer | Credit line the account was given. Set when the account is opened. |
| first_year_spend_usd | integer | Spend on the account over its first year. |
Preview the first 5 rowsHide preview
| application_id | applied_on | applicant_age | annual_income_usd | employment_type | employment_years | housing | state | zip_median_income_usd | bureau_score | credit_history_months | open_accounts | total_credit_limit_usd | revolving_balance_usd | inquiries_last_6m | delinquencies_last_24m | months_since_last_delinquency | requested_credit_line_usd | assigned_credit_line_usd | first_year_spend_usd |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 715194 | 2024-10-01 | 34 | 96500 | contract | 11 | rent | SC | 133000 | 594 | 111 | 1 | 20800 | 6920 | 2 | 0 | 47 | 12000 | 12200 | 6950 |
| 715195 | 2024-10-01 | 53 | 43000 | salaried | 13 | mortgage | TN | 76000 | 680 | 260 | 2 | 18000 | 15396 | 0 | 0 | empty | 2500 | 2800 | 1000 |
| 715196 | 2024-10-01 | 48 | 146000 | salaried | 21 | rent | AL | 178500 | 771 | 173 | 6 | 48700 | 12812 | 1 | 0 | empty | 6000 | 5000 | 2750 |
| 715197 | 2024-10-01 | 35 | 55500 | salaried | 15 | rent | TX | 70500 | 576 | 177 | 3 | 12300 | 7692 | 2 | 1 | 6 | 8000 | 2800 | 2250 |
| 715198 | 2024-10-01 | 49 | 102000 | salaried | empty | mortgage | NY | 126000 | 724 | 168 | 5 | 22700 | 0 | 4 | 0 | empty | 4000 | 4100 | 1400 |
Hints
A column that only exists once an account has been opened cannot help you decide a new application, however well it predicts the outcome. Check each one against the moment the form is submitted.
The reason for a decline comes from that applicant's own contribution to their score, not from which features matter most across everybody.
contribution = coefficients * applicant_scaled contribution.sort_values(ascending=False).head(3)
Deliverable
A public GitHub repo with your analysis (a notebook or scripts), predictions.csv for the test applications, and a README with the columns you excluded, your model comparison and the cutoff you chose.
When you're done, post your repo in the Solutions tab to share it with other learners.
What grading checks
Use this checklist to review your own work before you post and share it.
- Submitted GitHub repo is public and reachable.
- Repo contains at least one notebook or script file.
- predictions.csv has a probability, a decision and reasons for every test application.
- default_probability reaches an area under the ROC curve of at least 0.81 on the test applications.
- Under the cost assumptions in the brief, the approved applications are worth more than approving every applicant.
- Columns that only exist after an account is opened are excluded with the reason explained, and the applicant's age is excluded from the decision.
- Models are compared against a bureau score baseline, and decline reasons differ between applicants rather than repeating one list.