Skip to content

🧠 Case Study — ML for DA: Spotify, Shopee, VietCredit

Trong buổi học này, chúng ta đã nắm ML fundamentals — regression, classification, evaluation metrics, feature engineering. Bây giờ hãy xem 3 công ty áp dụng ML vào bài toán business thực tế như thế nào — từ Spotify personalize music cho 600M+ users, đến Shopee predict seller churn để giữ chân hệ sinh thái, và VietCredit dùng Logistic Regression + Decision Tree cho credit scoring.


Case Study 1: Spotify — Recommendation System cho 600M+ Users

Bối cảnh

Spotify (2025): 640 triệu monthly active users, 250 triệu premium subscribers, hoạt động tại 184 markets. Content library: 100+ triệu tracks6 triệu podcasts. Mỗi ngày, users tạo 1.4 tỷ playlists và stream 1.8 tỷ hours content.

Vấn đề kinh doanh: Với 100+ triệu tracks, user KHÔNG THỂ tự tìm nhạc hay. Nếu user không tìm được nhạc thích → giảm engagement → cancel premium → churn. Spotify cần biết: "Bài nào người này muốn nghe tiếp?" — cho mỗi user, mỗi thời điểm, mỗi context (gym, commute, study, sleep).

ML Team: 200+ ML engineers và data scientists. ML không chỉ là "feature" — ML LÀ product. Spotify CEO Daniel Ek: "Spotify is a machine learning company that happens to play music."

ML Architecture

Spotify sử dụng 3 lớp ML cho recommendation:

┌─────────────────────────────────────────────────────────────┐
│  LAYER 1: COLLABORATIVE FILTERING                           │
│  "Users giống bạn cũng nghe..."                             │
│  Input: Listening history + playlist co-occurrence           │
│  Model: Matrix Factorization (ALS), Neural Collaborative    │
│  Output: Similar users → similar taste → recommend tracks   │
├─────────────────────────────────────────────────────────────┤
│  LAYER 2: CONTENT-BASED FILTERING                            │
│  "Bài này GIỐNG bài bạn thích..."                           │
│  Input: Audio features (tempo, energy, valence, danceability)│
│  Model: CNN on spectrograms, NLP on lyrics                   │
│  Output: Track similarity score                              │
├─────────────────────────────────────────────────────────────┤
│  LAYER 3: CONTEXTUAL BANDIT                                  │
│  "Lúc này, ở đây, bài nào phù hợp?"                        │
│  Input: Time of day, device, activity, weather               │
│  Model: Multi-armed bandit, Reinforcement Learning           │
│  Output: Context-aware recommendation                        │
└─────────────────────────────────────────────────────────────┘

Discover Weekly — Flagship ML Product

Discover Weekly ra mắt 2015 — mỗi thứ 2, Spotify tạo playlist 30 bài hoàn toàn mới cho mỗi user. Không phải top charts, không phải hit mới — mà là bài user CHƯA nghe nhưng CÓ KHẢ NĂNG thích.

Cách hoạt động (simplified):

StepMô tảModel
1. User ProfilePhân tích 6 tháng listening history: genres, artists, audio featuresFeature Engineering
2. Find Taste NeighborsTìm 1,000 users có taste tương tự (cosine similarity trên user-track matrix)Collaborative Filtering (ALS)
3. Candidate GenerationLấy tracks mà taste neighbors nghe NHƯNG user chưa nghe → 3,000 candidatesMatrix Factorization
4. RankingRank 3,000 candidates theo predicted preference score → top 30Gradient Boosted Trees
5. Diversity FilterĐảm bảo ≥ 5 genres, ≤ 3 tracks/artist, mix known + unknown artistsRules + ML

Features dùng cho ranking model:

Feature GroupVí dụType
User featuresListening hours/week, top genres, skip rate, save rateBehavioral
Track featuresTempo, energy, valence, danceability, speechiness, popularityAudio (CNN)
Context featuresDay of week, time of day, device type, countryContextual
Interaction featuresUser × Genre affinity, Artist familiarity scoreCollaborative

Evaluation Metrics

Spotify đo recommendation quality bằng nhiều metrics:

MetricĐịnh nghĩaTarget
Stream Rate% tracks recommended mà user nghe > 30s> 35%
Skip Rate% tracks skipped trong 5s đầu< 25%
Save Rate% tracks user save vào library> 8%
Discovery Rate% tracks từ artists user CHƯA BAO GIỜ nghe> 40%
Retention ImpactDiscover Weekly users vs non-users, 30-day churn-15% churn

Impact

MetricGiá trị
Weekly users Discover Weekly150 triệu users/tuần
Stream Rate38% (vs 22% cho non-personalized playlists)
Discovery Rate45% new artists discovered
Revenue attribution~$1.5B/năm incremental streaming revenue
Churn reductionUsers dùng Discover Weekly churn ít hơn 15% so với non-users
Total tracks surfaced10 tỷ+ tracks/tháng recommended thành công

Key Learnings cho DA

  1. Collaborative Filtering = "wisdom of crowds" — không cần hiểu NỘI DUNG, chỉ cần patterns: "users giống nhau nghe gì"
  2. Feature Engineering quan trọng hơn model — Spotify dành 60% effort cho feature engineering (audio CNN, NLP lyrics, behavioral features)
  3. A/B test mọi thứ — mọi thay đổi algorithm đều qua A/B test trên millions of users
  4. DA role: Spotify DAs không train models — nhưng define metrics, analyze experiments, segment users, communicate insights

Case Study 2: Shopee — Churn Prediction cho Seller Retention

Bối cảnh

Shopee (2025): Nền tảng e-commerce lớn nhất Đông Nam Á — 350 triệu monthly active users, 15 triệu active sellers, hoạt động tại 7 markets (VN, TH, ID, PH, MY, SG, BR). GMV (Gross Merchandise Value) 2024: $80 tỷ.

Vấn đề: Shopee là marketplace — revenue đến từ commission fees sellers trả khi bán hàng. Nếu seller rời platform → SKUs giảm → buyer experience xấu → buyer cũng churn → death spiral. Seller retention = survival metric.

Data: Shopee có data khổng lồ về seller behavior:

  • 15 triệu sellers × 200+ features → 3 tỷ data points
  • Features: số đơn/tháng, response rate, rating, return rate, login frequency, promotion participation, competitor cross-listing...

ML Pipeline cho Seller Churn Prediction

mermaid
flowchart TD
    A["1️⃣ Data Collection<br/>200+ seller features<br/>từ 6 tháng history"] --> B["2️⃣ Feature Engineering<br/>Behavioral: login, response time<br/>Performance: orders, rating<br/>Financial: revenue, commission"]
    B --> C["3️⃣ Labeling<br/>Churn = no orders in 30 days<br/>After being active (≥5 orders/month)"]
    C --> D["4️⃣ Model Training<br/>XGBoost (primary)<br/>Logistic Regression (baseline)"]
    D --> E["5️⃣ Evaluation<br/>Recall ≥ 0.80 (bắt 80% churners)<br/>Precision ≥ 0.60"]
    E --> F["6️⃣ Score & Rank<br/>All sellers → churn probability<br/>Top 5,000 high-risk/market"]
    F --> G["7️⃣ Action<br/>Retention team: call, voucher<br/>Auto: push notification, fee waiver"]

Feature Engineering chi tiết

Feature CategoryFeaturesRationale
EngagementLogin frequency, days since last login, time on platform/sessionDeclining engagement = churn signal
PerformanceOrders/month trend, GMV trend, conversion rateDeclining sales → frustration → churn
QualityRating (1-5), return rate, late shipment rateLow quality → penalties → give up
FinancialRevenue/month, commission paid, profit margin estimateLow profit → not worth it
CompetitionCross-listing on Lazada/Tiki (detected via SKU matching)Seller hedging bets → partial churn risk
SupportTickets opened, resolution time, penalty countNhiều penalty → demoralized
Trends30-day vs 60-day vs 90-day rolling averagesDECLINE quan trọng hơn absolute value

Key insight: Shopee phát hiện trend features (thay đổi theo thời gian) predict churn tốt hơn snapshot features (giá trị tại 1 thời điểm):

Feature TypeExampleChurn Prediction Power
SnapshotOrders this month = 50AUC = 0.72
TrendOrders decreased 30% vs last monthAUC = 0.81
CombinedOrders = 50 AND decreased 30%AUC = 0.86

Model Results

ModelAccuracyPrecisionRecallF1AUC-ROC
Logistic Regression (baseline)0.780.620.710.660.79
Decision Tree (max_depth=8)0.800.650.740.690.82
Random Forest0.840.710.780.740.87
XGBoost (production)0.870.750.820.780.91

Top 10 Features (XGBoost importance):

RankFeatureImportance
1orders_30d_vs_60d_change0.15
2days_since_last_login0.12
3gmv_30d_trend0.11
4cross_listed_competitor0.09
5avg_rating_30d0.08
6return_rate_30d0.07
7late_shipment_rate0.06
8support_tickets_30d0.05
9promotion_participation_rate0.05
10login_frequency_trend0.04

Retention Actions

Dựa trên churn prediction score, Shopee áp dụng tiered retention strategy:

Risk TierChurn Probability# Sellers/MarketActionCost
🔴 Critical> 80%~500Account Manager gọi trực tiếp, offer fee waiver 30 ngày50K VND/seller
🟡 High60-80%~2,000Auto push notification + voucher 200K marketing credits15K VND/seller
🟠 Medium40-60%~5,000Email + in-app tips cải thiện performance2K VND/seller
🟢 Low< 40%~50,000No special action — monitor only0

Impact (Vietnam market, 2024)

MetricBefore ML (2022)After ML (2024)Improvement
Monthly seller churn rate4.2%2.8%-33%
Sellers retained/month3,200 sellers
Average seller GMV15M VND/month18M VND/month+20%
Estimated revenue saved120 tỷ VND/nămCommission từ retained sellers
Retention campaign ROI8.5xChi phí campaign vs revenue saved

Key Learnings cho DA

  1. Trend > Snapshot: Feature "orders giảm 30% vs tháng trước" predict churn tốt hơn "orders tháng này = 50"
  2. Tiered actions: Không phải mọi at-risk seller đều cần gọi điện — phân tier để optimize ROI
  3. DA role tại Shopee: DAs define churn definition, engineer features, analyze model output by segment, create dashboards tracking retention campaign effectiveness

Case Study 3: VietCredit — Credit Scoring bằng Logistic Regression + Decision Tree

Bối cảnh

VietCredit (tên đã thay đổi để bảo mật) — công ty tài chính tiêu dùng tại Việt Nam, cung cấp thẻ tín dụng và cho vay tiêu dùng không tài sản đảm bảo. 500,000+ khách hàng active, dư nợ 8,000 tỷ VND. Thị trường consumer finance Việt Nam tăng trưởng 25%/năm nhưng nợ xấu (NPL - Non-Performing Loan) là rủi ro lớn nhất — NPL rate trung bình ngành: 6-8%.

Vấn đề: VietCredit cần quyết định cho vay hay không cho 50,000+ hồ sơ/tháng. Manual review bởi credit officer: 15-20 phút/hồ sơ → bottleneck. Cần model tự động scoring → credit officer chỉ review borderline cases.

Đặc thù Việt Nam:

  • Nhiều khách hàng thin-file — ít lịch sử tín dụng (không có credit bureau data)
  • Income verification khó — nhiều người thu nhập không chính thức
  • Fraud risk cao — document forgery, identity theft
  • Regulatory: NHNN yêu cầu model phải interpretable (giải thích được tại sao reject)

Data & Features

Feature CategoryFeaturesVí dụ
DemographicsAge, gender, marital status, education, province28 tuổi, nữ, đại học, TP.HCM
EmploymentJob type, tenure, company size, industryNhân viên VP, 3 năm, 500+ NV, bán lẻ
FinancialMonthly income, existing debt, debt-to-income ratio15M/tháng, nợ 50M, DTI = 28%
Credit HistoryCIC score, existing loans, payment historyCIC 650, 2 khoản vay, on-time 90%
ApplicationLoan amount, loan purpose, channel30M, mua xe máy, online
Alternative DataPhone type, telco prepaid/postpaid, social mediaiPhone, postpaid, có Facebook verify

Model Architecture — Tại sao Logistic Regression + Decision Tree?

VietCredit chọn 2 models kết hợp thay vì 1 model phức tạp:

mermaid
flowchart TD
    A["📋 Hồ sơ vay mới<br/>50,000 hồ sơ/tháng"] --> B["🤖 Model 1: Logistic Regression<br/>Credit Score (0-1000)"]
    A --> C["🌳 Model 2: Decision Tree<br/>Risk Category + Reason Codes"]
    B --> D{"Score ≥ 650?"}
    D -->|"Yes"| E["✅ Auto-Approve<br/>(60% hồ sơ)"]
    D -->|"350-649"| F["⚠️ Manual Review<br/>Credit Officer xem<br/>(25% hồ sơ)"]
    D -->|"< 350"| G["❌ Auto-Reject<br/>(15% hồ sơ)"]
    C --> F
    F --> H["Officer dùng Decision Tree<br/>reasons để quyết định"]

Tại sao Logistic Regression cho scoring?

  • Output là probability (0-1) → dễ chuyển thành score (0-1000)
  • Interpretable: coefficient cho biết impact mỗi feature
  • Regulatory compliance: NHNN và Basel yêu cầu model giải thích được
  • Stable: ít biến động giữa các time periods

Tại sao Decision Tree cho reason codes?

  • Business cần nói TẠI SAO reject: "Thu nhập thấp so với khoản vay, Debt-to-income > 50%"
  • Decision Tree tạo IF-THEN rules dễ hiểu cho credit officers và khách hàng
  • Regulatory: luật yêu cầu adverse action notice — lý do từ chối rõ ràng

Implementation

python
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import roc_auc_score, classification_report

# ============================================
# MODEL 1: LOGISTIC REGRESSION - CREDIT SCORE
# ============================================
lr_model = LogisticRegression(
    max_iter=1000,
    class_weight='balanced',   # handle imbalanced (default 6% NPL)
    C=0.1,                     # regularization
    random_state=42
)
lr_model.fit(X_train, y_train)

# Probability → Score (0-1000)
prob_default = lr_model.predict_proba(X_test)[:, 1]
credit_score = ((1 - prob_default) * 1000).astype(int)

print("LOGISTIC REGRESSION - CREDIT SCORING")
print(f"AUC-ROC: {roc_auc_score(y_test, prob_default):.4f}")

# Coefficients → Feature Impact
coef_df = pd.DataFrame({
    'Feature': feature_names,
    'Coefficient': lr_model.coef_[0],
    'Impact': ['Tăng risk' if c > 0 else 'Giảm risk'
               for c in lr_model.coef_[0]]
}).sort_values('Coefficient', ascending=False)
print("\nFeature Impact:")
print(coef_df.to_string(index=False))
python
# ============================================
# MODEL 2: DECISION TREE - REASON CODES
# ============================================
dt_model = DecisionTreeClassifier(
    max_depth=5,               # giới hạn depth cho interpretability
    min_samples_leaf=500,      # tránh overfitting
    class_weight='balanced',
    random_state=42
)
dt_model.fit(X_train, y_train)

# Reason codes từ Decision Tree path
def get_rejection_reasons(model, features, sample):
    """Extract reason codes from Decision Tree path."""
    node = 0
    reasons = []
    tree = model.tree_
    while tree.children_left[node] != -1:  # not leaf
        feature_idx = tree.feature[node]
        threshold = tree.threshold[node]
        feature_name = features[feature_idx]
        if sample[feature_idx] <= threshold:
            reasons.append(f"{feature_name}{threshold:.1f}")
            node = tree.children_left[node]
        else:
            reasons.append(f"{feature_name} > {threshold:.1f}")
            node = tree.children_right[node]
    return reasons

Model Results

MetricLogistic RegressionDecision TreeEnsemble (Combined)
AUC-ROC0.820.780.84
Accuracy0.790.760.81
Precision (default)0.450.400.48
Recall (default)0.720.680.75
F1 (default)0.550.510.59

Confusion Matrix (Ensemble, production):

                    Predicted
                  Good (0)    Default (1)
Actual  Good (0)    8,520        980
        Default(1)    150        450

Total test: 10,100
- TP = 450: Correctly predicted default → PREVENT loss
- TN = 8,520: Correctly approved good loans → REVENUE
- FP = 980: Predicted default but actually good → LOST revenue (type I)
- FN = 150: Predicted good but actually default → BAD DEBT (type II)

Business trade-off:

  • FP (980): Reject khách tốt → mất revenue ~980 × 30M × 15% interest = 4.4 tỷ/năm opportunity cost
  • FN (150): Approve khách xấu → nợ xấu ~150 × 30M × 60% loss = 2.7 tỷ/năm actual loss
  • Net: FN (actual loss) đắt hơn per-case → optimize for Recall (catch more defaults)

Impact (2024)

MetricBefore ML (Manual)After MLImprovement
Processing time/hồ sơ15-20 phút2 phút (auto) + 5 phút (manual review)-75%
Auto-decision rate0%75% (auto approve + auto reject)Massive efficiency
NPL rate (30+ DPD)7.2%5.1%-29%
Revenue from approved loans450 tỷ/năm580 tỷ/năm+28.9% (more good loans approved)
Compliance audit"Không giải thích được quyết định""Score + 3 reason codes mỗi hồ sơ"100% compliant

Key Learnings cho DA

  1. Interpretability = requirement, không phải nice-to-have: Trong finance, healthcare, legal → model PHẢI giải thích được. Logistic Regression + Decision Tree > Black-box XGBoost
  2. 2 models tốt hơn 1: LR cho scoring (quantitative), DT cho reason codes (qualitative) → complementary
  3. FP vs FN tradeoff: Trong credit scoring, FN (approve bad loan → loss) đắt hơn FP (reject good applicant → opportunity cost). Optimize threshold theo business cost
  4. DA role: VietCredit DAs analyze model performance by segment (age, region, income), monitor model drift monthly, create scorecards for business review

🔗 So sánh 3 Case Studies

DimensionSpotifyShopeeVietCredit
Bài toánRecommendationChurn PredictionCredit Scoring
ML TypeCollaborative Filtering + Content-BasedClassification (XGBoost)Classification (LR + DT)
Scale640M users × 100M tracks15M sellers × 200 features50,000 applications/month
Key metricStream Rate, Discovery RateRecall ≥ 0.80AUC-ROC, NPL Rate
InterpretabilityKhông cần (black-box OK)Moderate (feature importance)PHẢI interpretable (regulatory)
DA RoleDefine metrics, A/B test analysisFeature engineering, segment analysisMonitor model, create scorecards
Revenue Impact$1.5B/năm120 tỷ VND/nămGiảm NPL 29%, tăng revenue 28.9%
Key LearningFeature engineering > algorithmTrend features > snapshotInterpretability = compliance

💡 Takeaway cho DA

  • Không cần biết train XGBoost hay neural network — nhưng PHẢI hiểu ML đang làm gì, metrics nghĩa gì, business impact bao nhiêu
  • DA = bridge giữa ML model và business decision — translate F1 score thành "tiết kiệm X tỷ/năm"
  • Feature engineering (domain knowledge → features) thường valuable hơn model tuning — và đây chính là thế mạnh của DA!