Bạn đã bao giờ tự hỏi liệu khách hàng mua vì nhận promotion, hay họ vẫn sẽ mua dù không có ưu đãi?
Đó là lý do tôi dùng Uplift Modeling. Framework này giúp đo chính xác ai thật sự bị thuyết phục bởi chiến dịch, ai chỉ đang nhận tiền free.
Framework 4 bước triển khai:
Bước 1: Phân nhóm khách hàng
- Sure Things: mua dù không khuyến mãi
- Persuadables: chỉ mua khi có ưu đãi (target chính)
- Lost Causes: không mua dù có ưu đãi
- Sleeping Dogs: phản tác dụng khi nhận ưu đãi
Bước 2: Thiết kế thử nghiệm
Random split 50-50 treatment/control, đảm bảo A/B test đúng chuẩn.
Bước 3: Mô hình hóa
Dùng Two-Model approach hoặc X-Learner để ước lượng:
Uplift = P(conversion|treatment) - P(conversion|control)
Bước 4: Tối ưu ROI
Chỉ gửi offer cho nhóm Persuadables, tiết kiệm 40-60% ngân sách marketing.
Ví dụ thực tế: E-commerce giảm 50% chi phí voucher nhưng tăng 25% doanh thu bằng cách chỉ target đúng nhóm khách hàng có uplift score cao.
Hầu hết công ty đang gửi ưu đãi cho cả Sure Things lẫn Lost Causes. Tiền bay không rõ lý do.
Công ty bạn đang "đốt tiền" vào những khách hàng nào?
The Curious Machine
Mình là 1 cỗ máy tò mò, hãy cùng mình khám phá thế giới xung quanh qua những Usecase thú vị nhé
Data drift là sát thủ thầm lặng giết chết model production. Giao dịch thẻ tín dụng tháng này khác hẳn tháng trước? PSI (Population Stability Index) giúp bạn phát hiện ngay.
Code nhanh:
import numpy as np
def calculate_psi(expected, actual, buckets=10):
exp_pct = np.histogram(expected, buckets)[0] / len(expected)
act_pct = np.histogram(actual, buckets)[0] / len(actual)
psi = np.sum((act_pct - exp_pct) * np.log(act_pct / exp_pct + 0.0001))
return psi
psi_score = calculate_psi(train_amounts, prod_amounts)
# PSI < 0.1: OK | 0.1-0.2: Cảnh báo | >0.2: Nguy hiểm
Ví dụ thực tế: Transaction amount shift từ 500k→2M trung bình? PSI = 0.25, model cần retrain gấp.
Case khác: User behavior thay đổi do COVID, PSI tăng vọt 0.18 trong tuần đầu lockdown. Team mình phải deploy lại model trong 3 ngày thay vì đợi tháng sau.
Bạn đang monitor drift ở đâu trong pipeline? Feature level hay prediction level?
Multi-Armed Bandits: Từ cơ bản đến Contextual
Framework 3 bước tối ưu exploration-exploitation:
Bước 1: MAB cổ điển - Epsilon-greedy/UCB khi không có context. Phù hợp A/B testing đơn giản: chọn 1 trong K arms, học reward distribution. Giới hạn: treat mọi user như nhau.
Bước 2: Thompson Sampling - Bayesian approach, sample từ posterior distribution của reward. Tự cân bằng explore/exploit tốt hơn epsilon-greedy, đặc biệt early stage. Code đơn giản hơn UCB.
Bước 3: Contextual Bandits - Thêm features (user, time, location). LinUCB/Neural bandits học f(context, arm) → reward. Scale với LLM: embed user query, chọn prompt template tối ưu real-time.
Ví dụ thực tế: Hệ thống RAG với 5 retrieval strategies. Thompson Sampling chọn strategy dựa trên click-through. Sau 1000 queries, thêm context (query length, domain), Contextual Bandit tăng precision 23%.
Trade-off: MAB đơn giản nhưng limited. Thompson Sampling cần prior knowledge. Contextual phức tạp, cần data lớn để học context mapping.
Bạn đang dùng approach nào cho LLM routing? Cold-start problem giải quyết thế nào?
Hôm nay team mình deploy model mới lên production. Accuracy tăng 5%, latency giảm 20ms. Nghe có vẻ ổn, nhưng đến chiều thì drama bắt đầu.
Sales Slack mình liên tục: "Sao model đoán sai khách hàng VIP?", "Khách phàn nàn kết quả không chính xác như trước". Mình check logs thì thấy edge case mà team không test kỹ. Model mới handle tốt phần lớn case, nhưng lại fail ở đúng segment khách hàng quan trọng nhất.
Đây không phải lần đầu mình gặp. Và bài học luôn giống nhau:
Metrics tổng thể tốt không có nghĩa là model đã sẵn sàng cho thực tế.
Mấy thứ mình học được sau các lần deploy lỗi:
- Test theo segment khách hàng, không chỉ test tổng thể. VIP khác mass market, behavior khác hẳn.
- Canary deployment với nhóm nhỏ trước. 5-10% traffic trong 2-3 ngày, quan sát kỹ feedback.
- Có rollback plan rõ ràng. Không phải "về code cũ" mà là "rollback trong 15 phút, ai làm gì".
- Đo metrics business, không chỉ technical metrics. Conversion rate, customer satisfaction quan trọng hơn accuracy.
Chiều nay mình rollback về model cũ. Tuần sau sẽ fix edge case và deploy lại, lần này có test kỹ hơn.
Bạn đã bao giờ deploy model rồi phải rollback gấp chưa? Xử lý thế nào?
Mình vừa phỏng vấn 8 ứng viên Data Analyst tuần này. 7 người fail cùng 1 câu hỏi: "Em xử lý missing data như thế nào?"
Câu trả lời tiêu chuẩn (và sai):
- "Em fillna() bằng mean/median"
- "Em drop hết missing values"
- "Em dùng KNN imputation"
Họ trả lời THUẬT TOÁN trước khi hiểu BỐI CẢNH.
Người duy nhất pass hỏi ngược lại mình 3 câu:
- Missing này là MAR, MCAR hay MNAR?
- Business impact nếu drop vs nếu fill sai là gì?
- Stakeholder cần accuracy hay coverage?
Đây là điều phân biệt junior với senior. Junior nghĩ data cleaning là kỹ thuật. Senior hiểu đó là business decision.
Ví dụ thực tế từ dự án retention model tuần trước:
- 30% user không có income data
- Junior: "Anh ơi em fill median nhé"
- Senior: "30% này là freelancer không khai thu nhập. Nếu fill median, model sẽ nghĩ họ giống nhóm income trung bình và predict sai behavior. Đề xuất: tạo category riêng 'income_unknown' hoặc dùng proxy feature là spending pattern"
Impact: AUC tăng từ 0.72 lên 0.79 chỉ vì cách handle missing đúng.
3 câu hỏi mình luôn hỏi trước khi xử lý missing data:
- Tại sao data missing? (User behavior, system error, hay privacy choice?)
- Missing pattern có correlation với target variable không?
- Cost của false positive vs false negative trong business context này là bao nhiêu?
Kỹ thuật là dễ. Google là ra fillna(), SimpleImputer, MICE. Khó là biết KHI NÀO dùng cái gì và TẠI SAO.
Bạn handle missing data như thế nào trong dự án gần nhất? Có bao giờ quyết định KHÔNG fill missing mà để nguyên không?
Thử nghiệm với RAG bây giờ như chơi Lego mà không có hướng dẫn. Bạn ném documents vào vector store, kỳ vọng nó sẽ tự biết trả lời đúng. Nhưng thực tế 70% câu hỏi của user lại không match với chunks bạn index.
Tôi vừa deploy một RAG system cho team product, và phát hiện ra vấn đề thật sự không phải ở retrieval. Nó nằm ở chỗ: bạn có đang hỏi đúng câu hỏi không?
Hầu hết RAG fails vì semantic gap. User hỏi "Làm sao tăng retention?" nhưng docs của bạn lại viết về "chiến lược giữ chân khách hàng dài hạn". Embedding model nhìn hai câu này như hai thứ khác nhau.
Vài patterns thực chiến giúp tôi improve hit rate từ 0.62 lên 0.89:
- Query expansion: rewrite câu hỏi thành 3-4 variants trước khi search
- Metadata filtering: đừng search toàn bộ, filter theo document type, date range, source
- Hybrid search: kết hợp semantic + keyword search, đặc biệt với tên riêng, số liệu
Nhưng trick quan trọng nhất: pre-index câu hỏi phổ biến. Thay vì chỉ index documents, tôi còn index một list 200 câu hỏi mẫu với answers từ docs. Khi user hỏi, system sẽ match với câu hỏi tương tự trước, rồi mới retrieve documents.
Bạn đang build RAG thế nào? Retrieval accuracy của bạn bao nhiêu khi test với real user queries?
14/08/2025
📌 𝑵𝒈𝒖𝒚𝒆̂𝒏 𝒕𝒂̆́𝒄 𝑪𝑨𝑷 – 𝑪𝒐̂́𝒕 𝒍𝒐̃𝒊 𝒄𝒖̉𝒂 𝒕𝒉𝒊𝒆̂́𝒕 𝒌𝒆̂́ 𝒉𝒆̣̂ 𝒕𝒉𝒐̂́𝒏𝒈 𝒑𝒉𝒂̂𝒏 𝒕𝒂́𝒏
Nếu bạn làm về Distributed Systems (hệ thống phân tán) thì sớm muộn gì cũng sẽ gặp CAP theorem – một nguyên tắc “định luật vật lý” của thế giới backend.
CAP là viết tắt của:
- 𝐂 – 𝐂𝐨𝐧𝐬𝐢𝐬𝐭𝐞𝐧𝐜𝐲: Tính nhất quán.
→ Mọi node trong hệ thống đều nhìn thấy cùng một dữ liệu tại cùng một thời điểm.
- 𝑨 – 𝑨𝒗𝒂𝒊𝒍𝒂𝒃𝒊𝒍𝒊𝒕𝒚: Tính sẵn sàng.
→ Mỗi request đều nhận được phản hồi (success hoặc fail) trong một khoảng thời gian hợp lý.
- 𝐏 – 𝐏𝐚𝐫𝐭𝐢𝐭𝐢𝐨𝐧 𝐓𝐨𝐥𝐞𝐫𝐚𝐧𝐜𝐞: Khả năng chịu phân vùng.
→ Hệ thống vẫn hoạt động khi có lỗi mạng khiến các node không thể giao tiếp với nhau.
⚠️ Nguyên tắc:
Trong điều kiện có Partition (mà thực tế hệ thống phân tán luôn có khả năng bị), bạn chỉ có thể đảm bảo tối đa 2 trong 3 yếu tố.
Nói cách khác: Không thể vừa C vừa A khi P xảy ra.
🎯 Ví dụ dễ hình dung
Giả sử bạn có 2 chi nhánh ngân hàng (Hà Nội và TP.HCM) cùng chia sẻ dữ liệu tài khoản khách hàng qua mạng.
P (Partition): Nếu đường truyền giữa 2 chi nhánh bị đứt.
Bây giờ bạn phải chọn:
𝐂𝐀 – 𝐊𝐡𝐨̂𝐧𝐠 𝐜𝐡𝐨̣𝐧 𝐏
Nếu không chịu được Partition, khi mạng hỏng → hệ thống dừng luôn. (Nếu mà nó chạy nữa thì dữ liệu của 2 bên nó sẽ hum có đồng bộ tuyệt đối được thì nó không có đúng với chữ C)
Ví dụ: core banking yêu cầu dữ liệu phải đồng bộ tuyệt đối → mạng đứt là toàn bộ giao dịch ngưng hoặc chờ.
𝐂𝐏 – 𝐊𝐡𝐨̂𝐧𝐠 𝐜𝐡𝐨̣𝐧 𝐀
Vẫn đảm bảo dữ liệu nhất quán giữa các node, nhưng phải chặn hoặc delay request khi mạng lỗi.
Ví dụ: mạng đứt → giao dịch ATM bị tạm khóa cho đến khi đồng bộ xong. (Thì bạn thấy đó không có sẵn ngay lúc này nên chờ xíu load đã)
𝐀𝐏 – 𝐊𝐡𝐨̂𝐧𝐠 𝐜𝐡𝐨̣𝐧 𝐂
Vẫn cho phép giao dịch dù dữ liệu có thể tạm thời không nhất quán. Sau đó sẽ đồng bộ lại.
Ví dụ: bạn rút tiền ở ATM Hà Nội và đồng thời chuyển khoản ở TP.HCM → số dư hiển thị có thể khác tạm thời (𝐓𝐡𝐨̂𝐢 đ𝐮̛̀𝐧𝐠 𝐜𝐡𝐨̛𝐢 𝐝𝐚̣𝐢 như 𝐨̛̉ 𝐭𝐫𝐮̛𝐨̛̀𝐧𝐠 𝐡𝐨̛̣𝐩 𝐧𝐡𝐮̛ 𝐧𝐚̀𝐲). Mà ví dụ như trường hợp xử lý tin nhắn giữa 2 người trong 1 khung chat vì mạng lag nên khiến cho nội dung hiển thị trên giao diện nó bị lệch tý cũng được F5 lại sau. Hoặc khi server ở Hà Nội và TP.HCM chưa đồng bộ, bạn có thể thấy “102 likes” ở một máy và “98 likes” ở máy khác, nhưng hệ thống vẫn cho bạn bấm like và sẽ đồng bộ lại sau vài giây.
💡 Kết luận:
CAP không phải “muốn cái gì cũng được” mà là trade-off.
Tùy vào bài toán và yêu cầu nghiệp vụ, kiến trúc sư hệ thống sẽ chọn CP hoặc AP (CA hiếm gặp vì không chịu được network partition).
📍 Ghi nhớ một câu cho dễ sống:
“Khi mạng phân mảnh, phải chọn: Hoặc có dữ liệu chuẩn, hoặc luôn trả lời. Không thể cả hai.”
07/08/2025
𝑭𝒆𝒂𝒕𝒖𝒓𝒆 𝑺𝒆𝒍𝒆𝒄𝒕𝒊𝒐𝒏 𝒇𝒐𝒓 𝑵𝒂𝒊𝒗𝒆 𝑩𝒂𝒚𝒆𝒔: 𝑾𝒉𝒚 𝑳𝒆𝒔𝒔 𝒊𝒔 𝑴𝒐𝒓𝒆
Bạn đang xây dựng một bộ phân loại email spam bằng Naive Bayes, với hàng trăm từ khoá khác nhau được trích xuất từ nội dung email. Tuy nhiên, sau khi huấn luyện mô hình, bạn nhận thấy độ chính xác không như kỳ vọng — thậm chí còn thấp hơn cả một mô hình logistic regression đơn giản.
Khi kiểm tra kỹ lại, bạn thấy rằng rất nhiều từ khóa thường xuyên xuất hiện cùng nhau — ví dụ như “free”, “offer”, “buy now”. Những feature này không hề độc lập với nhau. Và đó chính là vấn đề: Naive Bayes hoạt động tốt nhất khi các feature độc lập có điều kiện (conditionally independent) — một assumption "naive" nhưng rất quan trọng.
1. Naive Bayes và Assumption Feature Independence
Naive Bayes giả định rằng:
Điều này nghĩa là các feature phải độc lập với nhau khi đã biết nhãn. Trong thực tế, điều này hiếm khi đúng hoàn toàn, nhưng mô hình vẫn hoạt động ổn trong nhiều tình huống — đặc biệt là khi bạn biết cách chọn feature phù hợp.
Vấn đề: Feature Correlation
Nếu hai feature tương quan mạnh, ví dụ: 𝑥1="discount" và 𝑥2="sale", thì việc giữ cả hai có thể khiến Naive Bayes “đếm trùng” thông tin, dẫn đến overconfidence trong dự đoán.
Vì vậy, giảm thiểu tương quan (low correlation) giữa các feature là chiến lược then chốt khi chọn đặc trưng cho Naive Bayes.
2. Feature Selection bằng Mutual Information (MI)
Mutual Information là gì?
Mutual Information (MI) đo lường lượng thông tin mà một feature
(công thức trong hình)
Nếu 𝑋 và Y hoàn toàn độc lập → MI = 0
Nếu 𝑋 giúp dự đoán tốt 𝑌 → MI cao
Vì vậy, MI giúp chọn ra những feature có giá trị phân biệt cao, mà không cần mô hình hóa phức tạp.
3. Cách dùng MI để chọn feature cho Naive Bayes
- Tính MI giữa từng feature và nhãn lớp (label).
- Xếp hạng các feature theo giá trị MI.
- Chọn top-k feature có MI cao nhất.
Bạn có thể dùng hàm mutual_info_classif trong sklearn.feature_selection:
from sklearn.feature_selection import mutual_info_classif
mi = mutual_info_classif(X, y)
Lưu ý: MI đo lường mối quan hệ giữa feature và label — chứ không giữa các feature với nhau. Tuy nhiên, khi bạn chọn ít feature có MI cao, bạn giảm khả năng chọn trùng thông tin giữa các feature, từ đó gián tiếp làm giảm tương quan.
05/08/2025
10 CÁCH TỐI ƯU TRUY VẤN DATABASE MÀ DEV NÀO CŨNG NÊN BIẾT
Hôm trước chúng ta tìm hiểu về indexing trong DB rồi. Liệu nó đã đủ để hệ thống chạy mượt mà chưa chưa? Hôm nay chúng ta cùng tìm hiểu về những phương pháp khác nhé!
1. 🎯 Chỉ SELECT những cột cần thiết
Đừng SELECT *. Chọn đúng field giúp giảm data truyền về, nhẹ hơn, nhanh hơn.
-- 𝑇𝑒̣̂
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑢𝑠𝑒𝑟𝑠;
-- 𝑇𝑜̂́𝑡
𝑆𝐸𝐿𝐸𝐶𝑇 𝑖𝑑, 𝑛𝑎𝑚𝑒, 𝑒𝑚𝑎𝑖𝑙 𝐹𝑅𝑂𝑀 𝑢𝑠𝑒𝑟𝑠;
2. 🚦 WHERE đúng cách để giảm lượng dữ liệu
Đừng để DB quét toàn bảng chỉ vì bạn thiếu điều kiện.
Luôn dùng WHERE thông minh.
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝑊𝐻𝐸𝑅𝐸 𝑐𝑟𝑒𝑎𝑡𝑒𝑑_𝑎𝑡 >= 𝑁𝑂𝑊() - 𝐼𝑁𝑇𝐸𝑅𝑉𝐴𝐿 '30 𝑑𝑎𝑦𝑠';
3. 🧠 Index đúng cột, đúng lúc
Dùng index cho: WHERE, JOIN, ORDER BY, GROUP BY
Tránh index cột có ít giá trị lặp (vd: gender, status)
𝐶𝑅𝐸𝐴𝑇𝐸 𝐼𝑁𝐷𝐸𝑋 𝑖𝑑𝑥_𝑜𝑟𝑑𝑒𝑟𝑠_𝑢𝑠𝑒𝑟𝑖𝑑 𝑂𝑁 𝑜𝑟𝑑𝑒𝑟𝑠(𝑢𝑠𝑒𝑟_𝑖𝑑);
4. 🔍 Dùng EXPLAIN để hiểu DB đang làm gì
Đừng đoán, hãy EXPLAIN.
Nó cho bạn biết DB có dùng index không, có full scan không.
𝐸𝑋𝑃𝐿𝐴𝐼𝑁 𝐴𝑁𝐴𝐿𝑌𝑍𝐸
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝑊𝐻𝐸𝑅𝐸 𝑢𝑠𝑒𝑟_𝑖𝑑 = 123;
5. 🔥 Tránh OR, thay bằng UNION ALL nếu được
OR làm DB bỏ qua index 😓
Tách ra UNION ALL giúp DB dùng index hiệu quả hơn.
-- 𝐾ℎ𝑜̂𝑛𝑔 𝑡𝑜̂́𝑡
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝑊𝐻𝐸𝑅𝐸 𝑠𝑡𝑎𝑡𝑢𝑠 = '𝑝𝑒𝑛𝑑𝑖𝑛𝑔' 𝑂𝑅 𝑢𝑠𝑒𝑟_𝑖𝑑 = 5;
-- 𝑇𝑜̂́𝑡 ℎ𝑜̛𝑛
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝑊𝐻𝐸𝑅𝐸 𝑠𝑡𝑎𝑡𝑢𝑠 = '𝑝𝑒𝑛𝑑𝑖𝑛𝑔'
𝑈𝑁𝐼𝑂𝑁 𝐴𝐿𝐿
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝑊𝐻𝐸𝑅𝐸 𝑢𝑠𝑒𝑟_𝑖𝑑 = 5;
6. 🧩 Tối ưu JOIN:
- Chỉ JOIN những bảng cần thiết
- Index cột dùng trong JOIN ON
- Tránh JOIN nhiều bảng to cùng lúc nếu không bắt buộc
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑢𝑠𝑒𝑟𝑠
𝐽𝑂𝐼𝑁 𝑜𝑟𝑑𝑒𝑟𝑠 𝑂𝑁 𝑢𝑠𝑒𝑟𝑠.𝑖𝑑 = 𝑜𝑟𝑑𝑒𝑟𝑠.𝑢𝑠𝑒𝑟_𝑖𝑑;
7. 📦 Dùng LIMIT + OFFSET để phân trang
Không cần trả về 10k dòng 1 lần, hãy phân trang hợp lý.
𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝑂𝑅𝐷𝐸𝑅 𝐵𝑌 𝑐𝑟𝑒𝑎𝑡𝑒𝑑_𝑎𝑡 𝐷𝐸𝑆𝐶 𝐿𝐼𝑀𝐼𝑇 20 𝑂𝐹𝐹𝑆𝐸𝑇 40;
8. ⚡ Dùng cache với query nặng, ít thay đổi
Cache bằng Redis, Memcached, hoặc store vào biến/tệp
Ví dụ: tổng doanh thu, top 10 sản phẩm bán chạy
# Cache 5 phút 1 lần là hợp lý cho dashboard
9. 🧱 Dùng materialized view hoặc pre-aggregate
Nếu bạn GROUP BY nặng thường xuyên → hãy lưu kết quả tạm.
𝐶𝑅𝐸𝐴𝑇𝐸 𝑀𝐴𝑇𝐸𝑅𝐼𝐴𝐿𝐼𝑍𝐸𝐷 𝑉𝐼𝐸𝑊 𝑑𝑎𝑖𝑙𝑦_𝑠𝑎𝑙𝑒𝑠 𝐴𝑆
𝑆𝐸𝐿𝐸𝐶𝑇 𝑑𝑎𝑡𝑒(𝑐𝑟𝑒𝑎𝑡𝑒𝑑_𝑎𝑡), 𝑆𝑈𝑀(𝑡𝑜𝑡𝑎𝑙)
𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠
𝐺𝑅𝑂𝑈𝑃 𝐵𝑌 𝑑𝑎𝑡𝑒(𝑐𝑟𝑒𝑎𝑡𝑒𝑑_𝑎𝑡);
10. 📊 Partition bảng lớn / chia shard
Khi bảng > 10 triệu dòng, hãy xem xét chia nhỏ.
- PostgreSQL hỗ trợ partition by range
- Sharding nên dùng khi scale ngang (horizontal)
Bài sau mình sẽ lên một vài kỹ thuật ở mức độ sql level đănt tăng tốc độ chạy cảy truy vấn
Click here to claim your Sponsored Listing.
Location
Category
Website
Address
Ho Chi Minh City