HD95 trong phân đoạn ảnh y khoa: Chỉ số ranh giới bị bỏ qua nhưng quyết định độ tin cậy lâm sàng

Khi đánh giá mô hình phân đoạn ảnh — đặc biệt trong chẩn đoán y khoa — chỉ số Dice thường chiếm vị trí trung tâm trong báo cáo kết quả. Tuy nhiên, một chỉ số ít được nhắc đến nhưng lại mang tính quyết định đối với tính khả dụng lâm sàng là HD95 (Hausdorff Distance tại percentile thứ 95). Trong các tình huống yêu cầu độ chính xác ở mức pixel hoặc milimét — như lập kế hoạch xạ trị hay xác định ranh giới khối u — HD95 cung cấp thông tin về sai lệch biên mà Dice hoàn toàn không thể phản ánh.

1. Vì sao Dice không đủ để đánh giá chất lượng phân đoạn?

Dice đo lường mức độ chồng lấn toàn cục giữa dự đoán và nhãn thực tế, nhưng nó che khuất các lỗi hệ thống ở vùng ranh giới. Ví dụ: một mô hình đạt Dice = 0.93 có thể vẫn dịch chuyển toàn bộ viền khối u ra ngoài 3–4 pixel — điều này gây nguy cơ cắt bỏ thiếu mô bệnh hoặc chiếu xạ sai vùng. HD95 khắc phục điểm yếu này bằng cách định lượng khoảng cách lớn nhất giữa 95% các điểm trên đường viền dự đoán so với đường viền chuẩn, loại bỏ ảnh hưởng của các điểm ngoại lai đơn lẻ.

2. Cách tính HD95 một cách thực tiễn

Hausdorff Distance nguyên thủy lấy giá trị cực đại trong tập hợp khoảng cách ngắn nhất giữa hai tập điểm. HD95 thay thế "giá trị cực đại" bằng "percentile thứ 95", giúp tăng độ ổn định trước nhiễu và dị thường. Dưới đây là hai cách triển khai phổ biến:

Sử dụng medpy cho ảnh 2D/3D nhị phân:

from medpy.metric.binary import hd95

# pred_mask và gt_mask là tensor numpy nhị phân (0/1), cùng kích thước
distance_px = hd95(pred_mask, gt_mask, voxelspacing=(1.0, 1.0, 2.5))  # hỗ trợ spacing thực tế
print(f"HD95 = {distance_px:.2f} mm")

Sử dụng SimpleITK với kiểm soát đầy đủ về không gian ảnh:

import SimpleITK as sitk

def compute_hd95_sitk(pred_path, gt_path):
    pred_img = sitk.ReadImage(pred_path)
    gt_img = sitk.ReadImage(gt_path)
    
    # Đảm bảo cùng spacing và origin
    pred_img = sitk.Resample(
        pred_img, gt_img, sitk.Transform(), sitk.sitkNearestNeighbor,
        0.0, pred_img.GetPixelID()
    )
    
    filter_obj = sitk.HausdorffDistanceImageFilter()
    filter_obj.Execute(gt_img, pred_img)
    return filter_obj.Get95thPercentileHausdorffDistance()

3. So sánh trực quan: Khi nào HD95 cảnh báo rủi ro mà Dice im lặng?

Tình huống lỗi Dice HD95 (mm) Hệ quả lâm sàng
Dịch chuyển đồng đều viền khối u (+1.8 mm)0.872.1Có thể làm sai lệch kế hoạch xạ trị liều cao
Lỗi cục bộ tại vùng bờ não – khối u0.926.4Gây khó khăn trong phẫu thuật bảo tồn
Mất hoàn toàn cấu trúc nhỏ (ví dụ: hạch bạch huyết <3 mm)0.949.7Bỏ sót giai đoạn di căn

4. Tích hợp HD95 vào quy trình huấn luyện

Để cải thiện độ chính xác biên, không nên chỉ dùng HD95 ở giai đoạn đánh giá. Một chiến lược hiệu quả là kết hợp mất mát biên vào hàm mục tiêu:

import torch
import torch.nn.functional as F

class BoundaryAwareLoss(torch.nn.Module):
    def __init__(self, dice_weight=0.7, boundary_weight=0.3):
        super().__init__()
        self.dice_weight = dice_weight
        self.boundary_weight = boundary_weight

    def forward(self, logits, target):
        # Dice loss trên toàn ảnh
        prob = torch.sigmoid(logits)
        smooth = 1e-5
        intersection = (prob * target).sum()
        dice = (2. * intersection + smooth) / (prob.sum() + target.sum() + smooth)
        dice_loss = 1 - dice

        # Mất mát biên: sử dụng Sobel để phát hiện cạnh
        sobel_x = torch.tensor([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=torch.float32).view(1, 1, 3, 3)
        sobel_y = sobel_x.transpose(2, 3)
        
        pred_edge = torch.sqrt(
            F.conv2d(prob, sobel_x.to(prob.device), padding=1)**2 +
            F.conv2d(prob, sobel_y.to(prob.device), padding=1)**2
        )
        gt_edge = torch.sqrt(
            F.conv2d(target, sobel_x.to(target.device), padding=1)**2 +
            F.conv2d(target, sobel_y.to(target.device), padding=1)**2
        )

        edge_loss = F.l1_loss(pred_edge, gt_edge)

        return self.dice_weight * dice_loss + self.boundary_weight * edge_loss

5. Hướng phát triển mới

Các nghiên cứu gần đây mở rộng khái niệm HD95 theo ba hướng chính:

  • HDadaptive: Tự động chọn percentile tối ưu dựa trên độ phức tạp biên của từng mẫu;
  • Directional HD: Phân biệt lỗi dịch chuyển hướng xuyên tâm (radial) và tiếp tuyến (tangential) — đặc biệt hữu ích trong phân tích mạch máu;
  • Weighted HD95: Gán trọng số cao hơn cho các vùng解剖 học quan trọng (ví dụ: viền vỏ não, ranh giới tuyến tụy).

Một khuôn khổ đánh giá toàn diện hiện đại nên bao gồm đồng thời: (1) độ chồng lấn khu vực (Dice, NSD), (2) độ chính xác biên (HD95, ASSD), và (3) tính đúng đắn về mặt giải phẫu (ví dụ: số thành phần liên thông, độ liên tục topological).

Thẻ: hd95 hausdorff-distance medical-image-segmentation segmentation-metrics loss-function

Đăng vào ngày 23 tháng 10 lúc 09:31