Independent projects
Projects you can open and explore
Work done on public data, with the code and results published so anyone can check them. These show how I approach a problem end to end, from raw data to a decision-ready answer.
October 2026 · Survival analysis, LightGBM, SHAP
Subscription churn at scale
When do new subscribers to a music-streaming service leave, and who will leave next month? I worked through both questions end to end on KKBox's public churn dataset, from raw billing logs to a published analysis.
- 0.869
- AUC on an out-of-time March 2017 test (971K subscribers)
- 6.0×
- lift: the riskiest decile captured 60% of next month's churners
- 72% vs 37%
- 12-month retention, auto-renew vs manual renewal
- 0.45
- adjusted hazard ratio for auto-renew (95% CI 0.44–0.46)
- Data
- 392M daily usage records, 23M billing transactions and 6.8M member profiles from 2015 to 2017. A cohort of 564K new paying subscribers tracked from first payment.
- Approach
- Kaplan–Meier curves and a stratified Cox model for timing. LightGBM for next-month churn, validated out of time rather than on random splits, with recalibration when the base rate moved from 6.4% to 9.0%.
- Findings
- Manual-renewal risk spikes at the first expiry and again near month 7, when 180-day plans end. Converted free trials churn 1.7× faster than direct signups. Usage data added only 0.004 AUC over billing data alone.
Open the analysis
Code on GitHub
October 2026 · Credit risk, cash-flow IRR, LightGBM
Did the rate cover the risk?
A lender's pricing is a bet that each grade's interest rate will more than cover its losses. I checked that bet loan by loan across 2.26 million Lending Club loans, then asked whether a model built only on application data could have found the loans that lost money.
- 6.7% → 2.1%
- realized investor return, best sub-grade (B4) vs grade G, despite G paying 25% interest
- −1.1%
- lifetime return on the riskiest model decile, which paid a 16.4% rate
- 0.704
- out-of-time AUC on 283K 2015 loans, vs 0.678 for Lending Club's own sub-grade
- +$5.7M
- investor profit from declining the riskiest 5% of one year's loans
- Data
- 2.26M funded loans and 27.6M rejected applications, 2007 to 2018, with each loan's outcome as of March 2019.
- Approach
- Vintage loss curves; monthly cash flows rebuilt for 613K matured loans to compute pool IRRs by sub-grade; LightGBM trained on 2013–14 and tested once on 2015, using only application-time fields; a profit-based approval cutoff.
- Findings
- Returns peaked in grade B and fell as rates rose. Inside each grade the rate barely moved, but the riskiest fifth of grade D lost money while the safest fifth earned 8.9%. Later vintages charged off faster.
Open the analysis
Code on GitHub
October 2026 · Geospatial, panel regression, anomaly detection
Closing the broadband gap
Seven years of US internet speed tests, mapped county by county. Did rural America catch up, what still explains the gap, and can a surge in speed tests reveal network outages?
- 21 → 204
- median rural home download (Mbps), 2019 vs the latest four quarters
- 6% → 64%
- rural tests meeting the FCC 100/20 benchmark
- −43% → −11%
- rural speed gap before and after controlling for population density
- 17
- disruptions flagged in 58,950 county-quarters, including Hurricane Helene
- Data
- Ookla open data: 62M tile-quarters covering 594M fixed and mobile speed tests, Q1 2019 to Q2 2026, joined to 3,100+ counties with USDA rurality codes and Census income.
- Approach
- Quadkey decoding and point-in-polygon county assignment; test-weighted medians; county regressions with state fixed effects; a convergence model; robust z-score detection of test surges against each county's own trend.
- Findings
- Rural speeds rose tenfold and the slowest counties improved fastest, yet the absolute gap widened. What remains is about density, the cost of wiring sparse places, rather than income.
Open the analysis
Code on GitHub