Đừng đưa mô hình y tế lên sàn quá sớm

Đừng đưa mô hình y tế lên sàn quá sớm

Một playbook triển khai 3D segmentation bằng MONAI: thử nhỏ, đo đúng, biết khi nào nên scale và khi nào nên dừng.

Có một kiểu demo rất dễ làm tech lead mềm lòng: mở notebook, load CT volume, chạy 3D UNet, mask lá lách hiện ra màu mè trên màn hình. Cả phòng im 2 giây rồi có người hỏi: “Vậy tuần sau mình đóng gói thành API được chưa?”

Khoan đã. Với medical AI, notebook đẹp mới giống buổi đầu vào dojo: bạn mặc võ phục, học thế thủ, biết cú đấm đi về đâu. Nhưng để lên sàn đối luyện thật, bạn cần biết mình sẽ ngã ở đâu, ai chấm điểm, và khi nào phải dừng trận.

Luận điểm của mình hôm nay rất gọn: đừng đánh giá pipeline segmentation y tế bằng việc nó chạy được end-to-end; hãy đánh giá bằng việc team có kiểm soát được dữ liệu, failure mode, metric và chi phí vận hành hay không. MONAI, 3D UNet, DiceCE loss hay sliding-window inference đều là công cụ tốt. Nhưng quyết định triển khai nằm ở playbook vận hành, không nằm ở tên model.

Sơ đồ minh họa cho bài Đừng đưa mô hình y tế lên sàn quá sớm

Sơ đồ tóm tắt ý chính của bài viết.

Mục tiêu không phải là “train xong”, mà là biết có đáng đi tiếp

Nguồn chính dùng MONAI để dựng pipeline 3D spleen segmentation trên CT volume: load dữ liệu Medical Segmentation Decathlon Task09, chuẩn hóa orientation, normalize voxel spacing, scale intensity, crop foreground, sample patch, train 3D UNet, validate bằng Dice, rồi visualize mask dự đoán so với ground truth.

Nếu bạn là builder, phần đáng học không phải “UNet còn dùng được không”. Câu hỏi đúng hơn là:

MONAI là framework cho deep learning y tế, mạnh ở data transform và pipeline ảnh y khoa. 3D UNet là kiến trúc segmentation làm việc trực tiếp trên thể tích 3 chiều. Segmentation nghĩa là tô vùng đối tượng trong ảnh, ví dụ khoanh lá lách trong CT thay vì chỉ nói “có lá lách”.

Nói thẳng ra thì: một pipeline segmentation y tế không phải bài toán “model nào xịn”, mà là bài toán “chuỗi xử lý nào ít làm bậy nhất khi gặp dữ liệu lạ”.

Checklist một buổi: dựng bản thử có tiêu chí dừng

Bạn có thể làm bản thử trong một buổi chiều, nhưng đừng biến nó thành lời hứa production. Mục tiêu của buổi này là tạo deployment rehearsal — diễn tập triển khai — để xem hệ thống gãy ở đâu.

Checklist tối thiểu:

  1. Chốt task hẹp

Chỉ làm một organ, một modality, một dataset. Ví dụ: spleen segmentation trên CT volume. Đừng tiện tay mở rộng sang gan, thận, MRI, ultrasound.

  1. Ghi rõ pipeline transform

Với ảnh y tế, preprocessing không phải bước phụ. Orientation alignment là đưa ảnh về cùng hướng đọc. Voxel-spacing normalization là chuẩn hóa kích thước voxel để model không học nhầm tỷ lệ. Intensity windowing là cắt dải giá trị CT về vùng hữu ích.

  1. Tách train và validation theo case

Đừng để các slice gần nhau rò rỉ giữa train và validation. Với dữ liệu 3D, rò rỉ kiểu này làm metric nhìn rất ngoan, nhưng ra dữ liệu mới thì xuống đai ngay.

  1. Dùng metric chính và metric phụ

Dice score đo mức chồng khít giữa mask dự đoán và mask thật. Nhưng chỉ Dice không đủ. Bạn nên thêm kiểm tra trực quan, thống kê thể tích mask, và danh sách case model dự đoán quá lệch.

  1. Đặt tiêu chí dừng trước khi chạy

Ví dụ minh họa: nếu sau vài vòng thử, model chỉ tốt trên case dễ, fail nặng ở scan có spacing khác, hoặc inference quá chậm so với workflow mong muốn, team dừng để sửa dữ liệu/pipeline thay vì tăng epoch.

Đây là thế thủ đầu tiên: khóa phạm vi trước khi tăng tham vọng.

Các bước triển khai thử, đủ cụ thể để không bị lạc

Bước 1: dựng môi trường có thể lặp lại

Dùng Python environment riêng, pin version nếu team có nhiều máy. Với notebook demo, bạn có thể chạy nhanh. Với team, nên chuyển sớm sang script có config.

python -m venv .venv
source .venv/bin/activate
pip install monai torch nibabel matplotlib tqdm

Nếu dùng GPU, ghi lại CUDA version, driver, loại GPU. Bài cuTile trong nguồn liên quan nhắc một điểm rất thực dụng: trước khi tối ưu kernel hay khoe GPU, phải kiểm tra runtime có thật sự hỗ trợ backend không. Tư duy này áp dụng y chang ở MONAI: đừng để notebook chạy trên máy A rồi chết âm thầm trên máy B.

Bước 2: viết transform như hợp đồng dữ liệu

Trong MONAI, transform chain thường gồm:

Đừng xem đây là “mấy dòng chuẩn bị”. Đây là bản hợp đồng giữa dữ liệu thật và model. Nếu hợp đồng sai, model học sai rất chăm chỉ.

Ví dụ cụ thể: một scan có spacing khác hẳn phần lớn dữ liệu train. Nếu bạn không normalize spacing, model có thể học rằng lá lách “to/nhỏ” theo kiểu méo tỷ lệ. Ngoài đời, chuyện này giống võ sinh luyện đấm trước gương cong: động tác nhìn ổn, ra sàn thì hụt nhịp.

Bước 3: train nhỏ, validate kỹ

Bản thử nên dùng 3D UNet vừa đủ, DiceCE loss — kết hợp Dice loss với cross-entropy để vừa tối ưu vùng chồng khít vừa học phân loại voxel. Mixed precision training là huấn luyện với độ chính xác hỗn hợp để tiết kiệm memory và tăng tốc trên GPU phù hợp.

Điểm cần theo dõi:

Với volume lớn, sliding-window inference là cách chia volume thành các ô nhỏ để dự đoán rồi ghép lại, tránh hết VRAM. Tradeoff là inference chậm hơn và có thể sinh lỗi ở biên ô nếu cấu hình overlap kém.

Bước 4: visualize như một bước kiểm thử, không phải trang trí

Visualization không chỉ để báo cáo đẹp. Nó là test lâm sàng sơ khai.

Bạn nên lưu vài hình gồm:

Nếu chỉ nhìn metric, bạn có thể bỏ qua lỗi rất nguy hiểm: model khoanh đúng phần lớn thể tích nhưng cắt cụt một vùng quan trọng. Dice vẫn có thể nhìn ổn, nhưng người dùng cuối sẽ không vui.

Pitfall hay gặp: scale nhầm thứ

Có ba lỗi mình thấy rất nhiều team dễ mắc khi đi từ notebook sang hệ thống thật.

Một: tăng epoch thay vì sửa dữ liệu.
Nếu model fail vì orientation, spacing, label noise hoặc domain shift, train lâu hơn chỉ giúp nó học sai chắc hơn.

Hai: nhầm benchmark với readiness.
Dice cao trên validation nội bộ chưa nói được model sẵn sàng chạy ở bệnh viện khác, máy khác, protocol khác. Readiness cần kiểm thử phân nhóm: scan dễ/khó, spacing khác nhau, size organ khác nhau, dữ liệu có artifact.

Ba: thiếu đường lui khi inference fail.
Production cần guardrail: nếu confidence thấp, mask rỗng, thể tích bất thường, hoặc preprocessing phát hiện metadata lạ, hệ thống phải gắn cờ cho human review. Medical AI không nên im lặng trả kết quả như thể mọi thứ đều bình thường.

Nguồn city2graph có một chi tiết đáng mượn: workflow tốt nên có fallback khi dữ liệu bên ngoài lỗi. Với y tế, fallback không phải “tạo dữ liệu synthetic để chữa cháy production”, mà là chuyển case sang review thủ công và lưu lại lý do fail.

Khi nào scale, khi nào dừng?

Mình sẽ dùng khung quyết định 4 cửa, khá hợp cho tech lead:

| Cửa kiểm tra | Scale nếu... | Dừng hoặc quay lại nếu... |
|---|---|---|
| Dữ liệu | transform ổn định trên nhiều case | metadata thiếu, spacing/orientation lộn xộn |
| Metric | Dice tốt đi kèm qualitative review ổn | metric đẹp nhưng mask có lỗi khó chấp nhận |
| Vận hành | inference chạy được trong budget GPU | sliding-window quá chậm hoặc dễ OOM |
| An toàn | có guardrail và human review path | hệ thống trả mask kể cả khi input lạ |

Sau bài này, điều mình muốn bạn nghĩ khác là: triển khai AI y tế không bắt đầu bằng câu “model nào”, mà bằng câu “mình sẽ dừng ở đâu nếu pipeline nói dối?”

Nếu là mình, mình sẽ không scale ngay sau demo MONAI đầu tiên. Mình sẽ làm một đợt đối luyện nhỏ: chọn tập case khó, log mọi transform, kiểm tra mask bằng mắt, đo inference, rồi viết tiêu chí rollback. Qua được bài đó rồi hãy nói chuyện API, batch job, dashboard hay tích hợp PACS.

Demo đẹp là cú chào sân. Production là trận đấu có trọng tài, luật phạt, và khán giả không quan tâm bạn train bằng notebook nào.

---
Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng

Nguồn tham khảo